@inference-net/otel-cf-workers 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -71,6 +71,7 @@ export declare type ConfigurationOption = WorkerOtelConfig | ResolveConfigFn;
71
71
  export declare class ConsoleTransport implements LogTransport {
72
72
  readonly name = "console";
73
73
  private options;
74
+ private minSeverity;
74
75
  constructor(options?: ConsoleTransportConfig);
75
76
  export(logs: ReadableLogRecord[], callback: ExportResultCallback): void;
76
77
  private printLog;
@@ -84,6 +85,7 @@ export declare interface ConsoleTransportConfig {
84
85
  pretty?: boolean;
85
86
  colors?: boolean;
86
87
  includeTimestamp?: boolean;
88
+ level?: LogLevel;
87
89
  transformLog?: (logRecord: ReadableLogRecord) => ReadableLogRecord;
88
90
  }
89
91
 
@@ -225,9 +227,16 @@ export declare interface LocalTrace {
225
227
  readonly spans: ReadableSpan[];
226
228
  }
227
229
 
228
- export declare interface LogAttributes {
229
- [key: string]: any;
230
- }
230
+ /**
231
+ * Log attributes must be a plain object with string keys.
232
+ * This type explicitly excludes strings to prevent accidental argument swapping.
233
+ */
234
+ export declare type LogAttributes = {
235
+ [key: string]: unknown;
236
+ } & {
237
+ length?: never;
238
+ substring?: never;
239
+ };
231
240
 
232
241
  export declare type LogBody = string | Record<string, any>;
233
242
 
@@ -237,10 +246,11 @@ export declare interface Logger {
237
246
  debug(message: string, attributes?: LogAttributes): void;
238
247
  info(message: string, attributes?: LogAttributes): void;
239
248
  warn(message: string, attributes?: LogAttributes): void;
240
- error(message: string | Error, attributes?: LogAttributes): void;
249
+ error(message: string, attributes?: LogAttributes): void;
241
250
  fatal(message: string, attributes?: LogAttributes): void;
242
251
  forceFlush(): Promise<void>;
243
- child(attributes: LogAttributes): Logger;
252
+ child(name: string, attributes?: LogAttributes): Logger;
253
+ setProperties(attributes: LogAttributes): this;
244
254
  }
245
255
 
246
256
  export declare interface LoggerOptions {
@@ -253,6 +263,8 @@ export declare interface LoggerProvider {
253
263
  shutdown(): Promise<void>;
254
264
  }
255
265
 
266
+ export declare type LogLevel = 'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'FATAL';
267
+
256
268
  export declare interface LogRecord {
257
269
  readonly timeUnixNano: HrTime;
258
270
  readonly observedTimeUnixNano: HrTime;
@@ -275,7 +287,6 @@ export declare interface LogsConfig {
275
287
  transports?: LogTransport[];
276
288
  batching?: BatchConfig;
277
289
  instrumentation?: LogsInstrumentationOptions;
278
- level?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
279
290
  }
280
291
 
281
292
  export declare interface LogsInstrumentationOptions {
@@ -343,6 +354,7 @@ export declare class OTLPTransport implements LogTransport {
343
354
  readonly name = "otlp";
344
355
  private headers;
345
356
  private url;
357
+ private minSeverity;
346
358
  constructor(config: OTLPTransportConfig);
347
359
  export(logs: ReadableLogRecord[], callback: ExportResultCallback): void;
348
360
  private _export;
@@ -359,6 +371,7 @@ export declare class OTLPTransport implements LogTransport {
359
371
  export declare interface OTLPTransportConfig {
360
372
  url: string;
361
373
  headers?: Record<string, string>;
374
+ level?: LogLevel;
362
375
  }
363
376
 
364
377
  export declare interface ParentRatioSamplingConfig {
@@ -386,7 +399,6 @@ export declare type ResolveConfigFn<Env = any> = (env: Env, trigger: Trigger) =>
386
399
  export declare interface ResolvedLogsConfig {
387
400
  processors: LogRecordProcessor[];
388
401
  instrumentation: LogsInstrumentationOptions;
389
- level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
390
402
  }
391
403
 
392
404
  export declare interface ResolvedTraceConfig extends TraceConfigBase {
@@ -551,32 +563,33 @@ export declare class WorkerLogger implements Logger {
551
563
  private readonly resource;
552
564
  private readonly name;
553
565
  private readonly version?;
554
- private readonly inheritedAttributes;
555
- private readonly minSeverity;
556
- constructor(name: string, processors: LogRecordProcessor[], resource: Resource, version?: string, inheritedAttributes?: LogAttributes, minLevel?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal');
557
- private levelToSeverity;
558
- private shouldEmit;
566
+ private properties;
567
+ constructor(name: string, processors: LogRecordProcessor[], resource: Resource, version?: string, properties?: LogAttributes);
559
568
  emit(logRecord: Partial<LogRecord>): void;
560
569
  trace(message: string, attributes?: LogAttributes): void;
561
570
  debug(message: string, attributes?: LogAttributes): void;
562
571
  info(message: string, attributes?: LogAttributes): void;
563
572
  warn(message: string, attributes?: LogAttributes): void;
564
- error(message: string | Error, attributes?: LogAttributes): void;
573
+ error(message: string, attributes?: LogAttributes): void;
565
574
  fatal(message: string, attributes?: LogAttributes): void;
566
575
  forceFlush(): Promise<void>;
567
576
  /**
568
- * Create a child logger that inherits attributes from this logger
569
- * Child attributes are merged with parent attributes (child takes precedence)
577
+ * Create a child logger with a concatenated name (parent:child) that inherits properties from this logger
578
+ * Child properties are merged with parent properties (child takes precedence)
579
+ */
580
+ child(name: string, attributes?: LogAttributes): Logger;
581
+ /**
582
+ * Add properties to this logger that will be included in all future log records
583
+ * New properties are merged with existing properties (new takes precedence)
570
584
  */
571
- child(attributes: LogAttributes): Logger;
585
+ setProperties(attributes: LogAttributes): this;
572
586
  }
573
587
 
574
588
  export declare class WorkerLoggerProvider implements LoggerProvider {
575
589
  private loggers;
576
590
  private processors;
577
591
  private resource;
578
- private minLevel;
579
- constructor(processors: LogRecordProcessor[], resource: Resource, minLevel?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal');
592
+ constructor(processors: LogRecordProcessor[], resource: Resource);
580
593
  getLogger(name: string, version?: string, options?: LoggerOptions): Logger;
581
594
  register(): void;
582
595
  shutdown(): Promise<void>;
package/dist/index.js CHANGED
@@ -96,7 +96,7 @@ function passthroughGet(target, prop, thisArg) {
96
96
  }
97
97
  }
98
98
 
99
- const PACKAGE_VERSION = "2.2.0";
99
+ const PACKAGE_VERSION = "2.3.0";
100
100
  const PACKAGE_NAME = "@inference-net/otel-cf-workers";
101
101
  const ATTR_CLOUDFLARE_COLO = "cloudflare.colo";
102
102
  const ATTR_CLOUDFLARE_RAY_ID = "cloudflare.ray_id";
@@ -600,8 +600,7 @@ function parseLogsConfig(supplied) {
600
600
  processors,
601
601
  instrumentation: {
602
602
  instrumentConsole: supplied.instrumentation?.instrumentConsole ?? false
603
- },
604
- level: supplied.level ?? "info"
603
+ }
605
604
  };
606
605
  }
607
606
 
@@ -1022,6 +1021,53 @@ class WorkerTracerProvider {
1022
1021
  function millisToHr(millis) {
1023
1022
  return [Math.trunc(millis / 1e3), millis % 1e3 * 1e6];
1024
1023
  }
1024
+ function flattenError(error, prefix) {
1025
+ const result = {};
1026
+ result[`${prefix}.type`] = error.name;
1027
+ result[`${prefix}.message`] = error.message;
1028
+ if (error.stack) {
1029
+ result[`${prefix}.stacktrace`] = error.stack;
1030
+ }
1031
+ if ("cause" in error && error.cause) {
1032
+ if (error.cause instanceof Error) {
1033
+ Object.assign(result, flattenError(error.cause, `${prefix}.cause`));
1034
+ } else {
1035
+ result[`${prefix}.cause`] = String(error.cause);
1036
+ }
1037
+ }
1038
+ return result;
1039
+ }
1040
+ function flattenAttributes(attrs, prefix = "") {
1041
+ const result = {};
1042
+ for (const [key, value] of Object.entries(attrs)) {
1043
+ const fullKey = prefix ? `${prefix}.${key}` : key;
1044
+ if (value === null || value === void 0) {
1045
+ continue;
1046
+ } else if (value instanceof Error) {
1047
+ Object.assign(result, flattenError(value, fullKey));
1048
+ } else if (Array.isArray(value)) {
1049
+ const hasObjects = value.some((item) => item !== null && typeof item === "object" && !Array.isArray(item));
1050
+ if (hasObjects) {
1051
+ value.forEach((item, index) => {
1052
+ if (item instanceof Error) {
1053
+ Object.assign(result, flattenError(item, `${fullKey}.${index}`));
1054
+ } else if (item !== null && typeof item === "object" && !Array.isArray(item)) {
1055
+ Object.assign(result, flattenAttributes(item, `${fullKey}.${index}`));
1056
+ } else if (item !== null && item !== void 0) {
1057
+ result[`${fullKey}.${index}`] = item;
1058
+ }
1059
+ });
1060
+ } else {
1061
+ result[fullKey] = value;
1062
+ }
1063
+ } else if (typeof value === "object") {
1064
+ Object.assign(result, flattenAttributes(value, fullKey));
1065
+ } else {
1066
+ result[fullKey] = value;
1067
+ }
1068
+ }
1069
+ return result;
1070
+ }
1025
1071
  function getHrTime(input) {
1026
1072
  const now = Date.now();
1027
1073
  if (!input) {
@@ -1055,7 +1101,8 @@ class LogRecordImpl {
1055
1101
  this.severityNumber = init.severityNumber;
1056
1102
  this.severityText = init.severityText;
1057
1103
  this.body = init.body;
1058
- this.attributes = sanitizeAttributes(init.attributes || {});
1104
+ const flattenedAttributes = flattenAttributes(init.attributes || {});
1105
+ this.attributes = sanitizeAttributes(flattenedAttributes);
1059
1106
  this.resource = init.resource;
1060
1107
  this.instrumentationScope = init.instrumentationScope || {
1061
1108
  name: "@inference-net/otel-cf-workers"
@@ -1079,38 +1126,17 @@ class WorkerLogger {
1079
1126
  resource;
1080
1127
  name;
1081
1128
  version;
1082
- inheritedAttributes;
1083
- minSeverity;
1084
- constructor(name, processors, resource, version, inheritedAttributes, minLevel = "info") {
1129
+ properties;
1130
+ constructor(name, processors, resource, version, properties) {
1085
1131
  this.name = name;
1086
1132
  this.processors = processors;
1087
1133
  this.resource = resource;
1088
1134
  this.version = version;
1089
- this.inheritedAttributes = inheritedAttributes || {};
1090
- this.minSeverity = this.levelToSeverity(minLevel);
1091
- }
1092
- levelToSeverity(level) {
1093
- switch (level) {
1094
- case "trace":
1095
- return SEVERITY_NUMBERS.TRACE;
1096
- case "debug":
1097
- return SEVERITY_NUMBERS.DEBUG;
1098
- case "info":
1099
- return SEVERITY_NUMBERS.INFO;
1100
- case "warn":
1101
- return SEVERITY_NUMBERS.WARN;
1102
- case "error":
1103
- return SEVERITY_NUMBERS.ERROR;
1104
- case "fatal":
1105
- return SEVERITY_NUMBERS.FATAL;
1106
- }
1107
- }
1108
- shouldEmit(severityNumber) {
1109
- return severityNumber >= this.minSeverity;
1135
+ this.properties = properties || {};
1110
1136
  }
1111
1137
  emit(logRecord) {
1112
1138
  const mergedAttributes = {
1113
- ...this.inheritedAttributes,
1139
+ ...this.properties,
1114
1140
  ...logRecord.attributes || {}
1115
1141
  };
1116
1142
  const record = new LogRecordImpl({
@@ -1128,7 +1154,6 @@ class WorkerLogger {
1128
1154
  });
1129
1155
  }
1130
1156
  trace(message, attributes) {
1131
- if (!this.shouldEmit(SEVERITY_NUMBERS.TRACE)) return;
1132
1157
  this.emit({
1133
1158
  severityNumber: SEVERITY_NUMBERS.TRACE,
1134
1159
  severityText: "TRACE",
@@ -1137,7 +1162,6 @@ class WorkerLogger {
1137
1162
  });
1138
1163
  }
1139
1164
  debug(message, attributes) {
1140
- if (!this.shouldEmit(SEVERITY_NUMBERS.DEBUG)) return;
1141
1165
  this.emit({
1142
1166
  severityNumber: SEVERITY_NUMBERS.DEBUG,
1143
1167
  severityText: "DEBUG",
@@ -1146,7 +1170,6 @@ class WorkerLogger {
1146
1170
  });
1147
1171
  }
1148
1172
  info(message, attributes) {
1149
- if (!this.shouldEmit(SEVERITY_NUMBERS.INFO)) return;
1150
1173
  this.emit({
1151
1174
  severityNumber: SEVERITY_NUMBERS.INFO,
1152
1175
  severityText: "INFO",
@@ -1155,7 +1178,6 @@ class WorkerLogger {
1155
1178
  });
1156
1179
  }
1157
1180
  warn(message, attributes) {
1158
- if (!this.shouldEmit(SEVERITY_NUMBERS.WARN)) return;
1159
1181
  this.emit({
1160
1182
  severityNumber: SEVERITY_NUMBERS.WARN,
1161
1183
  severityText: "WARN",
@@ -1164,29 +1186,30 @@ class WorkerLogger {
1164
1186
  });
1165
1187
  }
1166
1188
  error(message, attributes) {
1167
- if (!this.shouldEmit(SEVERITY_NUMBERS.ERROR)) return;
1168
- let body;
1169
- let attrs = { ...attributes };
1170
- if (message instanceof Error) {
1171
- body = message.message;
1172
- attrs = {
1173
- ...attrs,
1174
- "exception.type": message.name,
1175
- "exception.message": message.message,
1176
- "exception.stacktrace": message.stack
1177
- };
1178
- } else {
1179
- body = message;
1189
+ const exception = attributes?.["error"] instanceof Error ? attributes["error"] : void 0;
1190
+ const activeSpan = trace.getActiveSpan();
1191
+ if (activeSpan) {
1192
+ activeSpan.setStatus({ code: SpanStatusCode.ERROR, message });
1193
+ if (exception) {
1194
+ activeSpan.recordException(exception);
1195
+ }
1180
1196
  }
1181
1197
  this.emit({
1182
1198
  severityNumber: SEVERITY_NUMBERS.ERROR,
1183
1199
  severityText: "ERROR",
1184
- body,
1185
- attributes: attrs
1200
+ body: message,
1201
+ attributes
1186
1202
  });
1187
1203
  }
1188
1204
  fatal(message, attributes) {
1189
- if (!this.shouldEmit(SEVERITY_NUMBERS.FATAL)) return;
1205
+ const exception = attributes?.["error"] instanceof Error ? attributes["error"] : void 0;
1206
+ const activeSpan = trace.getActiveSpan();
1207
+ if (activeSpan) {
1208
+ activeSpan.setStatus({ code: SpanStatusCode.ERROR, message });
1209
+ if (exception) {
1210
+ activeSpan.recordException(exception);
1211
+ }
1212
+ }
1190
1213
  this.emit({
1191
1214
  severityNumber: SEVERITY_NUMBERS.FATAL,
1192
1215
  severityText: "FATAL",
@@ -1199,22 +1222,27 @@ class WorkerLogger {
1199
1222
  await Promise.allSettled(promises);
1200
1223
  }
1201
1224
  /**
1202
- * Create a child logger that inherits attributes from this logger
1203
- * Child attributes are merged with parent attributes (child takes precedence)
1225
+ * Create a child logger with a concatenated name (parent:child) that inherits properties from this logger
1226
+ * Child properties are merged with parent properties (child takes precedence)
1204
1227
  */
1205
- child(attributes) {
1206
- const mergedAttributes = {
1207
- ...this.inheritedAttributes,
1228
+ child(name, attributes) {
1229
+ const childName = `${this.name}:${name}`;
1230
+ const mergedProperties = {
1231
+ ...this.properties,
1232
+ ...attributes || {}
1233
+ };
1234
+ return new WorkerLogger(childName, this.processors, this.resource, this.version, mergedProperties);
1235
+ }
1236
+ /**
1237
+ * Add properties to this logger that will be included in all future log records
1238
+ * New properties are merged with existing properties (new takes precedence)
1239
+ */
1240
+ setProperties(attributes) {
1241
+ this.properties = {
1242
+ ...this.properties,
1208
1243
  ...attributes
1209
1244
  };
1210
- let minLevel = "info";
1211
- if (this.minSeverity <= SEVERITY_NUMBERS.TRACE) minLevel = "trace";
1212
- else if (this.minSeverity <= SEVERITY_NUMBERS.DEBUG) minLevel = "debug";
1213
- else if (this.minSeverity <= SEVERITY_NUMBERS.INFO) minLevel = "info";
1214
- else if (this.minSeverity <= SEVERITY_NUMBERS.WARN) minLevel = "warn";
1215
- else if (this.minSeverity <= SEVERITY_NUMBERS.ERROR) minLevel = "error";
1216
- else minLevel = "fatal";
1217
- return new WorkerLogger(this.name, this.processors, this.resource, this.version, mergedAttributes, minLevel);
1245
+ return this;
1218
1246
  }
1219
1247
  }
1220
1248
 
@@ -1229,16 +1257,14 @@ class WorkerLoggerProvider {
1229
1257
  loggers = /* @__PURE__ */ new Map();
1230
1258
  processors;
1231
1259
  resource;
1232
- minLevel;
1233
- constructor(processors, resource, minLevel = "info") {
1260
+ constructor(processors, resource) {
1234
1261
  this.processors = processors;
1235
1262
  this.resource = resource;
1236
- this.minLevel = minLevel;
1237
1263
  }
1238
1264
  getLogger(name, version, options) {
1239
1265
  const key = `${name}@${version || ""}:${options?.schemaUrl || ""}`;
1240
1266
  if (!this.loggers.has(key)) {
1241
- this.loggers.set(key, new WorkerLogger(name, this.processors, this.resource, version, void 0, this.minLevel));
1267
+ this.loggers.set(key, new WorkerLogger(name, this.processors, this.resource, version));
1242
1268
  }
1243
1269
  return this.loggers.get(key);
1244
1270
  }
@@ -1269,6 +1295,9 @@ class NoopLogger {
1269
1295
  child() {
1270
1296
  return this;
1271
1297
  }
1298
+ setProperties() {
1299
+ return this;
1300
+ }
1272
1301
  }
1273
1302
  class NoopLoggerProvider {
1274
1303
  logger = new NoopLogger();
@@ -3531,7 +3560,7 @@ function init(config, serviceConfig, propagator) {
3531
3560
  traceProvider.register();
3532
3561
  }
3533
3562
  if (config.logs && config.logs.processors.length > 0) {
3534
- const logsProvider = new WorkerLoggerProvider(config.logs.processors, resource, config.logs.level);
3563
+ const logsProvider = new WorkerLoggerProvider(config.logs.processors, resource);
3535
3564
  logsProvider.register();
3536
3565
  if (config.logs.instrumentation.instrumentConsole) {
3537
3566
  import('./console-Cy5QdByD.js').then(({ instrumentConsole }) => {
@@ -3697,16 +3726,39 @@ class MultiSpanExporterAsync {
3697
3726
  }
3698
3727
  }
3699
3728
 
3729
+ function levelToSeverity(level) {
3730
+ switch (level) {
3731
+ case "TRACE":
3732
+ return SEVERITY_NUMBERS.TRACE;
3733
+ case "DEBUG":
3734
+ return SEVERITY_NUMBERS.DEBUG;
3735
+ case "INFO":
3736
+ return SEVERITY_NUMBERS.INFO;
3737
+ case "WARN":
3738
+ return SEVERITY_NUMBERS.WARN;
3739
+ case "ERROR":
3740
+ return SEVERITY_NUMBERS.ERROR;
3741
+ case "FATAL":
3742
+ return SEVERITY_NUMBERS.FATAL;
3743
+ }
3744
+ }
3700
3745
  class OTLPTransport {
3701
3746
  name = "otlp";
3702
3747
  headers;
3703
3748
  url;
3749
+ minSeverity;
3704
3750
  constructor(config) {
3705
3751
  this.url = config.url;
3706
3752
  this.headers = Object.assign({}, DEFAULT_OTLP_HEADERS, config.headers);
3753
+ this.minSeverity = levelToSeverity(config.level ?? "TRACE");
3707
3754
  }
3708
3755
  export(logs, callback) {
3709
- this._export(logs).then(() => {
3756
+ const filteredLogs = logs.filter((log) => (log.severityNumber ?? 0) >= this.minSeverity);
3757
+ if (filteredLogs.length === 0) {
3758
+ callback({ code: ExportResultCode.SUCCESS });
3759
+ return;
3760
+ }
3761
+ this._export(filteredLogs).then(() => {
3710
3762
  callback({ code: ExportResultCode.SUCCESS });
3711
3763
  }).catch((error) => {
3712
3764
  callback({ code: ExportResultCode.FAILED, error });
@@ -3834,6 +3886,7 @@ class OTLPTransport {
3834
3886
  class ConsoleTransport {
3835
3887
  name = "console";
3836
3888
  options;
3889
+ minSeverity;
3837
3890
  constructor(options = {}) {
3838
3891
  this.options = {
3839
3892
  pretty: options.pretty ?? true,
@@ -3841,10 +3894,12 @@ class ConsoleTransport {
3841
3894
  includeTimestamp: options.includeTimestamp ?? true,
3842
3895
  transformLog: options.transformLog ?? ((l) => l)
3843
3896
  };
3897
+ this.minSeverity = levelToSeverity(options.level ?? "TRACE");
3844
3898
  }
3845
3899
  export(logs, callback) {
3846
3900
  try {
3847
3901
  for (const log of logs) {
3902
+ if ((log.severityNumber ?? 0) < this.minSeverity) continue;
3848
3903
  this.printLog(this.options.transformLog ? this.options.transformLog(log) : log);
3849
3904
  }
3850
3905
  callback({ code: ExportResultCode.SUCCESS });