@gobing-ai/ts-infra 0.1.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/README.md +389 -0
- package/dist/api-client.d.ts +31 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +112 -0
- package/dist/event-bus/event-bus.d.ts +33 -0
- package/dist/event-bus/event-bus.d.ts.map +1 -0
- package/dist/event-bus/event-bus.js +211 -0
- package/dist/event-bus/index.d.ts +3 -0
- package/dist/event-bus/index.d.ts.map +1 -0
- package/dist/event-bus/index.js +1 -0
- package/dist/event-bus/types.d.ts +35 -0
- package/dist/event-bus/types.d.ts.map +1 -0
- package/dist/event-bus/types.js +3 -0
- package/dist/events/app-events.d.ts +7 -0
- package/dist/events/app-events.d.ts.map +1 -0
- package/dist/events/app-events.js +4 -0
- package/dist/events/create-system-bus.d.ts +6 -0
- package/dist/events/create-system-bus.d.ts.map +1 -0
- package/dist/events/create-system-bus.js +7 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +9 -0
- package/dist/job-queue/index.d.ts +2 -0
- package/dist/job-queue/index.d.ts.map +1 -0
- package/dist/job-queue/index.js +0 -0
- package/dist/job-queue/types.d.ts +57 -0
- package/dist/job-queue/types.d.ts.map +1 -0
- package/dist/job-queue/types.js +8 -0
- package/dist/logger.d.ts +28 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +100 -0
- package/dist/scheduler/action.d.ts +5 -0
- package/dist/scheduler/action.d.ts.map +1 -0
- package/dist/scheduler/action.js +0 -0
- package/dist/scheduler/cloudflare.d.ts +27 -0
- package/dist/scheduler/cloudflare.d.ts.map +1 -0
- package/dist/scheduler/cloudflare.js +24 -0
- package/dist/scheduler/factory.d.ts +19 -0
- package/dist/scheduler/factory.d.ts.map +1 -0
- package/dist/scheduler/factory.js +45 -0
- package/dist/scheduler/index.d.ts +6 -0
- package/dist/scheduler/index.d.ts.map +1 -0
- package/dist/scheduler/index.js +4 -0
- package/dist/scheduler/node.d.ts +16 -0
- package/dist/scheduler/node.d.ts.map +1 -0
- package/dist/scheduler/node.js +63 -0
- package/dist/scheduler/noop.d.ts +11 -0
- package/dist/scheduler/noop.d.ts.map +1 -0
- package/dist/scheduler/noop.js +12 -0
- package/dist/scheduler/types.d.ts +12 -0
- package/dist/scheduler/types.d.ts.map +1 -0
- package/dist/scheduler/types.js +3 -0
- package/dist/telemetry/config.d.ts +42 -0
- package/dist/telemetry/config.d.ts.map +1 -0
- package/dist/telemetry/config.js +24 -0
- package/dist/telemetry/db-sanitize.d.ts +15 -0
- package/dist/telemetry/db-sanitize.d.ts.map +1 -0
- package/dist/telemetry/db-sanitize.js +72 -0
- package/dist/telemetry/index.d.ts +7 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +5 -0
- package/dist/telemetry/metrics.d.ts +32 -0
- package/dist/telemetry/metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics.js +109 -0
- package/dist/telemetry/sdk.d.ts +13 -0
- package/dist/telemetry/sdk.d.ts.map +1 -0
- package/dist/telemetry/sdk.js +54 -0
- package/dist/telemetry/tracing.d.ts +13 -0
- package/dist/telemetry/tracing.d.ts.map +1 -0
- package/dist/telemetry/tracing.js +54 -0
- package/package.json +50 -0
- package/src/api-client.ts +162 -0
- package/src/event-bus/event-bus.ts +236 -0
- package/src/event-bus/index.ts +9 -0
- package/src/event-bus/types.ts +40 -0
- package/src/events/app-events.ts +8 -0
- package/src/events/create-system-bus.ts +8 -0
- package/src/events/index.ts +2 -0
- package/src/index.ts +74 -0
- package/src/job-queue/index.ts +9 -0
- package/src/job-queue/types.ts +60 -0
- package/src/logger.ts +123 -0
- package/src/scheduler/action.ts +4 -0
- package/src/scheduler/cloudflare.ts +45 -0
- package/src/scheduler/factory.ts +57 -0
- package/src/scheduler/index.ts +5 -0
- package/src/scheduler/node.ts +83 -0
- package/src/scheduler/noop.ts +20 -0
- package/src/scheduler/types.ts +13 -0
- package/src/telemetry/config.ts +63 -0
- package/src/telemetry/db-sanitize.ts +79 -0
- package/src/telemetry/index.ts +29 -0
- package/src/telemetry/metrics.ts +150 -0
- package/src/telemetry/sdk.ts +65 -0
- package/src/telemetry/tracing.ts +64 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry metrics — lazy-initialized instruments.
|
|
3
|
+
* All degrade to no-ops when telemetry is disabled.
|
|
4
|
+
*/
|
|
5
|
+
import { type Counter, type Histogram, metrics } from '@opentelemetry/api';
|
|
6
|
+
import type { MeterProvider } from '@opentelemetry/sdk-metrics';
|
|
7
|
+
|
|
8
|
+
export type { Counter, Histogram } from '@opentelemetry/api';
|
|
9
|
+
|
|
10
|
+
import type { TelemetryConfig } from './config';
|
|
11
|
+
|
|
12
|
+
let meterProvider: MeterProvider | undefined;
|
|
13
|
+
let metricsInitialized = false;
|
|
14
|
+
|
|
15
|
+
export function isMetricsInitialized(): boolean {
|
|
16
|
+
return metricsInitialized;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function getMeterProvider(): MeterProvider {
|
|
20
|
+
return meterProvider ?? (metrics.getMeterProvider() as MeterProvider);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const METER_NAME = '@gobing-ai/ts-infra';
|
|
24
|
+
const METER_VERSION = '0.1.0';
|
|
25
|
+
|
|
26
|
+
function getMeter() {
|
|
27
|
+
return getMeterProvider().getMeter(METER_NAME, METER_VERSION);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ── Instrument cache ────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
const instruments: Record<string, Counter | Histogram | undefined> = {};
|
|
33
|
+
|
|
34
|
+
function getOrCreateCounter(key: string, name: string, description: string, unit = '{operation}'): Counter {
|
|
35
|
+
if (!instruments[key]) {
|
|
36
|
+
instruments[key] = getMeter().createCounter(name, { description, unit });
|
|
37
|
+
}
|
|
38
|
+
return instruments[key] as Counter;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getOrCreateHistogram(key: string, name: string, description: string, unit = 'ms'): Histogram {
|
|
42
|
+
if (!instruments[key]) {
|
|
43
|
+
instruments[key] = getMeter().createHistogram(name, { description, unit });
|
|
44
|
+
}
|
|
45
|
+
return instruments[key] as Histogram;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ── HTTP server ─────────────────────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
export function getHttpServerRequestTotal(): Counter {
|
|
51
|
+
return getOrCreateCounter('httpSrvReq', 'http.server.request.total', 'Total inbound HTTP requests', '{request}');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function getHttpServerRequestDuration(): Histogram {
|
|
55
|
+
return getOrCreateHistogram('httpSrvDur', 'http.server.request.duration', 'Inbound HTTP request duration');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function getHttpServerRequestErrors(): Counter {
|
|
59
|
+
return getOrCreateCounter('httpSrvErr', 'http.server.request.errors', 'Inbound HTTP 5xx errors', '{error}');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ── HTTP client ─────────────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
export function getHttpClientRequestTotal(): Counter {
|
|
65
|
+
return getOrCreateCounter('httpCliReq', 'http.client.request.total', 'Total outbound HTTP requests', '{request}');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function getHttpClientRequestDuration(): Histogram {
|
|
69
|
+
return getOrCreateHistogram('httpCliDur', 'http.client.request.duration', 'Outbound HTTP request duration');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function getHttpClientRequestErrors(): Counter {
|
|
73
|
+
return getOrCreateCounter('httpCliErr', 'http.client.request.errors', 'Outbound HTTP errors', '{error}');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// ── DB ──────────────────────────────────────────────────────────────
|
|
77
|
+
|
|
78
|
+
export function getDbOperationTotal(): Counter {
|
|
79
|
+
return getOrCreateCounter('dbOpTotal', 'db.client.operation.total', 'Total DB operations', '{operation}');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function getDbOperationDuration(): Histogram {
|
|
83
|
+
return getOrCreateHistogram('dbOpDur', 'db.client.operation.duration', 'DB operation duration');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function getDbOperationErrors(): Counter {
|
|
87
|
+
return getOrCreateCounter('dbOpErr', 'db.client.operation.errors', 'DB operation errors', '{error}');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ── Event bus ───────────────────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
export function getEventbusEmitsTotal(): Counter {
|
|
93
|
+
return getOrCreateCounter('ebEmit', 'eventbus.emits.total', 'Total event bus emits', '{emit}');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function getEventbusErrorsTotal(): Counter {
|
|
97
|
+
return getOrCreateCounter('ebErr', 'eventbus.errors.total', 'Event bus errors', '{error}');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ── Queue ───────────────────────────────────────────────────────────
|
|
101
|
+
|
|
102
|
+
export function getQueueJobEnqueuedTotal(): Counter {
|
|
103
|
+
return getOrCreateCounter('qEnq', 'queue.jobs.enqueued', 'Total jobs enqueued', '{job}');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function getQueueJobCompletedTotal(): Counter {
|
|
107
|
+
return getOrCreateCounter('qComp', 'queue.jobs.completed', 'Total jobs completed', '{job}');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function getQueueJobFailedTotal(): Counter {
|
|
111
|
+
return getOrCreateCounter('qFail', 'queue.jobs.failed', 'Total jobs failed', '{job}');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function getQueueJobProcessingDuration(): Histogram {
|
|
115
|
+
return getOrCreateHistogram('qProcDur', 'queue.jobs.processing_duration', 'Job processing duration');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ── Scheduler ───────────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
export function getSchedulerJobExecutedTotal(): Counter {
|
|
121
|
+
return getOrCreateCounter('schedExec', 'scheduler.jobs.executed', 'Total scheduled job executions', '{execution}');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function getSchedulerJobDuration(): Histogram {
|
|
125
|
+
return getOrCreateHistogram('schedDur', 'scheduler.jobs.duration', 'Scheduled job duration');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function getSchedulerJobFailedTotal(): Counter {
|
|
129
|
+
return getOrCreateCounter('schedFail', 'scheduler.jobs.failed', 'Failed scheduled jobs', '{failure}');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ── Lifecycle ───────────────────────────────────────────────────────
|
|
133
|
+
|
|
134
|
+
export function initMetrics(_config?: Partial<TelemetryConfig>): void {
|
|
135
|
+
if (metricsInitialized) return;
|
|
136
|
+
metricsInitialized = true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function shutdownMetrics(): Promise<void> {
|
|
140
|
+
metricsInitialized = false;
|
|
141
|
+
return Promise.resolve();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function _resetMetrics(): void {
|
|
145
|
+
for (const key of Object.keys(instruments)) {
|
|
146
|
+
instruments[key] = undefined;
|
|
147
|
+
}
|
|
148
|
+
metricsInitialized = false;
|
|
149
|
+
metrics.disable();
|
|
150
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry SDK initialisation and tracer provider management.
|
|
3
|
+
*/
|
|
4
|
+
import { type Tracer, trace } from '@opentelemetry/api';
|
|
5
|
+
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
6
|
+
import type { TelemetryConfig } from './config';
|
|
7
|
+
import { getTelemetryConfig } from './config';
|
|
8
|
+
|
|
9
|
+
let tracerProvider: NodeTracerProvider | undefined;
|
|
10
|
+
let telemetryInitialized = false;
|
|
11
|
+
let resolvedConfig: TelemetryConfig = getTelemetryConfig();
|
|
12
|
+
|
|
13
|
+
const DEFAULT_TRACER = trace.getTracer('@gobing-ai/ts-infra', '0.1.0');
|
|
14
|
+
|
|
15
|
+
export function getResolvedConfig(): TelemetryConfig {
|
|
16
|
+
return resolvedConfig;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function initTelemetry(config?: Partial<TelemetryConfig>): void {
|
|
20
|
+
if (telemetryInitialized) return;
|
|
21
|
+
|
|
22
|
+
resolvedConfig = { ...getTelemetryConfig(), ...config };
|
|
23
|
+
|
|
24
|
+
if (!resolvedConfig.enabled) {
|
|
25
|
+
telemetryInitialized = true;
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
tracerProvider = new NodeTracerProvider();
|
|
30
|
+
tracerProvider.register();
|
|
31
|
+
telemetryInitialized = true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function shutdownTelemetry(): Promise<void> {
|
|
35
|
+
if (!tracerProvider) {
|
|
36
|
+
telemetryInitialized = false;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
await tracerProvider.shutdown();
|
|
40
|
+
tracerProvider = undefined;
|
|
41
|
+
telemetryInitialized = false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getTracer(): Tracer {
|
|
45
|
+
return tracerProvider?.getTracer('@gobing-ai/ts-infra', '0.1.0') ?? DEFAULT_TRACER;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function isTelemetryEnabled(): boolean {
|
|
49
|
+
return telemetryInitialized && resolvedConfig.enabled;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function _resetTelemetry(): void {
|
|
53
|
+
if (tracerProvider) {
|
|
54
|
+
try {
|
|
55
|
+
tracerProvider.shutdown();
|
|
56
|
+
} catch {
|
|
57
|
+
/* swallow */
|
|
58
|
+
}
|
|
59
|
+
tracerProvider = undefined;
|
|
60
|
+
}
|
|
61
|
+
telemetryInitialized = false;
|
|
62
|
+
resolvedConfig = getTelemetryConfig();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { context, propagation, trace } from '@opentelemetry/api';
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-level tracing helpers for application code.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { context, type Span, type SpanOptions, type Tracer, trace } from '@opentelemetry/api';
|
|
6
|
+
import { getTracer } from './sdk';
|
|
7
|
+
|
|
8
|
+
export async function traceAsync<T>(
|
|
9
|
+
name: string,
|
|
10
|
+
fn: (span: Span) => Promise<T>,
|
|
11
|
+
options?: SpanOptions,
|
|
12
|
+
tracer?: Tracer,
|
|
13
|
+
): Promise<T> {
|
|
14
|
+
const resolvedTracer = tracer ?? getTracer();
|
|
15
|
+
return resolvedTracer.startActiveSpan(name, options ?? {}, async (span) => {
|
|
16
|
+
try {
|
|
17
|
+
return await fn(span);
|
|
18
|
+
} catch (err) {
|
|
19
|
+
span.setStatus({ code: 2, message: err instanceof Error ? err.message : String(err) });
|
|
20
|
+
throw err;
|
|
21
|
+
} finally {
|
|
22
|
+
span.end();
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function traceSync<T>(name: string, fn: (span: Span) => T, options?: SpanOptions, tracer?: Tracer): T {
|
|
28
|
+
const resolvedTracer = tracer ?? getTracer();
|
|
29
|
+
return resolvedTracer.startActiveSpan(name, options ?? {}, (span) => {
|
|
30
|
+
try {
|
|
31
|
+
return fn(span);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
span.setStatus({ code: 2, message: err instanceof Error ? err.message : String(err) });
|
|
34
|
+
throw err;
|
|
35
|
+
} finally {
|
|
36
|
+
span.end();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function addSpanAttributes(attributes: Record<string, string | number | boolean>): void {
|
|
42
|
+
const span = trace.getActiveSpan();
|
|
43
|
+
if (span?.isRecording()) {
|
|
44
|
+
span.setAttributes(attributes);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function addSpanEvent(name: string, attributes?: Record<string, string | number | boolean>): void {
|
|
49
|
+
const span = trace.getActiveSpan();
|
|
50
|
+
if (span?.isRecording()) {
|
|
51
|
+
span.addEvent(name, attributes);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function getActiveSpan(): Span | undefined {
|
|
56
|
+
return trace.getActiveSpan() ?? undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function withSpan<T>(span: Span, fn: () => T): T {
|
|
60
|
+
return context.with(trace.setSpan(context.active(), span), fn);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type { Span, SpanOptions, Tracer } from '@opentelemetry/api';
|
|
64
|
+
export { context, propagation, trace } from './sdk';
|