CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-prisma--internals

Comprehensive internal utility library for Prisma's CLI operations, schema management, generator handling, and engine interactions

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

tracing.mddocs/

Tracing and Observability

The tracing domain provides comprehensive distributed tracing support with OpenTelemetry integration for monitoring, debugging, and performance analysis of Prisma operations across the entire request lifecycle.

Types and Interfaces

Core Tracing Types

SpanCallback<R>

Callback function signature for span execution with optional span and context parameters.

type SpanCallback<R> = (span?: Span, context?: Context) => R

Parameters:

  • span?: Span - Optional OpenTelemetry span instance
  • context?: Context - Optional tracing context

Returns: R - Return value from callback execution

ExtendedSpanOptions

Extended options for creating and configuring tracing spans.

interface ExtendedSpanOptions {
  name: string          // Span name/operation identifier
  internal?: boolean    // Whether span is internal to Prisma
  active?: boolean      // Whether span propagates context
  context?: Context     // Context to append span to
}

Properties:

  • name: string - Descriptive name for the span operation
  • internal?: boolean - Mark as internal span (for Prisma internals)
  • active?: boolean - Whether span should propagate context to child operations
  • context?: Context - Parent context to attach span to

Time and Identification Types

HrTime

High-resolution time tuple for precise timing measurements.

type HrTime = [number, number]

Format: [seconds, nanoseconds] - High-precision timestamp

Example:

const startTime: HrTime = [1640995200, 123456789]
// Represents 1640995200.123456789 seconds since epoch

EngineSpanId

Unique identifier for engine-generated spans.

type EngineSpanId = string

Format: UUID or hex-encoded unique identifier

EngineSpanKind

Categorization of engine spans by their operational context.

type EngineSpanKind = 'client' | 'internal'

Values:

  • 'client' - Client-facing operations (queries, mutations)
  • 'internal' - Internal engine operations (connection management, parsing)

Engine Tracing Structures

EngineSpan

Complete span information from the Prisma engine with timing and relationship data.

interface EngineSpan {
  id: EngineSpanId              // Unique span identifier
  parentId: string | null       // Parent span ID (null for root spans)
  name: string                  // Operation name
  startTime: HrTime            // Span start timestamp
  endTime: HrTime              // Span end timestamp
  kind: EngineSpanKind         // Span category
  attributes?: Record<string, unknown> // Optional span attributes
  links?: EngineSpanId[]       // Optional linked span IDs
}

Usage for Performance Analysis:

function analyzeSpanPerformance(span: EngineSpan): {
  duration: number
  category: string
} {
  // Calculate duration from HrTime
  const startMs = span.startTime[0] * 1000 + span.startTime[1] / 1000000
  const endMs = span.endTime[0] * 1000 + span.endTime[1] / 1000000
  const duration = endMs - startMs
  
  return {
    duration,
    category: span.kind === 'client' ? 'Query Operation' : 'Engine Internal'
  }
}

Event and Logging Types

LogLevel

Logging severity levels for trace events and debugging.

type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'query'

Levels:

  • 'trace' - Finest level debugging information
  • 'debug' - Detailed debugging information
  • 'info' - General informational messages
  • 'warn' - Warning conditions
  • 'error' - Error conditions
  • 'query' - Database query operations

EngineTraceEvent

Trace event with timing, context, and structured attributes.

interface EngineTraceEvent {
  spanId: EngineSpanId                    // Associated span identifier
  target: string                         // Event target/source module
  level: LogLevel                        // Event severity level
  timestamp: HrTime                      // Event timestamp
  attributes: Record<string, unknown>    // Event attributes
}

Common Attributes:

  • message?: string - Event message
  • query?: string - SQL query (for query events)
  • duration_ms?: number - Operation duration
  • params?: unknown[] - Query parameters

Example:

const queryEvent: EngineTraceEvent = {
  spanId: 'span-123',
  target: 'query_engine::executor',
  level: 'query',
  timestamp: [1640995200, 456789123],
  attributes: {
    message: 'Executing database query',
    query: 'SELECT * FROM users WHERE id = $1',
    params: [42],
    duration_ms: 15.2
  }
}

Complete Tracing Structure

EngineTrace

Complete tracing information containing all spans and events for an operation.

interface EngineTrace {
  spans: EngineSpan[]           // All spans in the trace
  events: EngineTraceEvent[]    // All events in the trace
}

Usage for Trace Analysis:

