dartastic_opentelemetry_api 1.0.0-beta.3 copy "dartastic_opentelemetry_api: ^1.0.0-beta.3" to clipboard
dartastic_opentelemetry_api: ^1.0.0-beta.3 copied to clipboard

Dartastic.io's OpenTelemetry API for Dart following the OpenTelemetry specification. Supports all platforms including web.

example/dartastic_opentelemetry_api_example.dart

// Licensed under the Apache License, Version 2.0
// Copyright 2025, Michael Bushe, All rights reserved.

import 'package:dartastic_opentelemetry_api/dartastic_opentelemetry_api.dart';

/// Example-only attribute keys used in this file. Prefer enums over raw
/// strings — the API's built-in semantic-convention enums (UserSemantics,
/// HttpResource, DatabaseResource, etc.) cover the OTel-defined keys; this
/// enum holds the keys that aren't in any convention. In your own app,
/// rename this to something domain-specific (e.g. `CheckoutAttribute`).
enum ExampleAttribute implements OTelSemantic {
  // Generic demo keys showing attribute types.
  exampleString('example.string'),
  exampleBool('example.bool'),
  exampleInt('example.int'),
  exampleDouble('example.double'),
  exampleStringList('example.string_list'),
  exampleBoolList('example.bool_list'),
  exampleIntList('example.int_list'),
  exampleDoubleList('example.double_list'),
  eventFoo('event.foo'),
  // Auth / cache / batch / payment / retry — none of these are in the
  // OTel semantic conventions, so they're app-defined here.
  authMethod('auth.method'),
  cacheKey('cache.key'),
  cacheRegion('cache.region'),
  batchId('batch.id'),
  jobsTotal('jobs.total'),
  paymentUserId('payment.user_id'),
  paymentMethod('payment.method'),
  paymentGateway('payment.gateway'),
  retryCount('retry.count');

  @override
  final String key;

  @override
  String toString() => key;

  const ExampleAttribute(this.key);
}

