purple_logger_otel_sdk 0.1.3 copy "purple_logger_otel_sdk: ^0.1.3" to clipboard
purple_logger_otel_sdk: ^0.1.3 copied to clipboard

PurpleOTel SDK bridge for purple_logger — structured logs flow to OpenTelemetry with trace correlation.

pub version license Dart SDK tests

PurpleLogger OTel SDK Bridge

Connect purple_logger to PurpleOTel SDK. Structured logs flow seamlessly into OpenTelemetry with automatic severity mapping and trace correlation.


Features #

  • EventLogger integration — Receives fully assembled LogEvent objects directly from purple_logger's provider pipeline, avoiding double allocation
  • Severity mapping — PurpleLogLevel → OTel SeverityNumber mapping following the OTel Logs specification
  • Trace correlation — LogRecords automatically inherit traceId and spanId from active spans when running inside a trace context
  • Property propagation — All structured properties (scope properties + caller properties) become OTel attributes
  • Error capturing — Exceptions and stack traces are attached as error.type, error.message, and error.stackTrace attributes
  • Provider caching — Logger instances are cached by category name, ensuring a single OTel logger per category

Architecture #

┌──────────────────────────────────────────────────────────────────────────┐
│                           purple_logger                                  │
│  • LoggerImpl.log() → LogEvent → ProviderLogger.write(event)            │
│  • Provides: Logger, LoggerProvider, LoggingScope, FilterRuleSet         │
└───────────────────────────────┬──────────────────────────────────────────┘
                                │ LogEvent
                                ▼
┌──────────────────────────────────────────────────────────────────────────┐
│                     purple_logger_otel (abstraction)                      │
│  • OtelLoggerProvider — abstract provider with logger caching            │
│  • OtelLogger — abstract logger with property merging & trace extraction│
│  • OtelSeverityMapping — PurpleLogLevel → OTel severity mixin            │
│  • TraceContext — vendor‑neutral traceId/spanId value object             │
└───────────────────────────────┬──────────────────────────────────────────┘
                                │ extends
                                ▼
┌──────────────────────────────────────────────────────────────────────────┐
│                purple_logger_otel_sdk (this package)                      │
│  • PurpleOtelLoggerProvider — concrete bridge to PurpleOTel SDK          │
│  • _PurpleOtelLogger.write(LogEvent) — converts event → OTel LogRecord   │
│  • emitToOtel() — calls SDKLogger.emit() with attributes                 │
└───────────────────────────────┬──────────────────────────────────────────┘
                                │ OTel LogRecord
                                ▼
┌──────────────────────────────────────────────────────────────────────────┐
│                          purple_otel_sdk                                  │
│  • SDKLoggerProvider, SDKLogger — OTel SDK logger implementation         │
│  • Processors & Exporters — Simple/Batch + Console/OTLP                  │
│  • Resource, Attributes, Severity — OTel data model                      │
└───────────────────────────────┬──────────────────────────────────────────┘
                                │ OTLP / console
                                ▼
┌──────────────────────────────────────────────────────────────────────────┐
│                     OTel Collector / Backend                              │
│  • Grafana + Tempo + Loki    • Azure Monitor / App Insights              │
│  • Jaeger                    • Datadog                                   │
│  • any OTLP-compatible backend                                            │
└──────────────────────────────────────────────────────────────────────────┘

Installation #

dependencies:
  purple_logger: ^0.3.0
  purple_logger_otel: ^0.1.0
  purple_logger_otel_sdk: ^0.1.0
  purple_otel_sdk: ^0.1.0
dart pub get

Quick Start #

A complete working example that bridges purple_logger logs into OpenTelemetry:

import 'package:purple_logger/purple_logger.dart';
import 'package:purple_otel_sdk/purple_otel_sdk.dart';
import 'package:purple_logger_otel_sdk/purple_logger_otel_sdk.dart';
import 'package:purple_otel_api/purple_otel_api.dart' show Resource, Attributes;

