{"version":3,"sources":["../../src/telemetry/feature.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 { ValueType } from '@opentelemetry/api';\nimport { hrTimeDuration, hrTimeToMilliseconds } from '@opentelemetry/core';\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nimport { GENKIT_VERSION, GenkitError } from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { toDisplayPath } from 'genkit/tracing';\nimport {\n  MetricCounter,\n  MetricHistogram,\n  internalMetricNamespaceWrap,\n  type Telemetry,\n} from '../metrics.js';\nimport {\n  createCommonLogAttributes,\n  extractErrorName,\n  truncate,\n  truncatePath,\n} from '../utils.js';\n\nclass FeaturesTelemetry implements Telemetry {\n  /**\n   * Wraps the declared metrics in a Genkit-specific, internal namespace.\n   */\n  private _N = internalMetricNamespaceWrap.bind(null, 'feature');\n\n  private featureCounter = new MetricCounter(this._N('requests'), {\n    description: 'Counts calls to genkit features.',\n    valueType: ValueType.INT,\n  });\n\n  private featureLatencies = new MetricHistogram(this._N('latency'), {\n    description: 'Latencies when calling Genkit features.',\n    valueType: ValueType.DOUBLE,\n    unit: 'ms',\n  });\n\n  tick(\n    span: ReadableSpan,\n    logInputAndOutput: boolean,\n    projectId?: string\n  ): void {\n    const attributes = span.attributes;\n    const name = attributes['genkit:name'] as string;\n    const path = attributes['genkit:path'] as string;\n    const latencyMs = hrTimeToMilliseconds(\n      hrTimeDuration(span.startTime, span.endTime)\n    );\n    const isRoot = attributes['genkit:isRoot'] as boolean;\n    if (!isRoot) {\n      throw new GenkitError({\n        status: 'FAILED_PRECONDITION',\n        message: 'FeatureTelemetry tick called with non-root span.',\n      });\n    }\n    const state = attributes['genkit:state'] as string;\n\n    if (state === 'success') {\n      this.writeFeatureSuccess(name, latencyMs);\n    } else if (state === 'error') {\n      const errorName = extractErrorName(span.events) || '<unknown>';\n      this.writeFeatureFailure(name, latencyMs, errorName);\n    } else {\n      logger.warn(`Unknown state; ${state}`);\n      return;\n    }\n\n    if (logInputAndOutput) {\n      const input = truncate(attributes['genkit:input'] as string);\n      const output = truncate(attributes['genkit:output'] as string);\n      const sessionId = attributes['genkit:sessionId'] as string;\n      const threadName = attributes['genkit:threadName'] as string;\n\n      if (input) {\n        this.writeLog(\n          span,\n          'Input',\n          name,\n          path,\n          input,\n          projectId,\n          sessionId,\n          threadName\n        );\n      }\n      if (output) {\n        this.writeLog(\n          span,\n          'Output',\n          name,\n          path,\n          output,\n          projectId,\n          sessionId,\n          threadName\n        );\n      }\n    }\n  }\n\n  private writeFeatureSuccess(featureName: string, latencyMs: number) {\n    const dimensions = {\n      name: featureName,\n      status: 'success',\n      source: 'ts',\n      sourceVersion: GENKIT_VERSION,\n    };\n    this.featureCounter.add(1, dimensions);\n    this.featureLatencies.record(latencyMs, dimensions);\n  }\n\n  private writeFeatureFailure(\n    featureName: string,\n    latencyMs: number,\n    errorName: string\n  ) {\n    const dimensions = {\n      name: featureName,\n      status: 'failure',\n      source: 'ts',\n      sourceVersion: GENKIT_VERSION,\n      error: errorName,\n    };\n    this.featureCounter.add(1, dimensions);\n    this.featureLatencies.record(latencyMs, dimensions);\n  }\n\n  private writeLog(\n    span: ReadableSpan,\n    tag: string,\n    featureName: string,\n    qualifiedPath: string,\n    content: string,\n    projectId?: string,\n    sessionId?: string,\n    threadName?: string\n  ) {\n    const path = truncatePath(toDisplayPath(qualifiedPath));\n    const sharedMetadata = {\n      ...createCommonLogAttributes(span, projectId),\n      path,\n      qualifiedPath,\n      featureName,\n      sessionId,\n      threadName,\n    };\n    logger.logStructured(`${tag}[${path}, ${featureName}]`, {\n      ...sharedMetadata,\n      content,\n    });\n  }\n}\n\nconst featuresTelemetry = new FeaturesTelemetry();\nexport { featuresTelemetry };\n"],"mappings":"AAgBA,SAAS,iBAAiB;AAC1B,SAAS,gBAAgB,4BAA4B;AAErD,SAAS,gBAAgB,mBAAmB;AAC5C,SAAS,cAAc;AACvB,SAAS,qBAAqB;AAC9B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,MAAM,kBAAuC;AAAA;AAAA;AAAA;AAAA,EAInC,KAAK,4BAA4B,KAAK,MAAM,SAAS;AAAA,EAErD,iBAAiB,IAAI,cAAc,KAAK,GAAG,UAAU,GAAG;AAAA,IAC9D,aAAa;AAAA,IACb,WAAW,UAAU;AAAA,EACvB,CAAC;AAAA,EAEO,mBAAmB,IAAI,gBAAgB,KAAK,GAAG,SAAS,GAAG;AAAA,IACjE,aAAa;AAAA,IACb,WAAW,UAAU;AAAA,IACrB,MAAM;AAAA,EACR,CAAC;AAAA,EAED,KACE,MACA,mBACA,WACM;AACN,UAAM,aAAa,KAAK;AACxB,UAAM,OAAO,WAAW,aAAa;AACrC,UAAM,OAAO,WAAW,aAAa;AACrC,UAAM,YAAY;AAAA,MAChB,eAAe,KAAK,WAAW,KAAK,OAAO;AAAA,IAC7C;AACA,UAAM,SAAS,WAAW,eAAe;AACzC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,YAAY;AAAA,QACpB,QAAQ;AAAA,QACR,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AACA,UAAM,QAAQ,WAAW,cAAc;AAEvC,QAAI,UAAU,WAAW;AACvB,WAAK,oBAAoB,MAAM,SAAS;AAAA,IAC1C,WAAW,UAAU,SAAS;AAC5B,YAAM,YAAY,iBAAiB,KAAK,MAAM,KAAK;AACnD,WAAK,oBAAoB,MAAM,WAAW,SAAS;AAAA,IACrD,OAAO;AACL,aAAO,KAAK,kBAAkB,KAAK,EAAE;AACrC;AAAA,IACF;AAEA,QAAI,mBAAmB;AACrB,YAAM,QAAQ,SAAS,WAAW,cAAc,CAAW;AAC3D,YAAM,SAAS,SAAS,WAAW,eAAe,CAAW;AAC7D,YAAM,YAAY,WAAW,kBAAkB;AAC/C,YAAM,aAAa,WAAW,mBAAmB;AAEjD,UAAI,OAAO;AACT,aAAK;AAAA,UACH;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,UAAI,QAAQ;AACV,aAAK;AAAA,UACH;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,oBAAoB,aAAqB,WAAmB;AAClE,UAAM,aAAa;AAAA,MACjB,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,eAAe;AAAA,IACjB;AACA,SAAK,eAAe,IAAI,GAAG,UAAU;AACrC,SAAK,iBAAiB,OAAO,WAAW,UAAU;AAAA,EACpD;AAAA,EAEQ,oBACN,aACA,WACA,WACA;AACA,UAAM,aAAa;AAAA,MACjB,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,eAAe;AAAA,MACf,OAAO;AAAA,IACT;AACA,SAAK,eAAe,IAAI,GAAG,UAAU;AACrC,SAAK,iBAAiB,OAAO,WAAW,UAAU;AAAA,EACpD;AAAA,EAEQ,SACN,MACA,KACA,aACA,eACA,SACA,WACA,WACA,YACA;AACA,UAAM,OAAO,aAAa,cAAc,aAAa,CAAC;AACtD,UAAM,iBAAiB;AAAA,MACrB,GAAG,0BAA0B,MAAM,SAAS;AAAA,MAC5C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO,cAAc,GAAG,GAAG,IAAI,IAAI,KAAK,WAAW,KAAK;AAAA,MACtD,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,MAAM,oBAAoB,IAAI,kBAAkB;","names":[]}