@agentuity/runtime 0.0.42 → 0.0.44

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 (134) hide show
  1. package/AGENTS.md +11 -9
  2. package/README.md +4 -4
  3. package/dist/_context.d.ts +12 -4
  4. package/dist/_context.d.ts.map +1 -1
  5. package/dist/_server.d.ts +7 -4
  6. package/dist/_server.d.ts.map +1 -1
  7. package/dist/_services.d.ts +13 -2
  8. package/dist/_services.d.ts.map +1 -1
  9. package/dist/_util.d.ts +1 -1
  10. package/dist/_util.d.ts.map +1 -1
  11. package/dist/_waituntil.d.ts +1 -3
  12. package/dist/_waituntil.d.ts.map +1 -1
  13. package/dist/agent.d.ts +41 -14
  14. package/dist/agent.d.ts.map +1 -1
  15. package/dist/app.d.ts +90 -8
  16. package/dist/app.d.ts.map +1 -1
  17. package/dist/eval.d.ts +79 -0
  18. package/dist/eval.d.ts.map +1 -0
  19. package/dist/index.d.ts +6 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/io/email.d.ts +77 -0
  22. package/dist/io/email.d.ts.map +1 -0
  23. package/dist/logger/console.d.ts +21 -1
  24. package/dist/logger/console.d.ts.map +1 -1
  25. package/dist/logger/index.d.ts +0 -1
  26. package/dist/logger/index.d.ts.map +1 -1
  27. package/dist/logger/user.d.ts +2 -2
  28. package/dist/logger/user.d.ts.map +1 -1
  29. package/dist/otel/config.d.ts +3 -1
  30. package/dist/otel/config.d.ts.map +1 -1
  31. package/dist/otel/console.d.ts +2 -1
  32. package/dist/otel/console.d.ts.map +1 -1
  33. package/dist/otel/exporters/index.d.ts +4 -0
  34. package/dist/otel/exporters/index.d.ts.map +1 -0
  35. package/dist/otel/exporters/jsonl-log-exporter.d.ts +36 -0
  36. package/dist/otel/exporters/jsonl-log-exporter.d.ts.map +1 -0
  37. package/dist/otel/exporters/jsonl-metric-exporter.d.ts +40 -0
  38. package/dist/otel/exporters/jsonl-metric-exporter.d.ts.map +1 -0
  39. package/dist/otel/exporters/jsonl-trace-exporter.d.ts +36 -0
  40. package/dist/otel/exporters/jsonl-trace-exporter.d.ts.map +1 -0
  41. package/dist/otel/http.d.ts.map +1 -1
  42. package/dist/otel/logger.d.ts +15 -11
  43. package/dist/otel/logger.d.ts.map +1 -1
  44. package/dist/otel/otel.d.ts +8 -2
  45. package/dist/otel/otel.d.ts.map +1 -1
  46. package/dist/router.d.ts +4 -1
  47. package/dist/router.d.ts.map +1 -1
  48. package/dist/services/evalrun/composite.d.ts +21 -0
  49. package/dist/services/evalrun/composite.d.ts.map +1 -0
  50. package/dist/services/evalrun/http.d.ts +24 -0
  51. package/dist/services/evalrun/http.d.ts.map +1 -0
  52. package/dist/services/evalrun/index.d.ts +5 -0
  53. package/dist/services/evalrun/index.d.ts.map +1 -0
  54. package/dist/services/evalrun/json.d.ts +21 -0
  55. package/dist/services/evalrun/json.d.ts.map +1 -0
  56. package/dist/services/evalrun/local.d.ts +19 -0
  57. package/dist/services/evalrun/local.d.ts.map +1 -0
  58. package/dist/services/local/_db.d.ts +4 -0
  59. package/dist/services/local/_db.d.ts.map +1 -0
  60. package/dist/services/local/_router.d.ts +3 -0
  61. package/dist/services/local/_router.d.ts.map +1 -0
  62. package/dist/services/local/_util.d.ts +18 -0
  63. package/dist/services/local/_util.d.ts.map +1 -0
  64. package/dist/services/local/index.d.ts +8 -0
  65. package/dist/services/local/index.d.ts.map +1 -0
  66. package/dist/services/local/keyvalue.d.ts +10 -0
  67. package/dist/services/local/keyvalue.d.ts.map +1 -0
  68. package/dist/services/local/objectstore.d.ts +11 -0
  69. package/dist/services/local/objectstore.d.ts.map +1 -0
  70. package/dist/services/local/stream.d.ts +10 -0
  71. package/dist/services/local/stream.d.ts.map +1 -0
  72. package/dist/services/local/vector.d.ts +13 -0
  73. package/dist/services/local/vector.d.ts.map +1 -0
  74. package/dist/services/session/composite.d.ts +21 -0
  75. package/dist/services/session/composite.d.ts.map +1 -0
  76. package/dist/services/session/http.d.ts +23 -0
  77. package/dist/services/session/http.d.ts.map +1 -0
  78. package/dist/services/session/index.d.ts +5 -0
  79. package/dist/services/session/index.d.ts.map +1 -0
  80. package/dist/services/session/json.d.ts +22 -0
  81. package/dist/services/session/json.d.ts.map +1 -0
  82. package/dist/services/session/local.d.ts +19 -0
  83. package/dist/services/session/local.d.ts.map +1 -0
  84. package/dist/session.d.ts +70 -0
  85. package/dist/session.d.ts.map +1 -0
  86. package/package.json +10 -6
  87. package/src/_config.ts +1 -1
  88. package/src/_context.ts +19 -16
  89. package/src/_server.ts +284 -42
  90. package/src/_services.ts +147 -34
  91. package/src/_util.ts +2 -3
  92. package/src/_waituntil.ts +5 -153
  93. package/src/agent.ts +667 -65
  94. package/src/app.ts +159 -13
  95. package/src/eval.ts +95 -0
  96. package/src/index.ts +6 -1
  97. package/src/io/email.ts +173 -0
  98. package/src/logger/console.ts +222 -15
  99. package/src/logger/index.ts +0 -1
  100. package/src/logger/user.ts +8 -4
  101. package/src/otel/config.ts +7 -44
  102. package/src/otel/console.ts +9 -4
  103. package/src/otel/exporters/README.md +217 -0
  104. package/src/otel/exporters/index.ts +3 -0
  105. package/src/otel/exporters/jsonl-log-exporter.ts +113 -0
  106. package/src/otel/exporters/jsonl-metric-exporter.ts +120 -0
  107. package/src/otel/exporters/jsonl-trace-exporter.ts +121 -0
  108. package/src/otel/http.ts +3 -1
  109. package/src/otel/logger.ts +106 -41
  110. package/src/otel/otel.ts +43 -22
  111. package/src/router.ts +44 -4
  112. package/src/services/evalrun/composite.ts +34 -0
  113. package/src/services/evalrun/http.ts +112 -0
  114. package/src/services/evalrun/index.ts +4 -0
  115. package/src/services/evalrun/json.ts +46 -0
  116. package/src/services/evalrun/local.ts +28 -0
  117. package/src/services/local/README.md +1576 -0
  118. package/src/services/local/_db.ts +182 -0
  119. package/src/services/local/_router.ts +86 -0
  120. package/src/services/local/_util.ts +49 -0
  121. package/src/services/local/index.ts +7 -0
  122. package/src/services/local/keyvalue.ts +118 -0
  123. package/src/services/local/objectstore.ts +152 -0
  124. package/src/services/local/stream.ts +296 -0
  125. package/src/services/local/vector.ts +264 -0
  126. package/src/services/session/composite.ts +33 -0
  127. package/src/services/session/http.ts +64 -0
  128. package/src/services/session/index.ts +4 -0
  129. package/src/services/session/json.ts +42 -0
  130. package/src/services/session/local.ts +28 -0
  131. package/src/session.ts +284 -0
  132. package/dist/_unauthenticated.d.ts +0 -26
  133. package/dist/_unauthenticated.d.ts.map +0 -1
  134. package/src/_unauthenticated.ts +0 -126
