Skip to main content
Glama

Prisma MCP Server

Official
by prisma
Apache 2.0
4
44,192
  • Linux
  • Apple
ActiveTracingHelper.ts5.01 kB
import { Attributes, Context, context as _context, Span, SpanKind, SpanOptions, trace, Tracer, TracerProvider, } from '@opentelemetry/api' import { EngineSpan, EngineSpanKind, ExtendedSpanOptions, SpanCallback, TracingHelper } from '@prisma/internals' // If true, will publish internal spans as well const showAllTraces = process.env.PRISMA_SHOW_ALL_TRACES === 'true' // https://www.w3.org/TR/trace-context/#examples-of-http-traceparent-headers // If traceparent ends with -00 this trace will not be sampled // the query engine needs the `10` for the span and trace id otherwise it does not parse this const nonSampledTraceParent = `00-10-10-00` type Options = { tracerProvider: TracerProvider ignoreSpanTypes: (string | RegExp)[] } function engineSpanKindToOtelSpanKind(engineSpanKind: EngineSpanKind): SpanKind { switch (engineSpanKind) { case 'client': return SpanKind.CLIENT case 'internal': default: // Other span kinds aren't currently supported return SpanKind.INTERNAL } } export class ActiveTracingHelper implements TracingHelper { private tracerProvider: TracerProvider private ignoreSpanTypes: (string | RegExp)[] constructor({ tracerProvider, ignoreSpanTypes }: Options) { this.tracerProvider = tracerProvider this.ignoreSpanTypes = ignoreSpanTypes } isEnabled(): boolean { return true } getTraceParent(context?: Context | undefined): string { const span = trace.getSpanContext(context ?? _context.active()) if (span) { return `00-${span.traceId}-${span.spanId}-0${span.traceFlags}` } return nonSampledTraceParent } dispatchEngineSpans(spans: EngineSpan[]): void { const tracer = this.tracerProvider.getTracer('prisma') const linkIds = new Map<string, string>() const roots = spans.filter((span) => span.parentId === null) for (const root of roots) { dispatchEngineSpan(tracer, root, spans, linkIds, this.ignoreSpanTypes) } } getActiveContext(): Context | undefined { return _context.active() } runInChildSpan<R>(options: string | ExtendedSpanOptions, callback: SpanCallback<R>): R { if (typeof options === 'string') { options = { name: options } } if (options.internal && !showAllTraces) { return callback() } const tracer = this.tracerProvider.getTracer('prisma') const context = options.context ?? this.getActiveContext() const name = `prisma:client:${options.name}` if (shouldIgnoreSpan(name, this.ignoreSpanTypes)) { return callback() } // these spans will not be nested by default even in recursive calls // it used to be useful for showing middleware sequentially instead of nested if (options.active === false) { const span = tracer.startSpan(name, options, context) return endSpan(span, callback(span, context)) } // by default spans are "active", which means context is propagated in // nested calls, which is useful for representing most of the calls return tracer.startActiveSpan(name, options, (span) => endSpan(span, callback(span, context))) } } function dispatchEngineSpan( tracer: Tracer, engineSpan: EngineSpan, allSpans: EngineSpan[], linkIds: Map<string, string>, ignoreSpanTypes: (string | RegExp)[], ) { if (shouldIgnoreSpan(engineSpan.name, ignoreSpanTypes)) return const spanOptions = { attributes: engineSpan.attributes as Attributes, kind: engineSpanKindToOtelSpanKind(engineSpan.kind), startTime: engineSpan.startTime, } satisfies SpanOptions tracer.startActiveSpan(engineSpan.name, spanOptions, (span) => { linkIds.set(engineSpan.id, span.spanContext().spanId) if (engineSpan.links) { span.addLinks( engineSpan.links.flatMap((link) => { const linkedId = linkIds.get(link) if (!linkedId) { return [] } return { context: { spanId: linkedId, traceId: span.spanContext().traceId, traceFlags: span.spanContext().traceFlags, }, } }), ) } const children = allSpans.filter((s) => s.parentId === engineSpan.id) for (const child of children) { dispatchEngineSpan(tracer, child, allSpans, linkIds, ignoreSpanTypes) } span.end(engineSpan.endTime) }) } function endSpan<T>(span: Span, result: T): T { if (isPromiseLike(result)) { return result.then( (value) => { span.end() return value }, (reason) => { span.end() throw reason }, ) as T } span.end() return result } function isPromiseLike(value: unknown): value is PromiseLike<unknown> { return value != null && typeof value['then'] === 'function' } function shouldIgnoreSpan(spanName: string, ignoreSpanTypes: (string | RegExp)[]): boolean { return ignoreSpanTypes.some((pattern) => typeof pattern === 'string' ? pattern === spanName : pattern.test(spanName), ) }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/prisma/prisma'

If you have feedback or need assistance with the MCP directory API, please join our Discord server