> ## Documentation Index
> Fetch the complete documentation index at: https://www.adaline.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Trace

# Trace Class

The `Trace` class represents a high-level operation or workflow in your LLM application. Traces capture the entire lifecycle of a request, batch job, or user interaction, and can contain multiple child spans for granular tracking.

## Overview

A trace is the top-level unit of observability that represents:

* A single user request to your API
* A background job or workflow
* A conversation turn in a chatbot
* A complete RAG pipeline execution
* Any end-to-end operation you want to track

Traces contain:

* **Metadata**: name, status, timestamps, tags, attributes
* **Context**: session ID, reference ID
* **Children**: one or more spans representing sub-operations

## Creation

Create a trace using the `Monitor.logTrace()` method:

```typescript theme={null}
const trace = monitor.logTrace({
  name: 'User Login',
  sessionId: 'session-abc-123',
  tags: ['auth', 'production'],
  attributes: { userId: 'user-456' }
});
```

## Properties

### trace

```typescript theme={null}
trace: CreateLogTraceRequest
```

The underlying trace request object that will be sent to the API. Contains all trace metadata.

**Structure:**

```typescript theme={null}
{
  projectId: string;
  trace: {
    name: string;
    status: TraceStatus;
    sessionId?: string;
    referenceId: string;
    tags?: string[];
    attributes?: Record<string, LogAttributesValue>;  // LogAttributesValue = string | number | boolean
    startedAt: number;     // Unix timestamp in milliseconds
    endedAt?: number;      // Set when trace.end() is called
  }
}
```

### traceId

```typescript theme={null}
traceId: string | undefined
```

The server-assigned trace ID, set after the trace is successfully flushed to the API.

```typescript theme={null}
const trace = monitor.logTrace({ name: 'Operation' });
console.log(trace.traceId); // undefined (not flushed yet)

trace.end();
await monitor.flush();

console.log(trace.traceId); // "trace_abc123xyz" (assigned by server)
```

## Methods

### logSpan()

Create a child span within this trace.

```typescript theme={null}
logSpan(options: LogSpanOptions): Span
```

#### Parameters

**options** `object` *required*

**properties**

**name** `string` *required*

Human-readable name for the span (e.g., "LLM Call", "Database Query").

**status** `SpanStatus` (default: unknown)

