@gobing-ai/ts-infra 0.3.5 → 0.3.7

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.
Files changed (63) hide show
  1. package/README.md +95 -60
  2. package/dist/application/index.d.ts +16 -18
  3. package/dist/application/index.d.ts.map +1 -1
  4. package/dist/application/index.js +59 -96
  5. package/dist/application/plugins/builtins.d.ts +64 -0
  6. package/dist/application/plugins/builtins.d.ts.map +1 -0
  7. package/dist/application/plugins/builtins.js +146 -0
  8. package/dist/application/plugins/host.d.ts +61 -0
  9. package/dist/application/plugins/host.d.ts.map +1 -0
  10. package/dist/application/plugins/host.js +131 -0
  11. package/dist/application/plugins/index.d.ts +3 -0
  12. package/dist/application/plugins/index.d.ts.map +1 -0
  13. package/dist/application/plugins/index.js +2 -0
  14. package/dist/application/plugins/types.d.ts +69 -0
  15. package/dist/application/plugins/types.d.ts.map +1 -0
  16. package/dist/application/plugins/types.js +10 -0
  17. package/dist/application/types.d.ts +7 -0
  18. package/dist/application/types.d.ts.map +1 -1
  19. package/dist/application-node.d.ts.map +1 -1
  20. package/dist/application-node.js +40 -57
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -1
  24. package/dist/scheduler/cloudflare.d.ts.map +1 -1
  25. package/dist/scheduler/cloudflare.js +9 -2
  26. package/dist/scheduler/factory.d.ts +4 -8
  27. package/dist/scheduler/factory.d.ts.map +1 -1
  28. package/dist/scheduler/factory.js +12 -22
  29. package/dist/scheduler/index.d.ts +1 -1
  30. package/dist/scheduler/index.d.ts.map +1 -1
  31. package/dist/scheduler/index.js +1 -1
  32. package/dist/scheduler/wrap-handler.d.ts +8 -4
  33. package/dist/scheduler/wrap-handler.d.ts.map +1 -1
  34. package/dist/scheduler/wrap-handler.js +8 -4
  35. package/dist/telemetry/index.d.ts +1 -2
  36. package/dist/telemetry/index.d.ts.map +1 -1
  37. package/dist/telemetry/index.js +1 -2
  38. package/dist/telemetry/metrics.d.ts +9 -1
  39. package/dist/telemetry/metrics.d.ts.map +1 -1
  40. package/dist/telemetry/metrics.js +22 -1
  41. package/dist/telemetry/sdk.d.ts +33 -1
  42. package/dist/telemetry/sdk.d.ts.map +1 -1
  43. package/dist/telemetry/sdk.js +14 -1
  44. package/package.json +5 -5
  45. package/src/application/index.ts +72 -102
  46. package/src/application/plugins/builtins.ts +178 -0
  47. package/src/application/plugins/host.ts +143 -0
  48. package/src/application/plugins/index.ts +3 -0
  49. package/src/application/plugins/types.ts +86 -0
  50. package/src/application/types.ts +7 -0
  51. package/src/application-node.ts +43 -61
  52. package/src/index.ts +0 -2
  53. package/src/scheduler/cloudflare.ts +16 -5
  54. package/src/scheduler/factory.ts +15 -26
  55. package/src/scheduler/index.ts +1 -1
  56. package/src/scheduler/wrap-handler.ts +8 -4
  57. package/src/telemetry/index.ts +9 -2
  58. package/src/telemetry/metrics.ts +22 -1
  59. package/src/telemetry/sdk.ts +51 -2
  60. package/dist/telemetry/config.d.ts +0 -41
  61. package/dist/telemetry/config.d.ts.map +0 -1
  62. package/dist/telemetry/config.js +0 -21
  63. package/src/telemetry/config.ts +0 -59
@@ -13,6 +13,8 @@ import type { BusLifecycleEvents, EventMap } from '../event-bus/types';
13
13
  import type { InfraEvents } from '../events';
14
14
  import type { Logger, LogLevel } from '../logger';