@@ -0,0 +1,113 @@
1
+ import { type ExportResult, ExportResultCode } from '@opentelemetry/core';
2
+ import type { LogRecordExporter, ReadableLogRecord } from '@opentelemetry/sdk-logs';
3
+ import { existsSync, appendFileSync, mkdirSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { randomUUID } from 'node:crypto';
6
+
7
+ /**
8
+ * JSONL implementation of the LogRecordExporter interface
9
+ * Writes logs to a timestamped JSONL file
10
+ */
11
+ export class JSONLLogExporter implements LogRecordExporter {
12
+ private currentFile: string | null = null;
13
+ private readonly basePath: string;
14
+ private readonly filePrefix: string;
15
+
16
+ /**
17
+ * Creates a new JSONL log record exporter
18
+ * @param basePath - Directory to store the JSONL files
19
+ */
20
+ constructor(basePath: string) {
21
+ this.basePath = basePath;
22
+ this.filePrefix = 'otel-log';
23
+ this.ensureDirectory();
24
+ }
25
+
26
+ private ensureDirectory(): void {
27
+ if (!existsSync(this.basePath)) {
28
+ mkdirSync(this.basePath, { recursive: true });
29
+ }
30
+ }
31
+
32
+ private getOrCreateFile(): string {
33
+ // If current file exists, use it
34
+ if (this.currentFile && existsSync(this.currentFile)) {
35
+ return this.currentFile;
36
+ }
37
+
38
+ this.currentFile = join(
39
+ this.basePath,
40
+ `${this.filePrefix}-${Date.now()}.${randomUUID()}.jsonl`
41
+ );
42
+ return this.currentFile;
43
+ }
44
+
45
+ /**
46
+ * Exports log records to a JSONL file
47
+ *
48
+ * @param logs - The log records to export
49
+ * @param resultCallback - Callback function to report the export result
50
+ */
51
+ export(logs: ReadableLogRecord[], resultCallback: (result: ExportResult) => void): void {
52
+ try {
53
+ if (logs.length === 0) {
54
+ resultCallback({ code: ExportResultCode.SUCCESS });
55
+ return;
56
+ }
57
+ const file = this.getOrCreateFile();
58
+ const lines: string[] = [];
59
+ for (const log of logs) {
60
+ const record = {
61
+ timestamp: log.hrTime,
62
+ observedTimestamp: log.hrTimeObserved,
63
+ severityNumber: log.severityNumber,
64
+ severityText: log.severityText,
65
+ body: log.body,
66
+ attributes: log.attributes,
67
+ resource: log.resource.attributes,
68
+ instrumentationScope: log.instrumentationScope,
69
+ spanContext: log.spanContext,
70
+ };
71
+
72
+ lines.push(JSON.stringify(record));
73
+ }
74
+ const payload = `${lines.join('\n')}\n`;
75
+ try {
76
+ appendFileSync(file, payload, 'utf-8');
77
+ } catch (err) {
78
+ // File may have been deleted, reset and retry once
79
+ const code = (err as NodeJS.ErrnoException).code;
80
+ if (code === 'ENOENT') {
81
+ this.currentFile = null;
82
+ const newFile = this.getOrCreateFile();
83
+ appendFileSync(newFile, payload, 'utf-8');
84
+ } else {
85
+ throw err;
86
+ }
87
+ }
88
+
89
+ resultCallback({ code: ExportResultCode.SUCCESS });
90
+ } catch (error) {
91
+ resultCallback({
92
+ code: ExportResultCode.FAILED,
93
+ error: error instanceof Error ? error : new Error(String(error)),
94
+ });
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Shuts down the exporter
100
+ *
101
+ * @returns A promise that resolves when shutdown is complete
102
+ */
103
+ async shutdown(): Promise<void> {
104
+ this.currentFile = null;
105
+ }
106
+
107
+ /**
108
+ * Forces a flush of any pending data
109
+ */
110
+ async forceFlush(): Promise<void> {
111
+ // No-op for file-based exporter as writes are synchronous
112
+ }
113
+ }
@@ -0,0 +1,120 @@
1
+ import { type ExportResult, ExportResultCode } from '@opentelemetry/core';
2
+ import {
3
+ type PushMetricExporter,
4
+ type ResourceMetrics,
5
+ AggregationTemporality,
6
+ InstrumentType,
7
+ } from '@opentelemetry/sdk-metrics';
8
+ import { existsSync, appendFileSync, mkdirSync } from 'node:fs';
9
+ import { join } from 'node:path';
10
+ import { randomUUID } from 'node:crypto';
11
+
12
+ /**
13
+ * JSONL implementation of the PushMetricExporter interface
14
+ * Writes metrics to a timestamped JSONL file
15
+ */
16
+ export class JSONLMetricExporter implements PushMetricExporter {
17
+ private currentFile: string | null = null;
18
+ private readonly basePath: string;
19
+ private readonly filePrefix: string;
20
+
21
+ /**
22
+ * Creates a new JSONL metric exporter
23
+ * @param basePath - Directory to store the JSONL files
24
+ */
25
+ constructor(basePath: string) {
26
+ this.basePath = basePath;
27
+ this.filePrefix = 'otel-metric';
28
+ this.ensureDirectory();
29
+ }
30
+
31
+ private ensureDirectory(): void {
32
+ if (!existsSync(this.basePath)) {
33
+ mkdirSync(this.basePath, { recursive: true });
34
+ }
35
+ }
36
+
37
+ private getOrCreateFile(): string {
38
+ // If current file exists, use it
39
+ if (this.currentFile && existsSync(this.currentFile)) {
40
+ return this.currentFile;
41
+ }
42
+
43
+ this.currentFile = join(
44
+ this.basePath,
45
+ `${this.filePrefix}-${Date.now()}.${randomUUID()}.jsonl`
46
+ );
47
+ return this.currentFile;
48
+ }
49
+
50
+ /**
51
+ * Exports metrics to a JSONL file
52
+ *
53
+ * @param metrics - The resource metrics to export
54
+ * @param resultCallback - Callback function to report the export result
55
+ */
56
+ export(metrics: ResourceMetrics, resultCallback: (result: ExportResult) => void): void {
57
+ try {
58
+ const file = this.getOrCreateFile();
59
+
60
+ const record = {
61
+ resource: metrics.resource.attributes,
62
+ scopeMetrics: metrics.scopeMetrics.map((sm) => ({
63
+ scope: sm.scope,
64
+ metrics: sm.metrics.map((m) => ({
65
+ descriptor: m.descriptor,
66
+ dataPointType: m.dataPointType,
67
+ dataPoints: m.dataPoints,
68
+ aggregationTemporality: m.aggregationTemporality,
69
+ })),
70
+ })),
71
+ };
72
+
73
+ const line = JSON.stringify(record) + '\n';
74
+ try {
75
+ appendFileSync(file, line, 'utf-8');
76
+ } catch (err) {
77
+ // File may have been deleted, reset and retry once
78
+ const code = (err as NodeJS.ErrnoException).code;
79
+ if (code === 'ENOENT') {
80
+ this.currentFile = null;
81
+ const newFile = this.getOrCreateFile();
82
+ appendFileSync(newFile, line, 'utf-8');
83
+ } else {
84
+ throw err;
85
+ }
86
+ }
87
+
88
+ resultCallback({ code: ExportResultCode.SUCCESS });
89
+ } catch (error) {
90
+ resultCallback({
91
+ code: ExportResultCode.FAILED,
92
+ error: error instanceof Error ? error : new Error(String(error)),
93
+ });
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Shuts down the exporter
99
+ *
100
+ * @returns A promise that resolves when shutdown is complete
101
+ */
102
+ async shutdown(): Promise<void> {
103
+ this.currentFile = null;
104
+ }
105
+
106
+ /**
107
+ * Forces a flush of any pending data
108
+ */
109
+ async forceFlush(): Promise<void> {
110
+ // No-op for file-based exporter as writes are synchronous
111
+ }
112
+
113
+ /**
114
+ * Selects the aggregation temporality for the given instrument type
115
+ */
116
+ selectAggregationTemporality?(_instrumentType: InstrumentType): AggregationTemporality {
117
+ // Default to cumulative temporality
118
+ return AggregationTemporality.CUMULATIVE;
119
+ }
120
+ }
@@ -0,0 +1,121 @@
1
+ import { type ExportResult, ExportResultCode } from '@opentelemetry/core';
2
+ import type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
3
+ import { existsSync, appendFileSync, mkdirSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { randomUUID } from 'node:crypto';
6
+
7
+ /**
8
+ * JSONL implementation of the SpanExporter interface
9
+ * Writes traces to a timestamped JSONL file
10
+ */
11
+ export class JSONLTraceExporter implements SpanExporter {
12
+ private currentFile: string | null = null;
13
+ private readonly basePath: string;
14
+ private readonly filePrefix: string;
15
+
16
+ /**
17
+ * Creates a new JSONL trace exporter
18
+ * @param basePath - Directory to store the JSONL files
19
+ */
20
+ constructor(basePath: string) {
21
+ this.basePath = basePath;
22
+ this.filePrefix = 'otel-trace';
23
+ this.ensureDirectory();
24
+ }
25
+
26
+ private ensureDirectory(): void {
27
+ if (!existsSync(this.basePath)) {
28
+ mkdirSync(this.basePath, { recursive: true });
29
+ }
30
+ }
31
+
32
+ private getOrCreateFile(): string {
33
+ // If current file exists, use it
34
+ if (this.currentFile && existsSync(this.currentFile)) {
35
+ return this.currentFile;
36
+ }
37
+
38
+ this.currentFile = join(
39
+ this.basePath,
40
+ `${this.filePrefix}-${Date.now()}.${randomUUID()}.jsonl`
41
+ );
42
+ return this.currentFile;
43
+ }
44
+
45
+ /**
46
+ * Exports spans to a JSONL file
47
+ *
48
+ * @param spans - The spans to export
49
+ * @param resultCallback - Callback function to report the export result
50
+ */
51
+ export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void {
52
+ try {
53
+ if (spans.length === 0) {
54
+ resultCallback({ code: ExportResultCode.SUCCESS });
55
+ return;
56
+ }
57
+ const file = this.getOrCreateFile();
58
+ const lines: string[] = [];
59
+ for (const span of spans) {
60
+ const record = {
61
+ traceId: span.spanContext().traceId,
62
+ spanId: span.spanContext().spanId,
63
+ traceState: span.spanContext().traceState?.serialize(),
64
+ name: span.name,
65
+ kind: span.kind,
66
+ startTime: span.startTime,
67
+ endTime: span.endTime,
68
+ attributes: span.attributes,
69
+ status: span.status,
70
+ events: span.events,
71
+ links: span.links,
72
+ resource: span.resource.attributes,
73
+ droppedAttributesCount: span.droppedAttributesCount,
74
+ droppedEventsCount: span.droppedEventsCount,
75
+ droppedLinksCount: span.droppedLinksCount,
76
+ duration: span.duration,
77
+ ended: span.ended,
78
+ };
79
+
80
+ lines.push(JSON.stringify(record));
81
+ }
82
+ const payload = `${lines.join('\n')}\n`;
83
+ try {
84
+ appendFileSync(file, payload, 'utf-8');
85
+ } catch (err) {
86
+ // File may have been deleted, reset and retry once
87
+ const code = (err as NodeJS.ErrnoException).code;
88
+ if (code === 'ENOENT') {
89
+ this.currentFile = null;
90
+ const newFile = this.getOrCreateFile();
91
+ appendFileSync(newFile, payload, 'utf-8');
92
+ } else {
93
+ throw err;
94
+ }
95
+ }
96
+
97
+ resultCallback({ code: ExportResultCode.SUCCESS });
98
+ } catch (error) {
99
+ resultCallback({
100
+ code: ExportResultCode.FAILED,
101
+ error: error instanceof Error ? error : new Error(String(error)),
102
+ });
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Shuts down the exporter
108
+ *
109
+ * @returns A promise that resolves when shutdown is complete
110
+ */
111
+ async shutdown(): Promise<void> {
112
+ this.currentFile = null;
113
+ }
114
+
115
+ /**
116
+ * Forces a flush of any pending data
117
+ */
118
+ async forceFlush(): Promise<void> {
119
+ // No-op for file-based exporter as writes are synchronous
120
+ }
121
+ }
package/src/otel/http.ts CHANGED
@@ -12,7 +12,9 @@ export function injectTraceContextToHeaders(
12
12
  let _headers: Record<string, string>;
13
13
  if (headers instanceof Headers) {
14
14
  _headers = {};
15
- headers.forEach((v, k) => (_headers[k] = v));
15
+ headers.forEach((v, k) => {
16
+ _headers[k] = v;
17
+ });
16
18
  } else {
17
19
  _headers = { ...headers };
18
20
  }
@@ -1,5 +1,5 @@
1
1
  import { format } from 'node:util';
2
- import { safeStringify } from '@agentuity/core';
2
+ import { safeStringify, type LogLevel } from '@agentuity/core';
3
3
  import * as LogsAPI from '@opentelemetry/api-logs';
4
4
  import type { Logger } from '../logger';
5
5
  import ConsoleLogger from '../logger/console';
@@ -11,22 +11,21 @@ import { getAgentContext } from '../_context';
11
11
  export const __originalConsole = Object.create(console); // save the original console before we patch it
12
12
 
13
13
  export class OtelLogger implements Logger {
14
- private readonly delegates: LogsAPI.Logger[];
14
+ private readonly delegate: LogsAPI.Logger;
15
15
  private readonly context: Record<string, unknown> | undefined;
16
16
  private readonly logger: ConsoleLogger | undefined;
17
+ private readonly logLevel: LogLevel;
17
18
 
18
19
  constructor(
19
20
  useConsole: boolean,
20
- delegates: LogsAPI.Logger | LogsAPI.Logger[],
21
- context?: Record<string, unknown> | undefined
21
+ delegate: LogsAPI.Logger,
22
+ context?: Record<string, unknown> | undefined,
23
+ logLevel?: LogLevel
22
24
  ) {
23
- this.delegates = Array.isArray(delegates) ? delegates : [delegates];
25
+ this.delegate = delegate;
24
26
  this.context = context;
25
- this.logger = useConsole ? new ConsoleLogger(context, false) : undefined;
26
- }
27
-
28
- addDelegate(delegate: LogsAPI.Logger) {
29
- this.delegates.push(delegate);
27
+ this.logLevel = logLevel ?? 'info';
28
+ this.logger = useConsole ? new ConsoleLogger(context, false, this.logLevel) : undefined;
30
29
  }
31
30
 
32
31
  private formatMessage(message: unknown) {
@@ -62,25 +61,65 @@ export class OtelLogger implements Logger {
62
61
  return this.context;
63
62
  }
64
63
 
65
- private emitToAll(severityNumber: LogsAPI.SeverityNumber, severityText: string, body: string) {
64
+ private emit(severityNumber: LogsAPI.SeverityNumber, severityText: string, body: string) {
66
65
  const attributes = this.getAttributes();
67
66
 
68
- this.delegates.forEach((delegate) => {
69
- try {
70
- delegate.emit({
71
- severityNumber,
72
- severityText,
73
- body,
74
- attributes: attributes as LogsAPI.LogRecord['attributes'],
75
- });
76
- } catch (error) {
77
- // Log error to console if available, but don't fail the entire operation
78
- this.logger?.error('Failed to emit log to OTLP instance:', error);
79
- }
80
- });
67
+ try {
68
+ this.delegate.emit({
69
+ severityNumber,
70
+ severityText,
71
+ body,
72
+ attributes: attributes as LogsAPI.LogRecord['attributes'],
73
+ });
74
+ } catch (error) {
75
+ // Log error to console if available, but don't fail the entire operation
76
+ this.logger?.error('Failed to emit log to OTLP instance:', error);
77
+ }
81
78
  }
82
79
 
83
- debug(message: string, ...args: unknown[]) {
80
+ private shouldLog(level: LogsAPI.SeverityNumber): boolean {
81
+ switch (this.logLevel) {
82
+ case 'trace':
83
+ return true;
84
+ case 'debug':
85
+ return (
86
+ level === LogsAPI.SeverityNumber.DEBUG ||
87
+ level == LogsAPI.SeverityNumber.INFO ||
88
+ level == LogsAPI.SeverityNumber.WARN ||
89
+ level == LogsAPI.SeverityNumber.ERROR
90
+ );
91
+ case 'info':
92
+ return (
93
+ level == LogsAPI.SeverityNumber.INFO ||
94
+ level == LogsAPI.SeverityNumber.WARN ||
95
+ level == LogsAPI.SeverityNumber.ERROR
96
+ );
97
+ case 'warn':
98
+ return level == LogsAPI.SeverityNumber.WARN || level == LogsAPI.SeverityNumber.ERROR;
99
+ case 'error':
100
+ return level == LogsAPI.SeverityNumber.ERROR;
101
+ }
102
+ return false;
103
+ }
104
+
105
+ trace(message: unknown, ...args: unknown[]) {
106
+ if (!this.shouldLog(LogsAPI.SeverityNumber.TRACE)) {
107
+ return;
108
+ }
109
+ this.logger?.trace(message, ...args);
110
+ let body: string;
111
+ try {
112
+ body = format(this.formatMessage(message), ...args);
113
+ } catch {
114
+ // Fallback if format causes recursion
115
+ body = `${this.formatMessage(message)} ${args.map((arg) => String(arg)).join(' ')}`;
116
+ }
117
+ this.emit(LogsAPI.SeverityNumber.TRACE, 'TRACE', body);
118
+ }
119
+ debug(message: unknown, ...args: unknown[]) {
120
+ if (!this.shouldLog(LogsAPI.SeverityNumber.DEBUG)) {
121
+ return;
122
+ }
84
123
  this.logger?.debug(message, ...args);
85
124
  let body: string;
86
125
  try {
@@ -89,9 +128,12 @@ export class OtelLogger implements Logger {
89
128
  // Fallback if format causes recursion
90
129
  body = `${this.formatMessage(message)} ${args.map((arg) => String(arg)).join(' ')}`;
91
130
  }
92
- this.emitToAll(LogsAPI.SeverityNumber.DEBUG, 'DEBUG', body);
131
+ this.emit(LogsAPI.SeverityNumber.DEBUG, 'DEBUG', body);
93
132
  }
94
- info(message: string, ...args: unknown[]) {
133
+ info(message: unknown, ...args: unknown[]) {
134
+ if (!this.shouldLog(LogsAPI.SeverityNumber.INFO)) {
135
+ return;
136
+ }
95
137
  this.logger?.info(message, ...args);
96
138
  let body: string;
97
139
  try {
@@ -100,9 +142,12 @@ export class OtelLogger implements Logger {
100
142
  // Fallback if format causes recursion
101
143
  body = `${this.formatMessage(message)} ${args.map((arg) => String(arg)).join(' ')}`;
102
144
  }
103
- this.emitToAll(LogsAPI.SeverityNumber.INFO, 'INFO', body);
145
+ this.emit(LogsAPI.SeverityNumber.INFO, 'INFO', body);
104
146
  }
105
- warn(message: string, ...args: unknown[]) {
147
+ warn(message: unknown, ...args: unknown[]) {
148
+ if (!this.shouldLog(LogsAPI.SeverityNumber.WARN)) {
149
+ return;
150
+ }
106
151
  this.logger?.warn(message, ...args);
107
152
  let body: string;
108
153
  try {
@@ -111,9 +156,12 @@ export class OtelLogger implements Logger {
111
156
  // Fallback if format causes recursion
112
157
  body = `${this.formatMessage(message)} ${args.map((arg) => String(arg)).join(' ')}`;
113
158
  }
114
- this.emitToAll(LogsAPI.SeverityNumber.WARN, 'WARN', body);
159
+ this.emit(LogsAPI.SeverityNumber.WARN, 'WARN', body);
115
160
  }
116
- error(message: string, ...args: unknown[]) {
161
+ error(message: unknown, ...args: unknown[]) {
162
+ if (!this.shouldLog(LogsAPI.SeverityNumber.ERROR)) {
163
+ return;
164
+ }
117
165
  this.logger?.error(message, ...args);
118
166
  let body: string;
119
167
  try {
@@ -122,13 +170,22 @@ export class OtelLogger implements Logger {
122
170
  // Fallback if format causes recursion
123
171
  body = `${this.formatMessage(message)} ${args.map((arg) => String(arg)).join(' ')}`;
124
172
  }
125
- this.emitToAll(LogsAPI.SeverityNumber.ERROR, 'ERROR', body);
173
+ this.emit(LogsAPI.SeverityNumber.ERROR, 'ERROR', body);
174
+ }
175
+ fatal(message: unknown, ...args: unknown[]): never {
176
+ this.error(message, ...args);
177
+ process.exit(1);
126
178
  }
127
- child(opts: Record<string, unknown>) {
128
- return new OtelLogger(!!this.logger, this.delegates, {
129
- ...(this.context ?? {}),
130
- ...opts,
131
- });
179
+ child(opts: Record<string, unknown>): Logger {
180
+ return new OtelLogger(
181
+ !!this.logger,
182
+ this.delegate,
183
+ {
184
+ ...(this.context ?? {}),
185
+ ...opts,
186
+ },
187
+ this.logLevel
188
+ );
132
189
  }
133
190
  }
134
191
 
@@ -139,11 +196,15 @@ export class OtelLogger implements Logger {
139
196
  * @param context - Additional context to include with log records
140
197
  * @returns A logger instance
141
198
  */
142
- export function createLogger(useConsole: boolean, context?: Record<string, unknown>): Logger {
199
+ export function createLogger(
200
+ useConsole: boolean,
201
+ context?: Record<string, unknown>,
202
+ logLevel?: LogLevel
203
+ ): Logger {
143
204
  const delegate = LogsAPI.logs.getLogger('default', undefined, {
144
205
  scopeAttributes: context as LogsAPI.LoggerOptions['scopeAttributes'],
145
206
  });
146
- return new OtelLogger(useConsole, [delegate], context);
207
+ return new OtelLogger(useConsole, delegate, context, logLevel);
147
208
  }
148
209
 
149
210
  /**
@@ -151,12 +212,16 @@ export function createLogger(useConsole: boolean, context?: Record<string, unkno
151
212
  *
152
213
  * @param attributes - Attributes to include with all console log records
153
214
  */
154
- export function patchConsole(enabled: boolean, attributes: Record<string, unknown>) {
215
+ export function patchConsole(
216
+ enabled: boolean,
217
+ attributes: Record<string, unknown>,
218
+ logLevel: LogLevel
219
+ ) {
155
220
  if (!enabled) {
156
221
  return;
157
222
  }
158
223
  const _patch = { ...__originalConsole };
159
- const delegate = createLogger(true, attributes);
224
+ const delegate = createLogger(true, attributes, logLevel);
160
225
 
161
226
  // Patch individual console methods instead of reassigning the whole object
162
227
  _patch.log = (...args: unknown[]) => {