@agentuity/runtime 0.0.43 → 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 (130) 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 +7 -1
  24. package/dist/logger/console.d.ts.map +1 -1
  25. package/dist/logger/user.d.ts.map +1 -1
  26. package/dist/otel/config.d.ts +3 -1
  27. package/dist/otel/config.d.ts.map +1 -1
  28. package/dist/otel/console.d.ts +2 -1
  29. package/dist/otel/console.d.ts.map +1 -1
  30. package/dist/otel/exporters/index.d.ts +4 -0
  31. package/dist/otel/exporters/index.d.ts.map +1 -0
  32. package/dist/otel/exporters/jsonl-log-exporter.d.ts +36 -0
  33. package/dist/otel/exporters/jsonl-log-exporter.d.ts.map +1 -0
  34. package/dist/otel/exporters/jsonl-metric-exporter.d.ts +40 -0
  35. package/dist/otel/exporters/jsonl-metric-exporter.d.ts.map +1 -0
  36. package/dist/otel/exporters/jsonl-trace-exporter.d.ts +36 -0
  37. package/dist/otel/exporters/jsonl-trace-exporter.d.ts.map +1 -0
  38. package/dist/otel/http.d.ts.map +1 -1
  39. package/dist/otel/logger.d.ts +8 -6
  40. package/dist/otel/logger.d.ts.map +1 -1
  41. package/dist/otel/otel.d.ts +8 -2
  42. package/dist/otel/otel.d.ts.map +1 -1
  43. package/dist/router.d.ts +4 -1
  44. package/dist/router.d.ts.map +1 -1
  45. package/dist/services/evalrun/composite.d.ts +21 -0
  46. package/dist/services/evalrun/composite.d.ts.map +1 -0
  47. package/dist/services/evalrun/http.d.ts +24 -0
  48. package/dist/services/evalrun/http.d.ts.map +1 -0
  49. package/dist/services/evalrun/index.d.ts +5 -0
  50. package/dist/services/evalrun/index.d.ts.map +1 -0
  51. package/dist/services/evalrun/json.d.ts +21 -0
  52. package/dist/services/evalrun/json.d.ts.map +1 -0
  53. package/dist/services/evalrun/local.d.ts +19 -0
  54. package/dist/services/evalrun/local.d.ts.map +1 -0
  55. package/dist/services/local/_db.d.ts +4 -0
  56. package/dist/services/local/_db.d.ts.map +1 -0
  57. package/dist/services/local/_router.d.ts +3 -0
  58. package/dist/services/local/_router.d.ts.map +1 -0
  59. package/dist/services/local/_util.d.ts +18 -0
  60. package/dist/services/local/_util.d.ts.map +1 -0
  61. package/dist/services/local/index.d.ts +8 -0
  62. package/dist/services/local/index.d.ts.map +1 -0
  63. package/dist/services/local/keyvalue.d.ts +10 -0
  64. package/dist/services/local/keyvalue.d.ts.map +1 -0
  65. package/dist/services/local/objectstore.d.ts +11 -0
  66. package/dist/services/local/objectstore.d.ts.map +1 -0
  67. package/dist/services/local/stream.d.ts +10 -0
  68. package/dist/services/local/stream.d.ts.map +1 -0
  69. package/dist/services/local/vector.d.ts +13 -0
  70. package/dist/services/local/vector.d.ts.map +1 -0
  71. package/dist/services/session/composite.d.ts +21 -0
  72. package/dist/services/session/composite.d.ts.map +1 -0
  73. package/dist/services/session/http.d.ts +23 -0
  74. package/dist/services/session/http.d.ts.map +1 -0
  75. package/dist/services/session/index.d.ts +5 -0
  76. package/dist/services/session/index.d.ts.map +1 -0
  77. package/dist/services/session/json.d.ts +22 -0
  78. package/dist/services/session/json.d.ts.map +1 -0
  79. package/dist/services/session/local.d.ts +19 -0
  80. package/dist/services/session/local.d.ts.map +1 -0
  81. package/dist/session.d.ts +70 -0
  82. package/dist/session.d.ts.map +1 -0
  83. package/package.json +10 -6
  84. package/src/_config.ts +1 -1
  85. package/src/_context.ts +19 -16
  86. package/src/_server.ts +284 -42
  87. package/src/_services.ts +147 -34
  88. package/src/_util.ts +2 -3
  89. package/src/_waituntil.ts +5 -153
  90. package/src/agent.ts +667 -65
  91. package/src/app.ts +159 -13
  92. package/src/eval.ts +95 -0
  93. package/src/index.ts +6 -1
  94. package/src/io/email.ts +173 -0
  95. package/src/logger/console.ts +196 -17
  96. package/src/logger/user.ts +7 -3
  97. package/src/otel/config.ts +7 -44
  98. package/src/otel/console.ts +8 -4
  99. package/src/otel/exporters/README.md +217 -0
  100. package/src/otel/exporters/index.ts +3 -0
  101. package/src/otel/exporters/jsonl-log-exporter.ts +113 -0
  102. package/src/otel/exporters/jsonl-metric-exporter.ts +120 -0
  103. package/src/otel/exporters/jsonl-trace-exporter.ts +121 -0
  104. package/src/otel/http.ts +3 -1
  105. package/src/otel/logger.ts +87 -37
  106. package/src/otel/otel.ts +43 -22
  107. package/src/router.ts +44 -4
  108. package/src/services/evalrun/composite.ts +34 -0
  109. package/src/services/evalrun/http.ts +112 -0
  110. package/src/services/evalrun/index.ts +4 -0
  111. package/src/services/evalrun/json.ts +46 -0
  112. package/src/services/evalrun/local.ts +28 -0
  113. package/src/services/local/README.md +1576 -0
  114. package/src/services/local/_db.ts +182 -0
  115. package/src/services/local/_router.ts +86 -0
  116. package/src/services/local/_util.ts +49 -0
  117. package/src/services/local/index.ts +7 -0
  118. package/src/services/local/keyvalue.ts +118 -0
  119. package/src/services/local/objectstore.ts +152 -0
  120. package/src/services/local/stream.ts +296 -0
  121. package/src/services/local/vector.ts +264 -0
  122. package/src/services/session/composite.ts +33 -0
  123. package/src/services/session/http.ts +64 -0
  124. package/src/services/session/index.ts +4 -0
  125. package/src/services/session/json.ts +42 -0
  126. package/src/services/session/local.ts +28 -0
  127. package/src/session.ts +284 -0
  128. package/dist/_unauthenticated.d.ts +0 -26
  129. package/dist/_unauthenticated.d.ts.map +0 -1
  130. 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,51 @@ 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