/// The API does nothing on its own; it's more typical to use the SDK.
/// However, as required by the OpenTelemetry Specification, the API
/// works (as a no-op) without the SDK installed.
void main() {
  OTelAPI.initialize(endpoint: 'http://localhost:4317');
  // Use typed enum keys — never raw strings.
  final stringAttribute =
      OTelAPI.attributeString(ExampleAttribute.exampleString.key, 'foo');
  final boolAttribute =
      OTelAPI.attributeBool(ExampleAttribute.exampleBool.key, true);
  final intAttr = OTelAPI.attributeInt(ExampleAttribute.exampleInt.key, 42);
  final doubleAttribute =
      OTelAPI.attributeDouble(ExampleAttribute.exampleDouble.key, 42.1);
  final stringListAttribute = OTelAPI.attributeStringList(
      ExampleAttribute.exampleStringList.key, ['foo', 'bar', 'baz']);
  final boolListAttribute = OTelAPI.attributeBoolList(
      ExampleAttribute.exampleBoolList.key, [true, false, true]);
  final intListAttr = OTelAPI.attributeIntList(
      ExampleAttribute.exampleIntList.key, [42, 43, 44]);
  final doubleListAttribute = OTelAPI.attributeDoubleList(
      ExampleAttribute.exampleDoubleList.key, [42.0, 42.1, 42.2]);

  OTelAPI.attributes([
    stringAttribute,
    boolAttribute,
    intAttr,
    doubleAttribute,
    stringListAttribute,
    boolListAttribute,
    intListAttr,
    doubleListAttribute
  ]);

  final baggage = OTelAPI.baggageForMap({'userId': 'yoda'});
  // Create a context with the baggage and run the example within it.
  // This ensures correct propagation across asynchronous boundaries.
  OTelAPI.context(baggage: baggage).runSync(() {
    //Trace Signal
    final defaultGlobalAPINOOPTracerProvider = OTelAPI.tracerProvider();
    final tracer = defaultGlobalAPINOOPTracerProvider
        .getTracer('dart-otel-api-example-service');

    // Use withSpan to make the span active within its scope. Wrap the work
    // in try/catch/finally so the span is always ended and any thrown
    // exception is recorded with SpanStatusCode.Error per the OTel spec.
    final span = tracer.startSpan('doSomeExampleSpan');
    try {
      tracer.withSpan(span, () {
        // Same thing as above, more simply but with some loss of type
        // checking. If your Map has anything but the types above an
        // exception will be thrown.
        final equalToTheAbove = OTelAPI.attributesFromMap({
          ExampleAttribute.exampleString.key: 'foo',
          ExampleAttribute.exampleBool.key: true,
          ExampleAttribute.exampleInt.key: 42,
          ExampleAttribute.exampleDouble.key: 42.1,
          ExampleAttribute.exampleStringList.key: ['foo', 'bar', 'baz'],
          ExampleAttribute.exampleBoolList.key: [true, false, true],
          ExampleAttribute.exampleIntList.key: [42, 43, 44],
          ExampleAttribute.exampleDoubleList.key: [42.0, 42.1, 42.2],
        });
        span.attributes = equalToTheAbove;
        span.addEventNow(
          'data-retrieved',
          OTelAPI.attributes(
              [OTelAPI.attributeString(ExampleAttribute.eventFoo.key, 'bar')]),
        );
      });
      // Capitalized Ok to match the OTel spec.
      span.setStatus(SpanStatusCode.Ok);
    } catch (e, stackTrace) {
      span.recordException(e, stackTrace: stackTrace);
      span.setStatus(SpanStatusCode.Error, e.toString());
      rethrow;
    } finally {
      span.end();
    }

    //Log Signal
    final defaultGlobalAPINOOPLoggerProvider = OTelAPI.loggerProvider();
    final logger = defaultGlobalAPINOOPLoggerProvider
        .getLogger('dart-otel-api-example-service');

    logger.emit(eventName: 'heartbeat', body: 'Service is healthy.');

    logger.emit(
      eventName: 'user_login',
      severityNumber: Severity.INFO,
      body: 'User successfully logged in.',
      attributes: Attributes.of({
        UserSemantics.userId.key: 42,
        ExampleAttribute.authMethod.key: 'password',
      }),
    );

    logger.emit(
      eventName: 'cache_miss',
      severityText: 'WARN',
      body: 'Cache miss for requested key.',
      attributes: Attributes.of({
        ExampleAttribute.cacheKey.key: 'profile_42',
        ExampleAttribute.cacheRegion.key: 'us-east-1',
      }),
    );

    final attrs = {
      DatabaseResource.dbOperation.key: 'update',
      DatabaseResource.dbCollectionName.key: 'orders',
      DatabaseResource.dbResponseReturnedRows.key: 3,
    }.toAttributes();

    logger.emit(
      eventName: 'order_update',
      severityNumber: Severity.INFO,
      body: 'Order update completed.',
      attributes: attrs,
    );

    logger.emit(
      eventName: 'batch_job_summary',
      severityNumber: Severity.INFO,
      // Body is a user-defined structure (per the OTel logs spec) — its
      // inner keys are not span/log attributes, so they don't go through
      // an OTelSemantic enum.
      body: [
        {'job': 'resize_images', 'status': 'ok'},
        {'job': 'generate_thumbnails', 'status': 'ok'},
        {'job': 'sync_metadata', 'status': 'failed'},
      ],
      attributes: Attributes.of({
        ExampleAttribute.batchId.key: 'batch-2025-11-15-01',
        ExampleAttribute.jobsTotal.key: 3,
      }),
    );

    logger.emit(
      eventName: 'payment_failure',
      severityText: 'ERROR',
      body: 'Payment could not be processed.',
      attributes: Attributes.of({
        ExampleAttribute.paymentUserId.key: 101,
        ExampleAttribute.paymentMethod.key: 'credit_card',
        ExampleAttribute.paymentGateway.key: 'stripe',
        ExampleAttribute.retryCount.key: 2,
      }),
    );
  });
}
3
likes
160
points
27.5k
downloads

Documentation

API reference

Publisher

verified publishermindfulsoftware.com

Weekly Downloads

Dartastic.io's OpenTelemetry API for Dart following the OpenTelemetry specification. Supports all platforms including web.

Homepage
Repository (GitHub)
View/report issues
Contributing

License

Apache-2.0 (license)

Dependencies

collection, fixnum, meta, web

More

Packages that depend on dartastic_opentelemetry_api