Observability - TypeScript SDK
The observability section of the TypeScript developer guide covers the many ways to view the current state of your Temporal Application—that is, ways to view which Workflow Executions are tracked by the Temporal Platform and the state of any specified Workflow Execution, either currently or at points of an execution.
This section covers features related to viewing the state of the application, including:
Emit metrics
Each Temporal SDK is capable of emitting an optional set of metrics from either the Client or the Worker process. For a complete list of metrics capable of being emitted, see the SDK metrics reference.
Metrics can be scraped and stored in time series databases, such as Prometheus. Temporal also provides a dashboard you can integrate with graphing services like Grafana. For more information, see:
- Temporal's implementation of the Grafana dashboard
- How to export metrics in Grafana
Workers can emit metrics and traces. There are a few telemetry options that can be provided to Runtime.install
. The common options are:
metrics: { otel: { url } }
: The URL of a gRPC OpenTelemetry collector.metrics: { prometheus: { bindAddress } }
: Address on the Worker host that will have metrics for Prometheus to scrape.
To set up tracing of Workflows and Activities, use our opentelemetry-interceptors
package.
(For details, see the next section.)
telemetryOptions: {
metrics: {
prometheus: { bindAddress: '0.0.0.0:9464' },
},
logging: { forward: { level: 'DEBUG' } },
},
Set up tracing
Tracing allows you to view the call graph of a Workflow along with its Activities and any Child Workflows.
Temporal Web's tracing capabilities mainly track Activity Execution within a Temporal context. If you need custom tracing specific for your use case, you should make use of context propagation to add tracing logic accordingly.
The interceptors-opentelemetry
sample shows how to use the SDK's built-in OpenTelemetry tracing to trace everything from starting a Workflow to Workflow Execution to running an Activity from that Workflow.
The built-in tracing uses protobuf message headers (like this one when starting a Workflow) to propagate the tracing information from the client to the Workflow and from the Workflow to its successors (when Continued As New), children, and Activities.
All of these executions are linked with a single trace identifier and have the proper parent -> child
span relation.
Tracing is compatible between different Temporal SDKs as long as compatible context propagators are used.
Context propagation
The TypeScript SDK uses the global OpenTelemetry propagator.
To extend the default (Trace Context and Baggage propagators) to also include the Jaeger propagator, follow these steps:
-
npm i @opentelemetry/propagator-jaeger
-
At the top level of your Workflow code, add the following lines:
import { propagation } from '@opentelemetry/api';
import {
CompositePropagator,
W3CBaggagePropagator,
W3CTraceContextPropagator,
} from '@opentelemetry/core';
import { JaegerPropagator } from '@opentelemetry/propagator-jaeger';
propagation.setGlobalPropagator(
new CompositePropagator({
propagators: [
new W3CTraceContextPropagator(),
new W3CBaggagePropagator(),
new JaegerPropagator(),
],
}),
);
Similarly, you can customize the OpenTelemetry NodeSDK
propagators by following the instructions in the Initialize the SDK section of the README.md
file.
Log from a Workflow
Logging enables you to record critical information during code execution. Loggers create an audit trail and capture information about your Workflow's operation. An appropriate logging level depends on your specific needs. During development or troubleshooting, you might use debug or even trace. In production, you might use info or warn to avoid excessive log volume.
The logger supports the following logging levels:
Level | Use |
---|---|
TRACE | The most detailed level of logging, used for very fine-grained information. |
DEBUG | Detailed information, typically useful for debugging purposes. |
INFO | General information about the application's operation. |
WARN | Indicates potentially harmful situations or minor issues that don't prevent the application from working. |
ERROR | Indicates error conditions that might still allow the application to continue running. |
The Temporal SDK core normally uses WARN
as its default logging level.
Logging from Activities
Activities run in the standard Node.js environment and may therefore use any Node.js logger directly.
The Temporal SDK however provides a convenient Activity Context logger, which funnels log messages to the Runtime's logger. Attributes from the current Activity context are automatically included as metadata on every log entries emitted using the Activity context logger, and some key events of the Activity's lifecycle are automatically logged (at DEBUG level for most messages; WARN for failures).
Using the Activity Context logger
import { log } from '@temporalio/activity';
export async function greet(name: string): Promise<string> {
log.info('Log from activity', { name });
return `Hello, ${name}!`;
}
Logging from Workflows
Workflows may not use regular Node.js loggers because:
- Workflows run in a sandboxed environment and cannot do any I/O.
- Workflow code might get replayed at any time, which would result in duplicated log messages.
The Temporal SDK however provides a Workflow Context logger, which funnels log messages to the Runtime's logger. Attributes from the current Workflow context are automatically included as metadata on every log entries emitted using the Workflow context logger, and some key events of the Workflow's lifecycle are automatically logged (at DEBUG level for most messages; WARN for failures).
Using the Workflow Context logger
import { log } from '@temporalio/workflow';
export async function myWorkflow(name: string): Promise<string> {
log.info('Log from workflow', { name });
return `Hello, ${name}!`;
}
The Workflow Context Logger tries to avoid reemitting log messages on Workflow Replays.