# @flashlog/tracker-sdk

The official browser-side SDK for **Flashlog** — a powerful bug tracking, real-time error reporting, and session replay platform.

Easily capture JavaScript exceptions, network failures, and WebSocket errors, while correlating frontend errors to backend logs with trace propagation. Include session replay recordings for debugging user journeys with high-fidelity visual playback.

---

## Key Features

*   **Error Monitoring**: Automatically captures unhandled runtime errors, promise rejections, and console errors.
*   **Network & Socket Tracking**: Records HTTP (fetch/XHR) failures, response statuses, and WebSocket connection errors/abnormal closures.
*   **Session Replay (rrweb)**: Records high-fidelity user sessions with custom flushing, masking, and chunking options.
*   **Trace Propagation**: Correlates frontend network requests with backend logs by injecting trace headers (e.g., `traceparent`, `x-flashlog-trace-id`).
*   **Privacy-First Sanitization**: Automatically redacts sensitive fields like passwords, tokens, API keys, and cookies from request/response payloads and replays.

---

## Installation

Install the tracker package in your application:

```bash
npm install @flashlog/tracker-sdk
# or
yarn add @flashlog/tracker-sdk
```

Initialize the tracker in your application bootstrap code (e.g., `index.js` or `main.ts`):

```typescript
import tracker from '@flashlog/tracker-sdk';

tracker.init('YOUR_PRODUCT_OR_BRAND_ID', {
  apiKey: 'YOUR_PUBLIC_API_KEY',
  apiUrl: 'https://api.flashlog.app/api', // optional override
  enableSessionReplay: true,
});
```

The SDK automatically sends an installation ping after `init(...)` and resolves the current page URL from the browser on its own. Your app does not need to provide a separate `url` value.

---

## Configuration Options

When calling `tracker.init(brandId, config)`, you can customize behavior using the following options:

| Property | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `apiKey` | `string` | `""` | **Required.** Your Flashlog public API key. |
| `apiUrl` | `string` | `"https://api.flashlog.app/api"` | Base API endpoint for reporting. (Overridden by `VITE_FLASHLOG_API_URL` at build time if set). |
| `debug` | `boolean` | `false` | Enables verbose logging to the browser console. |
| `autoCapture` | `boolean` | `true` | Automatically configures standard global handlers for errors and rejections. |
| `captureJsErrors` | `boolean` | `true` | Captures unhandled runtime exceptions and promise rejections. |
| `captureNetworkErrors` | `boolean` | `true` | Captures failed Fetch/XHR requests (status codes $\ge 400$, network dropouts). |
| `captureSocketErrors` | `boolean` | `true` | Captures abnormal close events and connection errors on `WebSocket` connections. |
| `captureRequestBody` | `boolean` | `true` | Includes HTTP request bodies in reported network logs (redacted for privacy). |
| `captureResponseBody` | `boolean` | `true` | Includes HTTP response bodies in reported network logs (redacted for privacy). |
| `redactKeys` | `string[]` | *See defaults below* | Payload object keys to redact (replace with `[REDACTED]`). |
| `redactUrlParams` | `string[]` | *See defaults below* | Query parameters in URLs to redact (replace with `[REDACTED]`). |
| `propagateTraceHeaders` | `boolean` | `false` | Generates trace contexts and injects tracking headers into fetch/XHR requests. |
| `traceOrigins` | `string[]` | `[]` | List of allowed backend origin URL prefixes for trace header propagation. |
| `traceHeaderName` | `string` | `"x-flashlog-trace-id"` | Header name used for custom trace correlation. |
| `enableSessionReplay` | `boolean` | `true` | Enables rrweb-based video playback of user sessions. |
| `replayFlushIntervalMs`| `number` | `10000` (10s) | The time frequency in milliseconds at which recording events are flushed to storage. |
| `replayMaxSegmentBytes`| `number` | `524288` (512KB) | Maximum payload size in bytes before splitting replay segments. |
| `replayMaxSegmentEvents`| `number` | `400` | Maximum recording events count before splitting replay segments. |
| `replayMaskAllInputs` | `boolean` | `true` | Mask all text inputs/forms during session recording for user privacy. |
| `ignoredStatusCodes` | `number[]` | `[401, 403]` | HTTP response status codes that should not trigger network errors. |
| `ignoredUrls` | `string[]` | *Third-party list* | URL strings or regex patterns to ignore from error tracking (e.g. analytics). |

