or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdcontext-correlation.mdindex.mdinitialization.mdlegacy-api.mdtelemetry-client.mdtelemetry-types.md
tile.json

context-correlation.mddocs/

Context and Correlation

Functions for managing request context and distributed tracing correlation across components. These APIs enable correlation of telemetry across service boundaries and asynchronous operations, maintaining trace context throughout the application lifecycle.

Capabilities

Correlation Context Management

Access and manage correlation context for the current request or operation.

/**
 * Returns an object that is shared across all code handling a given request
 * Used for request-scoped storage and cross-component correlation
 * @returns Correlation context object or null if correlation is disabled
 */
function getCorrelationContext(): ICorrelationContext | null;

interface ICorrelationContext {
  /** Operation context containing tracing information */
  operation: {
    /** Operation name */
    name: string;
    /** Operation ID (trace ID) */
    id: string;
    /** Parent operation ID */
    parentId: string;
    /** W3C trace parent context */
    traceparent?: ITraceparent;
    /** W3C trace state context */
    tracestate?: ITracestate;
  };
  /** Custom properties for cross-component correlation */
  customProperties: ICustomProperties;
}

interface ICustomProperties {
  /**
   * Get a custom property from the correlation context
   * @param key - Property key
   * @returns Property value or undefined
   */
  getProperty(key: string): string;

  /**
   * Store a custom property in the correlation context
   * Do not store sensitive information - properties are exposed via HTTP headers
   * @param key - Property key (comma and equals signs not allowed)
   * @param value - Property value (comma and equals signs not allowed)
   */
  setProperty(key: string, value: string): void;
}

interface ITraceparent {
  /** Legacy root ID for backward compatibility */
  legacyRootId: string;
  /** Parent span ID */
  parentId: string;
  /** Current span ID */
  spanId: string;
  /** Trace flags */
  traceFlag: string;
  /** Trace ID */
  traceId: string;
  /** Version number */
  version: string;
}

interface ITracestate {
  /** Field mappings for trace state */
  fieldmap: string[];
}

Usage Examples:

const appInsights = require("applicationinsights");

function processRequest(req, res) {
  // Get correlation context for current request
  const context = appInsights.getCorrelationContext();
  
  if (context) {
    console.log("Operation ID:", context.operation.id);
    console.log("Operation Name:", context.operation.name);
    
    // Store custom properties for cross-component correlation
    context.customProperties.setProperty("userId", req.user.id);
    context.customProperties.setProperty("sessionId", req.session.id);
    
    // Retrieve custom properties
    const userId = context.customProperties.getProperty("userId");
    console.log("Current user:", userId);
  }
  
  // Process request...
}

Operation Context Management

Start new operations and manage operation lifecycle for distributed tracing.

/**
 * Starts a fresh context or propagates the current internal one
 * @param context - Azure Functions context, HTTP request, or span context
 * @param request - HTTP request object (optional)
 * @returns New correlation context or null
 */
function startOperation(
  context: AzureFnContext | http.IncomingMessage | SpanContext | Span,
  request?: HttpRequest | string
): ICorrelationContext | null;

interface AzureFnContext {
  /** Trace context for Azure Functions */
  traceContext: TraceContext;
}

interface TraceContext {
  /** W3C traceparent header value */
  traceparent: string | null | undefined;
  /** W3C tracestate header value */
  tracestate: string | null | undefined;
  /** Additional trace attributes */
  attributes: { [k: string]: string } | null | undefined;
}

interface HttpRequest {
  /** HTTP method */
  method: string | null;
  /** Request URL */
  url: string;
  /** Request headers */
  headers: { [key: string]: string };
}

Usage Examples:

const appInsights = require("applicationinsights");
const http = require("http");

// Start operation from HTTP request
function handleRequest(req, res) {
  const operationContext = appInsights.startOperation(req, {
    method: req.method,
    url: req.url,
    headers: req.headers
  });
  
  if (operationContext) {
    console.log("Started operation:", operationContext.operation.name);
    
    // Process within operation context
    processWithContext(operationContext);
  }
}

// Azure Functions usage
module.exports = async function(azureFnContext, req) {
  const operationContext = appInsights.startOperation(azureFnContext, req);
  
  if (operationContext) {
    // Function processing within operation context
    const result = await processFunction(req);
    
    appInsights.defaultClient.trackEvent({
      name: "FunctionExecuted",
      properties: {
        operationId: operationContext.operation.id,
        functionName: azureFnContext.executionContext.functionName
      }
    });
    
    return result;
  }
};

Callback Wrapping

Wrap asynchronous callbacks to maintain correlation context across async boundaries.

/**
 * Returns a function that will get the same correlation context within its body
 * Use when automatic dependency correlation is not propagating correctly
 * @param fn - Function to wrap with correlation context
 * @param context - Specific correlation context to use (optional, uses current if not provided)
 * @returns Wrapped function that preserves correlation context
 */