15
15
  import type { SchedulerAdapter } from '../scheduler/types';
16
+ import type { PluginHost } from './plugins/host';
17
+ import type { Plugin } from './plugins/types';
16
18
 
17
19
  // ── Feature flag option groups ────────────────────────────────────────────
18
20
 
@@ -93,6 +95,8 @@ export interface ApplicationServices<TEvents extends EventMap = InfraEvents> {
93
95
  lifecycleBus?: EventBus<BusLifecycleEvents>;
94
96
  db?: DbAdapterLike;
95
97
  scheduler?: SchedulerAdapter;
98
+ /** Pre-built plugin host (when injecting instead of constructing). */
99
+ pluginHost?: PluginHost;
96
100
  }
97
101
 
98
102
  /**
@@ -130,6 +134,7 @@ export interface ApplicationRuntime<TAppConfig = unknown, TEvents extends EventM
130
134
  readonly db?: DbAdapterLike;
131
135
  /** Scheduler adapter (when enabled). */
132
136
  readonly scheduler?: SchedulerAdapter;
137
+ readonly pluginHost: PluginHost;
133
138
  /** Graceful shutdown. Idempotent — safe to call multiple times. */
134
139
  stop(reason?: ApplicationStopReason): Promise<void>;
135
140
  }
@@ -151,6 +156,8 @@ export interface ApplicationBootstrapOptions<TAppConfig = unknown, TEvents exten
151
156
  readonly appConfig?: TAppConfig;
152
157
  /** Pre-built services to inject instead of creating defaults. */
153
158
  readonly services?: Partial<ApplicationServices<TEvents>>;
159
+ /** Plugins to register and lifecycle-manage via PluginHost. */
160
+ readonly plugins?: Plugin[];
154
161
  /** User callback: application logic. Called after all services are ready. */
155
162
  readonly start: (app: ApplicationRuntime<TAppConfig, TEvents>) => Promise<void> | void;
156
163
  /** User callback: cleanup before services shut down. */
@@ -22,6 +22,8 @@ import { createDbAdapter, type DbAdapter } from '@gobing-ai/ts-db';
22
22
  import { interpolateTree, parseYamlObject } from '@gobing-ai/ts-runtime';
23
23
 
24
24
  import { runApplication } from './application/index';