Initial [SpanStatus](https://www.adaline.ai/docs/reference/sdk/v2/typescript/types/SpanStatus.md): `'success' | 'failure' | 'aborted' | 'cancelled' | 'unknown'`

**referenceId** `string`

Custom reference ID. Auto-generated UUID if not provided.

**promptId** `string`

ID of the prompt used in this span (for LLM calls).

**deploymentId** `string | null`

ID of the deployment used in this span.

**runEvaluation** `boolean`

Whether to run evaluators on this span after completion.

**tags** `string[]`

Tags for categorization (e.g., `['llm', 'openai']`).

**attributes** `Record\<string, LogAttributesValue\>`

Additional metadata (e.g., `{ model: 'gpt-4o', tokens: 1500 }`). [LogAttributesValue](https://www.adaline.ai/docs/reference/sdk/v2/typescript/types/LogAttributesValue.md) = `string | number | boolean`

**content** `LogSpanContent`

[LogSpanContent](https://www.adaline.ai/docs/reference/sdk/v2/typescript/types/LogSpanContent.md) (input/output data). Defaults to `monitor.defaultContent`.

#### Returns

**span** `Span`

A new Span instance. See [Span Class](https://www.adaline.ai/docs/reference/sdk/v2/typescript/classes/span.md) for details.

#### Examples

```typescript Basic Span theme={null}
const trace = monitor.logTrace({ name: 'API Request' });

const span = trace.logSpan({
  name: 'Process Data'
});

// Do work...
await processData();

span.update({ status: 'success' });
span.end();
trace.end();
```

```typescript LLM Call Span theme={null}
const trace = monitor.logTrace({
  name: 'Chat Completion',
  sessionId: userId
});

const llmSpan = trace.logSpan({
  name: 'OpenAI GPT-4',
  promptId: deployment.promptId,
  deploymentId: deployment.id,
  runEvaluation: true,
  tags: ['llm', 'openai', 'gpt-4o'],
  attributes: {
    model: 'gpt-4o',
    temperature: 0.7
  }
});

const response = await openai.chat.completions.create({ /* ... */ });

llmSpan.update({
  status: 'success',
  content: {
    type: 'Model',
    provider: 'openai',
    model: 'gpt-4o',
    input: JSON.stringify(messages),
    output: JSON.stringify(response.choices[0].message)
  }
});

llmSpan.end();
trace.end();
```

```typescript Nested Spans theme={null}
const trace = monitor.logTrace({ name: 'RAG Pipeline' });

// Parent span
const ragSpan = trace.logSpan({
  name: 'RAG Operation',
  tags: ['rag']
});

// Child spans
const embeddingSpan = ragSpan.logSpan({
  name: 'Generate Embedding',
  tags: ['embedding']
});
embeddingSpan.end();

const retrievalSpan = ragSpan.logSpan({
  name: 'Vector Search',
  tags: ['retrieval']
});
retrievalSpan.end();

const llmSpan = ragSpan.logSpan({
  name: 'Generate Answer',
  tags: ['llm']
});
llmSpan.end();

ragSpan.end();
trace.end();
```

### update()

Update trace metadata in place.

```typescript theme={null}
update(updates: TraceUpdates): this
```

#### Parameters

**updates** `object` *required*

Partial updates to apply to the trace.

**properties**

**name** `string`

Update the trace name.

**status** `TraceStatus`

Update the [TraceStatus](https://www.adaline.ai/docs/reference/sdk/v2/typescript/types/TraceStatus.md): `'success' | 'failure' | 'aborted' | 'cancelled' | 'pending' | 'unknown'`

**tags** `string[]`

Update tags (replaces existing tags).

**attributes** `Record\<string, LogAttributesValue\>`

Update attributes (merges with existing attributes). [LogAttributesValue](https://www.adaline.ai/docs/reference/sdk/v2/typescript/types/LogAttributesValue.md) = `string | number | boolean`

#### Returns

Returns `this` for method chaining.

#### Examples

```typescript Update Status theme={null}
const trace = monitor.logTrace({
  name: 'Process Order',
  status: 'pending'
});

try {
  await processOrder();
  trace.update({ status: 'success' });
} catch (error) {
  trace.update({ status: 'failure' });
}

trace.end();
```

```typescript Add Attributes theme={null}
const trace = monitor.logTrace({ name: 'User Request' });

// Add attribute after getting user info
const userId = await getUserId();
trace.update({
  attributes: { userId }
});

// Add more attributes
trace.update({
  attributes: { 
    processingTime: Date.now() - startTime,
    itemsProcessed: 42
  }
});

trace.end();
```

```typescript Method Chaining theme={null}
monitor.logTrace({ name: 'Quick Operation' })
  .update({ status: 'pending' })
  .update({ tags: ['fast', 'important'] })
  .end();
```

```typescript Update Everything theme={null}
trace.update({
  name: 'Updated Name',
  status: 'success',
  tags: ['completed', 'verified'],
  attributes: {
    duration: 1234,
    outcome: 'positive'
  }
});
```

### end()

Mark the trace as complete and ready to be flushed.

```typescript theme={null}
end(): string | undefined
```

#### Behavior

1. Sets `endedAt` timestamp if not already set
2. Marks the trace as `ready` in the monitor's buffer
3. Recursively ends all child spans (and their descendants)
4. Returns the trace's reference ID

> [!WARNING]
>
> Always call `end()` on your traces! Traces that are never ended will never be flushed to the API.

#### Returns

**referenceId** `string | undefined`

The trace's reference ID for correlation with external systems.

#### Examples

```typescript Basic theme={null}
const trace = monitor.logTrace({ name: 'Operation' });

// Do work...

trace.end(); // Required!
```

```typescript Try-Finally Pattern theme={null}
const trace = monitor.logTrace({ name: 'Critical Operation' });

try {
  await doWork();
  trace.update({ status: 'success' });
} catch (error) {
  trace.update({ status: 'failure' });
  throw error;
} finally {
  trace.end(); // Always called, even if error thrown
}
```

```typescript Get Reference ID theme={null}
const trace = monitor.logTrace({
  name: 'Async Job',
  referenceId: `job-${jobId}`
});

// Do work...

const refId = trace.end();
console.log(`Trace completed: ${refId}`); // "job-123"
```

```typescript Auto-End Children theme={null}
const trace = monitor.logTrace({ name: 'Parent' });

const span1 = trace.logSpan({ name: 'Child 1' });
const span2 = span1.logSpan({ name: 'Grandchild' });
const span3 = trace.logSpan({ name: 'Child 2' });

// Don't need to manually end children
trace.end(); // Automatically ends span1, span2, span3
```

## Complete Examples

### Example 1: Simple API Request

```typescript theme={null}
import { Adaline } from '@adaline/client';
import { Gateway } from '@adaline/gateway';
import { OpenAI } from '@adaline/openai';

const adaline = new Adaline();
const gateway = new Gateway();
const openaiProvider = new OpenAI();
const monitor = adaline.initMonitor({ projectId: 'my-api' });

async function handleChatRequest(userId: string, message: string) {
  // Create trace for this request
  const trace = monitor.logTrace({
    name: 'Chat Request',
    sessionId: userId,
    tags: ['chat', 'api'],
    attributes: {
      userId,
      messageLength: message.length
    }
  });

  try {
    // Log the LLM call
    const llmSpan = trace.logSpan({
      name: 'OpenAI Completion',
      tags: ['llm']
    });

    const model = openaiProvider.chatModel({
      modelName: 'gpt-4o',
      apiKey: process.env.OPENAI_API_KEY!
    });

    const gatewayResponse = await gateway.completeChat({
      model,
      messages: [
        { role: 'user', content: [{ modality: 'text', value: message }] }
      ]
    });

    llmSpan.update({
      status: 'success',
      content: {
        type: 'Model',
        provider: 'openai',
        model: 'gpt-4o',
        input: JSON.stringify(gatewayResponse.provider.request),
        output: JSON.stringify(gatewayResponse.provider.response)
      }
    });
    llmSpan.end();

    trace.update({ status: 'success' });
    return gatewayResponse.response.messages[0].content[0].value;

  } catch (error) {
    trace.update({
      status: 'failure',
      attributes: {
        error: error instanceof Error ? error.message : String(error)
      }
    });
    throw error;

  } finally {
    trace.end();
  }
}
```

### Example 2: Multi-Step Workflow

```typescript theme={null}
async function processUserOnboarding(userId: string) {
  const trace = monitor.logTrace({
    name: 'User Onboarding',
    sessionId: userId,
    status: 'pending',
    tags: ['onboarding', 'workflow'],
    attributes: { userId }
  });

  try {
    // Step 1: Create account
    const createSpan = trace.logSpan({
      name: 'Create Account',
      tags: ['database']
    });
    await createAccount(userId);
    createSpan.update({ status: 'success' });
    createSpan.end();

    // Step 2: Send welcome email
    const emailSpan = trace.logSpan({
      name: 'Send Welcome Email',
      tags: ['email']
    });
    await sendWelcomeEmail(userId);
    emailSpan.update({ status: 'success' });
    emailSpan.end();

    // Step 3: Generate personalized content
    const llmSpan = trace.logSpan({
      name: 'Generate Welcome Message',
      tags: ['llm', 'personalization']
    });
    const welcomeMsg = await generateWelcomeMessage(userId);
    llmSpan.update({
      status: 'success',
      content: {
        type: 'Model',
        provider: 'openai',
        model: 'gpt-4o',
        input: JSON.stringify({ userId }),
        output: JSON.stringify({ message: welcomeMsg })
      }
    });
    llmSpan.end();

    trace.update({ status: 'success' });

  } catch (error) {
    trace.update({
      status: 'failure',
      attributes: { error: String(error) }
    });
    throw error;

  } finally {
    trace.end();
  }
}
```

### Example 3: Nested Operations (RAG Pipeline)

```typescript theme={null}
async function answerQuestion(sessionId: string, question: string) {
  const trace = monitor.logTrace({
    name: 'RAG Question Answering',
    sessionId,
    tags: ['rag', 'qa'],
    attributes: { questionLength: question.length }
  });

  try {
    // Parent span for entire RAG operation
    const ragSpan = trace.logSpan({
      name: 'RAG Pipeline',
      tags: ['pipeline']
    });

    // Step 1: Generate embedding (child of ragSpan)
    const embedSpan = ragSpan.logSpan({
      name: 'Generate Query Embedding',
      tags: ['embedding']
    });
    const embedding = await generateEmbedding(question);
    embedSpan.update({
      status: 'success',
      content: {
        type: 'Embeddings',
        input: JSON.stringify({ query: question }),
        output: JSON.stringify({ dimensions: embedding.length })
      }
    });
    embedSpan.end();

    // Step 2: Retrieve documents (child of ragSpan)
    const retrieveSpan = ragSpan.logSpan({
      name: 'Vector Search',
      tags: ['retrieval', 'vector-db']
    });
    const docs = await retrieveDocuments(embedding);
    retrieveSpan.update({
      status: 'success',
      content: {
        type: 'Retrieval',
        input: JSON.stringify({ embedding: 'vector', topK: 5 }),
        output: JSON.stringify({ documentIds: docs.map(d => d.id) })
      },
      attributes: { documentsFound: docs.length }
    });
    retrieveSpan.end();

    // Step 3: Generate answer (child of ragSpan)
    const llmSpan = ragSpan.logSpan({
      name: 'Generate Answer',
      tags: ['llm', 'answer-generation'],
      runEvaluation: true
    });
    const answer = await generateAnswer(question, docs);
    llmSpan.update({
      status: 'success',
      content: {
        type: 'Model',
        provider: 'openai',
        model: 'gpt-4o',
        input: JSON.stringify({ question, context: docs }),
        output: JSON.stringify({ answer })
      }
    });
    llmSpan.end();

    ragSpan.update({ status: 'success' });
    ragSpan.end();

    trace.update({ status: 'success' });
    return answer;

  } catch (error) {
    trace.update({ status: 'failure' });
    throw error;

  } finally {
    trace.end();
  }
}
```

### Example 4: Long-Running Background Job

```typescript theme={null}
async function processBatch(batchId: string) {
  const trace = monitor.logTrace({
    name: 'Batch Processing',
    referenceId: `batch-${batchId}`,
    status: 'pending',
    tags: ['batch', 'background'],
    attributes: {
      batchId,
      startTime: Date.now()
    }
  });

  const items = await getBatchItems(batchId);
  
  trace.update({
    attributes: { itemCount: items.length }
  });

  let successCount = 0;
  let failureCount = 0;

  for (const item of items) {
    const itemSpan = trace.logSpan({
      name: `Process Item ${item.id}`,
      tags: ['item'],
      attributes: { itemId: item.id }
    });

    try {
      await processItem(item);
      itemSpan.update({ status: 'success' });
      successCount++;
    } catch (error) {
      itemSpan.update({
        status: 'failure',
        attributes: { error: String(error) }
      });
      failureCount++;
    }

    itemSpan.end();
  }

  trace.update({
    status: failureCount === 0 ? 'success' : 'failure',
    attributes: {
      successCount,
      failureCount,
      duration: Date.now() - trace.trace.trace.startedAt
    }
  });

  trace.end();
}
```

## Type Definitions

```typescript theme={null}
type LogAttributesValue = string | number | boolean;

type TraceStatus = 
  | 'success'
  | 'failure'
  | 'aborted'
  | 'cancelled'
  | 'pending'
  | 'unknown';

interface LogTraceOptions {
  name: string;
  status?: TraceStatus;
  sessionId?: string;
  referenceId?: string;
  tags?: string[];
  attributes?: Record<string, LogAttributesValue>;
}

interface TraceUpdates {
  name?: string;
  status?: TraceStatus;
  tags?: string[];
  attributes?: Record<string, LogAttributesValue>;
}

interface CreateLogTraceRequest {
  projectId: string;
  trace: {
    name: string;
    status: TraceStatus;
    sessionId?: string;
    referenceId: string;
    tags?: string[];
    attributes?: Record<string, LogAttributesValue>;  // LogAttributesValue = string | number | boolean
    startedAt: number;
    endedAt?: number;
  };
}
```

## Best Practices

### 1. Always Use Try-Finally

```typescript theme={null}
// ✅ Good: trace.end() always called
const trace = monitor.logTrace({ name: 'Operation' });
try {
  await doWork();
  trace.update({ status: 'success' });
} finally {
  trace.end();
}
```

```typescript theme={null}
// ❌ Bad: trace.end() might not be called
const trace = monitor.logTrace({ name: 'Operation' });
await doWork();
trace.end(); // Skipped if doWork() throws!
```

### 2. Use Meaningful Names

```typescript theme={null}
// ✅ Good: Descriptive names
const trace = monitor.logTrace({ name: 'User Registration Flow' });
const trace = monitor.logTrace({ name: 'PDF Processing Pipeline' });
const trace = monitor.logTrace({ name: 'RAG Question Answering' });
```

```typescript theme={null}
// ❌ Bad: Generic names
const trace = monitor.logTrace({ name: 'Request' });
const trace = monitor.logTrace({ name: 'Function' });
const trace = monitor.logTrace({ name: 'Process' });
```

### 3. Add Context with Attributes

```typescript theme={null}
// ✅ Good: Rich context
const trace = monitor.logTrace({
  name: 'API Request',
  sessionId: userId,
  tags: ['api', 'production', 'premium-tier'],
  attributes: {
    userId,
    endpoint: '/api/chat',
    method: 'POST',
    clientVersion: '2.1.0',
    region: 'us-east-1'
  }
});
```

### 4. Update Status Based on Outcome

```typescript theme={null}
// ✅ Good: Accurate status tracking
const trace = monitor.logTrace({ name: 'Operation', status: 'pending' });
try {
  await doWork();
  trace.update({ status: 'success' });
} catch (error) {
  trace.update({ status: 'failure' });
  throw error;
} finally {
  trace.end();
}
```

### 5. Use Sessions for Related Traces

```typescript theme={null}
// ✅ Good: Group related traces
const sessionId = `user-${userId}-${Date.now()}`;

// First trace
const trace1 = monitor.logTrace({
  name: 'Login',
  sessionId
});

// Later traces in same session
const trace2 = monitor.logTrace({
  name: 'Chat Message 1',
  sessionId
});

const trace3 = monitor.logTrace({
  name: 'Chat Message 2',
  sessionId
});
```

## Common Patterns

### Pattern 1: Request Handler

```typescript theme={null}
async function handleRequest(req: Request) {
  const trace = monitor.logTrace({
    name: `${req.method} ${req.url}`,
    sessionId: req.headers.get('session-id') || undefined,
    tags: ['api', 'http'],
    attributes: {
      method: req.method,
      path: req.url,
      userAgent: req.headers.get('user-agent') || 'unknown'
    }
  });

  try {
    const result = await processRequest(req);
    trace.update({ status: 'success' });
    return result;
  } catch (error) {
    trace.update({ status: 'failure' });
    throw error;
  } finally {
    trace.end();
  }
}
```

### Pattern 2: Background Job

```typescript theme={null}
async function runJob(jobId: string) {
  const trace = monitor.logTrace({
    name: 'Background Job',
    referenceId: jobId,
    status: 'pending',
    tags: ['job', 'async']
  });

  try {
    // Job logic with spans...
    trace.update({ status: 'success' });
  } catch (error) {
    trace.update({ status: 'failure' });
  } finally {
    trace.end();
  }
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.