{"version":3,"file":"OpenTelemetryBunyanStream.js","sourceRoot":"","sources":["../../src/OpenTelemetryBunyanStream.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n  logs,\n  SeverityNumber,\n  Logger,\n  type LogRecord,\n} from '@opentelemetry/api-logs';\nimport type { LogLevelString } from 'bunyan';\n/** @knipignore */\nimport { PACKAGE_NAME, PACKAGE_VERSION } from './version';\n\nconst DEFAULT_INSTRUMENTATION_SCOPE_NAME = PACKAGE_NAME;\nconst DEFAULT_INSTRUMENTATION_SCOPE_VERSION = PACKAGE_VERSION;\n\n// This block is a copy (modulo code style and TypeScript types) of the Bunyan\n// code that defines log level value and names. These values won't ever change\n// in bunyan@1. This file is part of *instrumenting* Bunyan, so we want to\n// avoid a dependency on the library.\nconst TRACE = 10;\nconst DEBUG = 20;\nconst INFO = 30;\nconst WARN = 40;\nconst ERROR = 50;\nconst FATAL = 60;\nconst levelFromName: Record<LogLevelString, number> = {\n  trace: TRACE,\n  debug: DEBUG,\n  info: INFO,\n  warn: WARN,\n  error: ERROR,\n  fatal: FATAL,\n};\nconst nameFromLevel: { [level: number]: string } = {};\nObject.keys(levelFromName).forEach(function (name) {\n  nameFromLevel[levelFromName[name as LogLevelString]] = name;\n});\n\nconst OTEL_SEV_NUM_FROM_BUNYAN_LEVEL: { [level: number]: SeverityNumber } = {\n  [TRACE]: SeverityNumber.TRACE,\n  [DEBUG]: SeverityNumber.DEBUG,\n  [INFO]: SeverityNumber.INFO,\n  [WARN]: SeverityNumber.WARN,\n  [ERROR]: SeverityNumber.ERROR,\n  [FATAL]: SeverityNumber.FATAL,\n};\n\nconst EXTRA_SEV_NUMS = [\n  SeverityNumber.TRACE2,\n  SeverityNumber.TRACE3,\n  SeverityNumber.TRACE4,\n  SeverityNumber.DEBUG2,\n  SeverityNumber.DEBUG3,\n  SeverityNumber.DEBUG4,\n  SeverityNumber.INFO2,\n  SeverityNumber.INFO3,\n  SeverityNumber.INFO4,\n  SeverityNumber.WARN2,\n  SeverityNumber.WARN3,\n  SeverityNumber.WARN4,\n  SeverityNumber.ERROR2,\n  SeverityNumber.ERROR3,\n  SeverityNumber.ERROR4,\n  SeverityNumber.FATAL2,\n  SeverityNumber.FATAL3,\n  SeverityNumber.FATAL4,\n];\n\nfunction severityNumberFromBunyanLevel(lvl: number) {\n  // Fast common case: one of the known levels\n  const sev = OTEL_SEV_NUM_FROM_BUNYAN_LEVEL[lvl];\n  if (sev !== undefined) {\n    return sev;\n  }\n\n  // Otherwise, scale the Bunyan level range -- 10 (TRACE) to 70 (FATAL+10)\n  // -- onto the extra OTel severity numbers (TRACE2, TRACE3, ..., FATAL4).\n  // Values below bunyan.TRACE map to SeverityNumber.TRACE2, which may be\n  // considered a bit weird, but it means the unnumbered levels are always\n  // just for exactly values.\n  const relativeLevelWeight = (lvl - 10) / (70 - 10);\n  const otelSevIdx = Math.floor(relativeLevelWeight * EXTRA_SEV_NUMS.length);\n  const cappedOTelIdx = Math.min(\n    EXTRA_SEV_NUMS.length - 1,\n    Math.max(0, otelSevIdx)\n  );\n  const otelSevValue = EXTRA_SEV_NUMS[cappedOTelIdx];\n  return otelSevValue;\n}\n\n/**\n * A Bunyan stream for sending log records to the OpenTelemetry Logs SDK.\n */\nexport class OpenTelemetryBunyanStream {\n  private _otelLogger: Logger;\n\n  constructor() {\n    this._otelLogger = logs.getLogger(\n      DEFAULT_INSTRUMENTATION_SCOPE_NAME,\n      DEFAULT_INSTRUMENTATION_SCOPE_VERSION\n    );\n  }\n\n  /**\n   * Convert from https://github.com/trentm/node-bunyan#log-record-fields\n   * to https://opentelemetry.io/docs/specs/otel/logs/data-model/\n   *\n   * Dev Notes:\n   * - We drop the Bunyan 'v' field. It is meant to indicate the format\n   *   of the Bunyan log record. FWIW, it has always been `0`.\n   * - The standard Bunyan `hostname` and `pid` fields are removed because they\n   *   are redundant with the OpenTelemetry `host.name` and `process.pid`\n   *   Resource attributes, respectively. This code cannot change the\n   *   LoggerProvider's `resource`, so getting the OpenTelemetry equivalents\n   *   depends on the user using relevant OpenTelemetry resource detectors.\n   *   \"examples/telemetry.js\" shows using HostDetector and ProcessDetector for\n   *   this.\n   * - The Bunyan `name` field *could* naturally map to OpenTelemetry's\n   *   `service.name` resource attribute. However, that is debatable, as some\n   *   users might use `name` more like a log4j logger name.\n   * - Strip the `trace_id` et al fields that may have been added by the\n   *   the _emit wrapper.\n   */\n  write(rec: Record<string, any>) {\n    const {\n      time,\n      level,\n      msg,\n      err,\n      v, // eslint-disable-line @typescript-eslint/no-unused-vars\n      hostname, // eslint-disable-line @typescript-eslint/no-unused-vars\n      pid, // eslint-disable-line @typescript-eslint/no-unused-vars\n      trace_id, // eslint-disable-line @typescript-eslint/no-unused-vars\n      span_id, // eslint-disable-line @typescript-eslint/no-unused-vars\n      trace_flags, // eslint-disable-line @typescript-eslint/no-unused-vars\n      ...fields\n    } = rec;\n    let timestamp = undefined;\n    if (typeof time.getTime === 'function') {\n      timestamp = time.getTime(); // ms\n    } else {\n      fields.time = time; // Expose non-Date \"time\" field on attributes.\n    }\n    const otelRec: LogRecord = {\n      timestamp,\n      observedTimestamp: timestamp,\n      severityNumber: severityNumberFromBunyanLevel(level),\n      severityText: nameFromLevel[level],\n      body: msg,\n      attributes: fields,\n    };\n    if (err !== undefined) {\n      otelRec.exception = err;\n    }\n    this._otelLogger.emit(otelRec);\n  }\n}\n"]}