LCOV - code coverage report
Current view: top level - src/trace/export - console_exporter.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 75.5 % 49 37
Test Date: 2025-11-15 13:23:01 Functions: - 0 0

            Line data    Source code
       1              : // Licensed under the Apache License, Version 2.0
       2              : // Copyright 2025, Michael Bushe, All rights reserved.
       3              : 
       4              : import 'package:dartastic_opentelemetry/src/trace/export/span_exporter.dart';
       5              : import 'package:dartastic_opentelemetry/src/trace/span.dart';
       6              : 
       7              : /// A simple span exporter that prints spans to the console.
       8              : ///
       9              : /// This exporter is primarily used for debugging and testing, as it formats
      10              : /// and prints span information to the standard output rather than sending them
      11              : /// to a telemetry backend.
      12              : ///
      13              : /// The output includes span name, trace ID, span ID, parent span ID, duration,
      14              : /// status, and attributes for better debugging visibility.
      15              : class ConsoleExporter extends SpanExporter {
      16            1 :   @override
      17              :   Future<void> export(List<Span> spans) async {
      18            2 :     for (final span in spans) {
      19            1 :       _printSpan(span);
      20              :     }
      21              :   }
      22              : 
      23            1 :   void _printSpan(Span span) {
      24            1 :     final buffer = StringBuffer();
      25            1 :     buffer.writeln('=== OpenTelemetry Span ===');
      26            3 :     buffer.writeln('Name: ${span.name}');
      27            4 :     buffer.writeln('Trace ID: ${span.spanContext.traceId}');
      28            4 :     buffer.writeln('Span ID: ${span.spanContext.spanId}');
      29              : 
      30            2 :     if (span.spanContext.parentSpanId != null &&
      31            3 :         span.spanContext.parentSpanId!.isValid) {
      32            0 :       buffer.writeln('Parent Span ID: ${span.spanContext.parentSpanId}');
      33              :     } else {
      34            1 :       buffer.writeln('Parent Span ID: (root span)');
      35              :     }
      36              : 
      37            3 :     buffer.writeln('Kind: ${span.kind}');
      38            3 :     buffer.writeln('Status: ${span.status}');
      39              : 
      40            1 :     if (span.statusDescription != null) {
      41            0 :       buffer.writeln('Status Description: ${span.statusDescription}');
      42              :     }
      43              : 
      44            4 :     buffer.writeln('Start Time: ${span.startTime.toIso8601String()}');
      45              : 
      46            1 :     if (span.endTime != null) {
      47            4 :       buffer.writeln('End Time: ${span.endTime!.toIso8601String()}');
      48            3 :       final duration = span.endTime!.difference(span.startTime);
      49            1 :       buffer.writeln(
      50            3 :           'Duration: ${duration.inMicroseconds}μs (${duration.inMilliseconds}ms)');
      51              :     } else {
      52            0 :       buffer.writeln('End Time: (not ended)');
      53              :     }
      54              : 
      55              :     // Print attributes if any
      56              :     // ignore: invalid_use_of_visible_for_testing_member
      57            2 :     final attributes = span.attributes.toList();
      58            1 :     if (attributes.isNotEmpty) {
      59            1 :       buffer.writeln('Attributes:');
      60            2 :       for (final attr in attributes) {
      61            4 :         buffer.writeln('  ${attr.key}: ${attr.value}');
      62              :       }
      63              :     }
      64              : 
      65              :     // Print events if any
      66            1 :     final events = span.spanEvents;
      67            1 :     if (events != null && events.isNotEmpty) {
      68            1 :       buffer.writeln('Events:');
      69            2 :       for (final event in events) {
      70            5 :         buffer.writeln('  ${event.timestamp.toIso8601String()}: ${event.name}');
      71            1 :         if (event.attributes != null) {
      72            0 :           for (final attr in event.attributes!.toList()) {
      73            0 :             buffer.writeln('    ${attr.key}: ${attr.value}');
      74              :           }
      75              :         }
      76              :       }
      77              :     }
      78              : 
      79              :     // Print links if any
      80            1 :     final links = span.spanLinks;
      81            0 :     if (links != null && links.isNotEmpty) {
      82            0 :       buffer.writeln('Links:');
      83            0 :       for (final link in links) {
      84            0 :         buffer.writeln(
      85            0 :             '  -> Trace: ${link.spanContext.traceId}, Span: ${link.spanContext.spanId}');
      86            0 :         for (final attr in link.attributes.toList()) {
      87            0 :           buffer.writeln('    ${attr.key}: ${attr.value}');
      88              :         }
      89              :       }
      90              :     }
      91              : 
      92            1 :     buffer.writeln('==========================');
      93            1 :     print(buffer);
      94              :   }
      95              : 
      96            1 :   @override
      97              :   Future<void> forceFlush() async {
      98              :     // ConsoleExporter writes immediately, so nothing to flush
      99              :   }
     100              : 
     101           72 :   @override
     102              :   Future<void> shutdown() async {
     103              :     // ConsoleExporter has no resources to clean up
     104              :   }
     105              : }
        

Generated by: LCOV version 2.0-1