LCOV - code coverage report
Current view: top level - lib/src/logs - readable_log_record.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 114 114
Test Date: 2026-07-11 13:35:19 Functions: - 0 0

            Line data    Source code
       1              : // Copyright The OpenTelemetry Authors
       2              : // SPDX-License-Identifier: Apache-2.0
       3              : 
       4              : import 'package:fixnum/fixnum.dart';
       5              : 
       6              : import '../../dartastic_opentelemetry.dart';
       7              : 
       8              : /// A read-only view of a log record.
       9              : ///
      10              : /// This interface provides read-only access to all LogRecord information
      11              : /// for exporters and processors that only need to read the data.
      12              : ///
      13              : /// Implementations can access InstrumentationScope and Resource implicitly.
      14              : ///
      15              : /// More information:
      16              : /// https://opentelemetry.io/docs/specs/otel/logs/sdk/#readablelogrecord
      17              : abstract class ReadableLogRecord implements LogRecord {
      18              :   /// The instrumentation scope associated with this log record.
      19              :   InstrumentationScope get instrumentationScope;
      20              : 
      21              :   /// The resource associated with this log record.
      22              :   Resource? get resource;
      23              : 
      24              :   /// The count of attributes that were dropped due to limits.
      25              :   int get droppedAttributesCount;
      26              : 
      27              :   /// The trace ID associated with this log record, if any.
      28              :   TraceId? get traceId;
      29              : 
      30              :   /// The span ID associated with this log record, if any.
      31              :   SpanId? get spanId;
      32              : 
      33              :   /// The trace flags associated with this log record, if any.
      34              :   TraceFlags? get traceFlags;
      35              : }
      36              : 
      37              : /// A mutable view of a log record.
      38              : ///
      39              : /// This interface extends ReadableLogRecord to provide write access to
      40              : /// log record fields. It is used by LogRecordProcessors that need to
      41              : /// modify log records.
      42              : ///
      43              : /// Implementations are NOT required to be concurrent-safe. Asynchronous
      44              : /// processors should clone the log record if needed.
      45              : ///
      46              : /// More information:
      47              : /// https://opentelemetry.io/docs/specs/otel/logs/sdk/#readwritelogrecord
      48              : abstract class ReadWriteLogRecord implements ReadableLogRecord {
      49              :   /// Sets the timestamp of when the event occurred.
      50              :   set timestamp(Int64? value);
      51              : 
      52              :   /// Sets the timestamp of when the event was observed.
      53              :   set observedTimestamp(Int64? value);
      54              : 
      55              :   /// Sets the severity number.
      56              :   set severityNumber(Severity? value);
      57              : 
      58              :   /// Sets the severity text.
      59              :   set severityText(String? value);
      60              : 
      61              :   /// Sets the body of the log record.
      62              :   set body(dynamic value);
      63              : 
      64              :   /// Sets the attributes of the log record.
      65              :   set attributes(Attributes? value);
      66              : 
      67              :   /// Sets the event name.
      68              :   set eventName(String? value);
      69              : 
      70              :   /// Sets the trace ID.
      71              :   set traceId(TraceId? value);
      72              : 
      73              :   /// Sets the span ID.
      74              :   set spanId(SpanId? value);
      75              : 
      76              :   /// Sets the trace flags.
      77              :   set traceFlags(TraceFlags? value);
      78              : 
      79              :   /// Adds an attribute to the log record.
      80              :   ///
      81              :   /// @param attribute The attribute to add
      82              :   void addAttribute(Attribute attribute);
      83              : 
      84              :   /// Removes an attribute from the log record by key.
      85              :   ///
      86              :   /// @param key The key of the attribute to remove
      87              :   void removeAttribute(String key);
      88              : 
      89              :   /// Creates a deep clone of this log record.
      90              :   ///
      91              :   /// This is useful for async processors that need to avoid race conditions.
      92              :   ReadWriteLogRecord clone();
      93              : }
      94              : 
      95              : /// SDK implementation of ReadWriteLogRecord.
      96              : ///
      97              : /// This class provides the concrete implementation of a log record with
      98              : /// both read and write capabilities.
      99              : class SDKLogRecord implements ReadWriteLogRecord {
     100              :   Int64? _timestamp;
     101              :   Int64? _observedTimestamp;
     102              :   final Context? _context;
     103              :   Severity? _severityNumber;
     104              :   String? _severityText;
     105              :   dynamic _body;
     106              :   Attributes? _attributes;
     107              :   String? _eventName;
     108              :   TraceId? _traceId;
     109              :   SpanId? _spanId;
     110              :   TraceFlags? _traceFlags;
     111              :   int _droppedAttributesCount = 0;
     112              : 
     113              :   final InstrumentationScope _instrumentationScope;
     114              :   Resource? _resource;
     115              : 
     116              :   /// Maximum number of attributes allowed per log record.
     117              :   /// This can be configured via LogRecordLimits.
     118              :   static int maxAttributeCount = 128;
     119              : 
     120              :   /// Maximum length of attribute values.
     121              :   /// This can be configured via LogRecordLimits.
     122              :   static int? maxAttributeValueLength;
     123              : 
     124              :   /// Creates a new SDK log record.
     125              :   ///
     126              :   /// @param instrumentationScope The instrumentation scope for this log record
     127              :   /// @param resource The resource associated with this log record
     128              :   /// @param timestamp When the event occurred
     129              :   /// @param observedTimestamp When the event was observed
     130              :   /// @param context The context associated with this log record
     131              :   /// @param severityNumber The severity level
     132              :   /// @param severityText The severity text
     133              :   /// @param body The log message body
     134              :   /// @param attributes Additional attributes
     135              :   /// @param eventName The event name
     136           16 :   SDKLogRecord({
     137              :     required InstrumentationScope instrumentationScope,
     138              :     Resource? resource,
     139              :     Int64? timestamp,
     140              :     Int64? observedTimestamp,
     141              :     Context? context,
     142              :     Severity? severityNumber,
     143              :     String? severityText,
     144              :     dynamic body,
     145              :     Attributes? attributes,
     146              :     String? eventName,
     147              :   })  : _instrumentationScope = instrumentationScope,
     148              :         _resource = resource,
     149              :         _timestamp = timestamp,
     150              :         _observedTimestamp = observedTimestamp,
     151              :         _context = context,
     152              :         _severityNumber = severityNumber,
     153              :         _severityText = severityText,
     154              :         _body = body,
     155              :         _attributes = attributes,
     156              :         _eventName = eventName {
     157              :     // Extract trace context from Context if available
     158           16 :     if (_context != null) {
     159           18 :       final spanContext = _context!.spanContext;
     160            2 :       if (spanContext != null && spanContext.isValid) {
     161            4 :         _traceId = spanContext.traceId;
     162            4 :         _spanId = spanContext.spanId;
     163            4 :         _traceFlags = spanContext.traceFlags;
     164              :       }
     165              :     }
     166              : 
     167              :     // Apply attribute limits
     168           16 :     _applyAttributeLimits();
     169              :   }
     170              : 
     171           16 :   void _applyAttributeLimits() {
     172           16 :     if (_attributes == null) return;
     173              : 
     174           16 :     final attrList = _attributes!.toList();
     175           16 :     if (attrList.length > maxAttributeCount) {
     176            4 :       final dropped = attrList.length - maxAttributeCount;
     177            4 :       _droppedAttributesCount += dropped;
     178            2 :       _attributes =
     179            6 :           OTel.attributesFromList(attrList.take(maxAttributeCount).toList());
     180              : 
     181            2 :       if (OTelLog.isDebug()) {
     182            2 :         OTelLog.debug(
     183            2 :             'SDKLogRecord: Dropped $dropped attributes due to limit ($maxAttributeCount)');
     184              :       }
     185              :     }
     186              :   }
     187              : 
     188           13 :   @override
     189           13 :   Int64? get timestamp => _timestamp;
     190              : 
     191            1 :   @override
     192              :   set timestamp(Int64? value) {
     193            1 :     _timestamp = value;
     194              :   }
     195              : 
     196           14 :   @override
     197           14 :   Int64? get observedTimestamp => _observedTimestamp;
     198              : 
     199            1 :   @override
     200              :   set observedTimestamp(Int64? value) {
     201            1 :     _observedTimestamp = value;
     202              :   }
     203              : 
     204            1 :   @override
     205            1 :   Context? get context => _context;
     206              : 
     207           14 :   @override
     208           14 :   Severity? get severityNumber => _severityNumber;
     209              : 
     210            1 :   @override
     211              :   set severityNumber(Severity? value) {
     212            1 :     _severityNumber = value;
     213              :   }
     214              : 
     215           14 :   @override
     216           14 :   String? get severityText => _severityText;
     217              : 
     218            1 :   @override
     219              :   set severityText(String? value) {
     220            1 :     _severityText = value;
     221              :   }
     222              : 
     223           15 :   @override
     224           15 :   dynamic get body => _body;
     225              : 
     226            1 :   @override
     227              :   set body(dynamic value) {
     228            1 :     _body = value;
     229              :   }
     230              : 
     231           14 :   @override
     232           14 :   Attributes? get attributes => _attributes;
     233              : 
     234            1 :   @override
     235              :   set attributes(Attributes? value) {
     236            1 :     _attributes = value;
     237            1 :     _applyAttributeLimits();
     238              :   }
     239              : 
     240           11 :   @override
     241           11 :   String? get eventName => _eventName;
     242              : 
     243            1 :   @override
     244              :   set eventName(String? value) {
     245            1 :     _eventName = value;
     246              :   }
     247              : 
     248            9 :   @override
     249            9 :   InstrumentationScope get instrumentationScope => _instrumentationScope;
     250              : 
     251           10 :   @override
     252           10 :   Resource? get resource => _resource;
     253              : 
     254              :   /// Sets the resource for this log record.
     255            1 :   set resource(Resource? value) {
     256            1 :     _resource = value;
     257              :   }
     258              : 
     259            8 :   @override
     260            8 :   int get droppedAttributesCount => _droppedAttributesCount;
     261              : 
     262           14 :   @override
     263           14 :   TraceId? get traceId => _traceId;
     264              : 
     265            4 :   @override
     266              :   set traceId(TraceId? value) {
     267            4 :     _traceId = value;
     268              :   }
     269              : 
     270           14 :   @override
     271           14 :   SpanId? get spanId => _spanId;
     272              : 
     273            4 :   @override
     274              :   set spanId(SpanId? value) {
     275            4 :     _spanId = value;
     276              :   }
     277              : 
     278            8 :   @override
     279            8 :   TraceFlags? get traceFlags => _traceFlags;
     280              : 
     281            3 :   @override
     282              :   set traceFlags(TraceFlags? value) {
     283            3 :     _traceFlags = value;
     284              :   }
     285              : 
     286            1 :   @override
     287              :   void addAttribute(Attribute attribute) {
     288            1 :     if (_attributes == null) {
     289            3 :       _attributes = OTel.attributesFromList([attribute]);
     290              :     } else {
     291            2 :       final currentList = _attributes!.toList();
     292            2 :       if (currentList.length >= maxAttributeCount) {
     293            2 :         _droppedAttributesCount++;
     294            1 :         if (OTelLog.isDebug()) {
     295            1 :           OTelLog.debug(
     296            2 :               'SDKLogRecord: Dropped attribute ${attribute.key} due to limit');
     297              :         }
     298              :         return;
     299              :       }
     300            4 :       _attributes = OTel.attributesFromList([...currentList, attribute]);
     301              :     }
     302              :   }
     303              : 
     304            1 :   @override
     305              :   void removeAttribute(String key) {
     306            1 :     if (_attributes == null) return;
     307            7 :     final filtered = _attributes!.toList().where((a) => a.key != key).toList();
     308            2 :     _attributes = OTel.attributesFromList(filtered);
     309              :   }
     310              : 
     311            9 :   @override
     312              :   ReadWriteLogRecord clone() {
     313            9 :     return SDKLogRecord(
     314            9 :       instrumentationScope: _instrumentationScope,
     315            9 :       resource: _resource,
     316            9 :       timestamp: _timestamp,
     317            9 :       observedTimestamp: _observedTimestamp,
     318            9 :       context: _context,
     319            9 :       severityNumber: _severityNumber,
     320            9 :       severityText: _severityText,
     321            9 :       body: _body,
     322            9 :       attributes: _attributes,
     323            9 :       eventName: _eventName,
     324              :     )
     325           18 :       .._traceId = _traceId
     326           18 :       .._spanId = _spanId
     327           18 :       .._traceFlags = _traceFlags
     328           18 :       .._droppedAttributesCount = _droppedAttributesCount;
     329              :   }
     330              : 
     331            9 :   @override
     332              :   String toString() {
     333            9 :     final buffer = StringBuffer('SDKLogRecord{');
     334           27 :     buffer.write('timestamp: $timestamp');
     335           27 :     buffer.write(', observedTimestamp: $observedTimestamp');
     336           27 :     buffer.write(', severity: $severityNumber');
     337           27 :     if (severityText != null) buffer.write(' ($severityText)');
     338           36 :     if (body != null) buffer.write(', body: $body');
     339           12 :     if (eventName != null) buffer.write(', eventName: $eventName');
     340           12 :     if (traceId != null) buffer.write(', traceId: $traceId');
     341           12 :     if (spanId != null) buffer.write(', spanId: $spanId');
     342           15 :     if (attributes != null && attributes!.length > 0) {
     343            8 :       buffer.write(', attributes: ${attributes!.length} items');
     344              :     }
     345            9 :     buffer.write('}');
     346            9 :     return buffer.toString();
     347              :   }
     348              : }
        

Generated by: LCOV version 2.0-1