Skip to main content
Tracing helps you understand the flow of operations in your LLM application.

Creating Traces

With Callback

import { Muxx } from 'muxx';

const muxx = new Muxx();

const result = await muxx.trace('my-operation', async () => {
  // All LLM calls inside are grouped under this trace
  return 'result';
});

With Options

const result = await muxx.trace(
  'my-operation',
  async () => {
    return 'result';
  },
  {
    metadata: { userId: 'user_123' },
    captureInput: true,
    captureOutput: true,
  }
);

Creating Spans

Spans represent individual operations within a trace.
await muxx.trace('document-processing', async () => {
  const extracted = await muxx.span('extraction', async () => {
    // Extraction logic
    return extractedData;
  });

  const result = await muxx.span('summarization', async () => {
    // Summarization logic
    return summary;
  });

  return result;
});

Nested Spans

await muxx.trace('complex-operation', async () => {
  await muxx.span('step-1', async () => {
    await muxx.span('step-1a', async () => {
      // Deeply nested operation
    });

    await muxx.span('step-1b', async () => {
      // Another nested operation
    });
  });
});

Manual Trace Management

For more control, use manual trace management:
const trace = muxx.startTrace('my-operation');

try {
  // Your code here
  const span = trace.startSpan('sub-operation');
  try {
    // Span code
  } finally {
    span.end();
  }
} finally {
  trace.end();
}

Adding Metadata

await muxx.trace(
  'user-request',
  async () => {
    // Add metadata to current span
    muxx.getCurrentSpan()?.setMetadata({
      responseLength: response.length,
    });

    return response;
  },
  {
    metadata: {
      userId: 'user_123',
      environment: 'production',
    },
  }
);

Error Handling

Errors are automatically captured:
await muxx.trace('risky-operation', async () => {
  throw new Error('Something went wrong');
  // Error is captured with stack trace
});
Add custom error context:
await muxx.trace('operation', async () => {
  try {
    await riskyCode();
  } catch (error) {
    muxx.getCurrentSpan()?.setError(error as Error, {
      recoveryAttempted: true,
    });
    throw error;
  }
});

Parallel Operations

Traces handle parallel operations correctly:
await muxx.trace('parallel-calls', async () => {
  const [result1, result2] = await Promise.all([
    muxx.span('call-1', async () => client.chat.completions.create({ ... })),
    muxx.span('call-2', async () => client.chat.completions.create({ ... })),
  ]);

  return { result1, result2 };
});

Express Middleware

For Express apps, use the middleware:
import express from 'express';
import { Muxx } from 'muxx';

const app = express();
const muxx = new Muxx();

// Add tracing middleware
app.use(muxx.expressMiddleware());

app.post('/chat', async (req, res) => {
  // Each request automatically gets its own trace
  const response = await client.chat.completions.create({ ... });
  res.json(response);
});