function analyzeTrace(trace: EngineTrace): {
  totalDuration: number
  spanCount: number
  queryCount: number
  errorCount: number
} {
  const queryEvents = trace.events.filter(e => e.level === 'query')
  const errorEvents = trace.events.filter(e => e.level === 'error')
  
  // Find root span (no parent) to calculate total duration
  const rootSpan = trace.spans.find(s => s.parentId === null)
  let totalDuration = 0
  
  if (rootSpan) {
    const startMs = rootSpan.startTime[0] * 1000 + rootSpan.startTime[1] / 1000000
    const endMs = rootSpan.endTime[0] * 1000 + rootSpan.endTime[1] / 1000000
    totalDuration = endMs - startMs
  }
  
  return {
    totalDuration,
    spanCount: trace.spans.length,
    queryCount: queryEvents.length,
    errorCount: errorEvents.length
  }
}

Tracing Interface

TracingHelper

Core interface for tracing operations and span management.

interface TracingHelper {
  isEnabled(): boolean
  getTraceParent(context?: Context): string
  dispatchEngineSpans(spans: EngineSpan[]): void
  getActiveContext(): Context | undefined
  runInChildSpan<R>(
    nameOrOptions: string | ExtendedSpanOptions,
    callback: SpanCallback<R>
  ): R
}

Methods:

isEnabled(): boolean

Checks if tracing is currently enabled and available.

getTraceParent(context?: Context): string

Gets the trace parent header for distributed tracing propagation.

dispatchEngineSpans(spans: EngineSpan[]): void

Processes and forwards engine spans to the tracing backend.

getActiveContext(): Context | undefined

Retrieves the current active tracing context.

runInChildSpan<R>(nameOrOptions, callback): R

Executes callback within a new child span context.

Parameters:

  • nameOrOptions: string | ExtendedSpanOptions - Span name or full options
  • callback: SpanCallback<R> - Function to execute within span

Global Tracing Configuration

PrismaInstrumentationGlobalValue

Global configuration interface for Prisma instrumentation and tracing.

interface PrismaInstrumentationGlobalValue {
  helper?: TracingHelper    // Optional tracing helper instance
}

Global Access:

declare global {
  var __PRISMA_INSTRUMENTATION__: PrismaInstrumentationGlobalValue | undefined
}

Examples

Basic Tracing Setup and Usage

import type { 
  TracingHelper,
  ExtendedSpanOptions,
  EngineSpan,
  EngineTrace 
} from '@prisma/internals'

class PrismaTracingManager {
  private helper?: TracingHelper
  
  constructor() {
    // Check for global tracing helper
    this.helper = globalThis.__PRISMA_INSTRUMENTATION__?.helper
  }
  
  /**
   * Check if tracing is available and enabled
   */
  isTracingEnabled(): boolean {
    return this.helper?.isEnabled() ?? false
  }
  
  /**
   * Execute operation with tracing
   */
  async traceOperation<T>(
    operationName: string,
    operation: () => Promise<T>,
    options?: Partial<ExtendedSpanOptions>
  ): Promise<T> {
    if (!this.helper || !this.helper.isEnabled()) {
      // No tracing - execute directly
      return await operation()
    }
    
    const spanOptions: ExtendedSpanOptions = {
      name: operationName,
      internal: false,
      active: true,
      ...options
    }
    
    return this.helper.runInChildSpan(spanOptions, async (span, context) => {
      try {
        const result = await operation()
        
        // Add success attributes
        if (span) {
          span.setAttributes({
            'operation.status': 'success',
            'operation.name': operationName
          })
        }
        
        return result
      } catch (error) {
        // Add error attributes
        if (span) {
          span.recordException(error)
          span.setAttributes({
            'operation.status': 'error',
            'operation.name': operationName,
            'error.message': error.message
          })
        }
        
        throw error
      }
    })
  }
  
  /**
   * Process engine spans for analysis
   */
  processEngineSpans(spans: EngineSpan[]): void {
    if (!this.helper) return
    
    // Add custom processing before forwarding
    const processedSpans = spans.map(span => ({
      ...span,
      attributes: {
        ...span.attributes,
        'prisma.version': '5.0.0', // Add version info
        'processed_at': Date.now()
      }
    }))
    
    this.helper.dispatchEngineSpans(processedSpans)
  }
  
  /**
   * Get trace context for propagation
   */
  getTraceContext(): string | undefined {
    if (!this.helper) return undefined
    
    const activeContext = this.helper.getActiveContext()
    return this.helper.getTraceParent(activeContext)
  }
}

Advanced Trace Analysis

import type {
  EngineTrace,
  EngineSpan,
  EngineTraceEvent,
  LogLevel
} from '@prisma/internals'

interface TraceMetrics {
  totalDuration: number
  spanCount: number
  queryCount: number
  errorCount: number
  slowestQuery: {
    query: string
    duration: number
  } | null
  spanHierarchy: SpanNode[]
}