void main() {
  // 1. Create the SDK logger provider — this is your OTel sink.
  final sdkProvider = SDKLoggerProvider(
    resource: Resource(Attributes.fromMap({'service.name': 'my-service'})),
    processors: [
      SimpleLogRecordProcessor(ConsoleLogRecordExporter()),
    ],
  );

  // 2. Wrap it in the bridge provider.
  final bridgeProvider = PurpleOtelLoggerProvider(otelProvider: sdkProvider);

  // 3. Build the logging pipeline with the bridge as a provider.
  final factory = LoggingBuilder()
    .addProvider(bridgeProvider)
    .build();

  // 4. Use purple_logger as usual — logs flow to OTel automatically.
  final logger = factory.createLogger('order-service');

  logger.info('Order placed', properties: {'orderId': 1042});
  logger.warning('Slow query detected', properties: {
    'query': 'SELECT * FROM orders',
    'durationMs': 1250,
  });
  logger.error('Payment failed', error: PaymentException('timeout'));

  factory.dispose();
}

Data Flow #

Every log call follows this path from purple_logger to the OTel backend:

logger.info("hello", {properties: {user: "alice"}})
    │
    ▼
LoggerImpl.log(PurpleLogLevel.info, ...)
    │ builds LogEvent with scope properties merged
    │
    ▼
ProviderLogger.write(event)
    │ checks: implements EventLogger? → yes
    │
    ▼
PurpleOtelLogger.write(LogEvent event)
    │ ① merges scopeProperties + properties
    │ ② attaches error info if present
    │ ③ extracts traceId/spanId from OTel context
    │ ④ maps severity via severityNumber()/severityText()
    │ ⑤ calls emitToOtel()
    │
    ▼
emitToOtel(severity, body, attributes)
    │ builds otel.LogRecord → logger.emit()
    │
    ▼
SDKLogger.emit(LogRecord)
    │
    ▼
SimpleLogRecordProcessor / BatchLogRecordProcessor
    │
    ▼
ConsoleLogRecordExporter / OtlpHttpLogRecordExporter
    │
    ▼
OTel Collector (OTLP) or stdout → Grafana, Azure Monitor, Jaeger, ...

Severity Mapping #

PurpleLogLevel OTel SeverityNumber OTel severityText
trace 1 (TRACE) TRACE
debug 5 (DEBUG) DEBUG
info 9 (INFO) INFO
warning 13 (WARN) WARN
error 17 (ERROR) ERROR
fatal 21 (FATAL) FATAL
none 0 (UNSPECIFIED) (empty)

This mapping follows the OTel Logs specification and ships with the purple_logger_otel abstraction package via the OtelSeverityMapping mixin.

Trace Correlation #

When running inside an active trace span, log records automatically carry the traceId and spanId. This enables one-click navigation from a log line to its parent span in Grafana, Azure Monitor, or Jaeger.

import 'package:purple_otel_sdk/purple_otel_sdk.dart';
import 'package:purple_logger_otel_sdk/purple_logger_otel_sdk.dart';
import 'package:purple_otel_api/purple_otel_api.dart' show Resource, Attributes, Context;

void main() {
  final sdkProvider = SDKLoggerProvider(
    resource: Resource(Attributes.fromMap({'service.name': 'checkout'})),
    processors: [SimpleLogRecordProcessor(ConsoleLogRecordExporter())],
  );
  final bridgeProvider = PurpleOtelLoggerProvider(otelProvider: sdkProvider);
  final factory = LoggingBuilder().addProvider(bridgeProvider).build();

  final tracerProvider = SDKTracerProvider(
    resource: Resource(Attributes.fromMap({'service.name': 'checkout'})),
    spanProcessors: [SimpleSpanProcessor(ConsoleSpanExporter())],
  );

  final tracer = tracerProvider.get('checkout');

  // Inside this span, every log call is automatically correlated.
  final span = tracer.start('process-checkout');
  final ctx = Context.span(span);
  ctx.run(() {
    final logger = factory.createLogger('checkout');
    logger.info('Payment processed'); // ← carries traceId + spanId
  });

  span.end();
  factory.dispose();
  tracerProvider.shutdown();
}

