Logging
Logs for this application can be viewed in one of two locations, depending on the type. Server Logs are drained to Google Cloud Logging, via the oxygen-observability-drain. Client Logs are sampled and ingested by Sentry Logs.
Server Logsโ
We are currently only forwarding QA and production logs to Google Cloud Logging for cost reasons. To view production logs, open Google Cloud's Log Explorer product and query by the following:
logName="projects/api-platform-421220/logs/hydrogen-storefront-logs"
If you need to view logs for an individual QA or staging deployment, please refer to the Shopify Admin console where you can view raw logs for a specific Hydrogen deployment.
The Hydrogen storefront supports several types of server logs and can be categorized into three buckets: request, exception, and runtime. Each of these categories corresponds to a log type defined by Shopify's Log Drain.
Request Logsโ
logName="projects/api-platform-421220/logs/hydrogen-storefront-logs"
labels.type="request"
These logs represent the raw request/response handled by React Router. This provides barebones information about the request, including the request method, pathname targeted, user agent, and response code. Unfortunately it does not include any timing data, as Shopify refers users to sampling OTEL Trace data for performance analysis.
Exception logsโ
logName="projects/api-platform-421220/logs/hydrogen-storefront-logs"
labels.type="exception"
These logs are generated by uncaught exceptions in the storefront. The most common exception log generated is "Network connection lost.".
Runtime logsโ
logName="projects/api-platform-421220/logs/hydrogen-storefront-logs"
labels.type="runtime"
These logs are captured by standard output, for example using console.log, console.warn, or console.error. To provide support log decoration when forwarding to Google Cloud Logging, we offer a LogDrainPayload shape in which objects may be serialized to conform to prior to being stringified for logging. Once received by the log drain application, these messages will be parsed to enrich the log entry.
We further categorize runtime logs into the following two options:
App logs are captured by our captureLog helper. Use captureLog to capture additional information that isn't necessarily an exception (see documentation on Sentry for more information on exception logging), but could be supplemental to an investigation. Typically, these are higher volume logs where we might look for spikes in frequency to tune into potential issues. App logs sent through captureLog are subject to sampling, which can be controlled via the SENTRY_LOGS_SAMPLE_RATE environment variable.
logName="projects/api-platform-421220/logs/hydrogen-storefront-logs"
labels.type="runtime"
labels.logType="app"
Timing logs are captured by our serverTiming middleware. This mechanism leverages React Router's middleware feature for capturing how long it takes for a handler to execute. While it does not capture the full transport duration back to the client, it gives us a standard measure for loader/action execution time. These logs are not captured by captureLog, as we do not want these logs sampled.
logName="projects/api-platform-421220/logs/hydrogen-storefront-logs"
labels.type="runtime"
labels.logType="timing"
Client Logsโ
Client Logs are primarily captured via the captureLog helper and are dispatched to Sentry Logs. We have chosen not to co-locate server and client logging to take advantage of Sentry's public ingestion endpoints, which are pre-configured with the appropriate rate limiting and other network level protections that our custom infrastructure has not implemented. Similar to the runtime app logs, client logs sent through captureLog are also subject to sampling. This is also configured by the same SENTRY_LOGS_SAMPLE_RATE environment variable.