@prismakit/opentelemetry 3.2.0 → 4.0.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/create-prisma-kit-telemetry.ts"],"sourcesContent":["export {\n createPrismaKitTelemetry,\n type CreatePrismaKitTelemetryOptions,\n} from './create-prisma-kit-telemetry';\n","import {\n metrics,\n trace,\n SpanStatusCode,\n type Meter,\n type Tracer,\n type Counter,\n type Histogram,\n} from '@opentelemetry/api';\nimport type { TelemetryEvent, TelemetryOptions } from '@prismakit/core';\n\nexport type CreatePrismaKitTelemetryOptions = {\n /** Defaults to `trace.getTracer('prismakit')`. */\n tracer?: Tracer;\n /** Defaults to `metrics.getMeter('prismakit')`. */\n meter?: Meter;\n /** Instrument name prefix. Default `prismakit`. */\n prefix?: string;\n /**\n * When set, also enable core `query.slow` emission at this threshold (ms).\n * Nest `queryLog.slowThreshold` remains the preferred Nest path.\n */\n slowThreshold?: number;\n};\n\ntype Instruments = {\n cache: Counter;\n compose: Histogram;\n query: Histogram;\n lock: Histogram;\n stampede: Counter;\n};\n\nfunction createInstruments(meter: Meter, prefix: string): Instruments {\n return {\n cache: meter.createCounter(`${prefix}.cache`, {\n description: 'PrismaKit cache events',\n }),\n compose: meter.createHistogram(`${prefix}.compose.duration`, {\n description: 'PrismaKit auto-compose duration (ms)',\n unit: 'ms',\n }),\n query: meter.createHistogram(`${prefix}.query.duration`, {\n description: 'PrismaKit repository query duration (ms)',\n unit: 'ms',\n }),\n lock: meter.createHistogram(`${prefix}.lock.duration`, {\n description: 'PrismaKit row-lock duration (ms)',\n unit: 'ms',\n }),\n stampede: meter.createCounter(`${prefix}.stampede`, {\n description: 'PrismaKit stampede protection events',\n }),\n };\n}\n\n/**\n * Build {@link TelemetryOptions} that map PrismaKit events to OpenTelemetry\n * metrics (and short spans for compose / slow queries).\n *\n * Bring your own OTel SDK — this package only depends on `@opentelemetry/api`.\n *\n * @example\n * ```ts\n * import { createPrismaKitTelemetry } from '@prismakit/opentelemetry';\n *\n * PrismaKitModule.forRoot({\n * prisma,\n * cache,\n * telemetry: createPrismaKitTelemetry({ slowThreshold: 500 }),\n * });\n * ```\n */\nexport function createPrismaKitTelemetry(\n options: CreatePrismaKitTelemetryOptions = {},\n): TelemetryOptions {\n const prefix = options.prefix ?? 'prismakit';\n const tracer = options.tracer ?? trace.getTracer(prefix);\n const meter = options.meter ?? metrics.getMeter(prefix);\n const instruments = createInstruments(meter, prefix);\n\n return {\n enabled: true,\n slowThreshold: options.slowThreshold,\n onEvent: (event: TelemetryEvent) => {\n const model = event.model ?? 'unknown';\n const method = 'method' in event ? (event.method ?? 'unknown') : 'unknown';\n\n switch (event.type) {\n case 'cache.hit':\n case 'cache.miss':\n case 'cache.bypass':\n case 'cache.invalidate':\n case 'cache.error':\n instruments.cache.add(1, {\n outcome: event.type.replace('cache.', ''),\n model,\n method,\n });\n break;\n\n case 'compose.start': {\n const span = tracer.startSpan('prismakit.compose', {\n attributes: {\n 'prismakit.model': event.model,\n 'prismakit.depth': event.depth ?? 0,\n 'prismakit.relation_count': event.relationCount ?? 0,\n },\n });\n span.end();\n break;\n }\n case 'compose.complete':\n instruments.compose.record(event.durationMs ?? 0, {\n model: event.model,\n query_count: String(event.queryCount ?? 0),\n });\n break;\n\n case 'query.complete':\n case 'query.slow':\n instruments.query.record(event.durationMs, {\n model,\n method,\n slow: String(event.type === 'query.slow'),\n });\n if (event.type === 'query.slow') {\n const span = tracer.startSpan('prismakit.query.slow', {\n attributes: {\n 'prismakit.model': model,\n 'prismakit.method': method,\n 'prismakit.duration_ms': event.durationMs,\n 'prismakit.threshold_ms': event.thresholdMs ?? 0,\n },\n });\n span.setStatus({ code: SpanStatusCode.ERROR, message: 'slow query' });\n span.end();\n }\n break;\n\n case 'lock.acquired':\n case 'lock.waited':\n case 'lock.timeout':\n instruments.lock.record(event.durationMs ?? 0, {\n outcome: event.type.replace('lock.', ''),\n model,\n mode: event.mode ?? 'unknown',\n });\n break;\n\n case 'stampede.locked':\n case 'stampede.waited':\n case 'stampede.fallthrough':\n instruments.stampede.add(1, {\n outcome: event.type.replace('stampede.', ''),\n model,\n });\n break;\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/create-prisma-kit-telemetry.ts"],"sourcesContent":["export {\n createPrismaKitTelemetry,\n type CreatePrismaKitTelemetryOptions,\n} from './create-prisma-kit-telemetry';\n","import {\n metrics,\n trace,\n SpanStatusCode,\n type Meter,\n type Tracer,\n type Counter,\n type Histogram,\n} from '@opentelemetry/api';\nimport type { TelemetryEvent, TelemetryOptions } from '@prismakit/core';\n\nexport type CreatePrismaKitTelemetryOptions = {\n /** Defaults to `trace.getTracer('prismakit')`. */\n tracer?: Tracer;\n /** Defaults to `metrics.getMeter('prismakit')`. */\n meter?: Meter;\n /** Instrument name prefix. Default `prismakit`. */\n prefix?: string;\n /**\n * When set, also enable core `query.slow` emission at this threshold (ms).\n * Prefer Nest `telemetry.slowThreshold` / `telemetry.onSlowQuery`.\n */\n slowThreshold?: number;\n};\n\ntype Instruments = {\n cache: Counter;\n compose: Histogram;\n query: Histogram;\n lock: Histogram;\n stampede: Counter;\n};\n\nfunction createInstruments(meter: Meter, prefix: string): Instruments {\n return {\n cache: meter.createCounter(`${prefix}.cache`, {\n description: 'PrismaKit cache events',\n }),\n compose: meter.createHistogram(`${prefix}.compose.duration`, {\n description: 'PrismaKit auto-compose duration (ms)',\n unit: 'ms',\n }),\n query: meter.createHistogram(`${prefix}.query.duration`, {\n description: 'PrismaKit repository query duration (ms)',\n unit: 'ms',\n }),\n lock: meter.createHistogram(`${prefix}.lock.duration`, {\n description: 'PrismaKit row-lock duration (ms)',\n unit: 'ms',\n }),\n stampede: meter.createCounter(`${prefix}.stampede`, {\n description: 'PrismaKit stampede protection events',\n }),\n };\n}\n\n/**\n * Build {@link TelemetryOptions} that map PrismaKit events to OpenTelemetry\n * metrics (and short spans for compose / slow queries).\n *\n * Bring your own OTel SDK — this package only depends on `@opentelemetry/api`.\n *\n * @example\n * ```ts\n * import { createPrismaKitTelemetry } from '@prismakit/opentelemetry';\n *\n * PrismaKitModule.forRoot({\n * prisma,\n * cache,\n * telemetry: createPrismaKitTelemetry({ slowThreshold: 500 }),\n * });\n * ```\n */\nexport function createPrismaKitTelemetry(\n options: CreatePrismaKitTelemetryOptions = {},\n): TelemetryOptions {\n const prefix = options.prefix ?? 'prismakit';\n const tracer = options.tracer ?? trace.getTracer(prefix);\n const meter = options.meter ?? metrics.getMeter(prefix);\n const instruments = createInstruments(meter, prefix);\n\n return {\n enabled: true,\n slowThreshold: options.slowThreshold,\n onEvent: (event: TelemetryEvent) => {\n const model = event.model ?? 'unknown';\n const method = 'method' in event ? (event.method ?? 'unknown') : 'unknown';\n\n switch (event.type) {\n case 'cache.hit':\n case 'cache.miss':\n case 'cache.bypass':\n case 'cache.invalidate':\n case 'cache.error':\n instruments.cache.add(1, {\n outcome: event.type.replace('cache.', ''),\n model,\n method,\n });\n break;\n\n case 'compose.start': {\n const span = tracer.startSpan('prismakit.compose', {\n attributes: {\n 'prismakit.model': event.model,\n 'prismakit.depth': event.depth ?? 0,\n 'prismakit.relation_count': event.relationCount ?? 0,\n },\n });\n span.end();\n break;\n }\n case 'compose.complete':\n instruments.compose.record(event.durationMs ?? 0, {\n model: event.model,\n query_count: String(event.queryCount ?? 0),\n });\n break;\n\n case 'query.complete':\n case 'query.slow':\n instruments.query.record(event.durationMs, {\n model,\n method,\n slow: String(event.type === 'query.slow'),\n });\n if (event.type === 'query.slow') {\n const span = tracer.startSpan('prismakit.query.slow', {\n attributes: {\n 'prismakit.model': model,\n 'prismakit.method': method,\n 'prismakit.duration_ms': event.durationMs,\n 'prismakit.threshold_ms': event.thresholdMs ?? 0,\n },\n });\n span.setStatus({ code: SpanStatusCode.ERROR, message: 'slow query' });\n span.end();\n }\n break;\n\n case 'lock.acquired':\n case 'lock.waited':\n case 'lock.timeout':\n instruments.lock.record(event.durationMs ?? 0, {\n outcome: event.type.replace('lock.', ''),\n model,\n mode: event.mode ?? 'unknown',\n });\n break;\n\n case 'stampede.locked':\n case 'stampede.waited':\n case 'stampede.fallthrough':\n instruments.stampede.add(1, {\n outcome: event.type.replace('stampede.', ''),\n model,\n });\n break;\n }\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,iBAQO;AAyBP,SAAS,kBAAkB,OAAc,QAA6B;AACpE,SAAO;AAAA,IACL,OAAO,MAAM,cAAc,GAAG,MAAM,UAAU;AAAA,MAC5C,aAAa;AAAA,IACf,CAAC;AAAA,IACD,SAAS,MAAM,gBAAgB,GAAG,MAAM,qBAAqB;AAAA,MAC3D,aAAa;AAAA,MACb,MAAM;AAAA,IACR,CAAC;AAAA,IACD,OAAO,MAAM,gBAAgB,GAAG,MAAM,mBAAmB;AAAA,MACvD,aAAa;AAAA,MACb,MAAM;AAAA,IACR,CAAC;AAAA,IACD,MAAM,MAAM,gBAAgB,GAAG,MAAM,kBAAkB;AAAA,MACrD,aAAa;AAAA,MACb,MAAM;AAAA,IACR,CAAC;AAAA,IACD,UAAU,MAAM,cAAc,GAAG,MAAM,aAAa;AAAA,MAClD,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AACF;AAmBO,SAAS,yBACd,UAA2C,CAAC,GAC1B;AAClB,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,SAAS,QAAQ,UAAU,iBAAM,UAAU,MAAM;AACvD,QAAM,QAAQ,QAAQ,SAAS,mBAAQ,SAAS,MAAM;AACtD,QAAM,cAAc,kBAAkB,OAAO,MAAM;AAEnD,SAAO;AAAA,IACL,SAAS;AAAA,IACT,eAAe,QAAQ;AAAA,IACvB,SAAS,CAAC,UAA0B;AAClC,YAAM,QAAQ,MAAM,SAAS;AAC7B,YAAM,SAAS,YAAY,QAAS,MAAM,UAAU,YAAa;AAEjE,cAAQ,MAAM,MAAM;AAAA,QAClB,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AACH,sBAAY,MAAM,IAAI,GAAG;AAAA,YACvB,SAAS,MAAM,KAAK,QAAQ,UAAU,EAAE;AAAA,YACxC;AAAA,YACA;AAAA,UACF,CAAC;AACD;AAAA,QAEF,KAAK,iBAAiB;AACpB,gBAAM,OAAO,OAAO,UAAU,qBAAqB;AAAA,YACjD,YAAY;AAAA,cACV,mBAAmB,MAAM;AAAA,cACzB,mBAAmB,MAAM,SAAS;AAAA,cAClC,4BAA4B,MAAM,iBAAiB;AAAA,YACrD;AAAA,UACF,CAAC;AACD,eAAK,IAAI;AACT;AAAA,QACF;AAAA,QACA,KAAK;AACH,sBAAY,QAAQ,OAAO,MAAM,cAAc,GAAG;AAAA,YAChD,OAAO,MAAM;AAAA,YACb,aAAa,OAAO,MAAM,cAAc,CAAC;AAAA,UAC3C,CAAC;AACD;AAAA,QAEF,KAAK;AAAA,QACL,KAAK;AACH,sBAAY,MAAM,OAAO,MAAM,YAAY;AAAA,YACzC;AAAA,YACA;AAAA,YACA,MAAM,OAAO,MAAM,SAAS,YAAY;AAAA,UAC1C,CAAC;AACD,cAAI,MAAM,SAAS,cAAc;AAC/B,kBAAM,OAAO,OAAO,UAAU,wBAAwB;AAAA,cACpD,YAAY;AAAA,gBACV,mBAAmB;AAAA,gBACnB,oBAAoB;AAAA,gBACpB,yBAAyB,MAAM;AAAA,gBAC/B,0BAA0B,MAAM,eAAe;AAAA,cACjD;AAAA,YACF,CAAC;AACD,iBAAK,UAAU,EAAE,MAAM,0BAAe,OAAO,SAAS,aAAa,CAAC;AACpE,iBAAK,IAAI;AAAA,UACX;AACA;AAAA,QAEF,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AACH,sBAAY,KAAK,OAAO,MAAM,cAAc,GAAG;AAAA,YAC7C,SAAS,MAAM,KAAK,QAAQ,SAAS,EAAE;AAAA,YACvC;AAAA,YACA,MAAM,MAAM,QAAQ;AAAA,UACtB,CAAC;AACD;AAAA,QAEF,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AACH,sBAAY,SAAS,IAAI,GAAG;AAAA,YAC1B,SAAS,MAAM,KAAK,QAAQ,aAAa,EAAE;AAAA,YAC3C;AAAA,UACF,CAAC;AACD;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
package/dist/index.d.cts CHANGED
@@ -10,7 +10,7 @@ type CreatePrismaKitTelemetryOptions = {
10
10
  prefix?: string;
11
11
  /**
12
12
  * When set, also enable core `query.slow` emission at this threshold (ms).
13
- * Nest `queryLog.slowThreshold` remains the preferred Nest path.
13
+ * Prefer Nest `telemetry.slowThreshold` / `telemetry.onSlowQuery`.
14
14
  */
15
15
  slowThreshold?: number;
16
16
  };
package/dist/index.d.ts CHANGED
@@ -10,7 +10,7 @@ type CreatePrismaKitTelemetryOptions = {
10
10
  prefix?: string;
11
11
  /**
12
12
  * When set, also enable core `query.slow` emission at this threshold (ms).
13
- * Nest `queryLog.slowThreshold` remains the preferred Nest path.
13
+ * Prefer Nest `telemetry.slowThreshold` / `telemetry.onSlowQuery`.
14
14
  */
15
15
  slowThreshold?: number;
16
16
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/create-prisma-kit-telemetry.ts"],"sourcesContent":["import {\n metrics,\n trace,\n SpanStatusCode,\n type Meter,\n type Tracer,\n type Counter,\n type Histogram,\n} from '@opentelemetry/api';\nimport type { TelemetryEvent, TelemetryOptions } from '@prismakit/core';\n\nexport type CreatePrismaKitTelemetryOptions = {\n /** Defaults to `trace.getTracer('prismakit')`. */\n tracer?: Tracer;\n /** Defaults to `metrics.getMeter('prismakit')`. */\n meter?: Meter;\n /** Instrument name prefix. Default `prismakit`. */\n prefix?: string;\n /**\n * When set, also enable core `query.slow` emission at this threshold (ms).\n * Nest `queryLog.slowThreshold` remains the preferred Nest path.\n */\n slowThreshold?: number;\n};\n\ntype Instruments = {\n cache: Counter;\n compose: Histogram;\n query: Histogram;\n lock: Histogram;\n stampede: Counter;\n};\n\nfunction createInstruments(meter: Meter, prefix: string): Instruments {\n return {\n cache: meter.createCounter(`${prefix}.cache`, {\n description: 'PrismaKit cache events',\n }),\n compose: meter.createHistogram(`${prefix}.compose.duration`, {\n description: 'PrismaKit auto-compose duration (ms)',\n unit: 'ms',\n }),\n query: meter.createHistogram(`${prefix}.query.duration`, {\n description: 'PrismaKit repository query duration (ms)',\n unit: 'ms',\n }),\n lock: meter.createHistogram(`${prefix}.lock.duration`, {\n description: 'PrismaKit row-lock duration (ms)',\n unit: 'ms',\n }),\n stampede: meter.createCounter(`${prefix}.stampede`, {\n description: 'PrismaKit stampede protection events',\n }),\n };\n}\n\n/**\n * Build {@link TelemetryOptions} that map PrismaKit events to OpenTelemetry\n * metrics (and short spans for compose / slow queries).\n *\n * Bring your own OTel SDK — this package only depends on `@opentelemetry/api`.\n *\n * @example\n * ```ts\n * import { createPrismaKitTelemetry } from '@prismakit/opentelemetry';\n *\n * PrismaKitModule.forRoot({\n * prisma,\n * cache,\n * telemetry: createPrismaKitTelemetry({ slowThreshold: 500 }),\n * });\n * ```\n */\nexport function createPrismaKitTelemetry(\n options: CreatePrismaKitTelemetryOptions = {},\n): TelemetryOptions {\n const prefix = options.prefix ?? 'prismakit';\n const tracer = options.tracer ?? trace.getTracer(prefix);\n const meter = options.meter ?? metrics.getMeter(prefix);\n const instruments = createInstruments(meter, prefix);\n\n return {\n enabled: true,\n slowThreshold: options.slowThreshold,\n onEvent: (event: TelemetryEvent) => {\n const model = event.model ?? 'unknown';\n const method = 'method' in event ? (event.method ?? 'unknown') : 'unknown';\n\n switch (event.type) {\n case 'cache.hit':\n case 'cache.miss':\n case 'cache.bypass':\n case 'cache.invalidate':\n case 'cache.error':\n instruments.cache.add(1, {\n outcome: event.type.replace('cache.', ''),\n model,\n method,\n });\n break;\n\n case 'compose.start': {\n const span = tracer.startSpan('prismakit.compose', {\n attributes: {\n 'prismakit.model': event.model,\n 'prismakit.depth': event.depth ?? 0,\n 'prismakit.relation_count': event.relationCount ?? 0,\n },\n });\n span.end();\n break;\n }\n case 'compose.complete':\n instruments.compose.record(event.durationMs ?? 0, {\n model: event.model,\n query_count: String(event.queryCount ?? 0),\n });\n break;\n\n case 'query.complete':\n case 'query.slow':\n instruments.query.record(event.durationMs, {\n model,\n method,\n slow: String(event.type === 'query.slow'),\n });\n if (event.type === 'query.slow') {\n const span = tracer.startSpan('prismakit.query.slow', {\n attributes: {\n 'prismakit.model': model,\n 'prismakit.method': method,\n 'prismakit.duration_ms': event.durationMs,\n 'prismakit.threshold_ms': event.thresholdMs ?? 0,\n },\n });\n span.setStatus({ code: SpanStatusCode.ERROR, message: 'slow query' });\n span.end();\n }\n break;\n\n case 'lock.acquired':\n case 'lock.waited':\n case 'lock.timeout':\n instruments.lock.record(event.durationMs ?? 0, {\n outcome: event.type.replace('lock.', ''),\n model,\n mode: event.mode ?? 'unknown',\n });\n break;\n\n case 'stampede.locked':\n case 'stampede.waited':\n case 'stampede.fallthrough':\n instruments.stampede.add(1, {\n outcome: event.type.replace('stampede.', ''),\n model,\n });\n break;\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/create-prisma-kit-telemetry.ts"],"sourcesContent":["import {\n metrics,\n trace,\n SpanStatusCode,\n type Meter,\n type Tracer,\n type Counter,\n type Histogram,\n} from '@opentelemetry/api';\nimport type { TelemetryEvent, TelemetryOptions } from '@prismakit/core';\n\nexport type CreatePrismaKitTelemetryOptions = {\n /** Defaults to `trace.getTracer('prismakit')`. */\n tracer?: Tracer;\n /** Defaults to `metrics.getMeter('prismakit')`. */\n meter?: Meter;\n /** Instrument name prefix. Default `prismakit`. */\n prefix?: string;\n /**\n * When set, also enable core `query.slow` emission at this threshold (ms).\n * Prefer Nest `telemetry.slowThreshold` / `telemetry.onSlowQuery`.\n */\n slowThreshold?: number;\n};\n\ntype Instruments = {\n cache: Counter;\n compose: Histogram;\n query: Histogram;\n lock: Histogram;\n stampede: Counter;\n};\n\nfunction createInstruments(meter: Meter, prefix: string): Instruments {\n return {\n cache: meter.createCounter(`${prefix}.cache`, {\n description: 'PrismaKit cache events',\n }),\n compose: meter.createHistogram(`${prefix}.compose.duration`, {\n description: 'PrismaKit auto-compose duration (ms)',\n unit: 'ms',\n }),\n query: meter.createHistogram(`${prefix}.query.duration`, {\n description: 'PrismaKit repository query duration (ms)',\n unit: 'ms',\n }),\n lock: meter.createHistogram(`${prefix}.lock.duration`, {\n description: 'PrismaKit row-lock duration (ms)',\n unit: 'ms',\n }),\n stampede: meter.createCounter(`${prefix}.stampede`, {\n description: 'PrismaKit stampede protection events',\n }),\n };\n}\n\n/**\n * Build {@link TelemetryOptions} that map PrismaKit events to OpenTelemetry\n * metrics (and short spans for compose / slow queries).\n *\n * Bring your own OTel SDK — this package only depends on `@opentelemetry/api`.\n *\n * @example\n * ```ts\n * import { createPrismaKitTelemetry } from '@prismakit/opentelemetry';\n *\n * PrismaKitModule.forRoot({\n * prisma,\n * cache,\n * telemetry: createPrismaKitTelemetry({ slowThreshold: 500 }),\n * });\n * ```\n */\nexport function createPrismaKitTelemetry(\n options: CreatePrismaKitTelemetryOptions = {},\n): TelemetryOptions {\n const prefix = options.prefix ?? 'prismakit';\n const tracer = options.tracer ?? trace.getTracer(prefix);\n const meter = options.meter ?? metrics.getMeter(prefix);\n const instruments = createInstruments(meter, prefix);\n\n return {\n enabled: true,\n slowThreshold: options.slowThreshold,\n onEvent: (event: TelemetryEvent) => {\n const model = event.model ?? 'unknown';\n const method = 'method' in event ? (event.method ?? 'unknown') : 'unknown';\n\n switch (event.type) {\n case 'cache.hit':\n case 'cache.miss':\n case 'cache.bypass':\n case 'cache.invalidate':\n case 'cache.error':\n instruments.cache.add(1, {\n outcome: event.type.replace('cache.', ''),\n model,\n method,\n });\n break;\n\n case 'compose.start': {\n const span = tracer.startSpan('prismakit.compose', {\n attributes: {\n 'prismakit.model': event.model,\n 'prismakit.depth': event.depth ?? 0,\n 'prismakit.relation_count': event.relationCount ?? 0,\n },\n });\n span.end();\n break;\n }\n case 'compose.complete':\n instruments.compose.record(event.durationMs ?? 0, {\n model: event.model,\n query_count: String(event.queryCount ?? 0),\n });\n break;\n\n case 'query.complete':\n case 'query.slow':\n instruments.query.record(event.durationMs, {\n model,\n method,\n slow: String(event.type === 'query.slow'),\n });\n if (event.type === 'query.slow') {\n const span = tracer.startSpan('prismakit.query.slow', {\n attributes: {\n 'prismakit.model': model,\n 'prismakit.method': method,\n 'prismakit.duration_ms': event.durationMs,\n 'prismakit.threshold_ms': event.thresholdMs ?? 0,\n },\n });\n span.setStatus({ code: SpanStatusCode.ERROR, message: 'slow query' });\n span.end();\n }\n break;\n\n case 'lock.acquired':\n case 'lock.waited':\n case 'lock.timeout':\n instruments.lock.record(event.durationMs ?? 0, {\n outcome: event.type.replace('lock.', ''),\n model,\n mode: event.mode ?? 'unknown',\n });\n break;\n\n case 'stampede.locked':\n case 'stampede.waited':\n case 'stampede.fallthrough':\n instruments.stampede.add(1, {\n outcome: event.type.replace('stampede.', ''),\n model,\n });\n break;\n }\n },\n };\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AAyBP,SAAS,kBAAkB,OAAc,QAA6B;AACpE,SAAO;AAAA,IACL,OAAO,MAAM,cAAc,GAAG,MAAM,UAAU;AAAA,MAC5C,aAAa;AAAA,IACf,CAAC;AAAA,IACD,SAAS,MAAM,gBAAgB,GAAG,MAAM,qBAAqB;AAAA,MAC3D,aAAa;AAAA,MACb,MAAM;AAAA,IACR,CAAC;AAAA,IACD,OAAO,MAAM,gBAAgB,GAAG,MAAM,mBAAmB;AAAA,MACvD,aAAa;AAAA,MACb,MAAM;AAAA,IACR,CAAC;AAAA,IACD,MAAM,MAAM,gBAAgB,GAAG,MAAM,kBAAkB;AAAA,MACrD,aAAa;AAAA,MACb,MAAM;AAAA,IACR,CAAC;AAAA,IACD,UAAU,MAAM,cAAc,GAAG,MAAM,aAAa;AAAA,MAClD,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AACF;AAmBO,SAAS,yBACd,UAA2C,CAAC,GAC1B;AAClB,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,SAAS,QAAQ,UAAU,MAAM,UAAU,MAAM;AACvD,QAAM,QAAQ,QAAQ,SAAS,QAAQ,SAAS,MAAM;AACtD,QAAM,cAAc,kBAAkB,OAAO,MAAM;AAEnD,SAAO;AAAA,IACL,SAAS;AAAA,IACT,eAAe,QAAQ;AAAA,IACvB,SAAS,CAAC,UAA0B;AAClC,YAAM,QAAQ,MAAM,SAAS;AAC7B,YAAM,SAAS,YAAY,QAAS,MAAM,UAAU,YAAa;AAEjE,cAAQ,MAAM,MAAM;AAAA,QAClB,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AACH,sBAAY,MAAM,IAAI,GAAG;AAAA,YACvB,SAAS,MAAM,KAAK,QAAQ,UAAU,EAAE;AAAA,YACxC;AAAA,YACA;AAAA,UACF,CAAC;AACD;AAAA,QAEF,KAAK,iBAAiB;AACpB,gBAAM,OAAO,OAAO,UAAU,qBAAqB;AAAA,YACjD,YAAY;AAAA,cACV,mBAAmB,MAAM;AAAA,cACzB,mBAAmB,MAAM,SAAS;AAAA,cAClC,4BAA4B,MAAM,iBAAiB;AAAA,YACrD;AAAA,UACF,CAAC;AACD,eAAK,IAAI;AACT;AAAA,QACF;AAAA,QACA,KAAK;AACH,sBAAY,QAAQ,OAAO,MAAM,cAAc,GAAG;AAAA,YAChD,OAAO,MAAM;AAAA,YACb,aAAa,OAAO,MAAM,cAAc,CAAC;AAAA,UAC3C,CAAC;AACD;AAAA,QAEF,KAAK;AAAA,QACL,KAAK;AACH,sBAAY,MAAM,OAAO,MAAM,YAAY;AAAA,YACzC;AAAA,YACA;AAAA,YACA,MAAM,OAAO,MAAM,SAAS,YAAY;AAAA,UAC1C,CAAC;AACD,cAAI,MAAM,SAAS,cAAc;AAC/B,kBAAM,OAAO,OAAO,UAAU,wBAAwB;AAAA,cACpD,YAAY;AAAA,gBACV,mBAAmB;AAAA,gBACnB,oBAAoB;AAAA,gBACpB,yBAAyB,MAAM;AAAA,gBAC/B,0BAA0B,MAAM,eAAe;AAAA,cACjD;AAAA,YACF,CAAC;AACD,iBAAK,UAAU,EAAE,MAAM,eAAe,OAAO,SAAS,aAAa,CAAC;AACpE,iBAAK,IAAI;AAAA,UACX;AACA;AAAA,QAEF,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AACH,sBAAY,KAAK,OAAO,MAAM,cAAc,GAAG;AAAA,YAC7C,SAAS,MAAM,KAAK,QAAQ,SAAS,EAAE;AAAA,YACvC;AAAA,YACA,MAAM,MAAM,QAAQ;AAAA,UACtB,CAAC;AACD;AAAA,QAEF,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AACH,sBAAY,SAAS,IAAI,GAAG;AAAA,YAC1B,SAAS,MAAM,KAAK,QAAQ,aAAa,EAAE;AAAA,YAC3C;AAAA,UACF,CAAC;AACD;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prismakit/opentelemetry",
3
- "version": "3.2.0",
3
+ "version": "4.0.0",
4
4
  "description": "OpenTelemetry adapter for @prismakit/core telemetry events",
5
5
  "license": "Apache-2.0",
6
6
  "engines": {
@@ -24,11 +24,11 @@
24
24
  "README.md"
25
25
  ],
26
26
  "dependencies": {
27
- "@prismakit/core": "3.2.0"
27
+ "@prismakit/core": "4.0.0"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "@opentelemetry/api": ">=1.9.0",
31
- "@prismakit/core": ">=3.2.0 <4"
31
+ "@prismakit/core": ">=4.0.0 <5"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@opentelemetry/api": "^1.9.0",
@@ -18,7 +18,7 @@ export type CreatePrismaKitTelemetryOptions = {
18
18
  prefix?: string;
19
19
  /**
20
20
  * When set, also enable core `query.slow` emission at this threshold (ms).
21
- * Nest `queryLog.slowThreshold` remains the preferred Nest path.
21
+ * Prefer Nest `telemetry.slowThreshold` / `telemetry.onSlowQuery`.
22
22
  */
23
23
  slowThreshold?: number;
24
24
  };