When this log record is exported, the attributes include:

{
  "body": "Payment processed",
  "severityText": "INFO",
  "attributes": {
    "traceId": "0af7651916cd43dd8448eb211c80319c",
    "spanId": "b7ad6b7169203331"
  }
}

The bridge extracts trace context via extractTraceContext(), which reads from otel.Context.root.span?.spanContext. If no span is active, TraceContext.empty is returned and no trace attributes are added.

Complete Setup with OTLP Export #

Ship logs to an OTel Collector or any OTLP-compatible backend:

import 'package:purple_logger/purple_logger.dart';
import 'package:purple_otel_sdk/purple_otel_sdk.dart';
import 'package:purple_logger_otel_sdk/purple_logger_otel_sdk.dart';
import 'package:purple_otel_api/purple_otel_api.dart' show Resource, Attributes;

void main() {
  final otelProvider = SDKLoggerProvider(
    resource: Resource(Attributes.fromMap({
      'service.name': 'my-service',
      'service.version': '1.0.0',
      'deployment.environment': 'production',
    })),
    processors: [
      BatchLogRecordProcessor(
        OtlpHttpLogRecordExporter(
          endpoint: Uri.parse('http://localhost:4318/v1/logs'),
        ),
      ),
    ],
  );

  final bridgeProvider = PurpleOtelLoggerProvider(otelProvider: otelProvider);

  final factory = LoggingBuilder()
    .addProvider(bridgeProvider)
    .setMinimumLevel(PurpleLogLevel.info)
    .build();

  final logger = factory.createLogger('api-gateway');

  // These logs are batched and shipped to your OTel Collector.
  logger.info('Server started', properties: {'port': 8080});
  logger.error('Connection refused', error: SocketException('ECONNREFUSED'));

  // Graceful shutdown flushes pending records.
  factory.dispose();
}

For production, prefer BatchLogRecordProcessor over SimpleLogRecordProcessor to reduce export overhead. During shutdown, factory.dispose() calls PurpleOtelLoggerProvider.dispose(), which triggers SDKLoggerProvider.shutdown() and flushes all pending log records.

Companion Packages #

Package Description
purple_logger Structured logger with provider pipeline, scopes, filters, and formatters
purple_logger_otel Vendor-neutral OTel bridge abstractions (zero SDK deps)
purple_logger_otel_sdk This package — concrete bridge from purple_logger to PurpleOTel SDK
purple_otel_sdk OpenTelemetry SDK with logging, tracing, metrics, and OTLP export






Built by PurpleSoft #

PurpleSoft S.r.l. — software house with offices in Monza, Milano, and Lugano (Switzerland). Since 2017.

We build what doesn't exist yet.

The sectors we dominate #

Database & Storage Engines. We design, implement, and ship production-grade databases. Our LSM-tree storage engine — built in Rust for performance, exposed via FFI to Dart/Flutter, compiled to WASM for web — uses WiscKey-style key-value separation with concurrent compaction and crash recovery. It runs on all 6 platforms. This is not a wrapper around SQLite. It is a ground-up embedded NoSQL database written from scratch.

Conversational AI & Voice Assistants. We ship end-to-end AI voice platforms — from the physical device (ESP32 with custom Opus codec firmware) to the cloud backend (.NET 10, ASP.NET Core, Blazor Server) to the mobile companion app (Flutter with BLE). Our multi-agent LLM architecture orchestrates specialized agents (conversation, memory, content enrichment, research) with a multi-layered memory system spanning graph, episodic, and working memory — including adaptive forgetting, poison detection via statistical outlier analysis, and automatic episodic-to-semantic compression. Our content intelligence pipelines ingest, enrich via LLM, embed (1024-dim vectors), and serve via hybrid semantic search with HNSW indexing and training-free chunk pre-filtering — 28,000+ items enriched, 30,000+ embeddings generated.

Fintech & Payments. We build payment orchestration layers that abstract multiple gateways and cryptocurrencies behind a single API. Our engineers have shipped POS terminal firmware, fiscal receipt systems compliant with Italian regulatory standards, and cash register management platforms processing millions of transactions.

