Trasys
Node.js SDK

Session Tracking

Correlate every request from a single user session across your backend services using an explicit session header or IP/user-agent fingerprinting as a fallback.

Session Tracking

Session tracking links every request to a consistent session identifier. This lets you answer questions like "show me everything that happened during this user's checkout session" — spanning all backend services, AI calls, and database queries.

How sessions are identified

The SDK uses two complementary mechanisms:

1. Explicit session header (primary)

When your frontend sends an auth token or session cookie, the SDK reads it, hashes it (SHA-256, one-way), and uses the hash as the session ID. The original token is never stored.

2. Fingerprinting (fallback)

For requests without an auth token — login pages, registration, public endpoints — the SDK falls back to fingerprinting (IP address, user-agent, etc.) to provide best-effort session continuity.

Fingerprinting on open routes provides a best-effort session ID. Once the user authenticates and the frontend starts sending a token, the session transitions to the explicit header approach. The two segments may not automatically merge in the dashboard.


Configuration

createSdk({
  session: {
    source: 'auto', // recommended for most applications
  },
});

Source options

SourceBehavior
'auto'Tries JWT → cookies → Authorization header. Uses the first match.
'jwt'Reads Authorization: Bearer <token> and hashes the full token.
'cookie'Reads a named cookie. Set cookieName to specify which one.
'header'Reads a named header. Set headerName to specify which one.
'none'Disables session tracking entirely.

JWT (most common)

createSdk({
  session: { source: 'jwt' },
});

If you are already sending JWT tokens with your API calls via Authorization: Bearer <token>, this works out of the box — no frontend changes required.

createSdk({
  session: {
    source:     'cookie',
    cookieName: 'connect.sid', // Express Session default
  },
});

Other common cookie names:

  • next-auth.session-token — NextAuth.js
  • __session — Firebase Auth / Remix
  • sid — custom session implementations

Custom header

createSdk({
  session: {
    source:     'header',
    headerName: 'x-session-token',
  },
});

Auto mode

auto tries the following in order and uses the first match:

  1. Authorization: Bearer <token> (JWT)
  2. Any cookie matching cookieName (if set)
  3. Authorization header value

This is the recommended setting for most applications.


What the frontend needs to do

For the explicit header approach, the frontend must include the auth token or session cookie with each request. In most applications this is already the case.

// Axios — set globally
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;

// fetch — set per request
fetch('/api/data', {
  headers: { Authorization: `Bearer ${token}` },
});

Cookies: If your auth token is in a cookie, the browser sends it automatically with same-origin requests. No frontend changes needed.


Session lifecycle

EventSession behavior
User logs inToken changes → new session ID from next request
User logs outToken cleared → fingerprint-only until next login
Token refreshNew token → new session ID (brief continuity gap)
Browser closedSession ends; new session on next visit

User identity

Session tracking and user identity work together. The SDK reads user ID and tenant ID from the request object after your auth middleware sets them:

createSdk({
  userIdPath:   'user.id',       // reads req.user.id
  tenantIdPath: 'user.tenantId', // reads req.user.tenantId
});

These are read at response finish time, so they are available regardless of where your auth middleware sets them relative to the Trasys middleware.

Attributes attached to every span:

AttributeSource
trasys.user.idreq.user.id
trasys.user.emailreq.user.email (auto)
trasys.user.rolereq.user.role (auto)
trasys.tenant.idreq.user.tenantId
trasys.session.idHashed token or fingerprint
trasys.session.sourcejwt, cookie, header, or fingerprint

Debugging specific users

To record 100% of requests for a specific user regardless of your sampling rate:

createSdk({
  sampling: {
    alwaysRecordUserIds: ['usr_problematic_customer_id'],
  },
});

Clear alwaysRecordUserIds once you are done debugging. Leaving specific users at 100% sampling in production increases data volume unexpectedly.


Next steps

  • Logging — user ID is automatically attached to all log entries within a session
  • TQL — query by session_id or user_id to investigate specific sessions

On this page