# @superblocksteam/telemetry

Canonical telemetry bootstrap package for all Superblocks services. This package provides policy-aware OpenTelemetry initialization with tier-based routing and sanitization.

## Overview

This is the **ONLY approved way** to initialize OpenTelemetry in Superblocks services. Direct usage of `NodeSDK` or `WebTracerProvider` outside this package is prohibited.

## Tiered Telemetry Model

| Tier | Description | Egress |
|------|-------------|--------|
| **Tier 1** | Full fidelity debugging (code, prompts, stack traces) | Local only (cloud-prem) |
| **Tier 2** | Sanitized operational telemetry (latency, errors, token usage) | Exported by default |
| **Tier 3** | AI experience telemetry (prompts, responses, quality signals) | Exported by default |

## Usage

### Node.js Services

```typescript
import { initNodeTelemetry } from '@superblocksteam/telemetry/node';
import { getDefaultPolicy, DeploymentType } from '@superblocksteam/shared';

const policy = getDefaultPolicy(DeploymentType.CLOUD_PREM);

const telemetry = initNodeTelemetry({
  serviceName: 'my-service',
  serviceVersion: '1.0.0',
  environment: process.env.NODE_ENV ?? 'development',
  otlpUrl: process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
}, policy);

// Graceful shutdown
process.on('SIGTERM', async () => {
  await telemetry.shutdown();
});
```

### Browser

```typescript
import { initBrowserTelemetry } from '@superblocksteam/telemetry/browser';
import { getDefaultPolicy, DeploymentType } from '@superblocksteam/shared';

const policy = getDefaultPolicy(DeploymentType.CLOUD);

initBrowserTelemetry({
  serviceName: 'superblocks-ui',
  serviceVersion: '1.0.0',
  environment: 'production',
  otlpUrl: 'https://app.superblocks.com/api/v1/traces',
}, policy);
```

### Testing

```typescript
import { initTestTelemetry } from '@superblocksteam/telemetry/testing';

describe('MyService', () => {
  const { spanExporter, reset } = initTestTelemetry();

  beforeEach(() => reset());

  it('creates expected spans', async () => {
    await myService.doSomething();

    const spans = spanExporter.getSpans();
    expect(spans).toHaveLength(1);
    expect(spans[0].name).toBe('doSomething');
  });

  it('does not leak Tier 1 data', async () => {
    await myService.processWithSensitiveData();

    spanExporter.assertNoAttribute('prompt', /.*/);
    spanExporter.assertNoAttribute('code', /.*/);
  });
});
```

## Tier Policy Hints

Use tier policy hints to inform the Collector how to route specific spans. This is useful when the SDK knows something the Collector can't infer from attributes alone.

```typescript
import { trace } from '@opentelemetry/api';
import { markSensitive, markForAIAnalysis, markDebugOnly } from '@superblocksteam/telemetry';

const tracer = trace.getTracer('my-service');

// Span containing secrets — Tier 1 only, never exported
tracer.startActiveSpan('decrypt_customer_secret', (span) => {
  markSensitive(span);
  // ... decrypt operation
  span.end();
});

// GenAI span for quality analysis — include in Tier 3
tracer.startActiveSpan('gen_ai.chat', (span) => {
  markForAIAnalysis(span);
  span.setAttribute('gen_ai.system', 'anthropic');
  // ... LLM call
  span.end();
});

// High-cardinality debug span — skip export (cost control)
tracer.startActiveSpan('debug.cache_lookup', (span) => {
  markDebugOnly(span);
  span.setAttribute('cache.key', cacheKey);
  // ... lookup
  span.end();
});
```

### Available Hints

| Helper | Hint Value | Effect |
|--------|------------|--------|
| `markSensitive(span)` | `tier1_only` | Tier 1 only, skip Tier 2/3 |
| `markForAIAnalysis(span)` | `include_tier3` | Include in Tier 3 (AI analytics) |
| `markDebugOnly(span)` | `skip_export` | Tier 1 only, skip all export |

You can also set hints directly:

```typescript
import { TIER_HINT_ATTRIBUTE, TierPolicyHint } from '@superblocksteam/telemetry';

span.setAttribute(TIER_HINT_ATTRIBUTE, TierPolicyHint.TIER1_ONLY);
```

## Key Principles

1. **Policy Required** — Cannot initialize telemetry without a `TelemetryPolicy`
2. **Tier Enforcement** — Exporters are automatically enabled/disabled based on policy
3. **Sanitization at Source** — Tier 2/3 payloads are sanitized before export
4. **Fire-and-Forget** — Export failures never block core request paths
5. **Consistent Resources** — All services emit standardized resource attributes

## Package Structure

```
@superblocksteam/telemetry
├── /node          # Node.js bootstrap (initNodeTelemetry)
├── /browser       # Browser bootstrap (initBrowserTelemetry)  
├── /testing       # Test utilities (in-memory exporters)
└── /common        # Shared utilities (resource, router, sanitizer)
```

## Related Documentation

- [O11y Refactor Project](../../engineering/projects/o11y-refactor/README.md)
- [Telemetry Policy Schema](../../engineering/projects/o11y-refactor/epics/epic-a1-telemetry-policy.md)
- [Tier 2 Traces Contract](https://github.com/superblocksteam/engineering/blob/main/projects/o11y-refactor/contracts/tier2-traces.v0.3.0.json)
