> ## 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.

# Monitor

# Monitor Class

The `Monitor` class manages buffering, batching, and flushing of traces and spans to the Adaline API. It handles automatic retries, background flushing, and buffer management.

## Overview

The Monitor acts as a central coordinator for all observability operations:

* **Buffers** traces and spans in memory
* **Batches** multiple entries for efficient API calls
* **Flushes** automatically based on time intervals or buffer size
* **Retries** failed requests with exponential backoff
* **Tracks** sent and dropped entries for monitoring

## Creation

Create a Monitor using the `Adaline.initMonitor()` method:

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

const adaline = new Adaline();

const monitor = adaline.initMonitor({
  projectId: 'your-project-id',
});
```

With custom configuration:

```typescript theme={null}
const monitor = adaline.initMonitor({
  projectId: 'your-project-id',
  flushInterval: 5,        // flush every 5 seconds (default: 1)
  maxBufferSize: 100,      // flush when 100 items buffered (default: 1000)
});
```

## Properties

### buffer

```typescript theme={null}
buffer: BufferedEntry[]
```

In-memory array of [BufferedEntry](/docs/reference/sdk/v2/typescript/types/BufferedEntry) items storing traces and spans waiting to be flushed.

<Note>
  Items are added when you call `logTrace()` or `logSpan()`, and removed after successful flush.
</Note>

**Example:**

```typescript theme={null}
console.log(`Buffer size: ${monitor.buffer.length}`);

// Inspect buffered items
monitor.buffer.forEach(entry => {
  if (entry.category === 'trace') {
    console.log('Trace:', entry.data.trace.trace.name);
  } else {
    console.log('Span:', entry.data.span.span.name);
  }
});
```

### projectId

```typescript theme={null}
projectId: string
```

The project ID that all traces and spans are associated with.

### sentCount

```typescript theme={null}
sentCount: number
```

Number of entries successfully sent to the API.

### droppedCount

```typescript theme={null}
droppedCount: number
```

Number of entries dropped due to buffer overflow or send failure.

### defaultContent

```typescript theme={null}
defaultContent: LogSpanContent
```

Default [LogSpanContent](/docs/reference/sdk/v2/typescript/types/LogSpanContent) used when no explicit content is provided. Defaults to `{ type: 'Other', input: '{}', output: '{}' }`.

### logger

```typescript theme={null}
readonly logger: Logger
```

[Logger](/docs/reference/sdk/v2/typescript/types/Logger) instance used for SDK diagnostics.

## Methods

### logTrace()

Create a new trace and add it to the buffer.

```typescript theme={null}
logTrace(options: LogTraceOptions): Trace
```

#### Parameters

<ParamField path="options" type="object" required>
  <Expandable title="properties">
    <ParamField path="name" type="string" required>
      Human-readable name for this trace (e.g., "User Login", "Generate Report").
    </ParamField>

    <ParamField path="status" type="TraceStatus" optional default="unknown">
      Initial [TraceStatus](/docs/reference/sdk/v2/typescript/types/TraceStatus): `'success' | 'failure' | 'aborted' | 'cancelled' | 'pending' | 'unknown'`
    </ParamField>

    <ParamField path="sessionId" type="string" optional>
      Session identifier to group related traces (e.g., user session ID).
    </ParamField>

    <ParamField path="referenceId" type="string" optional>
      Custom reference ID for this trace. Auto-generated UUID if not provided.
    </ParamField>

    <ParamField path="tags" type="string[]" optional>
      Array of tags for categorization and filtering (e.g., `['api', 'production']`).
    </ParamField>

    <ParamField path="attributes" type="Record<string, LogAttributesValue>" optional>
      Key-value metadata ([LogAttributesValue](/docs/reference/sdk/v2/typescript/types/LogAttributesValue)) for additional context (e.g., `{ userId: '123', region: 'us-east' }`).
    </ParamField>
  </Expandable>
</ParamField>

#### Returns

<ResponseField name="trace" type="Trace">
  A new Trace instance. See [Trace Class](/docs/reference/sdk/v2/typescript/classes/trace) for details.
</ResponseField>

#### Examples

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

  // Do work...

  trace.end();
  ```

  ```typescript With Session theme={null}
  const trace = monitor.logTrace({
    name: 'Chat Turn',
    sessionId: `user-${userId}`,
    tags: ['chat', 'production'],
    attributes: {
      userId: userId,
      messageCount: 5
    }
  });
  ```

  ```typescript Pending Operation theme={null}
  const trace = monitor.logTrace({
    name: 'Batch Processing',
    status: 'pending',
    tags: ['batch', 'async'],
    attributes: {
      batchId: 'batch-123',
      itemCount: 1000
    }
  });

  try {
    // Process batch...
    trace.update({ status: 'success' });
  } catch (error) {
    trace.update({ status: 'failure' });
  }

  trace.end();
  ```

  ```typescript Custom Reference ID theme={null}
  // Use your own ID for correlation with external systems
  const trace = monitor.logTrace({
    name: 'Order Processing',
    referenceId: `order-${orderId}`,
    attributes: { orderId }
  });
  ```
