Skip to content

Conversation

@buenaflor
Copy link
Contributor

@buenaflor buenaflor commented Dec 11, 2025

📜 Description

This PR is still WIP

Note that the proposed architecture is not yet final - the full spec is still WIP and this is only a minimal part of it.

This current impl does not include:

  • rate limiting before adding to buffer

💡 Motivation and Context

New Telemetry Buffer Architecture

Note that this only illustrates mainly the default InMemoryTelemetryBuffer but it is later swappable when we will eventually reuse iOS and Android (crash-safe) native buffers

(graphics made by Cursor :D)

┌─────────────────────────────────────────────────────────────────────────────┐
│                           TELEMETRY BUFFER ARCHITECTURE                      │
└─────────────────────────────────────────────────────────────────────────────┘

                              ┌──────────────────┐
                              │  TelemetryPayload │  (interface)
                              │  ───────────────  │
                              │  + toJson()       │
                              └────────┬─────────┘
                                       │ implements
              ┌────────────────────────┼────────────────────────┐
              │                        │                        │
              ▼                        ▼                        ▼
       ┌────────────┐          ┌─────────────┐          ┌─────────────┐
       │  SentryLog │          │    Span     │          │   Metrics   │
       └────────────┘          └─────────────┘          │  (future)   │
              │                        │                └─────────────┘
              │                        │                        │
              │ add()                  │ add()                  │ add()
              ▼                        ▼                        ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                          TelemetryBuffer<T>                                  │
│  ─────────────────────────────────────────────────────────────────────────  │
│  Abstract interface for buffering telemetry items.                           │
│                                                                              │
│  + add(T item)      → Adds an item to the buffer                             │
│  + flush()          → Flushes all buffered items                             │
│                                                                              │
│  Implementations:                                                            │
│  • InMemoryTelemetryBuffer  → Time/size-based flushing with BufferFlusher   │
│  • NoOpTelemetryBuffer      → Does nothing (disabled state)                  │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
                                       │
                                       │ extends
                                       ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                        InMemoryTelemetryBuffer<T>                            │
│  ─────────────────────────────────────────────────────────────────────────  │
│                                                                              │
│   ┌─────────────────────────────────────────────────────────────────────┐   │
│   │  Storage: List<BufferedItem<T>>                                      │   │
│   │  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐                 │   │
│   │  │ item: T      │ │ item: T      │ │ item: T      │  ...            │   │
│   │  │ encoded: []  │ │ encoded: []  │ │ encoded: []  │                 │   │
│   │  └──────────────┘ └──────────────┘ └──────────────┘                 │   │
│   └─────────────────────────────────────────────────────────────────────┘   │
│                                                                              │
│   Triggers flush when:                                                       │
│   • Timer fires (5s default)                                                 │
│   • Size threshold reached (1MB default)                                     │
│   • Manual flush() called                                                    │
│                                                                              │
│   Factory methods:                                                           │
│   • forLogs(options, {flusher?})  → InMemoryTelemetryBuffer<SentryLog>      │
│   • forSpans(options, {flusher?}) → InMemoryTelemetryBuffer<Span>           │
│   • forMetrics(options, {flusher?}) → (future)                              │
│                                                                              │
└──────────────────────────────────┬──────────────────────────────────────────┘
                                   │
                                   │ flush triggers
                                   │ _flusher.flush(items)
                                   ▼
                        ┌─────────────────────┐
                        │   BufferFlusher<T>   │  (abstract)
                        │   ────────────────   │
                        │   + flush(items)     │
                        └──────────┬──────────┘
                                   │ implements
              ┌────────────────────┼────────────────────────┐
              │                    │                        │
              ▼                    ▼                        ▼
   ┌──────────────────┐  ┌───────────────────┐  ┌───────────────────┐
   │  LogBufferFlusher │  │ SpanBufferFlusher │  │MetricsBufferFlusher│
   │  ────────────────  │  │ ───────────────── │  │    (future)        │
   │                    │  │                   │  └───────────────────┘
   │  • No grouping     │  │  • Group by key:  │
   │  • Single envelope │  │    "${traceId}-   │
   │                    │  │     ${segmentId}" │
   │                    │  │                   │
   │                    │  │  • One envelope   │
   │                    │  │    per group with │
   │                    │  │    trace context  │
   └─────────┬──────────┘  └─────────┬─────────┘
             │                       │
             │                       │ for each group
             ▼                       ▼
   ┌──────────────────────────────────────────────────────────────────────────┐
   │                              Transport                                    │
   │  ────────────────────────────────────────────────────────────────────    │
   │                                                                           │
   │  ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐       │
   │  │ Logs Envelope   │    │ Spans Envelope  │    │ Spans Envelope  │ ...   │
   │  │ (all logs)      │    │ (trace A spans) │    │ (trace B spans) │       │
   │  └─────────────────┘    └─────────────────┘    └─────────────────┘       │
   │                                                                           │
   └──────────────────────────────────────────────────────────────────────────┘
                                   │
                                   ▼
                            ┌─────────────┐
                            │   Sentry    │
                            └─────────────┘

💚 How did you test it?

📝 Checklist

  • I reviewed submitted code
  • I added tests to verify changes
  • No new PII added or SDK only sends newly added PII if sendDefaultPii is enabled
  • I updated the docs if needed
  • All tests passing
  • No breaking changes

🔮 Next steps

…to use new buffers, update captureSpan method, and enhance SimpleSpan serialization.
… logs and spans, update InMemoryTelemetryBuffer to utilize flusher, and streamline SentryClient initialization for telemetry buffers.
@buenaflor buenaflor changed the base branch from main to feat/span-first December 11, 2025 16:56
@github-actions
Copy link
Contributor

github-actions bot commented Dec 11, 2025

Fails
🚫 Please consider adding a changelog entry for the next release.

Instructions and example for changelog

Please add an entry to CHANGELOG.md to the "Unreleased" section. Make sure the entry includes this PR's number.

Example:

## Unreleased

### Features

- Span Buffer ([#3396](https://github.com/getsentry/sentry-dart/pull/3396))

If none of the above apply, you can opt out of this check by adding #skip-changelog to the PR description or adding a skip-changelog label.

Generated by 🚫 dangerJS against 0f6dbe6

… and segmentKey methods to Span and its subclasses. Update NoOpSpan, SimpleSpan, and UnsetSpan to implement these methods, improving span management and telemetry context handling.
@buenaflor buenaflor closed this Dec 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants