@relkit/otlp 0.3.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/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/otlp.d.ts +14 -0
- package/dist/otlp.d.ts.map +1 -0
- package/dist/otlp.js +52 -0
- package/dist/otlp.js.map +1 -0
- package/dist/runtime/exporter-support.d.ts +13 -0
- package/dist/runtime/exporter-support.d.ts.map +1 -0
- package/dist/runtime/exporter-support.js +52 -0
- package/dist/runtime/exporter-support.js.map +1 -0
- package/dist/runtime/exporter.d.ts +21 -0
- package/dist/runtime/exporter.d.ts.map +1 -0
- package/dist/runtime/exporter.js +127 -0
- package/dist/runtime/exporter.js.map +1 -0
- package/dist/runtime/index.d.ts +12 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +10 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/transport.d.ts +14 -0
- package/dist/runtime/transport.d.ts.map +1 -0
- package/dist/runtime/transport.js +48 -0
- package/dist/runtime/transport.js.map +1 -0
- package/package.json +63 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 rel-kit
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC"}
|
package/dist/otlp.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type TelemetryExporterDescriptor } from "@relkit/observability/telemetry";
|
|
2
|
+
import { type BindingValueRef } from "@relkit/provider";
|
|
3
|
+
type TextReference = BindingValueRef<string, string, "string"> | BindingValueRef<string, URL, "url"> | BindingValueRef<string, string, "secret-string">;
|
|
4
|
+
type TextInput = string | TextReference;
|
|
5
|
+
export interface OtlpOptions {
|
|
6
|
+
readonly endpoint: TextInput;
|
|
7
|
+
readonly headers?: Readonly<Record<string, TextInput>>;
|
|
8
|
+
readonly serviceName?: TextInput;
|
|
9
|
+
}
|
|
10
|
+
export type OtlpTelemetryExporter = TelemetryExporterDescriptor<"otlp", "otlp", OtlpOptions>;
|
|
11
|
+
/** Declares one statically loaded OTLP/HTTP telemetry exporter. */
|
|
12
|
+
export declare function otlp(options: OtlpOptions): OtlpTelemetryExporter;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=otlp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otlp.d.ts","sourceRoot":"","sources":["../src/otlp.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,2BAA2B,EACjC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAE3E,KAAK,aAAa,GACd,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,GACzC,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,GACnC,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;AACrD,KAAK,SAAS,GAAG,MAAM,GAAG,aAAa,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACvD,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC;CAClC;AAED,MAAM,MAAM,qBAAqB,GAAG,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;AAE7F,mEAAmE;AACnE,wBAAgB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,qBAAqB,CAUhE"}
|
package/dist/otlp.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { defineTelemetryExporter, } from "@relkit/observability/telemetry";
|
|
2
|
+
import { isBindingValueRef } from "@relkit/provider";
|
|
3
|
+
/** Declares one statically loaded OTLP/HTTP telemetry exporter. */
|
|
4
|
+
export function otlp(options) {
|
|
5
|
+
if (!record(options))
|
|
6
|
+
throw new TypeError("OTLP options are invalid");
|
|
7
|
+
exact(options, ["endpoint", "headers", "serviceName"]);
|
|
8
|
+
return defineTelemetryExporter("otlp", "otlp", {
|
|
9
|
+
endpoint: endpoint(options.endpoint),
|
|
10
|
+
...(options.headers === undefined ? {} : { headers: headerValues(options.headers) }),
|
|
11
|
+
...(options.serviceName === undefined
|
|
12
|
+
? {}
|
|
13
|
+
: { serviceName: text(options.serviceName, "serviceName") }),
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function endpoint(value) {
|
|
17
|
+
const selected = text(value, "endpoint");
|
|
18
|
+
if (typeof selected !== "string")
|
|
19
|
+
return selected;
|
|
20
|
+
const url = new URL(selected);
|
|
21
|
+
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
22
|
+
throw new TypeError("OTLP endpoint must use http or https");
|
|
23
|
+
return selected;
|
|
24
|
+
}
|
|
25
|
+
function headerValues(value) {
|
|
26
|
+
if (!record(value))
|
|
27
|
+
throw new TypeError("OTLP headers are invalid");
|
|
28
|
+
return Object.fromEntries(Object.entries(value)
|
|
29
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
30
|
+
.map(([name, selected]) => {
|
|
31
|
+
if (!/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(name))
|
|
32
|
+
throw new TypeError("OTLP header name is invalid");
|
|
33
|
+
return [name, text(selected, `header ${name}`)];
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
function text(value, name) {
|
|
37
|
+
if (typeof value === "string" && value.trim() !== "" && !/[\0\r\n]/.test(value))
|
|
38
|
+
return value.trim();
|
|
39
|
+
if (isBindingValueRef(value) &&
|
|
40
|
+
(value.type === "string" || value.type === "url" || value.type === "secret-string"))
|
|
41
|
+
return value;
|
|
42
|
+
throw new TypeError(`OTLP ${name} must be non-empty text or a named text value`);
|
|
43
|
+
}
|
|
44
|
+
function exact(value, allowed) {
|
|
45
|
+
const unknown = Object.keys(value).find((key) => !allowed.includes(key));
|
|
46
|
+
if (unknown !== undefined)
|
|
47
|
+
throw new TypeError(`Unknown OTLP option "${unknown}"`);
|
|
48
|
+
}
|
|
49
|
+
function record(value) {
|
|
50
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=otlp.js.map
|
package/dist/otlp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otlp.js","sourceRoot":"","sources":["../src/otlp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { JsonValue } from "@relkit/contracts";
|
|
2
|
+
import type { RedactedObservabilityRecord } from "@relkit/observability";
|
|
3
|
+
import type { OtlpSignal } from "./transport.js";
|
|
4
|
+
export declare function otlpPayload(serviceName: string | undefined, records: readonly RedactedObservabilityRecord[]): JsonValue;
|
|
5
|
+
export declare function otlpSignalFor(record: RedactedObservabilityRecord): OtlpSignal;
|
|
6
|
+
export declare function otlpUnitId(record: RedactedObservabilityRecord, sequence: number): string;
|
|
7
|
+
export declare function combinedSignal(first: AbortSignal, second: AbortSignal | undefined): AbortSignal;
|
|
8
|
+
export declare function within(operation: Promise<unknown>, timeoutMs: number): Promise<boolean>;
|
|
9
|
+
export declare function text(value: unknown, name: string): string;
|
|
10
|
+
export declare function textMap(value: unknown): Readonly<Record<string, string>>;
|
|
11
|
+
export declare function positive(value: number, name: string): number;
|
|
12
|
+
export declare function nonNegative(value: number, name: string): number;
|
|
13
|
+
//# sourceMappingURL=exporter-support.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exporter-support.d.ts","sourceRoot":"","sources":["../../src/runtime/exporter-support.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,OAAO,EAAE,SAAS,2BAA2B,EAAE,GAC9C,SAAS,CAKX;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,2BAA2B,GAAG,UAAU,CAI7E;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,2BAA2B,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIxF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,WAAW,CAE/F;AAED,wBAAsB,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAa7F;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAMxE;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/D"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export function otlpPayload(serviceName, records) {
|
|
2
|
+
return {
|
|
3
|
+
...(serviceName === undefined ? {} : { service: { name: serviceName } }),
|
|
4
|
+
records: records,
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
export function otlpSignalFor(record) {
|
|
8
|
+
return record.signal === "log" || record.signal === "diagnostic" || record.signal === "generation"
|
|
9
|
+
? "logs"
|
|
10
|
+
: "traces";
|
|
11
|
+
}
|
|
12
|
+
export function otlpUnitId(record, sequence) {
|
|
13
|
+
return record.traceId === undefined || otlpSignalFor(record) === "logs"
|
|
14
|
+
? `${record.signal}:${sequence}`
|
|
15
|
+
: `trace:${record.traceId}`;
|
|
16
|
+
}
|
|
17
|
+
export function combinedSignal(first, second) {
|
|
18
|
+
return second === undefined ? first : AbortSignal.any([first, second]);
|
|
19
|
+
}
|
|
20
|
+
export async function within(operation, timeoutMs) {
|
|
21
|
+
const timeout = nonNegative(timeoutMs, "timeoutMs");
|
|
22
|
+
let timer;
|
|
23
|
+
const expired = new Promise((resolve) => {
|
|
24
|
+
timer = setTimeout(() => resolve(false), timeout);
|
|
25
|
+
});
|
|
26
|
+
const completed = operation.then(() => true, () => false);
|
|
27
|
+
const result = await Promise.race([completed, expired]);
|
|
28
|
+
if (timer !== undefined)
|
|
29
|
+
clearTimeout(timer);
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
export function text(value, name) {
|
|
33
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
34
|
+
throw new TypeError(`OTLP ${name} must be non-empty text`);
|
|
35
|
+
return value.trim();
|
|
36
|
+
}
|
|
37
|
+
export function textMap(value) {
|
|
38
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
39
|
+
throw new TypeError("OTLP headers are invalid");
|
|
40
|
+
return Object.fromEntries(Object.entries(value).map(([name, entry]) => [name, text(entry, `header ${name}`)]));
|
|
41
|
+
}
|
|
42
|
+
export function positive(value, name) {
|
|
43
|
+
if (!Number.isSafeInteger(value) || value < 1)
|
|
44
|
+
throw new RangeError(`OTLP ${name} is invalid`);
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
export function nonNegative(value, name) {
|
|
48
|
+
if (!Number.isSafeInteger(value) || value < 0)
|
|
49
|
+
throw new RangeError(`OTLP ${name} is invalid`);
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=exporter-support.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exporter-support.js","sourceRoot":"","sources":["../../src/runtime/exporter-support.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type TelemetryExporterFactoryContext, type TelemetryExporterRuntime, type TelemetryExporterRuntimeStats } from "@relkit/observability";
|
|
2
|
+
import { type OtlpTransport } from "./transport.js";
|
|
3
|
+
export interface OtlpExporterOptions {
|
|
4
|
+
readonly transport: OtlpTransport;
|
|
5
|
+
readonly serviceName?: string;
|
|
6
|
+
readonly maxRecords?: number;
|
|
7
|
+
readonly batchSize?: number;
|
|
8
|
+
readonly maxRetries?: number;
|
|
9
|
+
readonly retryDelayMs?: number;
|
|
10
|
+
readonly signal?: AbortSignal;
|
|
11
|
+
readonly delay?: (milliseconds: number) => Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export interface OtlpExporter extends TelemetryExporterRuntime {
|
|
14
|
+
readonly stats: () => TelemetryExporterRuntimeStats & {
|
|
15
|
+
readonly exportedRecords: number;
|
|
16
|
+
readonly retries: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export declare function createOtlpExporter(options: OtlpExporterOptions): OtlpExporter;
|
|
20
|
+
export declare function createTelemetryExporter(context: TelemetryExporterFactoryContext): Promise<TelemetryExporterRuntime>;
|
|
21
|
+
//# sourceMappingURL=exporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exporter.d.ts","sourceRoot":"","sources":["../../src/runtime/exporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAC7B,KAAK,6BAA6B,EACnC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAwC,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAa1F,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,MAAM,WAAW,YAAa,SAAQ,wBAAwB;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,6BAA6B,GAAG;QACpD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;QACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAoH7E;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,+BAA+B,GACvC,OAAO,CAAC,wBAAwB,CAAC,CAanC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { createBoundedTelemetryExportQueue, } from "@relkit/observability";
|
|
2
|
+
import { createOtlpTransport } from "./transport.js";
|
|
3
|
+
import { combinedSignal, nonNegative, otlpPayload, otlpSignalFor, otlpUnitId, positive, text, textMap, within, } from "./exporter-support.js";
|
|
4
|
+
export function createOtlpExporter(options) {
|
|
5
|
+
const maximum = positive(options.maxRecords ?? 1_024, "maxRecords");
|
|
6
|
+
const batchSize = positive(options.batchSize ?? 64, "batchSize");
|
|
7
|
+
const maxRetries = nonNegative(options.maxRetries ?? 2, "maxRetries");
|
|
8
|
+
const retryDelayMs = nonNegative(options.retryDelayMs ?? 25, "retryDelayMs");
|
|
9
|
+
const delay = options.delay ??
|
|
10
|
+
((milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)));
|
|
11
|
+
const queue = createBoundedTelemetryExportQueue({ maxRecords: maximum, mergeAdjacent: true });
|
|
12
|
+
let worker;
|
|
13
|
+
let activeAbort;
|
|
14
|
+
let closing = false;
|
|
15
|
+
let sequence = 0;
|
|
16
|
+
let exportedRecords = 0;
|
|
17
|
+
let failedRecords = 0;
|
|
18
|
+
let failedUnits = 0;
|
|
19
|
+
let failures = 0;
|
|
20
|
+
let retries = 0;
|
|
21
|
+
const start = () => {
|
|
22
|
+
if (worker !== undefined)
|
|
23
|
+
return;
|
|
24
|
+
const current = Promise.resolve()
|
|
25
|
+
.then(drain)
|
|
26
|
+
.finally(() => {
|
|
27
|
+
if (worker === current)
|
|
28
|
+
worker = undefined;
|
|
29
|
+
if (!closing && queue.stats().queuedUnits > 0)
|
|
30
|
+
start();
|
|
31
|
+
});
|
|
32
|
+
worker = current;
|
|
33
|
+
};
|
|
34
|
+
const exportRecord = (record) => {
|
|
35
|
+
if (closing)
|
|
36
|
+
throw new Error("OTLP exporter is closed");
|
|
37
|
+
queue.enqueue({ id: otlpUnitId(record, ++sequence), records: [record] });
|
|
38
|
+
start();
|
|
39
|
+
};
|
|
40
|
+
const flush = async (timeoutMs = 1_000) => {
|
|
41
|
+
start();
|
|
42
|
+
if (!(await within(worker ?? Promise.resolve(), timeoutMs))) {
|
|
43
|
+
activeAbort?.abort();
|
|
44
|
+
queue.dropAll();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
await within(options.transport.flush(), timeoutMs);
|
|
48
|
+
};
|
|
49
|
+
const close = async (timeoutMs = 1_000) => {
|
|
50
|
+
if (closing)
|
|
51
|
+
return;
|
|
52
|
+
closing = true;
|
|
53
|
+
await flush(timeoutMs);
|
|
54
|
+
await within(options.transport.close(), timeoutMs);
|
|
55
|
+
};
|
|
56
|
+
const stats = () => {
|
|
57
|
+
const queued = queue.stats();
|
|
58
|
+
return Object.freeze({
|
|
59
|
+
queuedRecords: queued.queuedRecords,
|
|
60
|
+
queuedUnits: queued.queuedUnits,
|
|
61
|
+
droppedRecords: queued.droppedRecords + failedRecords,
|
|
62
|
+
droppedUnits: queued.droppedUnits + failedUnits,
|
|
63
|
+
failures,
|
|
64
|
+
exportedRecords,
|
|
65
|
+
retries,
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
async function drain() {
|
|
69
|
+
for (let first = queue.take(); first !== undefined; first = queue.take()) {
|
|
70
|
+
const units = [first];
|
|
71
|
+
let records = first.records.length;
|
|
72
|
+
while (records < batchSize) {
|
|
73
|
+
const next = queue.take();
|
|
74
|
+
if (next === undefined)
|
|
75
|
+
break;
|
|
76
|
+
units.push(next);
|
|
77
|
+
records += next.records.length;
|
|
78
|
+
}
|
|
79
|
+
for (const signal of ["logs", "traces"]) {
|
|
80
|
+
const selected = units.flatMap((unit) => unit.records
|
|
81
|
+
.filter((record) => otlpSignalFor(record) === signal)
|
|
82
|
+
.map((record) => ({ id: unit.id, record })));
|
|
83
|
+
if (selected.length > 0)
|
|
84
|
+
await send(signal, selected);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async function send(signal, selected) {
|
|
89
|
+
for (let attempt = 0;; attempt += 1) {
|
|
90
|
+
activeAbort = new AbortController();
|
|
91
|
+
try {
|
|
92
|
+
await options.transport.send(signal, otlpPayload(options.serviceName, selected.map(({ record }) => record)), combinedSignal(activeAbort.signal, options.signal));
|
|
93
|
+
exportedRecords += selected.length;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
failures += 1;
|
|
98
|
+
if (attempt >= maxRetries || activeAbort.signal.aborted || options.signal?.aborted) {
|
|
99
|
+
failedRecords += selected.length;
|
|
100
|
+
failedUnits += new Set(selected.map(({ id }) => id)).size;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
retries += 1;
|
|
104
|
+
await delay(retryDelayMs * 2 ** attempt);
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
activeAbort = undefined;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return Object.freeze({ exportRecord, flush, close, stats });
|
|
112
|
+
}
|
|
113
|
+
export async function createTelemetryExporter(context) {
|
|
114
|
+
const endpoint = text(context.configuration.endpoint, "endpoint");
|
|
115
|
+
const headers = context.configuration.headers;
|
|
116
|
+
return createOtlpExporter({
|
|
117
|
+
transport: createOtlpTransport({
|
|
118
|
+
endpoint,
|
|
119
|
+
...(headers === undefined ? {} : { headers: textMap(headers) }),
|
|
120
|
+
}),
|
|
121
|
+
...(context.configuration.serviceName === undefined
|
|
122
|
+
? {}
|
|
123
|
+
: { serviceName: text(context.configuration.serviceName, "serviceName") }),
|
|
124
|
+
...(context.signal === undefined ? {} : { signal: context.signal }),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=exporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exporter.js","sourceRoot":"","sources":["../../src/runtime/exporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./transport.js";
|
|
2
|
+
export * from "./exporter.js";
|
|
3
|
+
export declare const runtimeIntegration: Readonly<{
|
|
4
|
+
kind: "runtime-integration";
|
|
5
|
+
integrationId: "otlp";
|
|
6
|
+
registrations: readonly {
|
|
7
|
+
capability: string;
|
|
8
|
+
adapterId: string;
|
|
9
|
+
protocolVersion: number;
|
|
10
|
+
}[];
|
|
11
|
+
}>;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAE9B,eAAO,MAAM,kBAAkB;;;;;;;;EAM7B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from "./transport.js";
|
|
2
|
+
export * from "./exporter.js";
|
|
3
|
+
export const runtimeIntegration = Object.freeze({
|
|
4
|
+
kind: "runtime-integration",
|
|
5
|
+
integrationId: "otlp",
|
|
6
|
+
registrations: Object.freeze([
|
|
7
|
+
{ capability: "telemetry", adapterId: "otlp", protocolVersion: 1 },
|
|
8
|
+
]),
|
|
9
|
+
});
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAE9B,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9C,IAAI,EAAE,qBAAqB;IAC3B,aAAa,EAAE,MAAM;IACrB,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC;QAC3B,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,EAAE;KACnE,CAAC;CACH,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type JsonValue } from "@relkit/contracts";
|
|
2
|
+
export type OtlpSignal = "logs" | "traces";
|
|
3
|
+
export interface OtlpTransportOptions {
|
|
4
|
+
readonly endpoint: string;
|
|
5
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
6
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
7
|
+
}
|
|
8
|
+
export interface OtlpTransport {
|
|
9
|
+
readonly send: (signal: OtlpSignal, payload: JsonValue, abort?: AbortSignal) => Promise<void>;
|
|
10
|
+
readonly flush: () => Promise<void>;
|
|
11
|
+
readonly close: () => Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export declare function createOtlpTransport(options: OtlpTransportOptions): OtlpTransport;
|
|
14
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/runtime/transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAElE,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE3C,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CAC1C;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9F,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CA6BhF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { canonicalJson } from "@relkit/contracts";
|
|
2
|
+
export function createOtlpTransport(options) {
|
|
3
|
+
const endpoint = parseEndpoint(options.endpoint);
|
|
4
|
+
const fetcher = options.fetch ?? globalThis.fetch;
|
|
5
|
+
const headers = new Headers(options.headers);
|
|
6
|
+
headers.set("content-type", "application/json");
|
|
7
|
+
let closed = false;
|
|
8
|
+
return Object.freeze({
|
|
9
|
+
send: async (signal, payload, abort) => {
|
|
10
|
+
if (closed)
|
|
11
|
+
throw new Error("OTLP transport is closed");
|
|
12
|
+
if (signal !== "logs" && signal !== "traces")
|
|
13
|
+
throw new TypeError("OTLP signal is invalid");
|
|
14
|
+
const response = await fetcher(signalUrl(endpoint, signal), {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers,
|
|
17
|
+
body: canonicalJson(payload),
|
|
18
|
+
...(abort === undefined ? {} : { signal: abort }),
|
|
19
|
+
});
|
|
20
|
+
if (!response.ok) {
|
|
21
|
+
const detail = (await response.text()).trim().replace(/\s+/g, " ").slice(0, 500);
|
|
22
|
+
throw new Error(`OTLP ${signal} export failed with status ${response.status}${detail ? `: ${detail}` : ""}`);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
flush: () => Promise.resolve(),
|
|
26
|
+
close: () => {
|
|
27
|
+
closed = true;
|
|
28
|
+
return Promise.resolve();
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function parseEndpoint(value) {
|
|
33
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
34
|
+
throw new TypeError("OTLP endpoint must be non-empty text");
|
|
35
|
+
const endpoint = new URL(value);
|
|
36
|
+
if (endpoint.protocol !== "http:" && endpoint.protocol !== "https:")
|
|
37
|
+
throw new TypeError("OTLP endpoint must use http or https");
|
|
38
|
+
return endpoint;
|
|
39
|
+
}
|
|
40
|
+
function signalUrl(endpoint, signal) {
|
|
41
|
+
const target = new URL(endpoint);
|
|
42
|
+
if (/\/v1\/(?:logs|traces)\/?$/.test(target.pathname))
|
|
43
|
+
target.pathname = target.pathname.replace(/\/v1\/(?:logs|traces)\/?$/, `/v1/${signal}`);
|
|
44
|
+
else
|
|
45
|
+
target.pathname = `${target.pathname.replace(/\/$/, "")}/v1/${signal}`;
|
|
46
|
+
return target.toString();
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/runtime/transport.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@relkit/otlp",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "OTLP telemetry integration for RELKIT.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/rel-kit/relkit.git",
|
|
9
|
+
"directory": "integrations/packages/otlp"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/rel-kit/relkit#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/rel-kit/relkit/issues"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"bun": ">=1.3.10"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./runtime": {
|
|
31
|
+
"types": "./dist/runtime/index.d.ts",
|
|
32
|
+
"import": "./dist/runtime/index.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"relkit": {
|
|
36
|
+
"integration": {
|
|
37
|
+
"id": "otlp",
|
|
38
|
+
"exports": {
|
|
39
|
+
"authoring": ".",
|
|
40
|
+
"runtime": {
|
|
41
|
+
"export": "./runtime",
|
|
42
|
+
"registrations": [
|
|
43
|
+
{
|
|
44
|
+
"capability": "telemetry",
|
|
45
|
+
"adapterId": "otlp",
|
|
46
|
+
"protocolVersion": 1
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsc -b",
|
|
55
|
+
"check": "tsc -b --pretty false",
|
|
56
|
+
"typecheck": "tsc -b --pretty false"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@relkit/contracts": "0.3.0",
|
|
60
|
+
"@relkit/observability": "0.3.0",
|
|
61
|
+
"@relkit/provider": "0.3.0"
|
|
62
|
+
}
|
|
63
|
+
}
|