</CodeGroup>

### flush()

Manually flush all ready entries in the buffer to the API.

```typescript theme={null}
async flush(): Promise<void>
```

<Note>
  This method is automatically called on a timer (based on `flushInterval`) and when the buffer reaches `maxBufferSize`. Manual calls are typically only needed during shutdown (especially in serverless environments) or testing.
</Note>

#### Behavior

1. Skips if a flush is already in progress (prevents concurrent flushes)
2. Filters for entries marked as `ready` (via `trace.end()` or `span.end()`)
3. Sends each entry to the API with automatic retry
4. Updates `traceId` on traces after successful creation
5. Removes successfully flushed entries from buffer
6. Drops entries that fail after retries and increments `droppedCount`

#### Retry Logic

* **5xx errors**: Retry with exponential backoff (up to 10 retries, 20s total)
* **4xx errors**: Fail immediately (no retry)
* **Network errors**: Retry with exponential backoff

#### Examples

<CodeGroup>
  ```typescript Manual Flush theme={null}
  const trace = monitor.logTrace({ name: 'Important Event' });
  trace.end();

  // Ensure it's sent immediately
  await monitor.flush();
  ```

  ```typescript Graceful Shutdown theme={null}
  process.on('SIGTERM', async () => {
    console.log('Shutting down...');
    
    // Flush any remaining entries
    await monitor.flush();
    
    // Stop background flush
    monitor.stop();
    
    process.exit(0);
  });
  ```

  ```typescript Testing theme={null}
  test('logs trace successfully', async () => {
    const trace = monitor.logTrace({ name: 'Test Trace' });
    trace.end();
    
    // Flush and wait for API call
    await monitor.flush();
    
    // Check results
    expect(trace.traceId).toBeDefined();
    expect(monitor.buffer.length).toBe(0);
  });
  ```
</CodeGroup>

### stop()

Stop the background flush timer.

```typescript theme={null}
stop(): void
```

<Warning>
  After calling `stop()`, the monitor will no longer automatically flush. You must manually call `flush()` to send buffered entries.
</Warning>

#### Example

```typescript theme={null}
const monitor = adaline.initMonitor({ projectId: 'proj_123' });

// Use the monitor...

// Stop when done (e.g., during shutdown)
monitor.stop();

// Final flush
await monitor.flush();
```

### enforceBufferLimit()

Enforces the `maxBufferSize` limit by dropping the oldest entries when the buffer is full.

```typescript theme={null}
enforceBufferLimit(): void
```

<Note>
  This method is called automatically when entries are added to the buffer. You typically don't need to call it manually.
</Note>

## Complete Examples

### Basic Usage

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

const adaline = new Adaline();
const monitor = adaline.initMonitor({
  projectId: 'my-project',
});

