opentelemetry-swift

repository·main·Indexed 18 days ago

https://github.com/open-telemetry/opentelemetry-swift

Swift implementation of the OpenTelemetry client, providing APIs and an SDK for Tracing, Metrics, and Logs. It includes support for OTLP exporters via gRPC and HTTP, Prometheus exporters, and URLSession instrumentation for capturing network requests as spans.

Tokens
18.3K
Snippets
38
Records
53
Agent score
63%

What's inside opentelemetry-swift

  1. What is the Persistence Exporter

    main

    The Persistence Exporter is an exporter decorator designed for environments where stable export cannot be guaranteed (e.g., mobile apps with intermittent network connectivity).

    Instead of being a standalone exporter, it wraps an existing exporter. It works by:

    1. Asynchronously serializing and writing exported data to disk at a specified path.
    2. Asynchronously picking up that persisted data, deserializing it, and forwarding it to the original (decorated) exporter.

    This ensures that telemetry data collected while offline can be exported later, even after an app has been terminated and relaunched.

  2. How MetricKit data is represented in OpenTelemetry

    main

    MetricKit data is categorized into Metrics and Diagnostics. Instead of using the OpenTelemetry Metrics API, this instrumentation represents data as OpenTelemetry traces (spans) for the following reasons:

    1. Pre-aggregated data: MetricKit data is already aggregated over 24 hours, so OTel metric semantics (counters, gauges, etc.) do not map naturally.
    2. Timing semantics: Data represents activity over a 24-hour period. Using spans with start/end times better represents this temporal nature.
    3. API simplicity: Spans provide a simpler way to represent pre-aggregated, time-windowed data compared to the complex OTel metrics API.

    Units and Timestamps

    • Units: Measurements (e.g., "1 kb") are normalized to base units (bytes, seconds, etc.) and represented as doubles in attributes.
    • Metrics Spans: Use timeStampBegin as the span start time and timeStampEnd as the span end time. Spans are typically 24 hours long.
    • Diagnostics: Both timestamp (set to timeStampEnd) and observedTimestamp (the current time when the log is emitted) are included. Using timeStampEnd ensures diagnostic events appear as "new" data in observability systems when they arrive.
  3. Implement a custom HTTPClient for OpenTelemetry exporters

    main

    OpenTelemetry HTTP exporters (like OtlpHttpTraceExporter or OtlpHttpLogExporter) allow you to provide a custom implementation of the HTTPClient protocol. This is useful for injecting authentication, implementing retry logic, adding custom headers, or mocking network calls for testing.

    To use a custom client, implement the HTTPClient protocol, specifically the send(request:completion:) method, and pass your instance to the exporter's httpClient parameter.

    import OpenTelemetryProtocolExporterHttp
    
    // 1. Implement the HTTPClient protocol
    class MyCustomClient: HTTPClient {
        func send(request: URLRequest, completion: @escaping (Result<HTTPURLResponse, Error>) -> Void) {
            // Your custom logic here
        }
    }
    
    // 2. Pass it to an exporter
    let exporter = OtlpHttpTraceExporter(
        endpoint: URL(string: "https://api.example.com/v1/traces")!,
        httpClient: MyCustomClient()
    )
  4. How Session components work together

    main

    Session instrumentation is composed of several specialized components:

    • SessionManager: The core engine that manages the lifecycle, expiration, and renewal of sessions.
    • SessionManagerProvider: A thread-safe singleton provider used to register and access the SessionManager from anywhere in the app.
    • SessionSpanProcessor: A span processor that automatically injects session.id and session.previous_id into every span.
    • SessionLogRecordProcessor: A log processor that automatically injects session.id and session.previous_id into every log record.
    • SessionEventInstrumentation: A utility that emits specific OpenTelemetry log records (session.start and session.end) to track lifecycle transitions.
    • Session Model: The data object representing a session, containing its ID, timestamps, and expiration logic.
  5. Understand MXSignpostMetric span representation

    main

    Signpost metrics are custom performance measurements defined using Apple's os_signpost. Unlike other MetricKit metrics that are aggregated, each signpost metric generates its own individual OpenTelemetry span.

    Key Details:

    • Span Name: MXSignpostMetric
    • Instrumentation Scope: MetricKit
    • Behavior: Each signpost creates a separate span rather than being aggregated into a single span.
  6. Use OpenTracingShim to delegate OpenTracing calls to OpenTelemetry

    main
    The OpenTracingShim is an implementation of the OpenTracing API that acts as a bridge, delegating all tracing operations to the OpenTelemetry SDK. This allows you to use existing OpenTracing-based code or libraries within an OpenTelemetry-instrumented Swift application. You can use OpenTracingShim to create OpenTracing-compatible tracers that actually produce OpenTelemetry spans.
  7. How OpenTelemetry-Swift is structured

    main

    The project is split into two primary libraries to allow for clean separation between telemetry producers and the telemetry engine:

    1. OpenTelemetryApi: Contains protocols and no-op implementations following the OpenTelemetry specification. Libraries that produce telemetry should only depend on this library. This allows library authors to defer the choice of a specific SDK to the end-user application.
    2. OpenTelemetrySdk: The reference implementation of the API. Applications should depend on this (or another implementation) to actually process and export telemetry.
  8. Differences between MetricKit Stack Traces and Apple's MetricKit Format

    main

    The OpenTelemetry MetricKit stack trace format simplifies Apple's MXCallStackTree.jsonRepresentation() through the following changes:

    1. Removed callStackTree Wrapper: Eliminates unnecessary nesting at the root level.
    2. Flattened Stack Frames: Replaces the nested subFrames tree structure with a flat array (callStackFrames) ordered from innermost to outermost.
    3. Removed sampleCount Field: Removed as it is specific to CPU profiling and not required for crash analysis.
    4. Renamed offsetIntoBinaryTextSegment to offsetAddress: Shortened for brevity while maintaining the same semantic meaning for symbolication.
    5. Removed address Field: The runtime memory address is removed because ASLR makes it unreliable for post-mortem symbolication; offsetAddress is the authoritative field for symbolication.
  9. Understanding Stable Metrics in OpenTelemetry Swift

    main

    Stable Metrics is the implementation of the current OpenTelemetry metrics specification within opentelemetry-swift.

    Note: This implementation is currently in an experimental phase. To distinguish it from the legacy, out-of-spec metrics implementation, most constructs will carry a stable prefix.

    Migration Roadmap

    The project follows a three-phase transition plan:

    1. Phase 1 (Current): Stable Metrics are available alongside the existing (legacy) Metrics APIs.
    2. Phase 2: All existing (legacy) Metric APIs will be marked as deprecated.
    3. Phase 3: Legacy metrics APIs will be removed, and the stable prefix will be removed from the new APIs to make them the standard.
  10. Understand MXDiagnosticPayload log and span representation

    main

    Diagnostics (crashes, hangs, exceptions) are treated as discrete events.

    Data Model:

    1. Parent Span: A span named MXDiagnosticPayload is created to cover the entire reporting period (from timeStampBegin to timeStampEnd).
    2. Log Records: For every individual diagnostic event, an OpenTelemetry log record is emitted (not a span).

    Log Attributes:

    • name: Identifies the diagnostic type (e.g., metrickit.diagnostic.crash).
    • timestamp: Set to timeStampEnd (to ensure the event appears recent).
    • observedTimestamp: Set to the current time when the log is emitted.
    • Instrumentation Scope: MetricKit.
  11. How exception attributes are derived for crash diagnostics

    main

    The instrumentation maps Apple's MetricKit data to standard OpenTelemetry exception semantic conventions. For crash diagnostics, exception.type and exception.message are derived using the following priority order (highest to lowest):

    1. Objective-C exception info (iOS 17+): Uses objc.name for type and objc.message for message.
    2. Mach exception info: Uses mach_exception.name for type and mach_exception.description for message.
    3. POSIX signal info: Uses signal.name for type and signal.description for message.

    Note on Hangs: For hang diagnostics, only exception.stacktrace is set (from callStackTree). No exception.type or exception.message is provided.

  12. Install OpenTelemetry-Swift via CocoaPods

    main

    OpenTelemetry-Swift supports CocoaPods. You can choose between the API-only pod or the full SDK pod.

    • Use OpenTelemetry-Swift-Sdk to include both the API and the SDK (recommended for most applications).
    • Use OpenTelemetry-Swift-Api if you only need the API definitions.
    # To add both API and SDK:
    pod 'OpenTelemetry-Swift-Sdk'
    
    # To add only the API:
    pod 'OpenTelemetry-Swift-Api'