Skip to content

Commit fd4a7cb

Browse files
authored
feat: Add OTel correlation metadata on emitted logs from Workflow and Activity context loggers (#1565)
1 parent 147ec50 commit fd4a7cb

File tree

5 files changed

+285
-199
lines changed

5 files changed

+285
-199
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
container: quay.io/pypa/manylinux_2_24_aarch64
3939
out-file: libtemporal_sdk_typescript_bridge.so
4040
- platform: macos-x64
41-
runner: macos-12
41+
runner: macos-13
4242
target: x86_64-apple-darwin
4343
out-file: libtemporal_sdk_typescript_bridge.dylib
4444
- platform: macos-arm
@@ -221,7 +221,7 @@ jobs:
221221
- platform: linux-arm
222222
runner: buildjet-4vcpu-ubuntu-2204-arm
223223
- platform: macos-x64
224-
runner: macos-12
224+
runner: macos-13
225225
- platform: macos-arm
226226
runner: macos-14
227227
- platform: windows-x64
@@ -336,7 +336,7 @@ jobs:
336336
- platform: linux-arm
337337
runner: buildjet-4vcpu-ubuntu-2204-arm
338338
- platform: macos-x64
339-
runner: macos-12
339+
runner: macos-13
340340
- platform: macos-arm
341341
runner: macos-14
342342
- platform: windows-x64

packages/core-bridge/ts/index.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export interface ClientOptions {
107107
* @experimental
108108
*/
109109
export interface ConsoleLogger {
110-
console: {}; // eslint-disable-line @typescript-eslint/ban-types
110+
console: {}; // eslint-disable-line @typescript-eslint/no-empty-object-type
111111
}
112112

113113
/**
@@ -143,7 +143,13 @@ export interface OtelCollectorExporter {
143143
/**
144144
* URL of a gRPC OpenTelemetry collector.
145145
*
146-
* @format Starts with "grpc://" or "http://" for an unsecured connection (typical), or "grpcs://" or "https://" for a TLS connection.
146+
* Syntax should generally look like `http://server:4317` (the `grpc://` is also fine). Core's OTLP
147+
* metric exporter does not support the 'OTLP/HTTP' protocol (e.g. `http://server:4318/v1/metrics`).
148+
* For greater flexibility, you may setup an OTel collector running as a sidecar (e.g. to proxy
149+
* OTLP/gRPC requests to a remote OTLP/HTTP endpoint).
150+
*
151+
* @format Starts with "grpc://" or "http://" for an unsecured connection (typical),
152+
* or "grpcs://" or "https://" for a TLS connection.
147153
* @note The `OTEL_EXPORTER_OTLP_ENDPOINT` environment variable, if set, will override this property.
148154
*/
149155
url: string;
@@ -278,8 +284,8 @@ export type CompiledTelemetryOptions = {
278284
logging: {
279285
filter: string;
280286
} & (
281-
| { console: {} /* eslint-disable-line @typescript-eslint/ban-types */ }
282-
| { forward: {} /* eslint-disable-line @typescript-eslint/ban-types */ }
287+
| { console: {} /* eslint-disable-line @typescript-eslint/no-empty-object-type */ }
288+
| { forward: {} /* eslint-disable-line @typescript-eslint/no-empty-object-type */ }
283289
);
284290
metrics?: {
285291
temporality?: 'cumulative' | 'delta';

packages/interceptors-opentelemetry/src/worker/index.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@ import * as otel from '@opentelemetry/api';
22
import { Resource } from '@opentelemetry/resources';
33
import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
44
import { Context as ActivityContext } from '@temporalio/activity';
5-
import { ActivityExecuteInput, ActivityInboundCallsInterceptor, InjectedSink, Next } from '@temporalio/worker';
5+
import {
6+
ActivityExecuteInput,
7+
ActivityInboundCallsInterceptor,
8+
ActivityOutboundCallsInterceptor,
9+
GetLogAttributesInput,
10+
InjectedSink,
11+
Next,
12+
} from '@temporalio/worker';
613
import { instrument, extractContextFromHeaders } from '../instrumentation';
714
import { OpenTelemetryWorkflowExporter, SerializableSpan, SpanName, SPAN_DELIMITER } from '../workflow';
815

@@ -33,6 +40,33 @@ export class OpenTelemetryActivityInboundInterceptor implements ActivityInboundC
3340
}
3441
}
3542

43+
/**
44+
* Intercepts calls to emit logs from an Activity.
45+
*
46+
* Attach OpenTelemetry context tracing attributes to emitted log messages, if appropriate.
47+
*/
48+
export class OpenTelemetryActivityOutboundInterceptor implements ActivityOutboundCallsInterceptor {
49+
constructor(protected readonly ctx: ActivityContext) {}
50+
51+
public getLogAttributes(
52+
input: GetLogAttributesInput,
53+
next: Next<ActivityOutboundCallsInterceptor, 'getLogAttributes'>
54+
): Record<string, unknown> {
55+
const span = otel.trace.getSpan(otel.context.active());
56+
const spanContext = span?.spanContext();
57+
if (spanContext && otel.isSpanContextValid(spanContext)) {
58+
return next({
59+
trace_id: spanContext.traceId,
60+
span_id: spanContext.spanId,
61+
trace_flags: `0${spanContext.traceFlags.toString(16)}`,
62+
...input,
63+
});
64+
} else {
65+
return next(input);
66+
}
67+
}
68+
}
69+
3670
/**
3771
* Takes an opentelemetry SpanExporter and turns it into an injected Workflow span exporter sink
3872
*/

packages/interceptors-opentelemetry/src/workflow/index.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
ContinueAsNew,
99
ContinueAsNewInput,
1010
DisposeInput,
11+
GetLogAttributesInput,
1112
Next,
1213
SignalInput,
1314
SignalWorkflowInput,
@@ -154,6 +155,24 @@ export class OpenTelemetryOutboundInterceptor implements WorkflowOutboundCallsIn
154155
},
155156
});
156157
}
158+
159+
public getLogAttributes(
160+
input: GetLogAttributesInput,
161+
next: Next<WorkflowOutboundCallsInterceptor, 'getLogAttributes'>
162+
): Record<string, unknown> {
163+
const span = otel.trace.getSpan(otel.context.active());
164+
const spanContext = span?.spanContext();
165+
if (spanContext && otel.isSpanContextValid(spanContext)) {
166+
return next({
167+
trace_id: spanContext.traceId,
168+
span_id: spanContext.spanId,
169+
trace_flags: `0${spanContext.traceFlags.toString(16)}`,
170+
...input,
171+
});
172+
} else {
173+
return next(input);
174+
}
175+
}
157176
}
158177

159178
export class OpenTelemetryInternalsInterceptor implements WorkflowInternalsInterceptor {

0 commit comments

Comments
 (0)