@ogcio/o11y-sdk-node 0.1.0-beta.7 → 0.1.0-beta.9
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/CHANGELOG.md +20 -0
- package/dist/lib/exporter/console.d.ts +1 -1
- package/dist/lib/exporter/console.js +5 -1
- package/dist/lib/exporter/grpc.d.ts +1 -1
- package/dist/lib/exporter/grpc.js +2 -0
- package/dist/lib/exporter/http.d.ts +1 -1
- package/dist/lib/exporter/http.js +2 -0
- package/dist/lib/instrumentation.node.js +7 -19
- package/dist/lib/metrics.d.ts +12 -12
- package/dist/lib/metrics.js +6 -10
- package/dist/lib/processor/enrich-logger-processor.d.ts +10 -0
- package/dist/lib/processor/enrich-logger-processor.js +19 -0
- package/dist/lib/resource.d.ts +7 -0
- package/dist/lib/resource.js +18 -0
- package/dist/package.json +24 -20
- package/dist/vitest.config.js +1 -1
- package/lib/exporter/console.ts +6 -2
- package/lib/exporter/grpc.ts +3 -1
- package/lib/exporter/http.ts +3 -1
- package/lib/instrumentation.node.ts +8 -31
- package/lib/metrics.ts +34 -29
- package/lib/processor/enrich-logger-processor.ts +34 -0
- package/lib/resource.ts +29 -0
- package/package.json +24 -20
- package/test/integration/run.sh +3 -0
- package/test/metrics.test.ts +9 -9
- package/test/node-config.test.ts +8 -8
- package/test/processor/enrich-logger-processor.test.ts +58 -0
- package/test/{enrich-span-processor.test.ts → processor/enrich-span-processor.test.ts} +1 -2
- package/test/resource.test.ts +22 -0
- package/vitest.config.ts +1 -1
- /package/dist/lib/{options.d.ts → exporter/index.d.ts} +0 -0
- /package/dist/lib/{options.js → exporter/index.js} +0 -0
- /package/lib/{options.ts → exporter/index.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.0-beta.9](https://github.com/ogcio/o11y/compare/@ogcio/o11y-sdk-node@v0.1.0-beta.8...@ogcio/o11y-sdk-node@v0.1.0-beta.9) (2025-03-24)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add custom log processor for span enrich ([#102](https://github.com/ogcio/o11y/issues/102)) ([bbf8334](https://github.com/ogcio/o11y/commit/bbf83340940ed651dff63bbe7aaa52881d1e8c8c))
|
|
9
|
+
* upgrade to opentelemetry 2 AB[#25863](https://github.com/ogcio/o11y/issues/25863) ([#106](https://github.com/ogcio/o11y/issues/106)) ([3ff0314](https://github.com/ogcio/o11y/commit/3ff0314fef9f4d7b5db76da3b94e9035801384c7))
|
|
10
|
+
|
|
11
|
+
## [0.1.0-beta.8](https://github.com/ogcio/o11y/compare/@ogcio/o11y-sdk-node@v0.1.0-beta.7...@ogcio/o11y-sdk-node@v0.1.0-beta.8) (2025-03-07)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* o11y showcase AB[#25895](https://github.com/ogcio/o11y/issues/25895) ([#84](https://github.com/ogcio/o11y/issues/84)) ([f8f10af](https://github.com/ogcio/o11y/commit/f8f10af97d9f5c188e3e65f7d62d5c673edce25a))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* improve getMetric attributes types ([#76](https://github.com/ogcio/o11y/issues/76)) ([243649c](https://github.com/ogcio/o11y/commit/243649c4bfe750687a729fbd836772cce16e0cb1))
|
|
22
|
+
|
|
3
23
|
## [0.1.0-beta.7](https://github.com/ogcio/o11y/compare/@ogcio/o11y-sdk-node@v0.1.0-beta.6...@ogcio/o11y-sdk-node@v0.1.0-beta.7) (2025-02-18)
|
|
4
24
|
|
|
5
25
|
|
|
@@ -2,6 +2,7 @@ import { ConsoleLogRecordExporter, SimpleLogRecordProcessor, } from "@openteleme
|
|
|
2
2
|
import { metrics } from "@opentelemetry/sdk-node";
|
|
3
3
|
import { ConsoleSpanExporter, SimpleSpanProcessor, } from "@opentelemetry/sdk-trace-base";
|
|
4
4
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
5
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
5
6
|
export default function buildConsoleExporters(config) {
|
|
6
7
|
return {
|
|
7
8
|
spans: [
|
|
@@ -11,6 +12,9 @@ export default function buildConsoleExporters(config) {
|
|
|
11
12
|
metrics: new metrics.PeriodicExportingMetricReader({
|
|
12
13
|
exporter: new metrics.ConsoleMetricExporter(),
|
|
13
14
|
}),
|
|
14
|
-
logs: [
|
|
15
|
+
logs: [
|
|
16
|
+
new EnrichLogProcessor(config.spanAttributes),
|
|
17
|
+
new SimpleLogRecordProcessor(new ConsoleLogRecordExporter()),
|
|
18
|
+
],
|
|
15
19
|
};
|
|
16
20
|
}
|
|
@@ -5,6 +5,7 @@ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-grpc";
|
|
|
5
5
|
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
|
|
6
6
|
import { LogRecordProcessorMap, SpanProcessorMap } from "../utils.js";
|
|
7
7
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
8
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
8
9
|
export default function buildGrpcExporters(config) {
|
|
9
10
|
return {
|
|
10
11
|
spans: [
|
|
@@ -21,6 +22,7 @@ export default function buildGrpcExporters(config) {
|
|
|
21
22
|
}),
|
|
22
23
|
}),
|
|
23
24
|
logs: [
|
|
25
|
+
new EnrichLogProcessor(config.spanAttributes),
|
|
24
26
|
new LogRecordProcessorMap[config.collectorMode ?? "batch"](new OTLPLogExporter({
|
|
25
27
|
url: `${config.collectorUrl}`,
|
|
26
28
|
compression: CompressionAlgorithm.GZIP,
|
|
@@ -5,6 +5,7 @@ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
|
5
5
|
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
6
6
|
import { LogRecordProcessorMap, SpanProcessorMap } from "../utils.js";
|
|
7
7
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
8
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
8
9
|
export default function buildHttpExporters(config) {
|
|
9
10
|
if (config.collectorUrl.endsWith("/")) {
|
|
10
11
|
config.collectorUrl = config.collectorUrl.slice(0, -1);
|
|
@@ -24,6 +25,7 @@ export default function buildHttpExporters(config) {
|
|
|
24
25
|
}),
|
|
25
26
|
}),
|
|
26
27
|
logs: [
|
|
28
|
+
new EnrichLogProcessor(config.spanAttributes),
|
|
27
29
|
new LogRecordProcessorMap[config.collectorMode ?? "batch"](new OTLPLogExporter({
|
|
28
30
|
url: `${config.collectorUrl}/v1/logs`,
|
|
29
31
|
compression: CompressionAlgorithm.GZIP,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { diag, DiagConsoleLogger, DiagLogLevel
|
|
1
|
+
import { diag, DiagConsoleLogger, DiagLogLevel } from "@opentelemetry/api";
|
|
2
2
|
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
|
|
3
3
|
import { W3CTraceContextPropagator } from "@opentelemetry/core";
|
|
4
|
-
import { NodeSDK
|
|
4
|
+
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
5
5
|
import { AlwaysOffSampler, ParentBasedSampler, TraceIdRatioBasedSampler, } from "@opentelemetry/sdk-trace-base";
|
|
6
|
-
import packageJson from "../package.json" with { type: "json" };
|
|
7
6
|
import buildConsoleExporters from "./exporter/console.js";
|
|
8
7
|
import buildGrpcExporters from "./exporter/grpc.js";
|
|
9
8
|
import buildHttpExporters from "./exporter/http.js";
|
|
9
|
+
import { ObservabilityResourceDetector } from "./resource.js";
|
|
10
10
|
import { UrlSampler } from "./url-sampler.js";
|
|
11
11
|
export default function buildNodeInstrumentation(config) {
|
|
12
12
|
if (!config) {
|
|
@@ -44,11 +44,9 @@ export default function buildNodeInstrumentation(config) {
|
|
|
44
44
|
? DiagLogLevel[config.diagLogLevel]
|
|
45
45
|
: DiagLogLevel.INFO);
|
|
46
46
|
const sdk = new NodeSDK({
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
...config.resourceAttributes,
|
|
51
|
-
}),
|
|
47
|
+
resourceDetectors: [
|
|
48
|
+
new ObservabilityResourceDetector(config.resourceAttributes),
|
|
49
|
+
],
|
|
52
50
|
spanProcessors: exporter.spans,
|
|
53
51
|
serviceName: config.serviceName,
|
|
54
52
|
metricReader: exporter.metrics,
|
|
@@ -60,15 +58,6 @@ export default function buildNodeInstrumentation(config) {
|
|
|
60
58
|
"@opentelemetry/instrumentation-fs": {
|
|
61
59
|
enabled: config.enableFS ?? false,
|
|
62
60
|
},
|
|
63
|
-
"@opentelemetry/instrumentation-pino": {
|
|
64
|
-
logHook: (_span, record, _level) => {
|
|
65
|
-
if (config.spanAttributes != undefined) {
|
|
66
|
-
for (const [key, value] of Object.entries(config.spanAttributes)) {
|
|
67
|
-
record[key] = typeof value === "function" ? value() : value;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
61
|
}),
|
|
73
62
|
],
|
|
74
63
|
});
|
|
@@ -85,8 +74,7 @@ function isUrl(url) {
|
|
|
85
74
|
new URL(url);
|
|
86
75
|
return true;
|
|
87
76
|
}
|
|
88
|
-
catch (
|
|
89
|
-
console.error(err);
|
|
77
|
+
catch (_) {
|
|
90
78
|
return false;
|
|
91
79
|
}
|
|
92
80
|
}
|
package/dist/lib/metrics.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { Counter, Gauge, Histogram, MetricOptions, ObservableCounter, ObservableGauge, ObservableUpDownCounter, UpDownCounter } from "@opentelemetry/api";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
histogram: Histogram
|
|
5
|
-
|
|
6
|
-
updowncounter: UpDownCounter
|
|
7
|
-
"async-counter": ObservableCounter
|
|
8
|
-
"async-updowncounter": ObservableUpDownCounter
|
|
9
|
-
"async-gauge": ObservableGauge
|
|
1
|
+
import { Counter, Gauge, Histogram, MetricOptions, ObservableCounter, ObservableGauge, ObservableUpDownCounter, UpDownCounter, Attributes } from "@opentelemetry/api";
|
|
2
|
+
type MetricTypeMap<TAttributes extends Attributes> = {
|
|
3
|
+
counter: Counter<TAttributes>;
|
|
4
|
+
histogram: Histogram<TAttributes>;
|
|
5
|
+
gauge: Gauge<TAttributes>;
|
|
6
|
+
updowncounter: UpDownCounter<TAttributes>;
|
|
7
|
+
"async-counter": ObservableCounter<TAttributes>;
|
|
8
|
+
"async-updowncounter": ObservableUpDownCounter<TAttributes>;
|
|
9
|
+
"async-gauge": ObservableGauge<TAttributes>;
|
|
10
10
|
};
|
|
11
|
-
type MetricType = keyof
|
|
11
|
+
export type MetricType = keyof MetricTypeMap<Attributes>;
|
|
12
12
|
export interface MetricsParams {
|
|
13
|
+
meterName: string;
|
|
13
14
|
metricName: string;
|
|
14
|
-
attributeName: string;
|
|
15
15
|
options?: MetricOptions;
|
|
16
16
|
}
|
|
17
|
-
export declare function getMetric<T extends MetricType>(type: T, p: MetricsParams):
|
|
17
|
+
export declare function getMetric<T extends MetricType, TAttributes extends Attributes = Attributes>(type: T, p: MetricsParams): MetricTypeMap<TAttributes>[T];
|
|
18
18
|
export {};
|
package/dist/lib/metrics.js
CHANGED
|
@@ -8,21 +8,17 @@ const MetricsFactoryMap = {
|
|
|
8
8
|
"async-updowncounter": (meter) => meter.createObservableUpDownCounter,
|
|
9
9
|
"async-gauge": (meter) => meter.createObservableGauge,
|
|
10
10
|
};
|
|
11
|
-
function getMeter({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
meter = createNoopMeter();
|
|
11
|
+
function getMeter({ meterName }) {
|
|
12
|
+
if (!meterName) {
|
|
13
|
+
console.error("Invalid metric name!");
|
|
14
|
+
return createNoopMeter();
|
|
16
15
|
}
|
|
17
|
-
|
|
18
|
-
meter = metrics.getMeter(`custom_metric.${metricName}`);
|
|
19
|
-
}
|
|
20
|
-
return meter;
|
|
16
|
+
return metrics.getMeter(`custom_metric.${meterName}`);
|
|
21
17
|
}
|
|
22
18
|
export function getMetric(type, p) {
|
|
23
19
|
const meter = getMeter(p);
|
|
24
20
|
if (!MetricsFactoryMap[type]) {
|
|
25
21
|
throw new Error(`Unsupported metric type: ${type}`);
|
|
26
22
|
}
|
|
27
|
-
return MetricsFactoryMap[type](meter).bind(meter)(p.
|
|
23
|
+
return MetricsFactoryMap[type](meter).bind(meter)(p.metricName, p.options);
|
|
28
24
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { LogRecord, LogRecordProcessor } from "@opentelemetry/sdk-logs";
|
|
2
|
+
import { Context } from "@opentelemetry/api";
|
|
3
|
+
import { SignalAttributeValue } from "../index.js";
|
|
4
|
+
export declare class EnrichLogProcessor implements LogRecordProcessor {
|
|
5
|
+
private _spanAttributes?;
|
|
6
|
+
constructor(spanAttributes?: Record<string, SignalAttributeValue | (() => SignalAttributeValue)>);
|
|
7
|
+
forceFlush(): Promise<void>;
|
|
8
|
+
onEmit(logRecord: LogRecord, _context?: Context): void;
|
|
9
|
+
shutdown(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class EnrichLogProcessor {
|
|
2
|
+
_spanAttributes = undefined;
|
|
3
|
+
constructor(spanAttributes) {
|
|
4
|
+
this._spanAttributes = spanAttributes;
|
|
5
|
+
}
|
|
6
|
+
forceFlush() {
|
|
7
|
+
return Promise.resolve();
|
|
8
|
+
}
|
|
9
|
+
onEmit(logRecord, _context) {
|
|
10
|
+
if (this._spanAttributes) {
|
|
11
|
+
for (const [key, value] of Object.entries(this._spanAttributes)) {
|
|
12
|
+
logRecord.setAttribute(key, typeof value === "function" ? value() : value);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
shutdown() {
|
|
17
|
+
return Promise.resolve();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ResourceDetector, DetectedResource } from "@opentelemetry/resources";
|
|
2
|
+
import { SignalAttributeValue } from "./index.js";
|
|
3
|
+
export declare class ObservabilityResourceDetector implements ResourceDetector {
|
|
4
|
+
private _resourceAttributes;
|
|
5
|
+
constructor(resourceAttributes?: Record<string, SignalAttributeValue>);
|
|
6
|
+
detect(): DetectedResource;
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
2
|
+
export class ObservabilityResourceDetector {
|
|
3
|
+
_resourceAttributes;
|
|
4
|
+
constructor(resourceAttributes) {
|
|
5
|
+
this._resourceAttributes = resourceAttributes;
|
|
6
|
+
}
|
|
7
|
+
detect() {
|
|
8
|
+
let attributes = {};
|
|
9
|
+
if (this._resourceAttributes) {
|
|
10
|
+
attributes = {
|
|
11
|
+
...this._resourceAttributes,
|
|
12
|
+
"o11y.sdk.name": packageJson.name,
|
|
13
|
+
"o11y.sdk.version": packageJson.version,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return { attributes };
|
|
17
|
+
}
|
|
18
|
+
}
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ogcio/o11y-sdk-node",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.9",
|
|
4
4
|
"description": "Opentelemetry standard instrumentation SDK for NodeJS based project",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -28,26 +28,30 @@
|
|
|
28
28
|
"license": "ISC",
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@opentelemetry/api": "^1.9.0",
|
|
31
|
-
"@opentelemetry/auto-instrumentations-node": "^0.
|
|
32
|
-
"@opentelemetry/core": "
|
|
33
|
-
"@opentelemetry/exporter-logs-otlp-grpc": "^0.
|
|
34
|
-
"@opentelemetry/exporter-logs-otlp-http": "^0.
|
|
35
|
-
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.
|
|
36
|
-
"@opentelemetry/exporter-metrics-otlp-http": "^0.
|
|
37
|
-
"@opentelemetry/exporter-trace-otlp-grpc": "^0.
|
|
38
|
-
"@opentelemetry/exporter-trace-otlp-http": "^0.
|
|
39
|
-
"@opentelemetry/instrumentation": "^0.
|
|
40
|
-
"@opentelemetry/otlp-exporter-base": "^0.
|
|
41
|
-
"@opentelemetry/
|
|
42
|
-
"@opentelemetry/sdk-
|
|
43
|
-
"@opentelemetry/sdk-
|
|
44
|
-
"@opentelemetry/sdk-
|
|
31
|
+
"@opentelemetry/auto-instrumentations-node": "^0.57.0",
|
|
32
|
+
"@opentelemetry/core": "^2.0.0",
|
|
33
|
+
"@opentelemetry/exporter-logs-otlp-grpc": "^0.200.0",
|
|
34
|
+
"@opentelemetry/exporter-logs-otlp-http": "^0.200.0",
|
|
35
|
+
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.200.0",
|
|
36
|
+
"@opentelemetry/exporter-metrics-otlp-http": "^0.200.0",
|
|
37
|
+
"@opentelemetry/exporter-trace-otlp-grpc": "^0.200.0",
|
|
38
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.200.0",
|
|
39
|
+
"@opentelemetry/instrumentation": "^0.200.0",
|
|
40
|
+
"@opentelemetry/otlp-exporter-base": "^0.200.0",
|
|
41
|
+
"@opentelemetry/resources": "^2.0.0",
|
|
42
|
+
"@opentelemetry/sdk-logs": "^0.200.0",
|
|
43
|
+
"@opentelemetry/sdk-metrics": "^2.0.0",
|
|
44
|
+
"@opentelemetry/sdk-node": "^0.200.0",
|
|
45
|
+
"@opentelemetry/sdk-trace-base": "^2.0.0"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
|
-
"@types/node": "^22.13.
|
|
48
|
-
"@vitest/coverage-v8": "^3.0.
|
|
49
|
-
"tsx": "^4.19.
|
|
50
|
-
"typescript": "^5.
|
|
51
|
-
"vitest": "^3.0.
|
|
48
|
+
"@types/node": "^22.13.9",
|
|
49
|
+
"@vitest/coverage-v8": "^3.0.8",
|
|
50
|
+
"tsx": "^4.19.3",
|
|
51
|
+
"typescript": "^5.8.2",
|
|
52
|
+
"vitest": "^3.0.8"
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=20.6.0"
|
|
52
56
|
}
|
|
53
57
|
}
|
package/dist/vitest.config.js
CHANGED
package/lib/exporter/console.ts
CHANGED
|
@@ -8,8 +8,9 @@ import {
|
|
|
8
8
|
SimpleSpanProcessor,
|
|
9
9
|
} from "@opentelemetry/sdk-trace-base";
|
|
10
10
|
import { NodeSDKConfig } from "../index.js";
|
|
11
|
-
import { Exporters } from "
|
|
11
|
+
import { Exporters } from "./index.js";
|
|
12
12
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
13
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
13
14
|
|
|
14
15
|
export default function buildConsoleExporters(
|
|
15
16
|
config: NodeSDKConfig,
|
|
@@ -22,6 +23,9 @@ export default function buildConsoleExporters(
|
|
|
22
23
|
metrics: new metrics.PeriodicExportingMetricReader({
|
|
23
24
|
exporter: new metrics.ConsoleMetricExporter(),
|
|
24
25
|
}),
|
|
25
|
-
logs: [
|
|
26
|
+
logs: [
|
|
27
|
+
new EnrichLogProcessor(config.spanAttributes),
|
|
28
|
+
new SimpleLogRecordProcessor(new ConsoleLogRecordExporter()),
|
|
29
|
+
],
|
|
26
30
|
};
|
|
27
31
|
}
|
package/lib/exporter/grpc.ts
CHANGED
|
@@ -4,9 +4,10 @@ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
|
|
|
4
4
|
import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-grpc";
|
|
5
5
|
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
|
|
6
6
|
import { NodeSDKConfig } from "../index.js";
|
|
7
|
-
import { Exporters } from "
|
|
7
|
+
import { Exporters } from "./index.js";
|
|
8
8
|
import { LogRecordProcessorMap, SpanProcessorMap } from "../utils.js";
|
|
9
9
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
10
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
10
11
|
|
|
11
12
|
export default function buildGrpcExporters(config: NodeSDKConfig): Exporters {
|
|
12
13
|
return {
|
|
@@ -26,6 +27,7 @@ export default function buildGrpcExporters(config: NodeSDKConfig): Exporters {
|
|
|
26
27
|
}),
|
|
27
28
|
}),
|
|
28
29
|
logs: [
|
|
30
|
+
new EnrichLogProcessor(config.spanAttributes),
|
|
29
31
|
new LogRecordProcessorMap[config.collectorMode ?? "batch"](
|
|
30
32
|
new OTLPLogExporter({
|
|
31
33
|
url: `${config.collectorUrl}`,
|
package/lib/exporter/http.ts
CHANGED
|
@@ -5,8 +5,9 @@ import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
|
|
|
5
5
|
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
6
6
|
import { LogRecordProcessorMap, SpanProcessorMap } from "../utils.js";
|
|
7
7
|
import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
|
|
8
|
-
import { Exporters } from "
|
|
8
|
+
import { Exporters } from "./index.js";
|
|
9
9
|
import { NodeSDKConfig } from "../index.js";
|
|
10
|
+
import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
|
|
10
11
|
|
|
11
12
|
export default function buildHttpExporters(config: NodeSDKConfig): Exporters {
|
|
12
13
|
if (config.collectorUrl.endsWith("/")) {
|
|
@@ -30,6 +31,7 @@ export default function buildHttpExporters(config: NodeSDKConfig): Exporters {
|
|
|
30
31
|
}),
|
|
31
32
|
}),
|
|
32
33
|
logs: [
|
|
34
|
+
new EnrichLogProcessor(config.spanAttributes),
|
|
33
35
|
new LogRecordProcessorMap[config.collectorMode ?? "batch"](
|
|
34
36
|
new OTLPLogExporter({
|
|
35
37
|
url: `${config.collectorUrl}/v1/logs`,
|
|
@@ -1,23 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
diag,
|
|
3
|
-
DiagConsoleLogger,
|
|
4
|
-
DiagLogLevel,
|
|
5
|
-
Span,
|
|
6
|
-
} from "@opentelemetry/api";
|
|
1
|
+
import { diag, DiagConsoleLogger, DiagLogLevel } from "@opentelemetry/api";
|
|
7
2
|
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
|
|
8
3
|
import { W3CTraceContextPropagator } from "@opentelemetry/core";
|
|
9
|
-
import { NodeSDK
|
|
4
|
+
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
10
5
|
import {
|
|
11
6
|
AlwaysOffSampler,
|
|
12
7
|
ParentBasedSampler,
|
|
13
8
|
TraceIdRatioBasedSampler,
|
|
14
9
|
} from "@opentelemetry/sdk-trace-base";
|
|
15
|
-
import packageJson from "../package.json" with { type: "json" };
|
|
16
10
|
import buildConsoleExporters from "./exporter/console.js";
|
|
17
11
|
import buildGrpcExporters from "./exporter/grpc.js";
|
|
18
12
|
import buildHttpExporters from "./exporter/http.js";
|
|
13
|
+
import type { Exporters } from "./exporter/index.js";
|
|
19
14
|
import type { NodeSDKConfig } from "./index.js";
|
|
20
|
-
import
|
|
15
|
+
import { ObservabilityResourceDetector } from "./resource.js";
|
|
21
16
|
import { UrlSampler } from "./url-sampler.js";
|
|
22
17
|
|
|
23
18
|
export default function buildNodeInstrumentation(
|
|
@@ -76,11 +71,9 @@ export default function buildNodeInstrumentation(
|
|
|
76
71
|
);
|
|
77
72
|
|
|
78
73
|
const sdk = new NodeSDK({
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
...config.resourceAttributes,
|
|
83
|
-
}),
|
|
74
|
+
resourceDetectors: [
|
|
75
|
+
new ObservabilityResourceDetector(config.resourceAttributes),
|
|
76
|
+
],
|
|
84
77
|
spanProcessors: exporter.spans,
|
|
85
78
|
serviceName: config.serviceName,
|
|
86
79
|
metricReader: exporter.metrics,
|
|
@@ -92,21 +85,6 @@ export default function buildNodeInstrumentation(
|
|
|
92
85
|
"@opentelemetry/instrumentation-fs": {
|
|
93
86
|
enabled: config.enableFS ?? false,
|
|
94
87
|
},
|
|
95
|
-
"@opentelemetry/instrumentation-pino": {
|
|
96
|
-
logHook: (
|
|
97
|
-
_span: Span,
|
|
98
|
-
record: Record<string, unknown>,
|
|
99
|
-
_level?: number,
|
|
100
|
-
) => {
|
|
101
|
-
if (config.spanAttributes != undefined) {
|
|
102
|
-
for (const [key, value] of Object.entries(
|
|
103
|
-
config.spanAttributes,
|
|
104
|
-
)) {
|
|
105
|
-
record[key] = typeof value === "function" ? value() : value;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
88
|
}),
|
|
111
89
|
],
|
|
112
90
|
});
|
|
@@ -126,8 +104,7 @@ function isUrl(url: string): boolean {
|
|
|
126
104
|
try {
|
|
127
105
|
new URL(url);
|
|
128
106
|
return true;
|
|
129
|
-
} catch (
|
|
130
|
-
console.error(err);
|
|
107
|
+
} catch (_) {
|
|
131
108
|
return false;
|
|
132
109
|
}
|
|
133
110
|
}
|
package/lib/metrics.ts
CHANGED
|
@@ -10,26 +10,30 @@ import {
|
|
|
10
10
|
ObservableGauge,
|
|
11
11
|
ObservableUpDownCounter,
|
|
12
12
|
UpDownCounter,
|
|
13
|
+
Attributes,
|
|
13
14
|
} from "@opentelemetry/api";
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"async-
|
|
22
|
-
"async-
|
|
23
|
-
"async-gauge": ObservableGauge;
|
|
16
|
+
type MetricTypeMap<TAttributes extends Attributes> = {
|
|
17
|
+
counter: Counter<TAttributes>;
|
|
18
|
+
histogram: Histogram<TAttributes>;
|
|
19
|
+
gauge: Gauge<TAttributes>;
|
|
20
|
+
updowncounter: UpDownCounter<TAttributes>;
|
|
21
|
+
"async-counter": ObservableCounter<TAttributes>;
|
|
22
|
+
"async-updowncounter": ObservableUpDownCounter<TAttributes>;
|
|
23
|
+
"async-gauge": ObservableGauge<TAttributes>;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
type MetricType = keyof
|
|
26
|
+
export type MetricType = keyof MetricTypeMap<Attributes>;
|
|
27
27
|
|
|
28
|
-
const MetricsFactoryMap:
|
|
29
|
-
|
|
28
|
+
const MetricsFactoryMap: Record<
|
|
29
|
+
MetricType,
|
|
30
|
+
(
|
|
30
31
|
meter: Meter,
|
|
31
|
-
) => (
|
|
32
|
-
|
|
32
|
+
) => (
|
|
33
|
+
name: string,
|
|
34
|
+
options?: MetricOptions,
|
|
35
|
+
) => MetricTypeMap<Attributes>[MetricType]
|
|
36
|
+
> = {
|
|
33
37
|
gauge: (meter: Meter) => meter.createGauge,
|
|
34
38
|
histogram: (meter: Meter) => meter.createHistogram,
|
|
35
39
|
counter: (meter: Meter) => meter.createCounter,
|
|
@@ -37,34 +41,35 @@ const MetricsFactoryMap: {
|
|
|
37
41
|
"async-counter": (meter: Meter) => meter.createObservableCounter,
|
|
38
42
|
"async-updowncounter": (meter: Meter) => meter.createObservableUpDownCounter,
|
|
39
43
|
"async-gauge": (meter: Meter) => meter.createObservableGauge,
|
|
40
|
-
};
|
|
44
|
+
} as const;
|
|
41
45
|
|
|
42
46
|
export interface MetricsParams {
|
|
47
|
+
meterName: string;
|
|
43
48
|
metricName: string;
|
|
44
|
-
attributeName: string;
|
|
45
49
|
options?: MetricOptions;
|
|
46
50
|
}
|
|
47
51
|
|
|
48
|
-
function getMeter({
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
meter = createNoopMeter();
|
|
53
|
-
} else {
|
|
54
|
-
meter = metrics.getMeter(`custom_metric.${metricName}`);
|
|
52
|
+
function getMeter({ meterName }: MetricsParams) {
|
|
53
|
+
if (!meterName) {
|
|
54
|
+
console.error("Invalid metric name!");
|
|
55
|
+
return createNoopMeter();
|
|
55
56
|
}
|
|
56
|
-
|
|
57
|
+
|
|
58
|
+
return metrics.getMeter(`custom_metric.${meterName}`);
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
export function getMetric<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
export function getMetric<
|
|
62
|
+
T extends MetricType,
|
|
63
|
+
TAttributes extends Attributes = Attributes,
|
|
64
|
+
>(type: T, p: MetricsParams): MetricTypeMap<TAttributes>[T] {
|
|
63
65
|
const meter = getMeter(p);
|
|
64
66
|
|
|
65
67
|
if (!MetricsFactoryMap[type]) {
|
|
66
68
|
throw new Error(`Unsupported metric type: ${type}`);
|
|
67
69
|
}
|
|
68
70
|
|
|
69
|
-
return MetricsFactoryMap[type](meter).bind(meter)(
|
|
71
|
+
return MetricsFactoryMap[type](meter).bind(meter)(
|
|
72
|
+
p.metricName,
|
|
73
|
+
p.options,
|
|
74
|
+
) as MetricTypeMap<TAttributes>[T];
|
|
70
75
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { LogRecord, LogRecordProcessor } from "@opentelemetry/sdk-logs";
|
|
2
|
+
import { Context } from "@opentelemetry/api";
|
|
3
|
+
import { SignalAttributeValue } from "../index.js";
|
|
4
|
+
|
|
5
|
+
export class EnrichLogProcessor implements LogRecordProcessor {
|
|
6
|
+
private _spanAttributes?:
|
|
7
|
+
| Record<string, SignalAttributeValue | (() => SignalAttributeValue)>
|
|
8
|
+
| undefined = undefined;
|
|
9
|
+
|
|
10
|
+
constructor(
|
|
11
|
+
spanAttributes?: Record<
|
|
12
|
+
string,
|
|
13
|
+
SignalAttributeValue | (() => SignalAttributeValue)
|
|
14
|
+
>,
|
|
15
|
+
) {
|
|
16
|
+
this._spanAttributes = spanAttributes;
|
|
17
|
+
}
|
|
18
|
+
forceFlush(): Promise<void> {
|
|
19
|
+
return Promise.resolve();
|
|
20
|
+
}
|
|
21
|
+
onEmit(logRecord: LogRecord, _context?: Context): void {
|
|
22
|
+
if (this._spanAttributes) {
|
|
23
|
+
for (const [key, value] of Object.entries(this._spanAttributes)) {
|
|
24
|
+
logRecord.setAttribute(
|
|
25
|
+
key,
|
|
26
|
+
typeof value === "function" ? value() : value,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
shutdown(): Promise<void> {
|
|
32
|
+
return Promise.resolve();
|
|
33
|
+
}
|
|
34
|
+
}
|
package/lib/resource.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ResourceDetector,
|
|
3
|
+
DetectedResource,
|
|
4
|
+
DetectedResourceAttributes,
|
|
5
|
+
} from "@opentelemetry/resources";
|
|
6
|
+
import { SignalAttributeValue } from "./index.js";
|
|
7
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
8
|
+
|
|
9
|
+
export class ObservabilityResourceDetector implements ResourceDetector {
|
|
10
|
+
private _resourceAttributes: Record<string, SignalAttributeValue> | undefined;
|
|
11
|
+
|
|
12
|
+
constructor(resourceAttributes?: Record<string, SignalAttributeValue>) {
|
|
13
|
+
this._resourceAttributes = resourceAttributes;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
detect(): DetectedResource {
|
|
17
|
+
let attributes: DetectedResourceAttributes = {};
|
|
18
|
+
|
|
19
|
+
if (this._resourceAttributes) {
|
|
20
|
+
attributes = {
|
|
21
|
+
...this._resourceAttributes,
|
|
22
|
+
"o11y.sdk.name": packageJson.name,
|
|
23
|
+
"o11y.sdk.version": packageJson.version,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return { attributes };
|
|
28
|
+
}
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ogcio/o11y-sdk-node",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.9",
|
|
4
4
|
"description": "Opentelemetry standard instrumentation SDK for NodeJS based project",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -20,27 +20,31 @@
|
|
|
20
20
|
"license": "ISC",
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@opentelemetry/api": "^1.9.0",
|
|
23
|
-
"@opentelemetry/auto-instrumentations-node": "^0.
|
|
24
|
-
"@opentelemetry/core": "
|
|
25
|
-
"@opentelemetry/exporter-logs-otlp-grpc": "^0.
|
|
26
|
-
"@opentelemetry/exporter-logs-otlp-http": "^0.
|
|
27
|
-
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.
|
|
28
|
-
"@opentelemetry/exporter-metrics-otlp-http": "^0.
|
|
29
|
-
"@opentelemetry/exporter-trace-otlp-grpc": "^0.
|
|
30
|
-
"@opentelemetry/exporter-trace-otlp-http": "^0.
|
|
31
|
-
"@opentelemetry/instrumentation": "^0.
|
|
32
|
-
"@opentelemetry/otlp-exporter-base": "^0.
|
|
33
|
-
"@opentelemetry/
|
|
34
|
-
"@opentelemetry/sdk-
|
|
35
|
-
"@opentelemetry/sdk-
|
|
36
|
-
"@opentelemetry/sdk-
|
|
23
|
+
"@opentelemetry/auto-instrumentations-node": "^0.57.0",
|
|
24
|
+
"@opentelemetry/core": "^2.0.0",
|
|
25
|
+
"@opentelemetry/exporter-logs-otlp-grpc": "^0.200.0",
|
|
26
|
+
"@opentelemetry/exporter-logs-otlp-http": "^0.200.0",
|
|
27
|
+
"@opentelemetry/exporter-metrics-otlp-grpc": "^0.200.0",
|
|
28
|
+
"@opentelemetry/exporter-metrics-otlp-http": "^0.200.0",
|
|
29
|
+
"@opentelemetry/exporter-trace-otlp-grpc": "^0.200.0",
|
|
30
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.200.0",
|
|
31
|
+
"@opentelemetry/instrumentation": "^0.200.0",
|
|
32
|
+
"@opentelemetry/otlp-exporter-base": "^0.200.0",
|
|
33
|
+
"@opentelemetry/resources": "^2.0.0",
|
|
34
|
+
"@opentelemetry/sdk-logs": "^0.200.0",
|
|
35
|
+
"@opentelemetry/sdk-metrics": "^2.0.0",
|
|
36
|
+
"@opentelemetry/sdk-node": "^0.200.0",
|
|
37
|
+
"@opentelemetry/sdk-trace-base": "^2.0.0"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
|
-
"@types/node": "^22.13.
|
|
40
|
-
"@vitest/coverage-v8": "^3.0.
|
|
41
|
-
"tsx": "^4.19.
|
|
42
|
-
"typescript": "^5.
|
|
43
|
-
"vitest": "^3.0.
|
|
40
|
+
"@types/node": "^22.13.9",
|
|
41
|
+
"@vitest/coverage-v8": "^3.0.8",
|
|
42
|
+
"tsx": "^4.19.3",
|
|
43
|
+
"typescript": "^5.8.2",
|
|
44
|
+
"vitest": "^3.0.8"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=20.6.0"
|
|
44
48
|
},
|
|
45
49
|
"scripts": {
|
|
46
50
|
"build": "rm -rf dist && tsc -p tsconfig.json",
|
package/test/integration/run.sh
CHANGED
|
@@ -37,6 +37,9 @@ if [[ $ERROR_CODE -eq 0 ]]; then
|
|
|
37
37
|
docker run --detach \
|
|
38
38
|
--network $NETWORK_NAME \
|
|
39
39
|
--name $NODE_CONTAINER_NAME \
|
|
40
|
+
-e DB_DISABLED="true" \
|
|
41
|
+
-e SERVER_HOST="0.0.0.0" \
|
|
42
|
+
-e OTEL_COLLECTOR_URL="http://integrationalloy:4317" \
|
|
40
43
|
--health-cmd="curl -f http://${NODE_CONTAINER_NAME}:9091/api/health > /dev/null || exit 1" \
|
|
41
44
|
--health-start-period=1s \
|
|
42
45
|
--health-retries=10 \
|
package/test/metrics.test.ts
CHANGED
|
@@ -29,7 +29,7 @@ describe("MetricsFactoryMap", () => {
|
|
|
29
29
|
|
|
30
30
|
const validMetricParams: MetricsParams = {
|
|
31
31
|
metricName: "test-metric",
|
|
32
|
-
|
|
32
|
+
meterName: "test-meter",
|
|
33
33
|
options: { description: "A test metric" },
|
|
34
34
|
};
|
|
35
35
|
|
|
@@ -40,7 +40,7 @@ describe("MetricsFactoryMap", () => {
|
|
|
40
40
|
|
|
41
41
|
expect(result).toBe("mocked-gauge");
|
|
42
42
|
expect(mockMeter.createGauge).toHaveBeenCalledWith(
|
|
43
|
-
validMetricParams.
|
|
43
|
+
validMetricParams.metricName,
|
|
44
44
|
validMetricParams.options,
|
|
45
45
|
);
|
|
46
46
|
});
|
|
@@ -52,7 +52,7 @@ describe("MetricsFactoryMap", () => {
|
|
|
52
52
|
|
|
53
53
|
expect(result).toBe("mocked-histogram");
|
|
54
54
|
expect(mockMeter.createHistogram).toHaveBeenCalledWith(
|
|
55
|
-
validMetricParams.
|
|
55
|
+
validMetricParams.metricName,
|
|
56
56
|
validMetricParams.options,
|
|
57
57
|
);
|
|
58
58
|
});
|
|
@@ -64,7 +64,7 @@ describe("MetricsFactoryMap", () => {
|
|
|
64
64
|
|
|
65
65
|
expect(result).toBe("mocked-counter");
|
|
66
66
|
expect(mockMeter.createCounter).toHaveBeenCalledWith(
|
|
67
|
-
validMetricParams.
|
|
67
|
+
validMetricParams.metricName,
|
|
68
68
|
validMetricParams.options,
|
|
69
69
|
);
|
|
70
70
|
});
|
|
@@ -76,7 +76,7 @@ describe("MetricsFactoryMap", () => {
|
|
|
76
76
|
|
|
77
77
|
expect(result).toBe("mocked-updowncounter");
|
|
78
78
|
expect(mockMeter.createUpDownCounter).toHaveBeenCalledWith(
|
|
79
|
-
validMetricParams.
|
|
79
|
+
validMetricParams.metricName,
|
|
80
80
|
validMetricParams.options,
|
|
81
81
|
);
|
|
82
82
|
});
|
|
@@ -88,7 +88,7 @@ describe("MetricsFactoryMap", () => {
|
|
|
88
88
|
|
|
89
89
|
expect(result).toBe("mocked-async-counter");
|
|
90
90
|
expect(mockMeter.createObservableCounter).toHaveBeenCalledWith(
|
|
91
|
-
validMetricParams.
|
|
91
|
+
validMetricParams.metricName,
|
|
92
92
|
validMetricParams.options,
|
|
93
93
|
);
|
|
94
94
|
});
|
|
@@ -102,7 +102,7 @@ describe("MetricsFactoryMap", () => {
|
|
|
102
102
|
|
|
103
103
|
expect(result).toBe("mocked-async-updowncounter");
|
|
104
104
|
expect(mockMeter.createObservableUpDownCounter).toHaveBeenCalledWith(
|
|
105
|
-
validMetricParams.
|
|
105
|
+
validMetricParams.metricName,
|
|
106
106
|
validMetricParams.options,
|
|
107
107
|
);
|
|
108
108
|
});
|
|
@@ -114,7 +114,7 @@ describe("MetricsFactoryMap", () => {
|
|
|
114
114
|
|
|
115
115
|
expect(result).toBe("mocked-async-gauge");
|
|
116
116
|
expect(mockMeter.createObservableGauge).toHaveBeenCalledWith(
|
|
117
|
-
validMetricParams.
|
|
117
|
+
validMetricParams.metricName,
|
|
118
118
|
validMetricParams.options,
|
|
119
119
|
);
|
|
120
120
|
});
|
|
@@ -131,7 +131,7 @@ describe("MetricsFactoryMap", () => {
|
|
|
131
131
|
test("should return noop metric fallback for null config", async () => {
|
|
132
132
|
const nullMetricParams: MetricsParams = {
|
|
133
133
|
metricName: null!,
|
|
134
|
-
|
|
134
|
+
meterName: "",
|
|
135
135
|
};
|
|
136
136
|
|
|
137
137
|
const result = getMetric("async-gauge", nullMetricParams);
|
package/test/node-config.test.ts
CHANGED
|
@@ -44,8 +44,8 @@ describe("verify config settings", () => {
|
|
|
44
44
|
|
|
45
45
|
const logs = _configuration.logRecordProcessors;
|
|
46
46
|
|
|
47
|
-
assert.equal(logs.length,
|
|
48
|
-
assert.ok(logs[
|
|
47
|
+
assert.equal(logs.length, 2);
|
|
48
|
+
assert.ok(logs[1] instanceof BatchLogRecordProcessor);
|
|
49
49
|
|
|
50
50
|
const spans = _configuration.spanProcessors;
|
|
51
51
|
|
|
@@ -74,8 +74,8 @@ describe("verify config settings", () => {
|
|
|
74
74
|
|
|
75
75
|
const logs = _configuration.logRecordProcessors;
|
|
76
76
|
|
|
77
|
-
assert.equal(logs.length,
|
|
78
|
-
assert.ok(logs[
|
|
77
|
+
assert.equal(logs.length, 2);
|
|
78
|
+
assert.ok(logs[1] instanceof BatchLogRecordProcessor);
|
|
79
79
|
|
|
80
80
|
const spans = _configuration.spanProcessors;
|
|
81
81
|
|
|
@@ -105,8 +105,8 @@ describe("verify config settings", () => {
|
|
|
105
105
|
const logs = _configuration.logRecordProcessors;
|
|
106
106
|
|
|
107
107
|
// verify simple log processor for instant console logging
|
|
108
|
-
assert.equal(logs.length,
|
|
109
|
-
assert.ok(logs[
|
|
108
|
+
assert.equal(logs.length, 2);
|
|
109
|
+
assert.ok(logs[1] instanceof SimpleLogRecordProcessor);
|
|
110
110
|
|
|
111
111
|
const spans = _configuration.spanProcessors;
|
|
112
112
|
|
|
@@ -136,8 +136,8 @@ describe("verify config settings", () => {
|
|
|
136
136
|
const _configuration = sdk["_configuration"];
|
|
137
137
|
|
|
138
138
|
const logRecordProcessors = _configuration.logRecordProcessors;
|
|
139
|
-
assert.equal(logRecordProcessors.length,
|
|
140
|
-
assert.ok(logRecordProcessors[
|
|
139
|
+
assert.equal(logRecordProcessors.length, 2);
|
|
140
|
+
assert.ok(logRecordProcessors[1] instanceof SimpleLogRecordProcessor);
|
|
141
141
|
});
|
|
142
142
|
|
|
143
143
|
test("check if clear base endpoint final slash", () => {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { LogRecord } from "@opentelemetry/sdk-logs";
|
|
3
|
+
import { EnrichLogProcessor } from "../../lib/processor/enrich-logger-processor.js";
|
|
4
|
+
|
|
5
|
+
const createMockLogRecord = () => {
|
|
6
|
+
return {
|
|
7
|
+
setAttribute: vi.fn(),
|
|
8
|
+
} as unknown as LogRecord;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
describe("EnrichLogProcessor", () => {
|
|
12
|
+
it("should enrich log record with static attributes", () => {
|
|
13
|
+
const attributes = { key1: "value1", key2: 42 };
|
|
14
|
+
const processor = new EnrichLogProcessor(attributes);
|
|
15
|
+
const mockLogRecord = createMockLogRecord();
|
|
16
|
+
|
|
17
|
+
processor.onEmit(mockLogRecord);
|
|
18
|
+
|
|
19
|
+
expect(mockLogRecord.setAttribute).toHaveBeenCalledWith("key1", "value1");
|
|
20
|
+
expect(mockLogRecord.setAttribute).toHaveBeenCalledWith("key2", 42);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should enrich log record with dynamic attributes", () => {
|
|
24
|
+
const attributes = {
|
|
25
|
+
key1: () => "dynamicValue",
|
|
26
|
+
key2: () => 100,
|
|
27
|
+
};
|
|
28
|
+
const processor = new EnrichLogProcessor(attributes);
|
|
29
|
+
const mockLogRecord = createMockLogRecord();
|
|
30
|
+
|
|
31
|
+
processor.onEmit(mockLogRecord);
|
|
32
|
+
|
|
33
|
+
expect(mockLogRecord.setAttribute).toHaveBeenCalledWith(
|
|
34
|
+
"key1",
|
|
35
|
+
"dynamicValue",
|
|
36
|
+
);
|
|
37
|
+
expect(mockLogRecord.setAttribute).toHaveBeenCalledWith("key2", 100);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("should not set attributes if no span attributes are provided", () => {
|
|
41
|
+
const processor = new EnrichLogProcessor();
|
|
42
|
+
const mockLogRecord = createMockLogRecord();
|
|
43
|
+
|
|
44
|
+
processor.onEmit(mockLogRecord);
|
|
45
|
+
|
|
46
|
+
expect(mockLogRecord.setAttribute).not.toHaveBeenCalled();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("should reject forceFlush", async () => {
|
|
50
|
+
await expect(
|
|
51
|
+
new EnrichLogProcessor().forceFlush(),
|
|
52
|
+
).resolves.toBeUndefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("should resolve shutdown", async () => {
|
|
56
|
+
await expect(new EnrichLogProcessor().shutdown()).resolves.toBeUndefined();
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -5,13 +5,12 @@ import {
|
|
|
5
5
|
Link,
|
|
6
6
|
Span,
|
|
7
7
|
SpanAttributes,
|
|
8
|
-
SpanAttributeValue,
|
|
9
8
|
SpanContext,
|
|
10
9
|
SpanStatus,
|
|
11
10
|
TimeInput,
|
|
12
11
|
} from "@opentelemetry/api";
|
|
13
12
|
import { describe, expect, it } from "vitest";
|
|
14
|
-
import { EnrichSpanProcessor } from "
|
|
13
|
+
import { EnrichSpanProcessor } from "../../lib/processor/enrich-span-processor.js";
|
|
15
14
|
|
|
16
15
|
class MockSpan implements Span {
|
|
17
16
|
public attributes: Record<string, AttributeValue> = {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, test, expect, vi } from "vitest";
|
|
2
|
+
import { ObservabilityResourceDetector } from "../lib/resource";
|
|
3
|
+
|
|
4
|
+
describe("ObservabilityResourceDetector", () => {
|
|
5
|
+
test("should return custom resource attribute", () => {
|
|
6
|
+
const detector = new ObservabilityResourceDetector({
|
|
7
|
+
first: "first_value",
|
|
8
|
+
second: "second_value",
|
|
9
|
+
});
|
|
10
|
+
const result = detector.detect();
|
|
11
|
+
|
|
12
|
+
expect(result.attributes).not.toBeNull();
|
|
13
|
+
expect(result.attributes).toHaveProperty("first");
|
|
14
|
+
expect(result.attributes!["first"]).eq("first_value");
|
|
15
|
+
expect(result.attributes).toHaveProperty("second");
|
|
16
|
+
expect(result.attributes!["second"]).eq("second_value");
|
|
17
|
+
// default
|
|
18
|
+
expect(result.attributes).toHaveProperty("o11y.sdk.name");
|
|
19
|
+
expect(result.attributes!["o11y.sdk.name"]).eq("@ogcio/o11y-sdk-node");
|
|
20
|
+
expect(result.attributes).toHaveProperty("o11y.sdk.version");
|
|
21
|
+
});
|
|
22
|
+
});
|
package/vitest.config.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|