# Mastra Storage exporter The `MastraStorageExporter` persists traces to your configured storage backend, making them accessible through Studio. It requires no external services. > **Note:** `MastraStorageExporter` was previously called `DefaultExporter`. The original `DefaultExporter` class is still exported from `@mastra/observability` for backward compatibility, but it is deprecated. New code should use `MastraStorageExporter`. > **Production Observability:** Observability data can quickly overwhelm general-purpose databases in production. For high-traffic applications, route the observability storage domain to [ClickHouse](https://mastra.ai/reference/storage/clickhouse) through [composite storage](https://mastra.ai/reference/storage/composite). See [Production Recommendations](#production-recommendations) for details. ## Configuration ### Prerequisites 1. **Storage Backend**: Configure a storage provider (libSQL, PostgreSQL, etc.) 2. **Studio**: Install for viewing traces locally ### Basic Setup ```typescript import { Mastra } from '@mastra/core' import { Observability, MastraStorageExporter } from '@mastra/observability' import { LibSQLStore } from '@mastra/libsql' export const mastra = new Mastra({ storage: new LibSQLStore({ id: 'mastra-storage', url: 'file:./mastra.db', // Required for trace persistence }), observability: new Observability({ configs: { local: { serviceName: 'my-service', exporters: [new MastraStorageExporter()], }, }, }), }) ``` ### Recommended Configuration Include MastraStorageExporter in your observability configuration: ```typescript import { Mastra } from '@mastra/core' import { Observability, MastraStorageExporter, MastraPlatformExporter, SensitiveDataFilter, } from '@mastra/observability' import { LibSQLStore } from '@mastra/libsql' export const mastra = new Mastra({ storage: new LibSQLStore({ id: 'mastra-storage', url: 'file:./mastra.db', }), observability: new Observability({ configs: { default: { serviceName: 'mastra', exporters: [ new MastraStorageExporter(), // Persists observability events to Mastra Storage new MastraPlatformExporter(), // Sends observability events to Mastra platform (requires MASTRA_PLATFORM_ACCESS_TOKEN) ], spanOutputProcessors: [new SensitiveDataFilter()], }, }, }), }) ``` ## Studio Access your traces through Studio: 1. Start Studio 2. Navigate to Observability 3. Filter and search your local traces 4. Inspect detailed span information ## Tracing strategies MastraStorageExporter automatically selects the optimal tracing strategy based on your storage provider. You can also override this selection if needed. ### Available Strategies | Strategy | Description | Use Case | | ---------------------- | --------------------------------------------------------- | ----------------------------------- | | **realtime** | Process each event immediately | Development, debugging, low traffic | | **batch-with-updates** | Buffer events and batch write with full lifecycle support | Low volume Production | | **insert-only** | Only process completed spans, ignore updates | High volume Production | ### Strategy Configuration ```typescript new MastraStorageExporter({ strategy: 'auto', // Default - let storage provider decide // or explicitly set: // strategy: 'realtime' | 'batch-with-updates' | 'insert-only' // Batching configuration (applies to both batch-with-updates and insert-only) maxBatchSize: 1000, // Max spans per batch maxBatchWaitMs: 5000, // Max wait before flushing maxBufferSize: 10000, // Max spans to buffer }) ``` ## Storage provider support Different storage providers support different tracing strategies. Some providers support observability for production workloads, while others are intended primarily for local development. If you set the strategy to `'auto'`, the `MastraStorageExporter` automatically selects the optimal strategy for the storage provider. If you set an explicit strategy that the storage provider doesn't support, the exporter logs a warning and falls back to the provider's preferred strategy. ### Providers with Observability Support | Storage Provider | Preferred Strategy | Supported Strategies | Recommended Use | | ---------------------------------------------------------------- | ------------------ | ------------------------------- | ------------------------------------- | | **[ClickHouse](https://mastra.ai/reference/storage/clickhouse)** | insert-only | insert-only | Production (high-volume) | | **[PostgreSQL](https://mastra.ai/reference/storage/postgresql)** | batch-with-updates | batch-with-updates, insert-only | Production (low volume) | | **[MSSQL](https://mastra.ai/reference/storage/mssql)** | batch-with-updates | batch-with-updates, insert-only | Production (low volume) | | **[MongoDB](https://mastra.ai/reference/storage/mongodb)** | batch-with-updates | batch-with-updates, insert-only | Production (low volume) | | **[libSQL](https://mastra.ai/reference/storage/libsql)** | batch-with-updates | batch-with-updates, insert-only | Default storage, good for development | ### Providers without Observability Support The following storage providers **don't support** the observability domain. If you're using one of these providers and need observability, use [composite storage](https://mastra.ai/reference/storage/composite) to route observability data to a supported provider: - [Convex](https://mastra.ai/reference/storage/convex) - [DynamoDB](https://mastra.ai/reference/storage/dynamodb) - [Cloudflare D1](https://mastra.ai/reference/storage/cloudflare-d1) - [Cloudflare Durable Objects](https://mastra.ai/reference/storage/cloudflare) - [Upstash](https://mastra.ai/reference/storage/upstash) - [LanceDB](https://mastra.ai/reference/storage/lance) ### Strategy Benefits - **realtime**: Immediate visibility, best for debugging - **batch-with-updates**: 10-100x throughput improvement, full span lifecycle - **insert-only**: Additional 70% reduction in database operations, perfect for analytics ## Production recommendations Observability data grows quickly in production environments. A single agent interaction can generate hundreds of spans, and high-traffic applications can produce thousands of traces per day. Most general-purpose databases aren't optimized for this write-heavy, append-only workload. ### Recommended: ClickHouse for High-Volume Production [ClickHouse](https://mastra.ai/reference/storage/clickhouse) is a columnar database designed for high-volume analytics workloads. It's the recommended choice for production observability because: - **Optimized for writes**: Handles millions of inserts per second - **Efficient compression**: Reduces storage costs for trace data - **Fast queries**: Columnar storage enables quick trace lookups and aggregations - **Time-series native**: Built-in support for time-based data retention and partitioning ### Using Composite Storage If you're using a provider without observability support (like Convex or DynamoDB) or want to optimize performance, use [composite storage](https://mastra.ai/reference/storage/composite) to route observability data to ClickHouse while keeping other data in your primary database. ## Batching behavior ### Flush Triggers For both batch strategies (`batch-with-updates` and `insert-only`), traces are flushed to storage when any of these conditions are met: 1. **Size trigger**: Buffer reaches `maxBatchSize` spans 2. **Time trigger**: `maxBatchWaitMs` elapsed since first event 3. **Emergency flush**: Buffer approaches `maxBufferSize` limit 4. **Shutdown**: Force flush all pending events ### Error handling The MastraStorageExporter includes robust error handling for production use: - **Retry Logic**: Exponential backoff (500ms, 1s, 2s, 4s) - **Transient Failures**: Automatic retry with backoff - **Persistent Failures**: Drop batch after 4 failed attempts - **Buffer Overflow**: Prevent memory issues during storage outages ## Dropped observability events `DefaultExporter` emits structured drop events when it cannot persist observability data. Register an exporter or bridge with `onDroppedEvent` to forward these drops to alerting or monitoring. There are two drop reasons: - `unsupported-storage`: The storage provider does not implement the signal type. - `retry-exhausted`: The exporter retried a batch up to `maxRetries` times and then dropped it. The following example demonstrates forwarding drop details to a monitoring endpoint: ```typescript import { BaseExporter } from '@mastra/observability' import type { ObservabilityDropEvent, TracingEvent } from '@mastra/core/observability' class DropAlertExporter extends BaseExporter { name = 'drop-alerts' async onDroppedEvent(event: ObservabilityDropEvent) { await fetch('https://monitoring.example.com/observability-drops', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ count: event.count, signal: event.signal, reason: event.reason, exporterName: event.exporterName, }), }) } protected async _exportTracingEvent(_event: TracingEvent) {} } ``` ## Configuration examples ```typescript // Zero config - recommended for most users new MastraStorageExporter() // Development override new MastraStorageExporter({ strategy: 'realtime', // Immediate visibility for debugging }) // High-throughput production new MastraStorageExporter({ maxBatchSize: 2000, // Larger batches maxBatchWaitMs: 10000, // Wait longer to fill batches maxBufferSize: 50000, // Handle longer outages }) // Low-latency production new MastraStorageExporter({ maxBatchSize: 100, // Smaller batches maxBatchWaitMs: 1000, // Flush quickly }) ``` ## Related - [Tracing Overview](https://mastra.ai/docs/observability/tracing/overview) - [MastraPlatformExporter](https://mastra.ai/docs/observability/tracing/exporters/mastra-platform) - [Composite Storage](https://mastra.ai/reference/storage/composite): Combine multiple storage providers - [Storage Configuration](https://mastra.ai/docs/memory/storage)