interface SpanNode {
  span: EngineSpan
  children: SpanNode[]
  events: EngineTraceEvent[]
  duration: number
}

class TraceAnalyzer {
  
  /**
   * Comprehensive trace analysis
   */
  analyzeTrace(trace: EngineTrace): TraceMetrics {
    const spanHierarchy = this.buildSpanHierarchy(trace.spans, trace.events)
    const rootSpan = spanHierarchy[0] // Assuming first is root
    
    const queryEvents = trace.events.filter(e => e.level === 'query')
    const errorEvents = trace.events.filter(e => e.level === 'error')
    
    // Find slowest query
    let slowestQuery = null
    let maxDuration = 0
    
    for (const event of queryEvents) {
      const duration = event.attributes.duration_ms as number || 0
      if (duration > maxDuration) {
        maxDuration = duration
        slowestQuery = {
          query: event.attributes.query as string || 'Unknown',
          duration
        }
      }
    }
    
    return {
      totalDuration: rootSpan ? rootSpan.duration : 0,
      spanCount: trace.spans.length,
      queryCount: queryEvents.length,
      errorCount: errorEvents.length,
      slowestQuery,
      spanHierarchy
    }
  }
  
  /**
   * Build hierarchical span tree
   */
  private buildSpanHierarchy(
    spans: EngineSpan[],
    events: EngineTraceEvent[]
  ): SpanNode[] {
    const spanMap = new Map<string, SpanNode>()
    const rootSpans: SpanNode[] = []
    
    // Create span nodes
    for (const span of spans) {
      const node: SpanNode = {
        span,
        children: [],
        events: events.filter(e => e.spanId === span.id),
        duration: this.calculateSpanDuration(span)
      }
      
      spanMap.set(span.id, node)
      
      if (!span.parentId) {
        rootSpans.push(node)
      }
    }
    
    // Build parent-child relationships
    for (const span of spans) {
      if (span.parentId) {
        const parent = spanMap.get(span.parentId)
        const child = spanMap.get(span.id)
        
        if (parent && child) {
          parent.children.push(child)
        }
      }
    }
    
    return rootSpans
  }
  
  /**
   * Calculate span duration from HrTime
   */
  private calculateSpanDuration(span: EngineSpan): number {
    const startMs = span.startTime[0] * 1000 + span.startTime[1] / 1000000
    const endMs = span.endTime[0] * 1000 + span.endTime[1] / 1000000
    return endMs - startMs
  }
  
  /**
   * Generate performance report
   */
  generateReport(metrics: TraceMetrics): string {
    let report = '🔍 Trace Performance Report\n'
    report += '═'.repeat(50) + '\n\n'
    
    report += `📊 Overview:\n`
    report += `   Total Duration: ${metrics.totalDuration.toFixed(2)}ms\n`
    report += `   Spans: ${metrics.spanCount}\n`
    report += `   Database Queries: ${metrics.queryCount}\n`
    report += `   Errors: ${metrics.errorCount}\n\n`
    
    if (metrics.slowestQuery) {
      report += `🐌 Slowest Query (${metrics.slowestQuery.duration.toFixed(2)}ms):\n`
      report += `   ${metrics.slowestQuery.query}\n\n`
    }
    
    report += `📈 Span Hierarchy:\n`
    report += this.renderSpanHierarchy(metrics.spanHierarchy, 0)
    
    return report
  }
  
  /**
   * Render span hierarchy as tree
   */
  private renderSpanHierarchy(nodes: SpanNode[], depth: number): string {
    let output = ''
    const indent = '  '.repeat(depth)
    
    for (const node of nodes) {
      const icon = node.span.kind === 'client' ? '🔵' : '🔘'
      output += `${indent}${icon} ${node.span.name} (${node.duration.toFixed(2)}ms)\n`
      
      // Show events for this span
      for (const event of node.events) {
        const eventIcon = this.getEventIcon(event.level)
        output += `${indent}  ${eventIcon} ${event.attributes.message || event.target}\n`
      }
      
      // Recursively render children
      if (node.children.length > 0) {
        output += this.renderSpanHierarchy(node.children, depth + 1)
      }
    }
    
    return output
  }
  
  private getEventIcon(level: LogLevel): string {
    switch (level) {
      case 'error': return '🔴'
      case 'warn': return '🟡'
      case 'query': return '🗃️'
      case 'info': return 'ℹ️'
      case 'debug': return '🔧'
      case 'trace': return '🔍'
      default: return '📝'
    }
  }
}