---

## Detailed Usage Guides

### Distributing Tracing (Frontend $\rightarrow$ Backend Correlation)

To correlate frontend issues with backend execution logs:
1. Set `propagateTraceHeaders: true` in your config.
2. Specify your backend endpoints in `traceOrigins` (headers are blocked on external domains for security).
3. The SDK will inject `traceparent` (W3C standard) and `x-flashlog-trace-id` (custom) headers.

```javascript
tracker.init('YOUR_PRODUCT_ID', {
  apiKey: 'YOUR_PUBLIC_API_KEY',
  propagateTraceHeaders: true,
  traceOrigins: ['https://api.myapp.com', 'https://staging.api.myapp.com'],
  traceHeaderName: 'x-custom-trace-id' // Optional custom header override
});
```

To fetch active trace headers for manual injection (e.g. within customized Apollo, Axios, or GraphQL clients):

```javascript
const headers = window.FlashlogBugTracker.getTraceHeaders();
// Returns: { "traceparent": "...", "x-flashlog-trace-id": "..." }
```

### Identity Across Devices

You can tie browser sessions, device metadata, and recorded bugs to authenticated users:

```javascript
// Call after login
window.FlashlogBugTracker.identify("user_db_id_987", {
  email: "user@domain.com",
  plan: "enterprise",
  name: "John Doe"
});

// Call after logout to clear
window.FlashlogBugTracker.clearIdentity();
```

---

## Privacy & Redaction

The SDK automatically sanitizes request payloads, response bodies, and URLs to ensure PII (Personally Identifiable Information) and credentials never leave the client's browser.

### Redacted Keys by Default:
*   Credentials: `password`, `passwd`, `authorization`, `credentials`, `cookie`, `session`, `sessionToken`, `sessionCookie`, `sessionSecret`
*   Security: `token`, `jwt`, `csrf`, `passcode`, `otp`, `apiKey`, `accessToken`, `refreshToken`, `clientSecret`, `privateKey`, `authCode`, `verificationCode`

To add custom keys for redaction:

```javascript
tracker.init('YOUR_PRODUCT_ID', {
  apiKey: 'YOUR_PUBLIC_API_KEY',
  redactKeys: ['ssn', 'creditCardNumber', 'internalAccountNumber'],
  redactUrlParams: ['token', 'inviteCode']
});
```

---

## API Reference

The SDK exports the tracker instance as both the `default` export and a named export `flashlogTracker`.

```typescript
import flashlogTracker, { flashlogTracker as namedTracker } from '@flashlog/tracker-sdk';
```

When loaded in the browser, the instance is also attached to `window.FlashlogBugTracker` and `window.Tracker` (if the global name is not already occupied).

### Public Methods

*   **`init(brandId: string | number, config?: Partial<TrackerConfig>): Promise<void>`**  
    Initializes the tracking agent with your brand/product ID and optional configuration overrides.
*   **`track(eventName: string, data?: Record<string, unknown>): Promise<boolean>`**  
    Dispatches a custom event payload to the collector backend.
*   **`reportError(error: Error | string, context?: Record<string, unknown>): Promise<boolean>`**  
    Manually reports a handled exception/error with optional context metadata.
*   **`addUserAction(action: string, details?: Record<string, unknown>): void`**  
    Adds a custom user action (breadcrumb) to the current session action buffer.
*   **`identify(accountId: string, traits?: Record<string, unknown>): void`**  
    Associates the current session and subsequent reports with a specific user account.
*   **`clearIdentity(): void`**  
    Dissociates the user identity from the tracking session.
*   **`getTraceHeaders(): Record<string, string>`**  
    Generates and returns the active tracing headers (`traceparent` and `x-flashlog-trace-id`) for the current transaction.
*   **`getSessionId(): string | null`**  
    Retrieves the active browser session ID.
*   **`getDeviceId(): string | null`**  
    Retrieves the persistent device identifier.
*   **`flushReplay(reason?: string): Promise<ReplayFlushResult | null>`**  
    Manually flushes the current recording event queue to the backend.
*   **`finalizeReplay(reason?: string): Promise<ReplayFinalizeResult | null>`**  
    Manually finalizes the session recording and prepares it for replay playback.
*   **`reset(): void`**  
    Resets the tracker instance, cleans local storage states, and removes global error/rejection handlers.

---

## License

MIT © [Eastplayers](https://github.com/Eastplayers)
