@aztec/telemetry-client 0.0.0-test.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/attributes.d.ts +99 -0
- package/dest/attributes.d.ts.map +1 -0
- package/dest/attributes.js +67 -0
- package/dest/bench.d.ts +29 -0
- package/dest/bench.d.ts.map +1 -0
- package/dest/bench.js +98 -0
- package/dest/config.d.ts +12 -0
- package/dest/config.d.ts.map +1 -0
- package/dest/config.js +39 -0
- package/dest/event_loop_monitor.d.ts +18 -0
- package/dest/event_loop_monitor.d.ts.map +1 -0
- package/dest/event_loop_monitor.js +93 -0
- package/dest/index.d.ts +10 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +9 -0
- package/dest/lmdb_metrics.d.ts +16 -0
- package/dest/lmdb_metrics.d.ts.map +1 -0
- package/dest/lmdb_metrics.js +42 -0
- package/dest/metrics.d.ts +129 -0
- package/dest/metrics.d.ts.map +1 -0
- package/dest/metrics.js +126 -0
- package/dest/noop.d.ts +14 -0
- package/dest/noop.d.ts.map +1 -0
- package/dest/noop.js +71 -0
- package/dest/otel.d.ts +32 -0
- package/dest/otel.d.ts.map +1 -0
- package/dest/otel.js +319 -0
- package/dest/otel_filter_metric_exporter.d.ts +12 -0
- package/dest/otel_filter_metric_exporter.d.ts.map +1 -0
- package/dest/otel_filter_metric_exporter.js +33 -0
- package/dest/otel_logger_provider.d.ts +4 -0
- package/dest/otel_logger_provider.d.ts.map +1 -0
- package/dest/otel_logger_provider.js +25 -0
- package/dest/otel_propagation.d.ts +3 -0
- package/dest/otel_propagation.d.ts.map +1 -0
- package/dest/otel_propagation.js +44 -0
- package/dest/otel_resource.d.ts +3 -0
- package/dest/otel_resource.d.ts.map +1 -0
- package/dest/otel_resource.js +12 -0
- package/dest/prom_otel_adapter.d.ts +127 -0
- package/dest/prom_otel_adapter.d.ts.map +1 -0
- package/dest/prom_otel_adapter.js +183 -0
- package/dest/start.d.ts +6 -0
- package/dest/start.d.ts.map +1 -0
- package/dest/start.js +24 -0
- package/dest/telemetry.d.ts +118 -0
- package/dest/telemetry.d.ts.map +1 -0
- package/dest/telemetry.js +116 -0
- package/dest/vendor/attributes.d.ts +5 -0
- package/dest/vendor/attributes.d.ts.map +1 -0
- package/dest/vendor/attributes.js +5 -0
- package/dest/vendor/otel-pino-stream.d.ts +41 -0
- package/dest/vendor/otel-pino-stream.d.ts.map +1 -0
- package/dest/vendor/otel-pino-stream.js +229 -0
- package/dest/with_tracer.d.ts +33 -0
- package/dest/with_tracer.d.ts.map +1 -0
- package/dest/with_tracer.js +32 -0
- package/dest/wrappers/fetch.d.ts +16 -0
- package/dest/wrappers/fetch.d.ts.map +1 -0
- package/dest/wrappers/fetch.js +39 -0
- package/dest/wrappers/index.d.ts +4 -0
- package/dest/wrappers/index.d.ts.map +1 -0
- package/dest/wrappers/index.js +3 -0
- package/dest/wrappers/json_rpc_server.d.ts +4 -0
- package/dest/wrappers/json_rpc_server.d.ts.map +1 -0
- package/dest/wrappers/json_rpc_server.js +11 -0
- package/dest/wrappers/l2_block_stream.d.ts +15 -0
- package/dest/wrappers/l2_block_stream.d.ts.map +1 -0
- package/dest/wrappers/l2_block_stream.js +26 -0
- package/package.json +89 -0
- package/src/attributes.ts +115 -0
- package/src/bench.ts +147 -0
- package/src/config.ts +56 -0
- package/src/event_loop_monitor.ts +119 -0
- package/src/index.ts +9 -0
- package/src/lmdb_metrics.ts +45 -0
- package/src/metrics.ts +153 -0
- package/src/noop.ts +91 -0
- package/src/otel.ts +286 -0
- package/src/otel_filter_metric_exporter.ts +38 -0
- package/src/otel_logger_provider.ts +31 -0
- package/src/otel_propagation.ts +50 -0
- package/src/otel_resource.ts +16 -0
- package/src/prom_otel_adapter.ts +326 -0
- package/src/start.ts +33 -0
- package/src/telemetry.ts +267 -0
- package/src/vendor/attributes.ts +5 -0
- package/src/vendor/otel-pino-stream.ts +282 -0
- package/src/with_tracer.ts +35 -0
- package/src/wrappers/fetch.ts +52 -0
- package/src/wrappers/index.ts +3 -0
- package/src/wrappers/json_rpc_server.ts +15 -0
- package/src/wrappers/l2_block_stream.ts +37 -0
package/src/otel.ts
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import { type LogData, type Logger, addLogDataHandler } from '@aztec/foundation/log';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
DiagConsoleLogger,
|
|
5
|
+
DiagLogLevel,
|
|
6
|
+
type Meter,
|
|
7
|
+
type Tracer,
|
|
8
|
+
type TracerProvider,
|
|
9
|
+
context,
|
|
10
|
+
diag,
|
|
11
|
+
isSpanContextValid,
|
|
12
|
+
trace,
|
|
13
|
+
} from '@opentelemetry/api';
|
|
14
|
+
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
|
|
15
|
+
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
16
|
+
import { HostMetrics } from '@opentelemetry/host-metrics';
|
|
17
|
+
import type { IResource } from '@opentelemetry/resources';
|
|
18
|
+
import type { LoggerProvider } from '@opentelemetry/sdk-logs';
|
|
19
|
+
import {
|
|
20
|
+
ExplicitBucketHistogramAggregation,
|
|
21
|
+
InstrumentType,
|
|
22
|
+
MeterProvider,
|
|
23
|
+
PeriodicExportingMetricReader,
|
|
24
|
+
type PeriodicExportingMetricReaderOptions,
|
|
25
|
+
View,
|
|
26
|
+
} from '@opentelemetry/sdk-metrics';
|
|
27
|
+
import { BatchSpanProcessor, NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
28
|
+
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
|
|
29
|
+
|
|
30
|
+
import type { TelemetryClientConfig } from './config.js';
|
|
31
|
+
import { EventLoopMonitor } from './event_loop_monitor.js';
|
|
32
|
+
import { OtelFilterMetricExporter } from './otel_filter_metric_exporter.js';
|
|
33
|
+
import { registerOtelLoggerProvider } from './otel_logger_provider.js';
|
|
34
|
+
import { getOtelResource } from './otel_resource.js';
|
|
35
|
+
import type { TelemetryClient } from './telemetry.js';
|
|
36
|
+
|
|
37
|
+
export type OpenTelemetryClientFactory = (resource: IResource, log: Logger) => OpenTelemetryClient;
|
|
38
|
+
|
|
39
|
+
export class OpenTelemetryClient implements TelemetryClient {
|
|
40
|
+
hostMetrics: HostMetrics | undefined;
|
|
41
|
+
eventLoopMonitor: EventLoopMonitor | undefined;
|
|
42
|
+
private meters: Map<string, Meter> = new Map<string, Meter>();
|
|
43
|
+
private tracers: Map<string, Tracer> = new Map<string, Tracer>();
|
|
44
|
+
|
|
45
|
+
protected constructor(
|
|
46
|
+
private resource: IResource,
|
|
47
|
+
private meterProvider: MeterProvider,
|
|
48
|
+
private traceProvider: TracerProvider,
|
|
49
|
+
private loggerProvider: LoggerProvider | undefined,
|
|
50
|
+
private log: Logger,
|
|
51
|
+
) {}
|
|
52
|
+
|
|
53
|
+
getMeter(name: string): Meter {
|
|
54
|
+
let meter = this.meters.get(name);
|
|
55
|
+
if (!meter) {
|
|
56
|
+
meter = this.meterProvider.getMeter(name, this.resource.attributes[ATTR_SERVICE_VERSION] as string);
|
|
57
|
+
this.meters.set(name, meter);
|
|
58
|
+
}
|
|
59
|
+
return meter;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
getTracer(name: string): Tracer {
|
|
63
|
+
let tracer = this.tracers.get(name);
|
|
64
|
+
if (!tracer) {
|
|
65
|
+
tracer = this.traceProvider.getTracer(name, this.resource.attributes[ATTR_SERVICE_VERSION] as string);
|
|
66
|
+
this.tracers.set(name, tracer);
|
|
67
|
+
}
|
|
68
|
+
return tracer;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
public start() {
|
|
72
|
+
this.log.info('Starting OpenTelemetry client');
|
|
73
|
+
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.INFO);
|
|
74
|
+
|
|
75
|
+
// Add a callback to the logger to set context data from current trace
|
|
76
|
+
// Adapted from open-telemetry/opentelemetry-js-contrib PinoInstrumentation._getMixinFunction
|
|
77
|
+
addLogDataHandler((data: LogData) => {
|
|
78
|
+
const spanContext = trace.getSpan(context.active())?.spanContext();
|
|
79
|
+
return spanContext && isSpanContextValid(spanContext)
|
|
80
|
+
? {
|
|
81
|
+
...data,
|
|
82
|
+
['trace_id']: spanContext.traceId,
|
|
83
|
+
['span_id']: spanContext.spanId,
|
|
84
|
+
['trace_flags']: `0${spanContext.traceFlags.toString(16)}`,
|
|
85
|
+
}
|
|
86
|
+
: data;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
this.hostMetrics = new HostMetrics({
|
|
90
|
+
name: this.resource.attributes[ATTR_SERVICE_NAME] as string,
|
|
91
|
+
meterProvider: this.meterProvider,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
this.eventLoopMonitor = new EventLoopMonitor(
|
|
95
|
+
this.meterProvider.getMeter(this.resource.attributes[ATTR_SERVICE_NAME] as string),
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
this.hostMetrics.start();
|
|
99
|
+
this.eventLoopMonitor.start();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
public isEnabled() {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public async flush() {
|
|
107
|
+
await Promise.all([
|
|
108
|
+
this.meterProvider.forceFlush(),
|
|
109
|
+
this.loggerProvider?.forceFlush(),
|
|
110
|
+
this.traceProvider instanceof NodeTracerProvider ? this.traceProvider.forceFlush() : Promise.resolve(),
|
|
111
|
+
]);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public async stop() {
|
|
115
|
+
this.eventLoopMonitor?.stop();
|
|
116
|
+
|
|
117
|
+
const flushAndShutdown = async (provider?: { forceFlush: () => Promise<void>; shutdown: () => Promise<void> }) => {
|
|
118
|
+
if (!provider) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
await provider.forceFlush();
|
|
122
|
+
await provider.shutdown();
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
await Promise.all([
|
|
126
|
+
flushAndShutdown(this.meterProvider),
|
|
127
|
+
flushAndShutdown(this.loggerProvider),
|
|
128
|
+
this.traceProvider instanceof NodeTracerProvider ? flushAndShutdown(this.traceProvider) : Promise.resolve(),
|
|
129
|
+
]);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public static createMeterProvider(
|
|
133
|
+
resource: IResource,
|
|
134
|
+
options: Partial<PeriodicExportingMetricReaderOptions>,
|
|
135
|
+
): MeterProvider {
|
|
136
|
+
return new MeterProvider({
|
|
137
|
+
resource,
|
|
138
|
+
readers: options.exporter
|
|
139
|
+
? [new PeriodicExportingMetricReader(options as PeriodicExportingMetricReaderOptions)]
|
|
140
|
+
: [],
|
|
141
|
+
|
|
142
|
+
views: [
|
|
143
|
+
// Every histogram matching the selector (type + unit) gets these custom buckets assigned
|
|
144
|
+
new View({
|
|
145
|
+
instrumentType: InstrumentType.HISTOGRAM,
|
|
146
|
+
instrumentUnit: 's',
|
|
147
|
+
aggregation: new ExplicitBucketHistogramAggregation(
|
|
148
|
+
[1, 2, 4, 6, 10, 15, 30, 60, 90, 120, 180, 240, 300, 480, 600, 900, 1200],
|
|
149
|
+
true,
|
|
150
|
+
),
|
|
151
|
+
}),
|
|
152
|
+
new View({
|
|
153
|
+
instrumentType: InstrumentType.HISTOGRAM,
|
|
154
|
+
instrumentUnit: 'ms',
|
|
155
|
+
aggregation: new ExplicitBucketHistogramAggregation(
|
|
156
|
+
// 10ms to 1 minute
|
|
157
|
+
[10, 20, 35, 50, 75, 100, 250, 500, 750, 1_000, 2_500, 5_000, 7_500, 10_000, 15_000, 30_000, 60_000],
|
|
158
|
+
true,
|
|
159
|
+
),
|
|
160
|
+
}),
|
|
161
|
+
new View({
|
|
162
|
+
instrumentType: InstrumentType.HISTOGRAM,
|
|
163
|
+
instrumentUnit: 'us',
|
|
164
|
+
aggregation: new ExplicitBucketHistogramAggregation(
|
|
165
|
+
// 1us to 1s
|
|
166
|
+
[
|
|
167
|
+
5, 10, 25, 50, 75, 100, 250, 500, 750, 1_000, 2_500, 5_000, 7_500, 10_000, 25_000, 50_000, 100_000,
|
|
168
|
+
250_000, 500_000, 1_000_000,
|
|
169
|
+
],
|
|
170
|
+
true,
|
|
171
|
+
),
|
|
172
|
+
}),
|
|
173
|
+
new View({
|
|
174
|
+
instrumentType: InstrumentType.HISTOGRAM,
|
|
175
|
+
instrumentUnit: 'By',
|
|
176
|
+
aggregation: new ExplicitBucketHistogramAggregation(
|
|
177
|
+
// from 32 bytes to 2MB
|
|
178
|
+
[
|
|
179
|
+
32,
|
|
180
|
+
64,
|
|
181
|
+
128,
|
|
182
|
+
256,
|
|
183
|
+
512,
|
|
184
|
+
1024, // 1kb
|
|
185
|
+
2048,
|
|
186
|
+
4096,
|
|
187
|
+
8192,
|
|
188
|
+
16384,
|
|
189
|
+
32768,
|
|
190
|
+
65536,
|
|
191
|
+
131072,
|
|
192
|
+
262144,
|
|
193
|
+
524288,
|
|
194
|
+
1048576, // 1mb
|
|
195
|
+
1572864,
|
|
196
|
+
2097152, // 2mb
|
|
197
|
+
],
|
|
198
|
+
true,
|
|
199
|
+
),
|
|
200
|
+
}),
|
|
201
|
+
new View({
|
|
202
|
+
instrumentType: InstrumentType.HISTOGRAM,
|
|
203
|
+
instrumentUnit: 'gas/s',
|
|
204
|
+
aggregation: new ExplicitBucketHistogramAggregation(
|
|
205
|
+
[
|
|
206
|
+
1_000, 5_000, 10_000, 25_000, 50_000, 100_000, 250_000, 500_000, 750_000, 1_000_000, 2_000_000, 4_000_000,
|
|
207
|
+
8_000_000, 10_000_000, 15_000_000, 30_000_000,
|
|
208
|
+
],
|
|
209
|
+
true,
|
|
210
|
+
),
|
|
211
|
+
}),
|
|
212
|
+
new View({
|
|
213
|
+
instrumentType: InstrumentType.HISTOGRAM,
|
|
214
|
+
instrumentUnit: 'mana/s',
|
|
215
|
+
aggregation: new ExplicitBucketHistogramAggregation(
|
|
216
|
+
[
|
|
217
|
+
1_000, 5_000, 10_000, 25_000, 50_000, 100_000, 250_000, 500_000, 750_000, 1_000_000, 2_000_000, 4_000_000,
|
|
218
|
+
8_000_000, 10_000_000, 15_000_000, 30_000_000,
|
|
219
|
+
],
|
|
220
|
+
true,
|
|
221
|
+
),
|
|
222
|
+
}),
|
|
223
|
+
new View({
|
|
224
|
+
instrumentType: InstrumentType.HISTOGRAM,
|
|
225
|
+
instrumentUnit: 'gas/block',
|
|
226
|
+
aggregation: new ExplicitBucketHistogramAggregation(
|
|
227
|
+
[
|
|
228
|
+
1_000, 5_000, 10_000, 25_000, 50_000, 100_000, 250_000, 500_000, 750_000, 1_000_000, 2_000_000, 4_000_000,
|
|
229
|
+
8_000_000, 10_000_000, 15_000_000, 30_000_000,
|
|
230
|
+
],
|
|
231
|
+
true,
|
|
232
|
+
),
|
|
233
|
+
}),
|
|
234
|
+
new View({
|
|
235
|
+
instrumentType: InstrumentType.HISTOGRAM,
|
|
236
|
+
instrumentUnit: 'gas/tx',
|
|
237
|
+
aggregation: new ExplicitBucketHistogramAggregation(
|
|
238
|
+
[
|
|
239
|
+
25_000, 50_000, 100_000, 250_000, 500_000, 750_000, 1_000_000, 2_000_000, 4_000_000, 8_000_000,
|
|
240
|
+
10_000_000, 15_000_000, 30_000_000,
|
|
241
|
+
],
|
|
242
|
+
true,
|
|
243
|
+
),
|
|
244
|
+
}),
|
|
245
|
+
],
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private static getCustomClientFactory(config: TelemetryClientConfig): OpenTelemetryClientFactory {
|
|
250
|
+
return (resource: IResource, log: Logger) => {
|
|
251
|
+
const tracerProvider = new NodeTracerProvider({
|
|
252
|
+
resource,
|
|
253
|
+
spanProcessors: config.tracesCollectorUrl
|
|
254
|
+
? [new BatchSpanProcessor(new OTLPTraceExporter({ url: config.tracesCollectorUrl.href }))]
|
|
255
|
+
: [],
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
tracerProvider.register();
|
|
259
|
+
|
|
260
|
+
const meterProvider = OpenTelemetryClient.createMeterProvider(resource, {
|
|
261
|
+
exporter: config.metricsCollectorUrl
|
|
262
|
+
? new OtelFilterMetricExporter(
|
|
263
|
+
new OTLPMetricExporter({ url: config.metricsCollectorUrl.href }),
|
|
264
|
+
config.otelExcludeMetrics ?? [],
|
|
265
|
+
)
|
|
266
|
+
: undefined,
|
|
267
|
+
exportTimeoutMillis: config.otelExportTimeoutMs,
|
|
268
|
+
exportIntervalMillis: config.otelCollectIntervalMs,
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
const loggerProvider = registerOtelLoggerProvider(resource, config.logsCollectorUrl);
|
|
272
|
+
|
|
273
|
+
return new OpenTelemetryClient(resource, meterProvider, tracerProvider, loggerProvider, log);
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
public static createAndStart(config: TelemetryClientConfig, log: Logger): OpenTelemetryClient {
|
|
278
|
+
const resource = getOtelResource();
|
|
279
|
+
const factory = OpenTelemetryClient.getCustomClientFactory(config);
|
|
280
|
+
|
|
281
|
+
const service = factory(resource, log);
|
|
282
|
+
service.start();
|
|
283
|
+
|
|
284
|
+
return service;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ExportResult } from '@opentelemetry/core';
|
|
2
|
+
import type { MetricData, PushMetricExporter, ResourceMetrics } from '@opentelemetry/sdk-metrics';
|
|
3
|
+
|
|
4
|
+
export class OtelFilterMetricExporter implements PushMetricExporter {
|
|
5
|
+
constructor(private readonly exporter: PushMetricExporter, private readonly excludeMetricPrefixes: string[]) {
|
|
6
|
+
if (exporter.selectAggregation) {
|
|
7
|
+
(this as PushMetricExporter).selectAggregation = exporter.selectAggregation.bind(exporter);
|
|
8
|
+
}
|
|
9
|
+
if (exporter.selectAggregationTemporality) {
|
|
10
|
+
(this as PushMetricExporter).selectAggregationTemporality = exporter.selectAggregationTemporality.bind(exporter);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
public export(metrics: ResourceMetrics, resultCallback: (result: ExportResult) => void): void {
|
|
15
|
+
const filteredMetrics: ResourceMetrics = {
|
|
16
|
+
resource: metrics.resource,
|
|
17
|
+
scopeMetrics: metrics.scopeMetrics
|
|
18
|
+
.map(({ scope, metrics }) => ({ scope, metrics: this.filterMetrics(metrics) }))
|
|
19
|
+
.filter(({ metrics }) => metrics.length > 0),
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
this.exporter.export(filteredMetrics, resultCallback);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private filterMetrics(metrics: MetricData[]): MetricData[] {
|
|
26
|
+
return metrics.filter(
|
|
27
|
+
metric => !this.excludeMetricPrefixes.some(prefix => metric.descriptor.name.startsWith(prefix)),
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public forceFlush(): Promise<void> {
|
|
32
|
+
return this.exporter.forceFlush();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public shutdown(): Promise<void> {
|
|
36
|
+
return this.exporter.shutdown();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { logs as otelLogs } from '@opentelemetry/api-logs';
|
|
2
|
+
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http';
|
|
3
|
+
import { CompressionAlgorithm } from '@opentelemetry/otlp-exporter-base';
|
|
4
|
+
import type { IResource } from '@opentelemetry/resources';
|
|
5
|
+
import { BatchLogRecordProcessor, LoggerProvider } from '@opentelemetry/sdk-logs';
|
|
6
|
+
|
|
7
|
+
export function registerOtelLoggerProvider(resource: IResource, otelLogsUrl?: URL) {
|
|
8
|
+
const loggerProvider = new LoggerProvider({ resource });
|
|
9
|
+
if (!otelLogsUrl) {
|
|
10
|
+
// If no URL provided, return it disconnected.
|
|
11
|
+
return loggerProvider;
|
|
12
|
+
}
|
|
13
|
+
const logExporter = new OTLPLogExporter({
|
|
14
|
+
compression: CompressionAlgorithm.GZIP,
|
|
15
|
+
url: otelLogsUrl.href,
|
|
16
|
+
});
|
|
17
|
+
// Add a processor to the logger provider
|
|
18
|
+
loggerProvider.addLogRecordProcessor(
|
|
19
|
+
new BatchLogRecordProcessor(logExporter, {
|
|
20
|
+
/** The maximum batch size of every export. It must be smaller or equal to
|
|
21
|
+
* maxQueueSize. */
|
|
22
|
+
maxExportBatchSize: 1024,
|
|
23
|
+
/** The maximum queue size. After the size is reached log records are dropped. */
|
|
24
|
+
maxQueueSize: 4096,
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
otelLogs.setGlobalLoggerProvider(loggerProvider);
|
|
29
|
+
|
|
30
|
+
return loggerProvider;
|
|
31
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ROOT_CONTEXT, type Span, SpanKind, SpanStatusCode, propagation } from '@opentelemetry/api';
|
|
2
|
+
import type Koa from 'koa';
|
|
3
|
+
|
|
4
|
+
import { getTelemetryClient } from './start.js';
|
|
5
|
+
import {
|
|
6
|
+
ATTR_JSONRPC_ERROR_CODE,
|
|
7
|
+
ATTR_JSONRPC_ERROR_MSG,
|
|
8
|
+
ATTR_JSONRPC_METHOD,
|
|
9
|
+
ATTR_JSONRPC_REQUEST_ID,
|
|
10
|
+
} from './vendor/attributes.js';
|
|
11
|
+
|
|
12
|
+
export function getOtelJsonRpcPropagationMiddleware(
|
|
13
|
+
scope = 'JsonRpcServer',
|
|
14
|
+
): (ctx: Koa.Context, next: () => Promise<void>) => Promise<void> {
|
|
15
|
+
return function otelJsonRpcPropagation(ctx: Koa.Context, next: () => Promise<void>) {
|
|
16
|
+
const tracer = getTelemetryClient().getTracer(scope);
|
|
17
|
+
const context = propagation.extract(ROOT_CONTEXT, ctx.request.headers);
|
|
18
|
+
const method = (ctx.request.body as any)?.method;
|
|
19
|
+
return tracer.startActiveSpan(
|
|
20
|
+
`JsonRpcServer.${method ?? 'unknown'}`,
|
|
21
|
+
{ kind: SpanKind.SERVER },
|
|
22
|
+
context,
|
|
23
|
+
async (span: Span): Promise<void> => {
|
|
24
|
+
if (ctx.id) {
|
|
25
|
+
span.setAttribute(ATTR_JSONRPC_REQUEST_ID, ctx.id);
|
|
26
|
+
}
|
|
27
|
+
if (method) {
|
|
28
|
+
span.setAttribute(ATTR_JSONRPC_METHOD, method);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
await next();
|
|
33
|
+
const err = (ctx.body as any).error?.message;
|
|
34
|
+
const code = (ctx.body as any).error?.code;
|
|
35
|
+
if (err) {
|
|
36
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: err });
|
|
37
|
+
span.setAttribute(ATTR_JSONRPC_ERROR_CODE, code);
|
|
38
|
+
span.setAttribute(ATTR_JSONRPC_ERROR_MSG, err);
|
|
39
|
+
} else {
|
|
40
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
41
|
+
}
|
|
42
|
+
} catch (err) {
|
|
43
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
|
|
44
|
+
} finally {
|
|
45
|
+
span.end();
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type IResource,
|
|
3
|
+
detectResourcesSync,
|
|
4
|
+
envDetectorSync,
|
|
5
|
+
osDetectorSync,
|
|
6
|
+
processDetectorSync,
|
|
7
|
+
serviceInstanceIdDetectorSync,
|
|
8
|
+
} from '@opentelemetry/resources';
|
|
9
|
+
|
|
10
|
+
export function getOtelResource(): IResource {
|
|
11
|
+
const resource = detectResourcesSync({
|
|
12
|
+
detectors: [osDetectorSync, envDetectorSync, processDetectorSync, serviceInstanceIdDetectorSync],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return resource;
|
|
16
|
+
}
|