{"version":3,"sources":["../src/gcpOpenTelemetry.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n  MetricExporter,\n  type ExporterOptions,\n} from '@google-cloud/opentelemetry-cloud-monitoring-exporter';\nimport { TraceExporter } from '@google-cloud/opentelemetry-cloud-trace-exporter';\nimport { GcpDetectorSync } from '@google-cloud/opentelemetry-resource-util';\nimport { SpanStatusCode, TraceFlags, type Span } from '@opentelemetry/api';\nimport { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';\nimport { type ExportResult } from '@opentelemetry/core';\nimport type { Instrumentation } from '@opentelemetry/instrumentation';\nimport { PinoInstrumentation } from '@opentelemetry/instrumentation-pino';\nimport { WinstonInstrumentation } from '@opentelemetry/instrumentation-winston';\nimport { Resource } from '@opentelemetry/resources';\nimport {\n  AggregationTemporality,\n  DefaultAggregation,\n  ExponentialHistogramAggregation,\n  InMemoryMetricExporter,\n  InstrumentType,\n  PeriodicExportingMetricReader,\n  type PushMetricExporter,\n  type ResourceMetrics,\n} from '@opentelemetry/sdk-metrics';\nimport type { NodeSDKConfiguration } from '@opentelemetry/sdk-node';\nimport {\n  BatchSpanProcessor,\n  InMemorySpanExporter,\n  type ReadableSpan,\n  type SpanExporter,\n} from '@opentelemetry/sdk-trace-base';\nimport { GENKIT_VERSION } from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { actionTelemetry } from './telemetry/action.js';\nimport { engagementTelemetry } from './telemetry/engagement.js';\nimport { featuresTelemetry } from './telemetry/feature.js';\nimport { generateTelemetry } from './telemetry/generate.js';\nimport { pathsTelemetry } from './telemetry/path.js';\nimport type { GcpTelemetryConfig } from './types.js';\nimport {\n  metricsDenied,\n  metricsDeniedHelpText,\n  tracingDenied,\n  tracingDeniedHelpText,\n} from './utils.js';\n\nlet metricExporter: PushMetricExporter;\nlet spanProcessor: BatchSpanProcessor;\nlet spanExporter: AdjustingTraceExporter;\n\n/**\n * Provides a {TelemetryConfig} for exporting OpenTelemetry data (Traces,\n * Metrics, and Logs) to the Google Cloud Operations Suite.\n */\nexport class GcpOpenTelemetry {\n  private readonly config: GcpTelemetryConfig;\n  private readonly resource: Resource;\n\n  constructor(config: GcpTelemetryConfig) {\n    this.config = config;\n    this.resource = new Resource({ type: 'global' }).merge(\n      new GcpDetectorSync().detect()\n    );\n  }\n\n  /**\n   * Log hook for writing trace and span metadata to log messages in the format\n   * required by GCP.\n   */\n  private gcpTraceLogHook = (span: Span, record: any) => {\n    const spanContext = span.spanContext();\n    const isSampled = !!(spanContext.traceFlags & TraceFlags.SAMPLED);\n    const projectId = this.config.projectId;\n\n    record['logging.googleapis.com/trace'] ??=\n      `projects/${projectId}/traces/${spanContext.traceId}`;\n    record['logging.googleapis.com/trace_sampled'] ??= isSampled ? '1' : '0';\n    record['logging.googleapis.com/spanId'] ??= spanContext.spanId;\n\n    // Clear out the duplicate trace and span information in the log metadata.\n    // These will be incorrect for logs written during span export time since\n    // the logs are written after the span has fully executed. Those logs are\n    // explicitly tied to the correct span in createCommonLogAttributes in\n    // utils.ts.\n    delete record['span_id'];\n    delete record['trace_id'];\n    delete record['trace_flags'];\n  };\n\n  async getConfig(): Promise<Partial<NodeSDKConfiguration>> {\n    spanProcessor = new BatchSpanProcessor(await this.createSpanExporter());\n    return {\n      resource: this.resource,\n      spanProcessor: spanProcessor,\n      sampler: this.config.sampler,\n      instrumentations: this.getInstrumentations(),\n      metricReader: await this.createMetricReader(),\n    };\n  }\n\n  private async createSpanExporter(): Promise<SpanExporter> {\n    spanExporter = new AdjustingTraceExporter(\n      this.shouldExportTraces()\n        ? new TraceExporter({\n            // provided projectId should take precedence over env vars, etc\n            projectId: this.config.projectId,\n            // creds for non-GCP environments, in lieu of using ADC.\n            credentials: this.config.credentials,\n          })\n        : new InMemorySpanExporter(),\n      this.config.exportInputAndOutput,\n      this.config.projectId,\n      getErrorHandler(\n        (err) => {\n          return tracingDenied(err);\n        },\n        await tracingDeniedHelpText()\n      )\n    );\n    return spanExporter;\n  }\n\n  /**\n   * Creates a {MetricReader} for pushing metrics out to GCP via OpenTelemetry.\n   */\n  private async createMetricReader(): Promise<PeriodicExportingMetricReader> {\n    metricExporter = await this.buildMetricExporter();\n    return new PeriodicExportingMetricReader({\n      exportIntervalMillis: this.config.metricExportIntervalMillis,\n      exportTimeoutMillis: this.config.metricExportTimeoutMillis,\n      exporter: metricExporter,\n    });\n  }\n\n  /** Gets all open telemetry instrumentations as configured by the plugin. */\n  private getInstrumentations() {\n    let instrumentations: Instrumentation[] = [];\n\n    if (this.config.autoInstrumentation) {\n      instrumentations = getNodeAutoInstrumentations(\n        this.config.autoInstrumentationConfig\n      );\n    }\n\n    return instrumentations\n      .concat(this.getDefaultLoggingInstrumentations())\n      .concat(this.config.instrumentations ?? []);\n  }\n\n  private shouldExportTraces(): boolean {\n    return this.config.export && !this.config.disableTraces;\n  }\n\n  private shouldExportMetrics(): boolean {\n    return this.config.export && !this.config.disableMetrics;\n  }\n\n  /** Always configure the Pino and Winston instrumentations */\n  private getDefaultLoggingInstrumentations(): Instrumentation[] {\n    return [\n      new WinstonInstrumentation({ logHook: this.gcpTraceLogHook }),\n      new PinoInstrumentation({ logHook: this.gcpTraceLogHook }),\n    ];\n  }\n\n  private async buildMetricExporter(): Promise<PushMetricExporter> {\n    const exporter: PushMetricExporter = this.shouldExportMetrics()\n      ? new MetricExporterWrapper(\n          {\n            userAgent: {\n              product: 'genkit',\n              version: GENKIT_VERSION,\n            },\n            // provided projectId should take precedence over env vars, etc\n            projectId: this.config.projectId,\n            // creds for non-GCP environments, in lieu of using ADC.\n            credentials: this.config.credentials,\n          },\n          getErrorHandler(\n            (err) => {\n              return metricsDenied(err);\n            },\n            await metricsDeniedHelpText()\n          )\n        )\n      : new InMemoryMetricExporter(AggregationTemporality.DELTA);\n    return exporter;\n  }\n}\n\n/**\n * Rewrites the export method to include an error handler which logs\n * helpful information about how to set up metrics/telemetry in GCP.\n */\nclass MetricExporterWrapper extends MetricExporter {\n  private promise = new Promise<void>((resolve) => resolve());\n\n  constructor(\n    options?: ExporterOptions,\n    private errorHandler?: (error: Error) => void\n  ) {\n    super(options);\n  }\n\n  async export(\n    metrics: ResourceMetrics,\n    resultCallback: (result: ExportResult) => void\n  ): Promise<void> {\n    await this.promise;\n    this.modifyStartTimes(metrics);\n    this.promise = new Promise<void>((resolve) => {\n      super.export(metrics, (result) => {\n        try {\n          if (this.errorHandler && result.error) {\n            this.errorHandler(result.error);\n          }\n          resultCallback(result);\n        } finally {\n          resolve();\n        }\n      });\n    });\n  }\n\n  selectAggregation(instrumentType: InstrumentType) {\n    if (instrumentType === InstrumentType.HISTOGRAM) {\n      return new ExponentialHistogramAggregation();\n    }\n    return new DefaultAggregation();\n  }\n\n  selectAggregationTemporality(instrumentType: InstrumentType) {\n    return AggregationTemporality.DELTA;\n  }\n\n  /**\n   * Modify the start times of each data point to ensure no\n   * overlap with previous exports.\n   *\n   * Cloud metrics do not support delta metrics for custom metrics\n   * and will convert any DELTA aggregations to CUMULATIVE ones on\n   * export. There is implicit overlap in the start/end times that\n   * the Metric reader is sending -- the end_time of the previous\n   * export will become the start_time of the current export. The\n   * overlap in times means that only one of those records will\n   * persist and the other will be overwritten. This\n   * method adds a thousandth of a second to ensure discrete export\n   * timeframes.\n   */\n  private modifyStartTimes(metrics: ResourceMetrics): void {\n    metrics.scopeMetrics.forEach((scopeMetric) => {\n      scopeMetric.metrics.forEach((metric) => {\n        metric.dataPoints.forEach((dataPoint) => {\n          dataPoint.startTime[1] = dataPoint.startTime[1] + 1_000_000;\n        });\n      });\n    });\n  }\n\n  async shutdown(): Promise<void> {\n    return await this.forceFlush();\n  }\n\n  async forceFlush(): Promise<void> {\n    await this.promise;\n  }\n}\n\n/**\n * Adjusts spans before exporting to GCP. Redacts model input\n * and output content, and augments span attributes before sending to GCP.\n */\nclass AdjustingTraceExporter implements SpanExporter {\n  constructor(\n    private exporter: SpanExporter,\n    private logInputAndOutput: boolean,\n    private projectId?: string,\n    private errorHandler?: (error: Error) => void\n  ) {}\n\n  export(\n    spans: ReadableSpan[],\n    resultCallback: (result: ExportResult) => void\n  ): void {\n    this.exporter?.export(this.adjust(spans), (result) => {\n      if (this.errorHandler && result.error) {\n        this.errorHandler(result.error);\n      }\n      resultCallback(result);\n    });\n  }\n\n  shutdown(): Promise<void> {\n    return this.exporter?.shutdown();\n  }\n\n  getExporter(): SpanExporter {\n    return this.exporter;\n  }\n\n  forceFlush(): Promise<void> {\n    if (this.exporter?.forceFlush) {\n      return this.exporter.forceFlush();\n    }\n    return Promise.resolve();\n  }\n\n  private adjust(spans: ReadableSpan[]): ReadableSpan[] {\n    return spans.map((span) => {\n      this.tickTelemetry(span);\n\n      span = this.redactInputOutput(span);\n      span = this.markErrorSpanAsError(span);\n      span = this.markFailedSpan(span);\n      span = this.markGenkitFeature(span);\n      span = this.markGenkitModel(span);\n      span = this.normalizeLabels(span);\n      return span;\n    });\n  }\n\n  private tickTelemetry(span: ReadableSpan) {\n    const attributes = span.attributes;\n    if (!Object.keys(attributes).includes('genkit:type')) {\n      return;\n    }\n\n    const type = attributes['genkit:type'] as string;\n    const subtype = attributes['genkit:metadata:subtype'] as string;\n    const isRoot = !!span.attributes['genkit:isRoot'];\n\n    pathsTelemetry.tick(span, this.logInputAndOutput, this.projectId);\n    if (isRoot) {\n      // Report top level feature request and latency only for root spans\n      // Log input to and output from to the feature\n      featuresTelemetry.tick(span, this.logInputAndOutput, this.projectId);\n      // Set root status explicitly\n      span.attributes['genkit:rootState'] = span.attributes['genkit:state'];\n    } else {\n      if (type === 'action' && subtype === 'model') {\n        // Report generate metrics () for all model actions\n        generateTelemetry.tick(span, this.logInputAndOutput, this.projectId);\n      }\n      if (type === 'action' && subtype === 'tool') {\n        // TODO: Report input and output for tool actions\n      }\n      if (\n        type === 'action' ||\n        type === 'flow' ||\n        type == 'flowStep' ||\n        type == 'util'\n      ) {\n        // Report request and latency metrics for all actions\n        actionTelemetry.tick(span, this.logInputAndOutput, this.projectId);\n      }\n    }\n    if (type === 'userEngagement') {\n      // Report user acceptance and feedback metrics\n      engagementTelemetry.tick(span, this.logInputAndOutput, this.projectId);\n    }\n  }\n\n  private redactInputOutput(span: ReadableSpan): ReadableSpan {\n    const hasInput = 'genkit:input' in span.attributes;\n    const hasOutput = 'genkit:output' in span.attributes;\n\n    return !hasInput && !hasOutput\n      ? span\n      : {\n          ...span,\n          spanContext: span.spanContext,\n          attributes: {\n            ...span.attributes,\n            'genkit:input': '<redacted>',\n            'genkit:output': '<redacted>',\n          },\n        };\n  }\n\n  // This is a workaround for GCP Trace to mark a span with a red\n  // exclamation mark indicating that it is an error.\n  private markErrorSpanAsError(span: ReadableSpan): ReadableSpan {\n    return span.status.code !== SpanStatusCode.ERROR\n      ? span\n      : {\n          ...span,\n          spanContext: span.spanContext,\n          attributes: {\n            ...span.attributes,\n            '/http/status_code': '599',\n          },\n        };\n  }\n\n  private normalizeLabels(span: ReadableSpan): ReadableSpan {\n    const normalized = {} as Record<string, any>;\n    for (const [key, value] of Object.entries(span.attributes)) {\n      normalized[key.replace(/\\:/g, '/')] = value;\n    }\n    return {\n      ...span,\n      spanContext: span.spanContext,\n      attributes: normalized,\n    };\n  }\n\n  private markFailedSpan(span: ReadableSpan): ReadableSpan {\n    if (span.attributes['genkit:isFailureSource']) {\n      span.attributes['genkit:failedSpan'] = span.attributes['genkit:name'];\n      span.attributes['genkit:failedPath'] = span.attributes['genkit:path'];\n    }\n    return span;\n  }\n\n  private markGenkitFeature(span: ReadableSpan): ReadableSpan {\n    if (span.attributes['genkit:isRoot'] && !!span.attributes['genkit:name']) {\n      span.attributes['genkit:feature'] = span.attributes['genkit:name'];\n    }\n    return span;\n  }\n\n  private markGenkitModel(span: ReadableSpan): ReadableSpan {\n    if (\n      span.attributes['genkit:metadata:subtype'] === 'model' &&\n      !!span.attributes['genkit:name']\n    ) {\n      span.attributes['genkit:model'] = span.attributes['genkit:name'];\n    }\n    return span;\n  }\n}\n\nfunction getErrorHandler(\n  shouldLogFn: (err: Error) => boolean,\n  helpText: string\n): (err: Error) => void {\n  // only log the first time\n  let instructionsLogged = false;\n\n  return (err) => {\n    // Use the defaultLogger so that logs don't get swallowed by the open\n    // telemetry exporter\n    const defaultLogger = logger.defaultLogger;\n    if (err && shouldLogFn(err)) {\n      if (!instructionsLogged) {\n        instructionsLogged = true;\n        defaultLogger.error(\n          `Unable to send telemetry to Google Cloud: ${err.message}\\n\\n${helpText}\\n`\n        );\n      }\n    } else if (err) {\n      defaultLogger.error(`Unable to send telemetry to Google Cloud: ${err}`);\n    }\n  };\n}\n\n/** @hidden */\nexport function __getMetricExporterForTesting(): InMemoryMetricExporter {\n  return metricExporter as InMemoryMetricExporter;\n}\n\n/** @hidden */\nexport function __getSpanExporterForTesting(): InMemorySpanExporter {\n  return spanExporter.getExporter() as InMemorySpanExporter;\n}\n\n/** @hidden */\nexport function __forceFlushSpansForTesting() {\n  spanProcessor.forceFlush();\n}\n"],"mappings":"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","names":[]}