# Performance Monitoring and Tracing

OpenTelemetry-based performance monitoring with spans, traces, and distributed tracing support.

## Capabilities

### Span Creation and Management

Create and manage performance monitoring spans.

```typescript { .api }
/**
 * Start a new span and execute a callback within its context
 * @param context - Span configuration options
 * @param callback - Function to execute within the span
 * @returns Return value of the callback function
 */
function startSpan<T>(context: StartSpanOptions, callback: (span: Span) => T): T;

/**
 * Start a span manually with callback-based control
 * @param context - Span configuration options
 * @param callback - Function to execute with span and finish function
 * @returns Return value of the callback function
 */
function startSpanManual<T>(context: StartSpanOptions, callback: (span: Span, finish: () => void) => T): T;

/**
 * Start an inactive span that won't be automatically set as active
 * @param context - Span configuration options
 * @returns Inactive span instance
 */
function startInactiveSpan(context: StartSpanOptions): Span;
```

**Usage Examples:**

```typescript
import * as Sentry from "@sentry/node";

// Basic span with callback
const result = Sentry.startSpan(
  { name: "database-query", op: "db.query" },
  (span) => {
    span.setAttribute("db.query", "SELECT * FROM users");
    span.setAttribute("db.rows", 150);
    return database.query("SELECT * FROM users");
  }
);

// Manual span management with callback
const result = Sentry.startSpanManual({
  name: "file-processing",
  op: "file.process",
  attributes: {
    "file.name": fileName,
    "file.size": fileSize,
  },
}, (span, finish) => {
  try {
    const result = processFile(fileName);
    span.setStatus({ code: 1 }); // OK
    return result;
  } catch (error) {
    span.setStatus({ code: 2, message: error.message }); // ERROR
    throw error;
  } finally {
    finish(); // Ends the span
  }
});

// Inactive span for custom timing
const inactiveSpan = Sentry.startInactiveSpan({
  name: "background-task",
  op: "task.background",
});
// Span exists but isn't active in the context
setTimeout(() => {
  inactiveSpan.end();
}, 5000);
```

### Active Span Management

Work with the currently active span.

```typescript { .api }
/**
 * Get the currently active span
 * @returns Active span or undefined if no span is active
 */
function getActiveSpan(): Span | undefined;

/**
 * Execute a callback with a specific span as active
 * @param span - Span to set as active (or null to clear active span)
 * @param callback - Function to execute with the active span and scope
 * @returns Return value of the callback function
 */
function withActiveSpan<T>(span: Span | null, callback: (scope: Scope) => T): T;
```

**Usage Examples:**

```typescript
import * as Sentry from "@sentry/node";

// Get current active span
const activeSpan = Sentry.getActiveSpan();
if (activeSpan) {
  activeSpan.setAttribute("custom.metric", 42);
  activeSpan.addEvent("Processing started");
}

// Execute with specific active span
const parentSpan = Sentry.startSpanManual({ name: "parent-operation" });

Sentry.withActiveSpan(parentSpan, (scope) => {
  // Child spans created here will use parentSpan as parent
  Sentry.startSpan({ name: "child-operation" }, () => {
    // This span will be a child of parentSpan
    performChildOperation();
  });
});

parentSpan.end();

// Execute with no active span
Sentry.withActiveSpan(null, (scope) => {
  // Code here runs without an active span
  performIndependentOperation();
});
```

### Trace Management

Manage traces and distributed tracing.

```typescript { .api }
/**
 * Start a new trace (root span)
 * @param callback - Function to execute in the new trace
 * @returns Return value of the callback function
 */
function startNewTrace<T>(callback: () => T): T;

/**
 * Continue a distributed trace from trace data
 * @param tracingData - Trace propagation data
 * @param callback - Function to execute in the continued trace
 * @returns Return value of the callback function
 */
function continueTrace<T>(tracingData: TracingData, callback: () => T): T;

/**
 * Get trace propagation data for the current trace
 * @returns Trace data for propagating to downstream services
 */
function getTraceData(): TraceData;

/**
 * Get trace meta tags for HTML injection
 * @returns HTML meta tags string for trace propagation
 */
function getTraceMetaTags(): string;
```

**Usage Examples:**

```typescript
import * as Sentry from "@sentry/node";
import express from "express";

// Start a new trace
const result = Sentry.startNewTrace(() => {
  // This creates a new root span
  return Sentry.startSpan({ name: "background-job" }, () => {
    return processBackgroundJob();
  });
});

// Continue trace from incoming request
app.use((req, res, next) => {
  const tracingData = {
    "sentry-trace": req.headers["sentry-trace"],
    baggage: req.headers.baggage,
  };
  
  Sentry.continueTrace(tracingData, () => {
    Sentry.startSpan({ name: `${req.method} ${req.path}` }, () => {
      next();
    });
  });
});

// Get trace data for outgoing requests
function makeApiCall(url) {
  const traceData = Sentry.getTraceData();
  
  return fetch(url, {
    headers: {
      "sentry-trace": traceData["sentry-trace"],
      baggage: traceData.baggage || "",
    },
  });
}

// Inject trace meta tags in HTML response
app.get("/", (req, res) => {
  const metaTags = Sentry.getTraceMetaTags();
  res.send(`
    <html>
      <head>
        ${metaTags}
      </head>
      <body>Content here</body>
    </html>
  `);
});
```

### Span Utilities

Utility functions for working with spans.

