VooTelemetry

pub package Flutter OpenTelemetry License: MIT

A comprehensive OpenTelemetry SDK for Flutter applications, providing distributed tracing, metrics collection, and structured logging with OTLP (OpenTelemetry Protocol) export capabilities.

Features

  • πŸ“Š Full OpenTelemetry Support: Traces, Metrics, and Logs
  • πŸš€ Easy Integration: Simple API for Flutter apps
  • πŸ”„ Automatic Batching: Efficient data transmission
  • 🎯 Context Propagation: W3C Trace Context support
  • πŸ“‘ OTLP Export: HTTP/JSON and gRPC protocols
  • πŸ”§ Instrumentation: Built-in instrumentations for HTTP, Dio, and more
  • πŸ’Ύ Offline Support: Local storage with automatic retry
  • πŸ” Secure: API key authentication support

Installation

Add to your pubspec.yaml:

dependencies:
  voo_telemetry: ^2.0.0

Quick Start

Initialize VooTelemetry

import 'package:voo_telemetry/voo_telemetry.dart';

void main() async {
  // Initialize with your OTLP endpoint
  await VooTelemetry.initialize(
    endpoint: 'https://your-api.com', // Your DevStack API endpoint
    apiKey: 'your-api-key', // Optional API key
    serviceName: 'my-flutter-app',
    serviceVersion: '1.0.0',
    debug: true, // Enable debug logging
  );
  
  runApp(MyApp());
}

Using Traces

// Get a tracer
final tracer = VooTelemetry.instance.getTracer('my-component');

// Create spans
await tracer.withSpan('fetch-data', (span) async {
  span.setAttribute('user.id', userId);
  
  try {
    final data = await fetchData();
    span.setAttribute('data.count', data.length);
    return data;
  } catch (e, stackTrace) {
    span.recordException(e, stackTrace);
    rethrow;
  }
});

// Manual span management
final span = tracer.startSpan('manual-operation');
try {
  // Your code here
  span.setStatus(SpanStatus.ok());
} catch (e) {
  span.setStatus(SpanStatus.error(description: e.toString()));
} finally {
  span.end();
}

Using Metrics

// Get a meter
final meter = VooTelemetry.instance.getMeter('my-metrics');

// Create instruments
final counter = meter.createCounter(
  'api_calls',
  description: 'Number of API calls',
  unit: 'calls',
);

final histogram = meter.createHistogram(
  'response_time',
  description: 'API response time',
  unit: 'ms',
);

// Record metrics
counter.add(1, attributes: {'endpoint': '/users'});
histogram.record(responseTime, attributes: {'status': '200'});

Using Logs

// Get a logger
final logger = VooTelemetry.instance.getLogger('my-logger');

// Log messages
logger.info('User logged in', attributes: {'user.id': userId});
logger.warn('API rate limit approaching');
logger.error('Failed to fetch data', 
  error: exception,
  stackTrace: stackTrace,
  attributes: {'endpoint': '/api/data'},
);

HTTP Instrumentation

With Dio

import 'package:dio/dio.dart';

final dio = Dio();

// Add telemetry interceptor
dio.interceptors.add(VooTelemetryDioInterceptor());

// All HTTP calls will be automatically traced
final response = await dio.get('https://api.example.com/data');

With http package

import 'package:http/http.dart' as http;

// Wrap your HTTP client
final client = VooTelemetryHttpClient(http.Client());

// All HTTP calls will be automatically traced
final response = await client.get(Uri.parse('https://api.example.com/data'));

Advanced Configuration

await VooTelemetry.initialize(
  endpoint: 'https://your-api.com',
  apiKey: 'your-api-key',
  serviceName: 'my-app',
  serviceVersion: '1.0.0',
  additionalAttributes: {
    'deployment.environment': 'production',
    'team': 'mobile',
    'region': 'us-west-2',
  },
  batchInterval: Duration(seconds: 60), // Batch export interval
  maxBatchSize: 500, // Maximum batch size
  debug: false,
);

Context Propagation

VooTelemetry automatically propagates trace context through async operations:

final tracer = VooTelemetry.instance.getTracer();

await tracer.withSpan('parent-operation', (parentSpan) async {
  // This span will be a child of parent-operation
  await tracer.withSpan('child-operation', (childSpan) async {
    // Nested operation
  });
});

Error Handling

VooTelemetry provides comprehensive error tracking:

try {
  await riskyOperation();
} catch (e, stackTrace) {
  // Record exception with context
  VooTelemetry.instance.recordException(
    e, 
    stackTrace,
    attributes: {
      'operation': 'risky_operation',
      'user.id': currentUserId,
    },
  );
}

Performance Monitoring

Track performance metrics automatically:

final meter = VooTelemetry.instance.getMeter();
final timer = meter.createHistogram('operation_duration', unit: 'ms');

final stopwatch = Stopwatch()..start();
try {
  await performOperation();
} finally {
  stopwatch.stop();
  timer.record(
    stopwatch.elapsedMilliseconds.toDouble(),
    attributes: {'operation': 'data_processing'},
  );
}

Shutdown

Properly shutdown VooTelemetry when your app terminates:

@override
void dispose() {
  VooTelemetry.shutdown();
  super.dispose();
}

Integration with DevStack API

VooTelemetry is designed to work seamlessly with the DevStack OpenTelemetry API:

  1. Deploy DevStack API: Follow the DevStack deployment guide
  2. Configure Endpoint: Use your DevStack API URL as the endpoint
  3. Set API Key: Use the API key from your DevStack project
  4. View Telemetry: Access your data through GCP Console or Grafana

Environment Variables

You can configure VooTelemetry using environment variables:

  • OTEL_SERVICE_NAME: Service name
  • OTEL_SERVICE_VERSION: Service version
  • OTEL_EXPORTER_OTLP_ENDPOINT: OTLP endpoint URL
  • OTEL_EXPORTER_OTLP_HEADERS: Additional headers
  • OTEL_RESOURCE_ATTRIBUTES: Resource attributes

Best Practices

  1. Initialize Early: Initialize VooTelemetry as early as possible in your app lifecycle
  2. Use Semantic Attributes: Follow OpenTelemetry semantic conventions
  3. Batch Operations: Let VooTelemetry handle batching for efficiency
  4. Handle Errors: Always record exceptions with context
  5. Clean Shutdown: Ensure proper shutdown to flush pending data

Troubleshooting

Debug Mode

Enable debug mode to see detailed logs:

await VooTelemetry.initialize(
  // ... other config
  debug: true,
);

Check Connectivity

Verify endpoint connectivity:

final exporter = VooTelemetry.instance.exporter;
// Check if exports are successful

Common Issues

  • No data appearing: Check endpoint URL and API key
  • High memory usage: Reduce batch size or flush interval
  • Network errors: Ensure proper network permissions

Contributing

Contributions are welcome! Please read our contributing guidelines before submitting PRs.

License

MIT License - see LICENSE file for details

Support

For issues and questions:

Libraries

voo_telemetry