25
+ import { dbPlugin } from './application/plugins/builtins';
26
+ import type { Plugin } from './application/plugins/types';
25
27
  import type {
26
28
  ApplicationBootstrapOptions,
27
29
  ApplicationConfigLoader,
@@ -213,8 +215,6 @@ export interface NodeApplicationOptions<TAppConfig = unknown, TEvents extends Ev
213
215
  export async function runNodeApplication<TAppConfig = unknown, TEvents extends EventMap = InfraEvents>(
214
216
  options: NodeApplicationOptions<TAppConfig, TEvents>,
215
217
  ): Promise<ApplicationRuntime<TAppConfig, TEvents>> {
216
- let nodeTelemetryInitialized = false;
217
-
218
218
  // ── Load config ─────────────────────────────────────────────────────
219
219
  let loadedAppConfig: TAppConfig | undefined;
220
220
  let yamlBootstrap: Record<string, unknown> = {};
@@ -231,44 +231,54 @@ export async function runNodeApplication<TAppConfig = unknown, TEvents extends E
231
231
  }
232
232
 
233
233
  // ── Resolve bootstrap config from YAML + inline options ────────────
234
- // YAML loads as Record<string, unknown>; bridge into typed options.
235
- // Inline options (options.config) take precedence over YAML sections.
236
234
  const yamlLog = yamlBootstrap.logging as Partial<LoggingOptions> | undefined;
237
235
  const yamlTel = yamlBootstrap.telemetry as Partial<TelemetryOptions> | undefined;
238
236
  const yamlSched = yamlBootstrap.scheduler as Partial<SchedulerOptions> | undefined;
239
237
  const databaseOpts = (yamlBootstrap.database ?? {}) as Record<string, unknown>;
240
238
 
241
- const loggingOpts: Partial<LoggingOptions> = {
242
- ...yamlLog,
243
- ...options.config?.logging,
244
- };
245
- const telemetryOpts: Partial<TelemetryOptions> = {
246
- ...yamlTel,
247
- ...options.config?.telemetry,
248
- };
249
- const schedulerOpts: Partial<SchedulerOptions> = {
250
- ...yamlSched,
251
- ...options.config?.scheduler,
252
- };
239
+ const loggingOpts: Partial<LoggingOptions> = { ...yamlLog, ...options.config?.logging };
240
+ const telemetryOpts: Partial<TelemetryOptions> = { ...yamlTel, ...options.config?.telemetry };
241
+ const schedulerOpts: Partial<SchedulerOptions> = { ...yamlSched, ...options.config?.scheduler };
253
242
 
254
- // File sink from logging.filePath
255
243
  const logFilePath = (yamlBootstrap.logging as Record<string, unknown> | undefined)?.filePath as string | undefined;
256
244
  const loggingConfig: Partial<LoggingOptions> =
257
245
  typeof logFilePath === 'string' ? { ...loggingOpts, fileSink: createFileSink(logFilePath) } : loggingOpts;
258
246
 
259
- // ── Node OTel telemetry ─────────────────────────────────────────────
247
+ // ── Scheduler adapter ───────────────────────────────────────────────
248
+ const schedulerConfig: SchedulerOptions = {};
249
+ const rawSched = { ...schedulerOpts } as Record<string, unknown>;
250
+ if (rawSched.enabled === true) {
251
+ schedulerConfig.enabled = true;
252
+ schedulerConfig.autoStart = schedulerOpts.autoStart;
253
+ schedulerConfig.adapter = new NodeSchedulerAdapter();
254
+ }
255
+
256
+ // ── Node-owned plugins ──────────────────────────────────────────────
257
+ const plugins: Plugin[] = [];
258
+ let dbAdapter: DbAdapterLike | undefined = options.services?.db;
260
259
  const rawTel = { ...telemetryOpts } as Record<string, unknown>;
260
+
261
+ // Node OTel telemetry as a failFast plugin
261
262
  if (rawTel.enabled !== false && rawTel.endpoint) {
262
- initNodeTelemetry({
263
- serviceName: (rawTel.serviceName as string | undefined) ?? 'ts-libs',
264
- endpoint: rawTel.endpoint as string,
265
- headers: rawTel.headers as Record<string, string> | undefined,
263
+ plugins.push({
264
+ name: 'builtin:node-telemetry',
265
+ version: '0.0.0',
266
+ failFast: true,
267
+ onLoad: async () => {},
268
+ onStart: async () => {
269
+ initNodeTelemetry({
270
+ serviceName: (rawTel.serviceName as string | undefined) ?? 'ts-libs',
271
+ endpoint: rawTel.endpoint as string,
272
+ headers: rawTel.headers as Record<string, string> | undefined,
273
+ });
274
+ },
275
+ onStop: async () => {
276
+ await shutdownNodeTelemetry();
277
+ },
266
278
  });
267
- nodeTelemetryInitialized = true;
268
279
  }
269
280
 
270
- // ── DB adapter ──────────────────────────────────────────────────────
271
- let dbAdapter: DbAdapterLike | undefined = options.services?.db;
281
+ // DB adapter (owned — registered as a plugin with fail-soft close)
272
282
  if (!dbAdapter && databaseOpts.enabled === true) {
273
283
  const driver = databaseOpts.driver as string | undefined;
274
284
  if (driver === 'bun-sqlite') {
@@ -277,6 +287,7 @@ export async function runNodeApplication<TAppConfig = unknown, TEvents extends E
277
287
  url: databaseOpts.url as string | undefined,
278
288
  });
279
289
  dbAdapter = adapter as DbAdapter;
290
+ plugins.push(dbPlugin(dbAdapter));
280
291
  } else {
281
292
  throw new ConfigValidationError(
282
293
  `database.enabled is true but driver ${driver ? `"${driver}"` : 'is missing'} is not supported ` +
@@ -285,45 +296,16 @@ export async function runNodeApplication<TAppConfig = unknown, TEvents extends E
285
296
  }
286
297
  }
287
298
 
288
- // ── Scheduler adapter ───────────────────────────────────────────────
289
- const schedulerConfig: SchedulerOptions = {};
290
- const rawSched = { ...schedulerOpts } as Record<string, unknown>;
291
- if (rawSched.enabled === true) {
292
- schedulerConfig.enabled = true;
293
- schedulerConfig.autoStart = schedulerOpts.autoStart;
294
- // Use Node scheduler adapter by default in this subpath
295
- schedulerConfig.adapter = new NodeSchedulerAdapter();
296
- }
297
-
298
299
  // ── Delegate to portable runApplication ─────────────────────────────
299
- const app = await runApplication<TAppConfig, TEvents>({
300
- config: {
301
- ...options.config,
302
- logging: loggingConfig,
303
- telemetry: telemetryOpts,
304
- scheduler: schedulerConfig,
305
- },
300
+ // Node-specific cleanup is handled by plugins in the service ring —
301
+ // node-telemetry onStop, owned-db onStop. No manual try/catch or stop
302
+ // override needed.
303
+ return await runApplication<TAppConfig, TEvents>({
304
+ config: { ...options.config, logging: loggingConfig, telemetry: telemetryOpts, scheduler: schedulerConfig },
306
305
  appConfig: loadedAppConfig,
307
- services: {
308
- ...options.services,
309
- ...(dbAdapter ? { db: dbAdapter } : {}),
310
- },
306
+ services: { ...options.services, ...(dbAdapter ? { db: dbAdapter } : {}) },
311
307
  start: options.start,
312
308
  stop: options.stop,
309
+ plugins: plugins.length ? plugins : undefined,
313
310
  });
314
-
315
- // ── Compose a handle with Node-specific cleanup on stop ─────────────
316
- const originalStop = app.stop.bind(app);
317
- return {
318
- ...app,
319
- stop: async (reason?: ApplicationStopReason) => {
320
- await originalStop(reason);
321
-
322
- // Node-specific cleanup (after portable shutdown):
323
- // 5. Shut down Node telemetry exporter
324
- if (nodeTelemetryInitialized) {
325
- await shutdownNodeTelemetry();
326
- }
327
- },
328
- };
329
311
  }
package/src/index.ts CHANGED
@@ -52,7 +52,6 @@ export {
52
52
  ActionRegistry,
53
53
  type CreateDefaultRegistryOptions,
54
54
  createDefaultRegistry,
55
- getSchedulerAdapter,
56
55
  HealthPingAction,
57
56
  type HealthPingWriter,
58
57
  initScheduler,
@@ -63,7 +62,6 @@ export {
63
62
  type ScheduledAction,
64
63
  type SchedulerAction,
65
64
  type SchedulerAdapter,
66
- setSchedulerAdapter,
67
65
  toScheduledAction,
68
66
  wrapScheduledHandler,
69
67
  } from './scheduler/index';
@@ -2,7 +2,11 @@
2
2
  * Cloudflare Workers scheduler adapter using Cron Triggers.
3
3
  * Uses minimal local type declarations — no @cloudflare/workers-types dependency.
4
4
  */
5
- import { getSchedulerJobExecutedTotal, getSchedulerJobFailedTotal } from '../telemetry/metrics';
5
+ import {
6
+ getSchedulerJobDuration,
7
+ getSchedulerJobExecutedTotal,
8
+ getSchedulerJobFailedTotal,
9
+ } from '../telemetry/metrics';
6
10
  import type { ScheduledAction, SchedulerAdapter } from './types';
7
11
 
8
12
  interface CfScheduledEvent {
@@ -46,12 +50,19 @@ export class CloudflareSchedulerAdapter implements SchedulerAdapter {
46
50
  handleScheduledEvent(event: CfScheduledEvent, ctx: CfEventContext): void {
47
51
  const action = this.entries.get(event.cron);
48
52
  if (action) {
53
+ const startMs = performance.now();
49
54
  getSchedulerJobExecutedTotal().add(1, { cron: event.cron });
50
55
  ctx.waitUntil(
51
- action().catch((error: unknown) => {
52
- getSchedulerJobFailedTotal().add(1, { cron: event.cron });
53
- throw error;
54
- }),
56
+ action()
57
+ .catch((error: unknown) => {
58
+ getSchedulerJobFailedTotal().add(1, { cron: event.cron });
59
+ throw error;
60
+ })
61
+ .finally(() => {
62
+ // Duration parity with NodeSchedulerAdapter — record the job
63
+ // duration metric keyed by cron for both runtimes.
64
+ getSchedulerJobDuration().record(performance.now() - startMs, { cron: event.cron });
65
+ }),
55
66
  );
56
67
  }
57
68
  }
@@ -1,26 +1,13 @@
1
1
  /**
2
- * Scheduler factory — selects adapter based on runtime.
2
+ * Scheduler factory — initializes an adapter and registers cron entries.
3
+ *
4
+ * The adapter is passed in explicitly (dependency injection); there is no
5
+ * process-global adapter state. Callers that don't supply one get a
6
+ * {@link NoopSchedulerAdapter}.
3
7
  */
4
8
  import { NoopSchedulerAdapter } from './noop';
5
9
  import type { ScheduledAction, SchedulerAdapter } from './types';
6
10
 
7
- let runtimeAdapter: SchedulerAdapter | undefined;
8
-
9
- /** Set the runtime scheduler adapter. Call before {@link initScheduler}. */
10
- export function setSchedulerAdapter(adapter: SchedulerAdapter): void {
11
- runtimeAdapter = adapter;
12
- }
13
-
14
- /** Reset the scheduler adapter singleton. For testing. */
15
- export function resetSchedulerAdapter(): void {
16
- runtimeAdapter = undefined;
17
- }
18
-
19
- /** Get the currently configured scheduler adapter, or `undefined` if not set. */
20
- export function getSchedulerAdapter(): SchedulerAdapter | undefined {
21
- return runtimeAdapter;
22
- }
23
-
24
11
  /**
25
12
  * Initialize the scheduler adapter and register cron entries.
26
13
  *
@@ -28,19 +15,21 @@ export function getSchedulerAdapter(): SchedulerAdapter | undefined {
28
15
  * running, newly registered entries will NOT be started until the next
29
16
  * `start()` call.
30
17
  *
31
- * Returns the configured adapter (defaults to noop if none set).
18
+ * @param adapter - Adapter to use. Defaults to a {@link NoopSchedulerAdapter}.
19
+ * @param cronEntries - `[cron, action]` pairs to register on the adapter.
20
+ * @returns The configured adapter.
32
21
  */
33
- export function initScheduler(cronEntries?: Array<[string, ScheduledAction]>): SchedulerAdapter {
34
- // Default: create a noop adapter. Apps inject their own via setSchedulerAdapter.
35
- if (!runtimeAdapter) {
36
- runtimeAdapter = new NoopSchedulerAdapter();
37
- }
22
+ export function initScheduler(
23
+ adapter?: SchedulerAdapter,
24
+ cronEntries?: Array<[string, ScheduledAction]>,
25
+ ): SchedulerAdapter {
26
+ const resolved = adapter ?? new NoopSchedulerAdapter();
38
27
 
39
28
  if (cronEntries) {
40
29
  for (const [cron, action] of cronEntries) {
41
- runtimeAdapter.register(cron, action);
30
+ resolved.register(cron, action);
42
31
  }
43
32
  }
44
33
 
45
- return runtimeAdapter;
34
+ return resolved;
46
35
  }
@@ -10,7 +10,7 @@ export {
10
10
  type SchedulerAction,
11
11
  toScheduledAction,
12
12
  } from './action';
13
- export { getSchedulerAdapter, initScheduler, resetSchedulerAdapter, setSchedulerAdapter } from './factory';
13
+ export { initScheduler } from './factory';
14
14
  export { NoopSchedulerAdapter } from './noop';
15
15
  export type { ScheduledAction, SchedulerAdapter } from './types';
16
16
  export { wrapScheduledHandler } from './wrap-handler';
@@ -7,10 +7,14 @@ import type { ScheduledAction } from './types';
7
7
  * Wrap a scheduled action with OTel tracing, duration measurement, and
8
8
  * `scheduler.job.executed` event emission.
9
9
  *
10
- * Composes *on top of* the adapter's inline metrics (executed/failed/duration
11
- * counters live in the Node/Cloudflare adapters) — this wrapper adds the named
12
- * tracing span and the lifecycle event, neither of which the adapters provide.
13
- * Opt-in: wrap an action before registering it when you want that visibility.
10
+ * Observability is split by design across two axes, not duplicated:
11
+ * - The adapters (`NodeSchedulerAdapter`, `CloudflareSchedulerAdapter`) record
12
+ * executed/failed/duration **metrics keyed by `cron`** for aggregate dashboards.
13
+ * - This opt-in wrapper adds a named **tracing span + lifecycle event keyed by
14
+ * the human `name`**, for per-job diagnosis. Its timer measures the inner action
15
+ * scope; the adapter's measures the full tick — nested, not double-counted.
16
+ *
17
+ * Wrap an action before registering it when you want the named span/event.
14
18
  *
15
19
  * @param name - Job name, surfaced as `scheduler.job_name` on the span/event.
16
20
  * @param action - The action to wrap (new no-arg `ScheduledAction` signature).
@@ -1,4 +1,3 @@
1
- export { getTelemetryConfig, type TelemetryConfig, type TelemetryConfigPartial } from './config';
2
1
  export { extractSqlOperation, sanitizeSql } from './db-sanitize';
3
2
  export {
4
3
  type Counter,
@@ -18,6 +17,14 @@ export {
18
17
  initMetrics,
19
18
  shutdownMetrics,
20
19
  } from './metrics';
21
- export { getTracer, initTelemetry, isTelemetryEnabled, shutdownTelemetry } from './sdk';
20
+ export {
21
+ getTelemetryConfig,
22
+ getTracer,
23
+ initTelemetry,
24
+ isTelemetryEnabled,
25
+ shutdownTelemetry,
26
+ type TelemetryConfig,
27
+ type TelemetryConfigPartial,
28
+ } from './sdk';
22
29
  export type { Span, SpanOptions, Tracer } from './tracing';
23
30
  export { addSpanAttributes, addSpanEvent, getActiveSpan, traceAsync, traceSync, withSpan } from './tracing';
@@ -109,9 +109,30 @@ export function getSchedulerJobFailedTotal(): Counter {
109
109
 
110
110
  // ── Lifecycle ───────────────────────────────────────────────────────
111
111
 
112
- /** Mark the metrics subsystem as initialized. Idempotent. */
112
+ /**
113
+ * Pre-warm every instrument against the currently-registered meter and mark the
114
+ * subsystem initialized. Idempotent.
115
+ *
116
+ * Instruments are otherwise created lazily on first getter call (so metrics keep
117
+ * working even if this is never called — see the module contract). Calling this
118
+ * during bootstrap eagerly materializes them, so `isMetricsInitialized()` reflects
119
+ * real wiring rather than being a flag that gates nothing.
120
+ */
113
121
  export function initMetrics(): void {
114
122
  if (metricsInitialized) return;
123
+ // Eagerly materialize all instruments against the live meter.
124
+ getHttpClientRequestTotal();
125
+ getHttpClientRequestDuration();
126
+ getHttpClientRequestErrors();
127
+ getEventbusEmitsTotal();
128
+ getEventbusErrorsTotal();
129
+ getQueueJobEnqueuedTotal();
130
+ getQueueJobCompletedTotal();
131
+ getQueueJobFailedTotal();
132
+ getQueueJobProcessingDuration();
133
+ getSchedulerJobExecutedTotal();
134
+ getSchedulerJobDuration();
135
+ getSchedulerJobFailedTotal();
115
136
  metricsInitialized = true;
116
137
  }
117
138
 
@@ -8,8 +8,57 @@
8
8
  * keeps the main barrel free of any SDK runtime dependency.
9
9
  */
10
10
  import { type Tracer, trace } from '@opentelemetry/api';
11
- import type { TelemetryConfig } from './config';
12
- import { getTelemetryConfig } from './config';
11
+
12
+ // ── Configuration ───────────────────────────────────────────────────────────
13
+
14
+ /**
15
+ * Full telemetry configuration: master enable switch, service name,
16
+ * environment, and debug-level DB statement capture.
17
+ */
18
+ export interface TelemetryConfig {
19
+ /** Master switch — when false, all tracing degrades to no-ops. */
20
+ enabled: boolean;
21
+ /** Logical service name emitted on every span. */
22
+ serviceName: string;
23
+ /** Deployment environment (development, staging, production). */
24
+ environment: string;
25
+ /**
26
+ * Debug-only DB statement capture.
27
+ *
28
+ * When true, DB spans may include sanitized SQL text in a `db.statement`
29
+ * attribute. SQL text is redacted — parameter values, literals, and
30
+ * identifiers are stripped before capture.
31
+ *
32
+ * Default: `false`. Controlled by `OTEL_DB_STATEMENT_DEBUG` env var.
33
+ */
34
+ dbStatementDebug: boolean;
35
+ }
36
+
37
+ /** Partial telemetry config from the centralized config system. */
38
+ export interface TelemetryConfigPartial {
39
+ enabled?: boolean | undefined;
40
+ serviceName?: string | undefined;
41
+ environment?: string | undefined;
42
+ dbStatementDebug?: boolean | undefined;
43
+ /** Deployment environment fallback (from app.env). */
44
+ appEnv?: string | undefined;
45
+ }
46
+
47
+ const CONFIG_DEFAULTS = {
48
+ enabled: true as const,
49
+ serviceName: 'ts-libs' as const,
50
+ environment: 'development' as const,
51
+ };
52
+
53
+ /** Resolve the full telemetry config by merging a partial override with defaults. */
54
+ export function getTelemetryConfig(configPartial: TelemetryConfigPartial = {}): TelemetryConfig {
55
+ return {
56
+ enabled: configPartial.enabled ?? CONFIG_DEFAULTS.enabled,
57
+ serviceName: configPartial.serviceName ?? CONFIG_DEFAULTS.serviceName,
58
+ environment: configPartial.environment ?? configPartial.appEnv ?? CONFIG_DEFAULTS.environment,
59
+ dbStatementDebug: configPartial.dbStatementDebug ?? false,
60
+ };
61
+ }
13
62
 
14
63
  const TRACER_NAME = '@gobing-ai/ts-infra';
15
64
  const TRACER_VERSION = '0.1.0';
@@ -1,41 +0,0 @@
1
- /**
2
- * Telemetry configuration interface.
3
- */
4
- /**
5
- * Full telemetry configuration: master enable switch, service name,
6
- * environment, and debug-level DB statement capture.
7
- */
8
- export interface TelemetryConfig {
9
- /** Master switch — when false, all tracing degrades to no-ops. */
10
- enabled: boolean;
11
- /** Logical service name emitted on every span. */
12
- serviceName: string;
13
- /** Deployment environment (development, staging, production). */
14
- environment: string;
15
- /**
16
- * Debug-only DB statement capture.
17
- *
18
- * When true, DB spans may include sanitized SQL text in a `db.statement`
19
- * attribute. SQL text is redacted — parameter values, literals, and
20
- * identifiers are stripped before capture.
21
- *
22
- * Default: `false`. Controlled by `OTEL_DB_STATEMENT_DEBUG` env var.
23
- */
24
- dbStatementDebug: boolean;
25
- }
26
- /**
27
- * Partial telemetry config from the centralized config system.
28
- */
29
- export interface TelemetryConfigPartial {
30
- enabled?: boolean | undefined;
31
- serviceName?: string | undefined;
32
- environment?: string | undefined;
33
- dbStatementDebug?: boolean | undefined;
34
- /** Deployment environment fallback (from app.env). */
35
- appEnv?: string | undefined;
36
- }
37
- /**
38
- * Resolve the full telemetry config by merging a partial override with defaults.
39
- */
40
- export declare function getTelemetryConfig(configPartial?: TelemetryConfigPartial): TelemetryConfig;
41
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/telemetry/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC5B,kEAAkE;IAClE,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;;;OAQG;IACH,gBAAgB,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAQD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,GAAE,sBAA2B,GAAG,eAAe,CAU9F"}
@@ -1,21 +0,0 @@
1
- /**
2
- * Telemetry configuration interface.
3
- */
4
- const DEFAULTS = {
5
- enabled: true,
6
- serviceName: 'ts-libs',
7
- environment: 'development',
8
- };
9
- /**
10
- * Resolve the full telemetry config by merging a partial override with defaults.
11
- */
12
- export function getTelemetryConfig(configPartial = {}) {
13
- const enabled = configPartial.enabled ?? DEFAULTS.enabled;
14
- const serviceName = configPartial.serviceName ?? DEFAULTS.serviceName;
15
- return {
16
- enabled,
17
- serviceName,
18
- environment: configPartial.environment ?? configPartial.appEnv ?? DEFAULTS.environment,
19
- dbStatementDebug: configPartial.dbStatementDebug ?? false,
20
- };
21
- }
@@ -1,59 +0,0 @@
1
- /**
2
- * Telemetry configuration interface.
3
- */
4
-
5
- /**
6
- * Full telemetry configuration: master enable switch, service name,
7
- * environment, and debug-level DB statement capture.
8
- */
9
- export interface TelemetryConfig {
10
- /** Master switch — when false, all tracing degrades to no-ops. */
11
- enabled: boolean;
12
- /** Logical service name emitted on every span. */
13
- serviceName: string;
14
- /** Deployment environment (development, staging, production). */
15
- environment: string;
16
- /**
17
- * Debug-only DB statement capture.
18
- *
19
- * When true, DB spans may include sanitized SQL text in a `db.statement`
20
- * attribute. SQL text is redacted — parameter values, literals, and
21
- * identifiers are stripped before capture.
22
- *
23
- * Default: `false`. Controlled by `OTEL_DB_STATEMENT_DEBUG` env var.
24
- */
25
- dbStatementDebug: boolean;
26
- }
27
-
28
- /**
29
- * Partial telemetry config from the centralized config system.
30
- */
31
- export interface TelemetryConfigPartial {
32
- enabled?: boolean | undefined;
33
- serviceName?: string | undefined;
34
- environment?: string | undefined;
35
- dbStatementDebug?: boolean | undefined;
36
- /** Deployment environment fallback (from app.env). */
37
- appEnv?: string | undefined;
38
- }
39
-
40
- const DEFAULTS = {
41
- enabled: true as const,
42
- serviceName: 'ts-libs' as const,
43
- environment: 'development' as const,
44
- };
45
-
46
- /**
47
- * Resolve the full telemetry config by merging a partial override with defaults.
48
- */
49
- export function getTelemetryConfig(configPartial: TelemetryConfigPartial = {}): TelemetryConfig {
50
- const enabled = configPartial.enabled ?? DEFAULTS.enabled;
51
- const serviceName = configPartial.serviceName ?? DEFAULTS.serviceName;
52
-
53
- return {
54
- enabled,
55
- serviceName,
56
- environment: configPartial.environment ?? configPartial.appEnv ?? DEFAULTS.environment,
57
- dbStatementDebug: configPartial.dbStatementDebug ?? false,
58
- };
59
- }