New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@playwright-opentelemetry/trace-api

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@playwright-opentelemetry/trace-api

H3-based API library for storing and serving Playwright OpenTelemetry traces in S3-compatible storage.

Source
npmnpm
Version
0.12.1
Version published
Weekly downloads
2.6K
-59.06%
Maintainers
1
Weekly downloads
 
Created
Source

@playwright-opentelemetry/trace-api

H3-based API library for storing and serving Playwright OpenTelemetry traces in S3-compatible object storage.

Introduction

The Trace API is a customizable library that can be deployed to Cloudflare Workers, Deno, Bun, Node.js, or any platform supporting web-standard Request/Response handlers. It provides endpoints for writing OTLP trace data, registering expected Playwright trace IDs, and Playwright screenshots, then serves them in a format compatible with the trace viewer. Test metadata is stored on the root playwright.test span.

Reporter uploads follow Playwright trace retention by default. If Playwright does not produce or retain a trace for a test, no remote trace data is uploaded for that test and viewer read endpoints may return 404. Configure use.playwrightOpentelemetry.trace to override that decision for OpenTelemetry output independently of Playwright's own use.trace setting.

Usage

Basic Usage

import { createTraceApi } from '@playwright-opentelemetry/trace-api';

const api = createTraceApi({
  storageConfig: {
    bucket: 'my-traces',
    endpoint: 'https://xxx.r2.cloudflarestorage.com',
    accessKeyId: env.R2_ACCESS_KEY_ID,
    secretAccessKey: env.R2_SECRET_ACCESS_KEY,
    region: 'auto',
  },
});

export default {
  fetch: api.fetch,
};

Low-Level Building Blocks with Authentication

For maximum flexibility, compose your own API using individual handlers:

import { H3, getHeader, createError } from 'h3';
import {
  createS3Storage,
  createOtlpHandler,
  createPlaywrightHandler,
  createViewerHandler,
  OTLP_TRACES_WRITE_PATH,
  PLAYWRIGHT_REPORTER_WRITE_PATH,
  TRACE_VIEWER_READ_PATH,
} from '@playwright-opentelemetry/trace-api';

const storage = createS3Storage({
  bucket: 'my-traces',
  endpoint: env.R2_ENDPOINT,
  accessKeyId: env.R2_ACCESS_KEY_ID,
  secretAccessKey: env.R2_SECRET_ACCESS_KEY,
});

const app = new H3();

// Authentication middleware for write endpoints
const authMiddleware = async (event) => {
  const token = getHeader(event, 'authorization')?.replace('Bearer ', '');
  if (!token || !await validateToken(token)) {
    throw createError({ statusCode: 401, message: 'Unauthorized' });
  }
};

// Apply auth to write endpoints
app.use(OTLP_TRACES_WRITE_PATH, authMiddleware);
app.use(PLAYWRIGHT_REPORTER_WRITE_PATH, authMiddleware);

// Add handlers
// /v1/traces/
app.post(OTLP_TRACES_WRITE_PATH, createOtlpHandler({ storage }));
// /playwright-otel-reporter/v1/**
app.put(PLAYWRIGHT_REPORTER_WRITE_PATH, createPlaywrightHandler({ storage }));
// /playwright-otel-trace-viewer/v1/**
app.get(TRACE_VIEWER_READ_PATH, createViewerHandler({ storage }));

export default {
  fetch: app.fetch,
};

Other Runtimes

Deno:

import { createTraceApi } from '@playwright-opentelemetry/trace-api';

const api = createTraceApi({ storageConfig: { ... } });

Deno.serve({ port: 3000 }, api.fetch);

Bun:

import { createTraceApi } from '@playwright-opentelemetry/trace-api';

const api = createTraceApi({ storageConfig: { ... } });

export default {
  port: 3000,
  fetch: api.fetch,
};

Node.js:

import { serve } from 'h3/node';
import { createTraceApi } from '@playwright-opentelemetry/trace-api';

const api = createTraceApi({ storageConfig: { ... } });

serve(api, { port: 3000 });

API Reference

Configuration

interface TraceApiConfig {
  storage?: TraceStorage;
  storageConfig?: {
    bucket: string;
    endpoint: string;
    accessKeyId: string;
    secretAccessKey: string;
    region?: string; // Default: 'auto'
  };
  resolvePath?: (event: H3Event, path: string) => Promise<string> | string;
  corsOrigin?: string | false;
}

Provide either storage for a custom TraceStorage implementation or storageConfig to create the built-in S3-compatible storage.

Endpoints

Write Endpoints:

POST /v1/traces
Content-Type: application/json
Body: Standard OTLP JSON payload

Partitions OTLP spans by trace ID and writes OTLP-shaped fragments to traces/{traceId}/traces/{requestId}.json. The fragment filename is a unique request ID, not a service name or span ID.

OTLP requests from the Playwright reporter include X-Playwright-Otel-Source: reporter and are stored directly. Other OTLP requests are only stored when traces/{traceId}/.expected already exists. Unknown trace IDs are silently dropped with HTTP 200, so exporters do not retry unrelated telemetry.

PUT /playwright-otel-reporter/v1/expected-trace
X-Trace-Id: {traceId}

Writes a zero-byte expected-trace marker to traces/{traceId}/.expected. The Playwright fixture sends this before the test body runs when the configured trace mode could retain the current attempt, which allows app-under-test telemetry that received the propagated traceparent header to be admitted.

PUT /playwright-otel-reporter/v1/screenshots.zip
X-Trace-Id: {traceId}
Body: ZIP containing manifest.json and screenshots/*

Writes the screenshot bundle to traces/{traceId}/screenshots.zip.

Read Endpoints:

GET /playwright-otel-trace-viewer/v1/{traceId}/traces
GET /playwright-otel-trace-viewer/v1/{traceId}/screenshots.zip

Serves merged OTLP trace data and the stored screenshot ZIP expected by the trace viewer. The trace endpoint returns 404 when no trace fragments exist. A missing screenshot ZIP returns 404; the viewer treats that as no screenshots.

Storage Setup

Configure your S3-compatible bucket with a lifecycle rule to expire traces after the desired retention period.

AWS S3

aws s3api put-bucket-lifecycle-configuration \
  --bucket my-traces \
  --lifecycle-configuration '{
    "Rules": [{
      "ID": "ExpireTraces",
      "Status": "Enabled",
      "Filter": { "Prefix": "traces/" },
      "Expiration": { "Days": 30 }
    }]
  }'

Cloudflare R2

wrangler r2 bucket lifecycle set my-traces --rules '[{
  "id": "expire-traces",
  "enabled": true,
  "conditions": { "prefix": "traces/" },
  "deleteObjectsTransition": { "daysAfterUpload": 30 }
}]'

Storage Structure

s3://bucket/
└── traces/
	└── {traceId}/
		├── .expected
		├── traces/
		│   └── {requestId}.json
		└── screenshots.zip

Keywords

playwright

FAQs

Package last updated on 06 Jul 2026

Related posts