function wrapWithCorrelationContext<T>(fn: T, context?: ICorrelationContext): T;

Usage Examples:

const appInsights = require("applicationinsights");

function processWithAsyncCallback() {
  const currentContext = appInsights.getCorrelationContext();
  
  // Wrap setTimeout callback to preserve context
  const wrappedCallback = appInsights.wrapWithCorrelationContext(() => {
    // This callback will have the same correlation context as the parent
    const context = appInsights.getCorrelationContext();
    console.log("Async operation ID:", context?.operation.id);
    
    appInsights.defaultClient.trackEvent({
      name: "AsyncOperationCompleted"
    });
  }, currentContext);
  
  setTimeout(wrappedCallback, 1000);
}

// Wrap Promise callbacks
function processWithPromise() {
  return new Promise((resolve, reject) => {
    const wrappedResolve = appInsights.wrapWithCorrelationContext(resolve);
    const wrappedReject = appInsights.wrapWithCorrelationContext(reject);
    
    // Async operation
    someAsyncOperation((err, result) => {
      if (err) {
        wrappedReject(err);
      } else {
        wrappedResolve(result);
      }
    });
  });
}

// Wrap event handlers
const wrappedHandler = appInsights.wrapWithCorrelationContext((data) => {
  // Event handler maintains correlation context
  const context = appInsights.getCorrelationContext();
  
  appInsights.defaultClient.trackEvent({
    name: "EventProcessed",
    properties: {
      operationId: context?.operation.id,
      eventType: data.type
    }
  });
});

eventEmitter.on('data', wrappedHandler);

Distributed Tracing Modes

Configure distributed tracing header propagation behavior.

/**
 * Distributed tracing modes for header propagation
 */
enum DistributedTracingModes {
  /** Send Application Insights correlation headers only */
  AI = 0,
  /** Send both W3C Trace Context headers and Application Insights headers (default) */
  AI_AND_W3C = 1
}

Usage Examples:

const appInsights = require("applicationinsights");

// Configure distributed tracing mode
appInsights
  .setup()
  .setDistributedTracingMode(appInsights.DistributedTracingModes.AI_AND_W3C)
  .start();

// Check current mode
const currentMode = appInsights.defaultClient.config.distributedTracingMode;
if (currentMode === appInsights.DistributedTracingModes.AI_AND_W3C) {
  console.log("Using W3C and AI correlation headers");
}

Context Propagation Best Practices

Automatic Context Propagation: Application Insights automatically propagates context for most scenarios:

// Context is automatically propagated through:
// - HTTP requests (incoming and outgoing)  
// - Database calls
// - Message queue operations
// - Timer callbacks
// - Promise chains

const appInsights = require("applicationinsights");
appInsights.setup().start();

// Context automatically flows through this chain
app.get('/api/users', async (req, res) => {
  // Context available here
  const users = await database.getUsers(); // Context propagated to DB call
  
  const enriched = await Promise.all(
    users.map(async user => {
      // Context propagated to each async operation
      const profile = await externalAPI.getProfile(user.id);
      return { ...user, profile };
    })
  );
  
  res.json(enriched);
});

Manual Context Management: Use manual context functions when automatic propagation fails:

// Scenario: Custom async libraries that don't auto-propagate context
function customAsyncOperation(callback) {
  const context = appInsights.getCorrelationContext();
  
  // Store context information
  if (context) {
    context.customProperties.setProperty("operationType", "custom");
  }
  
  // Wrap callback to maintain context
  const wrappedCallback = appInsights.wrapWithCorrelationContext(callback, context);
  
  // Use wrapped callback
  customLibrary.doAsync(wrappedCallback);
}

Cross-Service Correlation: Propagate context across service boundaries:

async function callDownstreamService(data) {
  const context = appInsights.getCorrelationContext();
  
  const headers = {
    'Content-Type': 'application/json'
  };
  
  // Context headers are automatically added by Application Insights
  // But you can access them manually if needed
  if (context?.operation.traceparent) {
    headers['traceparent'] = context.operation.traceparent;
  }
  
  const response = await fetch('https://downstream-service/api/process', {
    method: 'POST',
    headers,
    body: JSON.stringify(data)
  });
  
  return response.json();
}

Context Storage Warnings

Security Considerations:

  • Never store sensitive information in correlation context
  • Custom properties are exposed via HTTP headers for cross-component correlation
  • Properties may be logged and transmitted in telemetry
// ❌ DON'T store sensitive data
context.customProperties.setProperty("password", userPassword); // NEVER DO THIS
context.customProperties.setProperty("creditCard", cardNumber); // NEVER DO THIS

// ✅ DO store correlation identifiers
context.customProperties.setProperty("userId", user.id);
context.customProperties.setProperty("tenantId", tenant.id);
context.customProperties.setProperty("sessionId", session.id);
context.customProperties.setProperty("operationType", "checkout");