Transactional

Sessions

Grouping related traces into sessions for conversation tracking.

What is a Session?

A session groups related traces together, typically representing a user conversation or interaction flow. Sessions help you analyze multi-turn conversations, debug user journeys, and understand interaction patterns.

Session Structure

Session: conversation-abc123
├── metadata: { userId, startTime }
├── traces:
│   ├── Trace: chat-turn-1 (10:30:00)
│   ├── Trace: chat-turn-2 (10:30:15)
│   ├── Trace: chat-turn-3 (10:30:45)
│   └── Trace: chat-turn-4 (10:31:00)
└── aggregates:
    ├── totalDuration: 60s
    ├── totalTokens: 2500
    └── totalCost: $0.05

Creating Sessions

Sessions are created automatically when you use sessionId:

const obs = getObservability();
 
// All traces with this sessionId are grouped
const trace = obs.trace({
  name: 'chat-turn',
  sessionId: 'conversation-abc123',  // Session identifier
  userId: 'user-456',
  input: { message: 'Hello!' },
});

Session Identification

Conversation-Based

// Generate session ID when conversation starts
const sessionId = `conversation-${nanoid()}`;
 
// Use same ID for all turns
async function handleMessage(message: string) {
  const trace = obs.trace({
    name: 'chat-turn',
    sessionId,  // Same for entire conversation
    input: { message },
  });
  // ...
}

User-Based

// One session per user per day
const sessionId = `user-${userId}-${new Date().toISOString().split('T')[0]}`;
 
const trace = obs.trace({
  name: 'user-action',
  sessionId,
  userId,
});

Request-Based

// One session per API request
const sessionId = request.headers.get('x-request-id');
 
const trace = obs.trace({
  name: 'api-request',
  sessionId,
});

Session Properties

PropertyTypeDescription
idstringSession identifier (your sessionId)
userIdstringAssociated user (from traces)
traceCountnumberNumber of traces
startTimeDateFirst trace timestamp
endTimeDateLast trace timestamp
durationnumberTotal session duration
totalTokensnumberSum of all tokens
totalCostnumberSum of all costs

Viewing Sessions

Dashboard

  1. Go to Observability
  2. Select your project
  3. Click Sessions tab
  4. View session list with:
    • Session ID
    • User
    • Trace count
    • Duration
    • Total cost

Session Detail View

Click a session to see:

  • Complete trace timeline
  • Conversation flow
  • Token usage over time
  • Cost breakdown

Session Analytics

Conversation Metrics

Track conversation patterns:

  • Average turns per session: How long conversations last
  • Session duration: Time from first to last trace
  • Cost per session: Total LLM cost for conversation
  • Completion rate: Sessions that reach a goal

User Journey Analysis

Understand how users interact:

// Tag important events
const trace = obs.trace({
  name: 'checkout-complete',
  sessionId,
  tags: ['conversion', 'checkout'],
});

Example: Chat Application

import { getObservability } from '@transactional/observability';
import { nanoid } from 'nanoid';
 
class ChatSession {
  private sessionId: string;
  private userId: string;
  private messages: { role: string; content: string }[] = [];
 
  constructor(userId: string) {
    this.userId = userId;
    this.sessionId = `chat-${nanoid()}`;
  }
 
  async sendMessage(content: string): Promise<string> {
    const obs = getObservability();
 
    // Add user message
    this.messages.push({ role: 'user', content });
 
    // Create trace for this turn
    const trace = obs.trace({
      name: 'chat-turn',
      sessionId: this.sessionId,  // Links all turns
      userId: this.userId,
      input: { message: content, turnNumber: this.messages.length },
      metadata: {
        messageCount: this.messages.length,
      },
    });
 
    try {
      const generation = obs.generation({
        name: 'generate-response',
        modelName: 'gpt-4o',
        input: { messages: this.messages },
      });
 
      const response = await openai.chat.completions.create({
        model: 'gpt-4o',
        messages: this.messages,
      });
 
      const assistantMessage = response.choices[0].message.content ?? '';
 
      await generation.end({
        output: { content: assistantMessage },
        promptTokens: response.usage?.prompt_tokens,
        completionTokens: response.usage?.completion_tokens,
      });
 
      // Add assistant message
      this.messages.push({ role: 'assistant', content: assistantMessage });
 
      await trace.end({
        output: { response: assistantMessage },
      });
 
      return assistantMessage;
    } catch (error) {
      await trace.error(error as Error);
      throw error;
    }
  }
 
  getSessionId(): string {
    return this.sessionId;
  }
}
 
// Usage
const chat = new ChatSession('user-123');
await chat.sendMessage('Hello!');
await chat.sendMessage('What can you help me with?');
await chat.sendMessage('Tell me about your features');
// All 3 traces are grouped in the same session

Session-Based Features

Conversation Replay

Replay entire sessions in the dashboard:

  1. Go to Sessions
  2. Click a session
  3. View conversation flow with all traces
  4. See exact inputs and outputs

Session Export

Export session data for analysis:

curl https://api.transactional.dev/observability/sessions/abc123/export \
  -H "Authorization: Bearer pk_xxx" \
  -o session-abc123.json

Session Metrics

Aggregate metrics by session:

// Dashboard shows per-session:
{
  sessionId: 'chat-abc123',
  traceCount: 5,
  totalTokens: 3500,
  totalCost: 0.07,
  duration: '2m 30s',
  userId: 'user-456',
}

Best Practices

1. Consistent Session IDs

Use consistent ID generation:

// Good - deterministic ID based on conversation
const sessionId = `user-${userId}-conv-${conversationId}`;
 
// Bad - random ID each time
const sessionId = nanoid();  // Can't reconstruct

2. Include User Context

Always include userId with sessions:

obs.trace({
  sessionId: 'abc123',
  userId: 'user-456',  // Important for user-level analytics
});

3. Session Boundaries

Define clear session boundaries:

// New session for:
// - New conversation
// - 30+ minutes of inactivity
// - User explicitly starts new chat
 
const shouldStartNewSession = (lastActivity: Date) => {
  const thirtyMinutes = 30 * 60 * 1000;
  return Date.now() - lastActivity.getTime() > thirtyMinutes;
};

4. Session Metadata

Add useful session context:

obs.trace({
  sessionId,
  metadata: {
    channel: 'web',      // or 'mobile', 'api'
    intent: 'support',   // Initial user intent
    version: '2.0',      // Chat version
  },
});

Next Steps