UNPKG

openlit

Version:

OpenTelemetry-native Auto instrumentation library for monitoring LLM Applications, facilitating the integration of observability into your GenAI-driven projects

171 lines 7.54 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const sdk_metrics_1 = require("@opentelemetry/sdk-metrics"); const api_1 = require("@opentelemetry/api"); const semantic_convention_1 = __importDefault(require("../semantic-convention")); const exporter_metrics_otlp_http_1 = require("@opentelemetry/exporter-metrics-otlp-http"); const utils_1 = require("./utils"); const DB_CLIENT_OPERATION_DURATION_BUCKETS = [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, 5, 10]; const GEN_AI_CLIENT_OPERATION_DURATION_BUCKETS = [ 0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, 20.48, 40.96, 81.92, ]; const GEN_AI_SERVER_TBT = [0.01, 0.025, 0.05, 0.075, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.75, 1.0, 2.5]; const GEN_AI_SERVER_TFTT = [ 0.001, 0.005, 0.01, 0.02, 0.04, 0.06, 0.08, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 7.5, 10.0, ]; const GEN_AI_CLIENT_TOKEN_USAGE_BUCKETS = [ 1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216, 67108864, ]; let METER_SET = false; class Metrics { static initializeMetrics() { this.genaiClientUsageTokens = this.meter.createHistogram(semantic_convention_1.default.GEN_AI_CLIENT_TOKEN_USAGE, { description: 'Measures number of input and output tokens used', unit: '{token}', advice: { explicitBucketBoundaries: GEN_AI_CLIENT_TOKEN_USAGE_BUCKETS, }, }); this.genaiClientOperationDuration = this.meter.createHistogram(semantic_convention_1.default.GEN_AI_CLIENT_OPERATION_DURATION, { description: 'GenAI operation duration', unit: 's', advice: { explicitBucketBoundaries: GEN_AI_CLIENT_OPERATION_DURATION_BUCKETS, }, }); this.genaiServerTbt = this.meter.createHistogram(semantic_convention_1.default.GEN_AI_SERVER_TBT, { description: 'Time per output token generated after the first token for successful responses', unit: 's', advice: { explicitBucketBoundaries: GEN_AI_SERVER_TBT, }, }); this.genaiServerTtft = this.meter.createHistogram(semantic_convention_1.default.GEN_AI_SERVER_TTFT, { description: 'Time to generate first token for successful responses', unit: 's', advice: { explicitBucketBoundaries: GEN_AI_SERVER_TFTT, }, }); this.genaiClientTimeToFirstChunk = this.meter.createHistogram(semantic_convention_1.default.GEN_AI_CLIENT_OPERATION_TIME_TO_FIRST_CHUNK, { description: 'Time from client request to first response chunk', unit: 's', advice: { explicitBucketBoundaries: GEN_AI_CLIENT_OPERATION_DURATION_BUCKETS, }, }); this.genaiClientTimePerOutputChunk = this.meter.createHistogram(semantic_convention_1.default.GEN_AI_CLIENT_OPERATION_TIME_PER_OUTPUT_CHUNK, { description: 'Time between consecutive response chunks from client perspective', unit: 's', advice: { explicitBucketBoundaries: GEN_AI_CLIENT_OPERATION_DURATION_BUCKETS, }, }); this.genaiServerRequestDuration = this.meter.createHistogram(semantic_convention_1.default.GEN_AI_SERVER_REQUEST_DURATION, { description: 'Total server-side processing time from request receipt to response transmission', unit: 's', advice: { explicitBucketBoundaries: GEN_AI_CLIENT_OPERATION_DURATION_BUCKETS, }, }); this.dbClientOperationDuration = this.meter.createHistogram(semantic_convention_1.default.DB_CLIENT_OPERATION_DURATION, { description: 'DB operation duration', unit: 's', advice: { explicitBucketBoundaries: DB_CLIENT_OPERATION_DURATION_BUCKETS, }, }); this.genaiCost = this.meter.createHistogram(semantic_convention_1.default.GEN_AI_USAGE_COST, { description: 'The distribution of GenAI request costs.', unit: 'USD', }); this.dbRequests = this.meter.createCounter(semantic_convention_1.default.DB_REQUESTS, { description: 'Number of requests to VectorDBs.', unit: '1', }); } static setup(options) { if (options.meter) { this.meter = options.meter; this.initializeMetrics(); return this.meter; } try { if (!METER_SET) { const existingProvider = api_1.metrics.getMeterProvider(); const isSDKProvider = existingProvider && typeof existingProvider.getMeter === 'function' && existingProvider.constructor.name !== 'NoopMeterProvider'; if (isSDKProvider) { this.meterProvider = existingProvider; } else { const readers = Metrics.buildMetricReaders(options); this.meterProvider = new sdk_metrics_1.MeterProvider({ resource: options.resource, readers, }); api_1.metrics.setGlobalMeterProvider(this.meterProvider); this.metricReaders.push(...readers); } this.meter = this.meterProvider.getMeter('openlit', '1.0.0'); this.initializeMetrics(); METER_SET = true; } return this.meter; } catch (e) { console.error('[Metrics] Failed to initialize metrics:', e); return null; } } static buildMetricReaders(options) { const readers = []; const exporterList = (0, utils_1.parseExporters)('OTEL_METRICS_EXPORTER'); if (exporterList) { for (const name of exporterList) { if (name === 'otlp') { readers.push(Metrics.createOTLPReader(options)); } else if (name === 'console') { readers.push(Metrics.createConsoleReader(options)); } } } else { if (options.otlpEndpoint) { readers.push(Metrics.createOTLPReader(options)); } else { readers.push(Metrics.createConsoleReader(options)); } } return readers; } static createOTLPReader(options) { const url = (options.otlpEndpoint || '') + '/v1/metrics'; const exporter = new exporter_metrics_otlp_http_1.OTLPMetricExporter({ url, headers: options.otlpHeaders, }); return new sdk_metrics_1.PeriodicExportingMetricReader({ exportIntervalMillis: options.exportIntervalMillis || 60000, exporter, }); } static createConsoleReader(options) { return new sdk_metrics_1.PeriodicExportingMetricReader({ exportIntervalMillis: options.exportIntervalMillis || 60000, exporter: new sdk_metrics_1.ConsoleMetricExporter(), }); } static resetForTesting() { METER_SET = false; } } Metrics.metricReaders = []; exports.default = Metrics; //# sourceMappingURL=metrics.js.map