async function handleRequest(userId: string) {
  const trace = monitor.logTrace({
    name: 'User Request',
    sessionId: userId,
    tags: ['api']
  });

  const span = trace.logSpan({
    name: 'Process Data',
    tags: ['processing']
  });

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

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

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

  // Automatically flushed based on timer/buffer size
}
```

### Production Setup with Health Monitoring

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

const adaline = new Adaline({ debug: true });

const monitor = adaline.initMonitor({
  projectId: process.env.PROJECT_ID!,
  flushInterval: 5,
  maxBufferSize: 100,
});

// Health check
setInterval(() => {
  const bufferSize = monitor.buffer.length;

  console.log('Monitor Health:', {
    bufferSize,
    sentCount: monitor.sentCount,
    droppedCount: monitor.droppedCount,
  });

  if (monitor.droppedCount > 0) {
    console.warn(`${monitor.droppedCount} entries have been dropped`);
  }

  if (bufferSize > 50) {
    console.warn('Monitor buffer growing', { bufferSize });
  }
}, 60000); // Check every minute

// Graceful shutdown
process.on('SIGTERM', async () => {
  console.log('Shutting down...');
  
  try {
    await monitor.flush();
    console.log('Flushed remaining entries');
  } catch (error) {
    console.error('Error during final flush:', error);
  }
  
  monitor.stop();
  process.exit(0);
});
```

### High-Volume Application

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

const adaline = new Adaline();

// Optimize for high volume
const monitor = adaline.initMonitor({
  projectId: 'high-volume-app',
  flushInterval: 2,
  maxBufferSize: 500,
});

// Monitor buffer usage
setInterval(() => {
  const bufferSize = monitor.buffer.length;
  
  // Warn if buffer is growing
  if (bufferSize > 300) {
    console.warn(`Buffer size: ${bufferSize} (high volume)`);
  }
  
  // Force flush if critical
  if (bufferSize > 450) {
    console.warn('Forcing flush due to high buffer size');
    monitor.flush().catch(err => {
      console.error('Forced flush failed:', err);
    });
  }
}, 1000);

// Request handler
async function handleRequest(req: Request) {
  const trace = monitor.logTrace({
    name: req.url,
    sessionId: req.headers.get('session-id') || undefined,
    tags: ['api', 'high-volume'],
    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();
  }
}
```

### Testing with Monitor

```typescript theme={null}
import { Adaline } from '@adaline/client';
import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';

describe('Monitor Tests', () => {
  let adaline: Adaline;
  let monitor: Monitor;

  beforeEach(() => {
    adaline = new Adaline();
    monitor = adaline.initMonitor({
      projectId: 'test-project',
      flushInterval: 999999 // Don't auto-flush during tests
    });
  });

  afterEach(async () => {
    await monitor.flush();
    monitor.stop();
  });

  test('creates trace and span', async () => {
    const trace = monitor.logTrace({ name: 'Test Trace' });
    const span = trace.logSpan({ name: 'Test Span' });

    expect(monitor.buffer.length).toBe(2);

    span.end();
    trace.end();

    expect(monitor.buffer.filter(e => e.ready).length).toBe(2);

    await monitor.flush();

    expect(trace.traceId).toBeDefined();
    expect(monitor.buffer.length).toBe(0);
    expect(monitor.sentCount).toBeGreaterThan(0);
  });

  test('handles flush failures', async () => {
    const trace = monitor.logTrace({ name: 'Invalid' });
    trace.end();

    // Mock API to fail
    // ... your mocking code ...

    await monitor.flush();

    expect(monitor.droppedCount).toBeGreaterThan(0);
  });

  test('respects buffer size limit', () => {
    const smallMonitor = adaline.initMonitor({
      projectId: 'test',
      maxBufferSize: 2,
      flushInterval: 999999
    });

    const trace1 = smallMonitor.logTrace({ name: 'T1' });
    const trace2 = smallMonitor.logTrace({ name: 'T2' });
    const trace3 = smallMonitor.logTrace({ name: 'T3' });

    trace1.end();
    trace2.end();
    trace3.end();

    // Buffer should be capped at maxBufferSize
    // ... assertions ...
  });
});
```

## Type Definitions

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

type LogAttributesValue = string | number | boolean;

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

type BufferedEntry =
  | { ready: boolean; category: 'trace'; data: Trace }
  | { ready: boolean; category: 'span'; data: Span };
```

<Note>
  The `attributes` field accepts `Record<string, LogAttributesValue>` where [LogAttributesValue](/docs/reference/sdk/v2/typescript/types/LogAttributesValue) = `string | number | boolean`.
</Note>