Cybersecurity & Identity. We ship post-quantum cryptography implementations using NIST-standardized algorithms on .NET 10 — the cryptography standard that will replace RSA and ECC. Our authentication infrastructure integrates SPID (Italian public digital identity) and OAuth 2.0/OpenID Connect across every major identity provider. We build digital signature platforms with PKCS#11 HSM support handling the full envelope lifecycle.

Artificial Intelligence & On-Device ML. We deploy ONNX models to phones via custom Dart runtime bindings with GPU acceleration. We integrate on-device LLM inference engines. We build neural text-to-speech engines that run across all 6 Flutter platforms and speech recognition systems with Italian dialect support. Our scientific research pipeline uses a multi-scorer verification chain with consensus voting to ensure factual accuracy in LLM outputs.

Enterprise SaaS & Cloud-Native Architecture. We architect and operate platforms at enterprise scale. Our .NET 10 monorepo spans 239 C# projects with consistent CI/CD, 297 test suites, zero build errors. We design multi-engine database abstraction layers (PostgreSQL, MySQL, Microsoft SQL Server) with automated schema-to-code generation. Our notification engine handles 6 channels with DNS-based email validation.

IoT & Embedded Systems. We write ESP32 firmware targeting ESP-IDF v5.4 with 21 FreeRTOS tasks, I²S audio pipelines, Opus codec integration, and a validated WiFi state machine. We build certificate authority infrastructure for device TLS. We write native Flutter plugins for hardware that doesn't have one yet.

Observability & DevOps. Full-stack observability is the foundation of our client solutions. We ship a complete OpenTelemetry SDK for Dart/Flutter (traces, logs, metrics, W3C propagation, OTLP export), enterprise structured logging with file rotation, and auto-instrumentation — all red-team audited with 256 automated tests.

The technologies we master #

Our engineering team works across the full stack — from ESP32 firmware to cloud-native backends to cross-platform mobile apps. We write production code in Rust (database engines, FFI), C# (.NET 10), Dart/Flutter, C (ESP-IDF, audio codecs), TypeScript, Python, and C++. Our frameworks of choice are ASP.NET Core, Blazor Server, Flutter, Angular, and React. We operate Microsoft Azure (Key Vault, Blob Storage, IoT Hub), deploy on NGINX, and manage PostgreSQL + pgvector, MySQL, Microsoft SQL Server, and ESP-IDF at scale. Our database layer uses EF Core with Npgsql, our embedded engine uses Rust + dart:ffi + WASM. Our AI stack spans LLMs, embeddings, vector search, semantic kernel, and multi-agent orchestration. We use FFmpeg for audio, LVGL for embedded displays, and BLE for device provisioning. Our CI/CD runs on Azure Pipelines.

Microsoft Partner since 2018 · SumUp Partner · Dell Partner #


Trusted by #

ABB Intesa Sanpaolo Tenaris Reply Aubay Comune di Milano BCC FIMAP Alten Altran Prometeia illimity Be Shaping the Future DS Group NVALUE Inoptim Docflow P&C

and 40+ other enterprises across banking, manufacturing, energy, and public sector.


Your project can't wait. We've solved these exact problems for companies you know. Let's solve them for you.

🌐 purplesoft.io  ·  📧 developers@purplesoft.io  ·  📞 +39 0362 148 3978  ·  💼 LinkedIn  ·  🐙 GitHub

License #

AGPL-3.0 — see LICENSE.

0
likes
150
points
96
downloads

Documentation

API reference

Publisher

verified publisherpurplesoft.io

Weekly Downloads

PurpleOTel SDK bridge for purple_logger — structured logs flow to OpenTelemetry with trace correlation.

Repository (GitHub)
View/report issues

Topics

#logging #opentelemetry #observability

License

AGPL-3.0 (license)

Dependencies

purple_logger, purple_logger_otel, purple_otel_api, purple_otel_sdk

More

Packages that depend on purple_logger_otel_sdk