Custom Tracing Implementation

import type {
  TracingHelper,
  ExtendedSpanOptions,
  SpanCallback,
  EngineSpan
} from '@prisma/internals'

interface CustomSpan {
  id: string
  name: string
  startTime: number
  endTime?: number
  attributes: Record<string, any>
  parent?: CustomSpan
}

class CustomTracingHelper implements TracingHelper {
  private enabled = true
  private spans = new Map<string, CustomSpan>()
  private activeSpan?: CustomSpan
  
  isEnabled(): boolean {
    return this.enabled
  }
  
  getTraceParent(context?: any): string {
    if (this.activeSpan) {
      return `00-${this.generateTraceId()}-${this.activeSpan.id}-01`
    }
    return `00-${this.generateTraceId()}-${this.generateSpanId()}-01`
  }
  
  dispatchEngineSpans(spans: EngineSpan[]): void {
    console.log(`📤 Dispatching ${spans.length} engine spans`)
    
    for (const span of spans) {
      console.log(`   Span: ${span.name} (${span.kind})`)
      if (span.attributes) {
        console.log(`     Attributes:`, span.attributes)
      }
    }
  }
  
  getActiveContext(): any {
    return { activeSpan: this.activeSpan }
  }
  
  runInChildSpan<R>(
    nameOrOptions: string | ExtendedSpanOptions,
    callback: SpanCallback<R>
  ): R {
    const options = typeof nameOrOptions === 'string' 
      ? { name: nameOrOptions }
      : nameOrOptions
    
    const span: CustomSpan = {
      id: this.generateSpanId(),
      name: options.name,
      startTime: Date.now(),
      attributes: {},
      parent: this.activeSpan
    }
    
    this.spans.set(span.id, span)
    const previousActive = this.activeSpan
    this.activeSpan = span
    
    try {
      // Create mock OpenTelemetry span-like object
      const mockSpan = {
        setAttributes: (attrs: Record<string, any>) => {
          Object.assign(span.attributes, attrs)
        },
        recordException: (error: Error) => {
          span.attributes.error = {
            message: error.message,
            stack: error.stack
          }
        }
      }
      
      const result = callback(mockSpan as any, { activeSpan: span })
      
      span.endTime = Date.now()
      
      if (options.internal !== true) {
        console.log(`✅ Span completed: ${span.name} (${span.endTime - span.startTime}ms)`)
      }
      
      return result
      
    } catch (error) {
      span.endTime = Date.now()
      span.attributes.error = {
        message: error.message,
        stack: error.stack
      }
      
      console.log(`❌ Span failed: ${span.name} (${span.endTime - span.startTime}ms)`)
      throw error
      
    } finally {
      this.activeSpan = previousActive
    }
  }
  
  private generateTraceId(): string {
    return Math.random().toString(16).substring(2, 18).padStart(16, '0')
  }
  
  private generateSpanId(): string {
    return Math.random().toString(16).substring(2, 10).padStart(8, '0')
  }
  
  /**
   * Get all collected spans
   */
  getCollectedSpans(): CustomSpan[] {
    return Array.from(this.spans.values())
  }
  
  /**
   * Clear all spans
   */
  clearSpans(): void {
    this.spans.clear()
  }
}

// Usage example with Prisma operations
async function tracedPrismaOperations() {
  const tracingHelper = new CustomTracingHelper()
  
  // Install as global helper
  globalThis.__PRISMA_INSTRUMENTATION__ = {
    helper: tracingHelper
  }
  
  const manager = new PrismaTracingManager()
  
  // Traced database operations
  await manager.traceOperation('user-creation', async () => {
    // Simulate user creation
    await new Promise(resolve => setTimeout(resolve, 100))
    
    await manager.traceOperation('email-validation', async () => {
      // Simulate email validation
      await new Promise(resolve => setTimeout(resolve, 50))
    })
    
    await manager.traceOperation('password-hashing', async () => {
      // Simulate password hashing
      await new Promise(resolve => setTimeout(resolve, 200))
    })
  })
  
  // Generate report
  const spans = tracingHelper.getCollectedSpans()
  console.log('\n📊 Collected Spans:')
  
  for (const span of spans) {
    const duration = (span.endTime || Date.now()) - span.startTime
    console.log(`   ${span.name}: ${duration}ms`)
    
    if (Object.keys(span.attributes).length > 0) {
      console.log(`     Attributes:`, span.attributes)
    }
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-prisma--internals

docs

binary-resolution.md

cli-utilities.md

database-operations.md

engine-commands.md

error-handling.md

generators.md

index.md

syntax-highlighting.md

tracing.md

utilities.md

tile.json