+ }
78
+ }
79
+
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;
81
103
  }
82
104
 
83
105
  trace(message: unknown, ...args: unknown[]) {
106
+ if (!this.shouldLog(LogsAPI.SeverityNumber.TRACE)) {
107
+ return;
108
+ }
84
109
  this.logger?.trace(message, ...args);
85
110
  let body: string;
86
111
  try {
@@ -89,9 +114,12 @@ export class OtelLogger implements Logger {
89
114
  // Fallback if format causes recursion
90
115
  body = `${this.formatMessage(message)} ${args.map((arg) => String(arg)).join(' ')}`;
91
116
  }
92
- this.emitToAll(LogsAPI.SeverityNumber.TRACE, 'TRACE', body);
117
+ this.emit(LogsAPI.SeverityNumber.TRACE, 'TRACE', body);
93
118
  }
94
119
  debug(message: unknown, ...args: unknown[]) {
120
+ if (!this.shouldLog(LogsAPI.SeverityNumber.DEBUG)) {
121
+ return;
122
+ }
95
123
  this.logger?.debug(message, ...args);
96
124
  let body: string;
97
125
  try {
@@ -100,9 +128,12 @@ export class OtelLogger implements Logger {
100
128
  // Fallback if format causes recursion
101
129
  body = `${this.formatMessage(message)} ${args.map((arg) => String(arg)).join(' ')}`;
102
130
  }
103
- this.emitToAll(LogsAPI.SeverityNumber.DEBUG, 'DEBUG', body);
131
+ this.emit(LogsAPI.SeverityNumber.DEBUG, 'DEBUG', body);
104
132
  }
105
133
  info(message: unknown, ...args: unknown[]) {
134
+ if (!this.shouldLog(LogsAPI.SeverityNumber.INFO)) {
135
+ return;
136
+ }
106
137
  this.logger?.info(message, ...args);
107
138
  let body: string;
108
139
  try {
@@ -111,9 +142,12 @@ export class OtelLogger implements Logger {
111
142
  // Fallback if format causes recursion
112
143
  body = `${this.formatMessage(message)} ${args.map((arg) => String(arg)).join(' ')}`;
113
144
  }
114
- this.emitToAll(LogsAPI.SeverityNumber.INFO, 'INFO', body);
145
+ this.emit(LogsAPI.SeverityNumber.INFO, 'INFO', body);
115
146
  }
116
147
  warn(message: unknown, ...args: unknown[]) {
148
+ if (!this.shouldLog(LogsAPI.SeverityNumber.WARN)) {
149
+ return;
150
+ }
117
151
  this.logger?.warn(message, ...args);
118
152
  let body: string;
119
153
  try {
@@ -122,9 +156,12 @@ export class OtelLogger implements Logger {
122
156
  // Fallback if format causes recursion
123
157
  body = `${this.formatMessage(message)} ${args.map((arg) => String(arg)).join(' ')}`;
124
158
  }
125
- this.emitToAll(LogsAPI.SeverityNumber.WARN, 'WARN', body);
159
+ this.emit(LogsAPI.SeverityNumber.WARN, 'WARN', body);
126
160
  }
127
161
  error(message: unknown, ...args: unknown[]) {
162
+ if (!this.shouldLog(LogsAPI.SeverityNumber.ERROR)) {
163
+ return;
164
+ }
128
165
  this.logger?.error(message, ...args);
129
166
  let body: string;
130
167
  try {
@@ -133,17 +170,22 @@ export class OtelLogger implements Logger {
133
170
  // Fallback if format causes recursion
134
171
  body = `${this.formatMessage(message)} ${args.map((arg) => String(arg)).join(' ')}`;
135
172
  }
136
- this.emitToAll(LogsAPI.SeverityNumber.ERROR, 'ERROR', body);
173
+ this.emit(LogsAPI.SeverityNumber.ERROR, 'ERROR', body);
137
174
  }
138
175
  fatal(message: unknown, ...args: unknown[]): never {
139
176
  this.error(message, ...args);
140
177
  process.exit(1);
141
178
  }
142
179
  child(opts: Record<string, unknown>): Logger {
143
- return new OtelLogger(!!this.logger, this.delegates, {
144
- ...(this.context ?? {}),
145
- ...opts,
146
- });
180
+ return new OtelLogger(
181
+ !!this.logger,
182
+ this.delegate,
183
+ {
184
+ ...(this.context ?? {}),
185
+ ...opts,
186
+ },
187
+ this.logLevel
188
+ );
147
189
  }
148
190
  }
149
191
 
@@ -154,11 +196,15 @@ export class OtelLogger implements Logger {
154
196
  * @param context - Additional context to include with log records
155
197
  * @returns A logger instance
156
198
  */
157
- 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 {
158
204
  const delegate = LogsAPI.logs.getLogger('default', undefined, {
159
205
  scopeAttributes: context as LogsAPI.LoggerOptions['scopeAttributes'],
160
206
  });
161
- return new OtelLogger(useConsole, [delegate], context);
207
+ return new OtelLogger(useConsole, delegate, context, logLevel);
162
208
  }
163
209
 
164
210
  /**
@@ -166,12 +212,16 @@ export function createLogger(useConsole: boolean, context?: Record<string, unkno
166
212
  *
167
213
  * @param attributes - Attributes to include with all console log records
168
214
  */
169
- 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
+ ) {
170
220
  if (!enabled) {
171
221
  return;
172
222
  }
173
223
  const _patch = { ...__originalConsole };
174
- const delegate = createLogger(true, attributes);
224
+ const delegate = createLogger(true, attributes, logLevel);
175
225
 
176
226
  // Patch individual console methods instead of reassigning the whole object
177
227
  _patch.log = (...args: unknown[]) => {