```typescript { .api }
/**
 * Convert a span to JSON representation
 * @param span - Span to convert
 * @returns JSON representation of the span
 */
function spanToJSON(span: Span): SpanJSON;

/**
 * Get trace header from a span
 * @param span - Span to get header from
 * @returns Sentry trace header string
 */
function spanToTraceHeader(span: Span): string;

/**
 * Get baggage header from a span
 * @param span - Span to get baggage from
 * @returns Baggage header string
 */
function spanToBaggageHeader(span: Span): string;

/**
 * Update the name of a span
 * @param span - Span to update
 * @param name - New span name
 */
function updateSpanName(span: Span, name: string): void;

/**
 * Get all descendant spans of a span
 * @param span - Parent span
 * @returns Array of descendant spans
 */
function getSpanDescendants(span: Span): Span[];

/**
 * Get the root span of a span hierarchy
 * @param span - Span to find root for (optional, uses active span if not provided)
 * @returns Root span or undefined
 */
function getRootSpan(span?: Span): Span | undefined;
```

**Usage Examples:**

```typescript
import * as Sentry from "@sentry/node";

// Convert span to JSON for logging
const span = Sentry.getActiveSpan();
if (span) {
  const spanData = Sentry.spanToJSON(span);
  console.log("Span data:", spanData);
}

// Get headers for outgoing requests
function addTracingHeaders(span, headers) {
  if (span) {
    headers["sentry-trace"] = Sentry.spanToTraceHeader(span);
    headers.baggage = Sentry.spanToBaggageHeader(span);
  }
  return headers;
}

// Update span name based on route
function updateSpanForRoute(span, route) {
  if (span) {
    Sentry.updateSpanName(span, `${req.method} ${route}`);
  }
}

// Get all child spans for debugging
function debugSpanHierarchy(rootSpan) {
  const descendants = Sentry.getSpanDescendants(rootSpan);
  console.log(`Root span has ${descendants.length} descendants`);
  
  descendants.forEach((span, index) => {
    const spanData = Sentry.spanToJSON(span);
    console.log(`Child ${index}:`, spanData.description);
  });
}
```

### Tracing Control

Control tracing behavior and suppress instrumentation.

```typescript { .api }
/**
 * Execute a callback without tracing
 * @param callback - Function to execute without tracing
 * @returns Return value of the callback function
 */
function suppressTracing<T>(callback: () => T): T;
```

**Usage Examples:**

```typescript
import * as Sentry from "@sentry/node";

// Suppress tracing for sensitive operations
const sensitiveResult = Sentry.suppressTracing(() => {
  // This code won't create spans or traces
  return performSensitiveOperation();
});

// Suppress tracing for internal health checks
function healthCheck() {
  return Sentry.suppressTracing(() => {
    // Health check calls won't appear in traces
    return {
      database: checkDatabase(),
      cache: checkCache(),
      external_api: checkExternalApi(),
    };
  });
}

// Suppress tracing for high-frequency operations
function logMetrics() {
  return Sentry.suppressTracing(() => {
    // Don't trace metric collection to avoid noise
    collectAndSendMetrics();
  });
}
```

## Types

### Span Options and Configuration

```typescript { .api }
interface StartSpanOptions {
  /** Span name/description */
  name: string;
  /** Span attributes/tags */
  attributes?: Record<string, any>;
  /** Span start time (timestamp in milliseconds) */
  startTime?: number;
  /** Parent span (optional, uses active span if not provided) */
  parentSpan?: Span;
  /** Scope to use for the span */
  scope?: Scope;
  /** Only create span if there's a parent span */
  onlyIfParent?: boolean;
  /** Force this span to be a transaction */
  forceTransaction?: boolean;
  /** Span operation type */
  op?: string;
  /** Span origin */
  origin?: string;
}
```

### Span Interface

```typescript { .api }
interface Span {
  /** Get span context information */
  spanContext(): SpanContext;
  
  /** Set a single attribute */
  setAttribute(key: string, value: any): Span;
  
  /** Set multiple attributes */
  setAttributes(attributes: Record<string, any>): Span;
  
  /** Set span status */
  setStatus(status: SpanStatus): Span;
  
  /** Update span name */
  updateName(name: string): Span;
  
  /** Add an event to the span */
  addEvent(name: string, attributes?: Record<string, any>): Span;
  
  /** End the span */
  end(endTime?: number): void;
  
  /** Check if span is recording */
  isRecording(): boolean;
  
  /** Record an exception on the span */
  recordException(exception: Exception): void;
}

interface SpanContext {
  /** Trace ID */
  traceId: string;
  /** Span ID */
  spanId: string;
  /** Trace flags */
  traceFlags: number;
  /** Trace state */
  traceState?: string;
}

interface SpanStatus {
  /** Status code (0=unset, 1=ok, 2=error) */
  code: number;
  /** Optional status message */
  message?: string;
}
```

### Trace Data Types

```typescript { .api }
interface TraceData {
  /** Sentry trace header */
  "sentry-trace": string;
  /** Baggage header (optional) */
  baggage?: string;
}

interface TracingData {
  /** Sentry trace header */
  "sentry-trace"?: string;
  /** Baggage header */
  baggage?: string;
}

interface SpanJSON {
  /** Span description */
  description?: string;
  /** Span ID */
  span_id: string;
  /** Parent span ID */
  parent_span_id?: string;
  /** Trace ID */
  trace_id: string;
  /** Span operation */
  op?: string;
  /** Span origin */
  origin?: string;
  /** Span status */
  status?: string;
  /** Span tags */
  tags?: Record<string, any>;
  /** Span data */
  data?: Record<string, any>;
  /** Start timestamp */
  start_timestamp: number;
  /** End timestamp */
  timestamp?: number;
}
```

### Exception Type

```typescript { .api }
interface Exception {
  /** Exception type */
  type?: string;
  /** Exception value/message */
  value?: string;
  /** Exception mechanism */
  mechanism?: {
    type?: string;
    handled?: boolean;
    data?: Record<string, any>;
  };
  /** Exception stacktrace */
  stacktrace?: Stacktrace;
}
```