From fbbe03858825a75bbd5fe1f6ff5c794df3b6b1c2 Mon Sep 17 00:00:00 2001 From: provRushabhShah Date: Wed, 8 May 2024 14:37:01 +0530 Subject: [PATCH 1/5] Otel Logs implementation --- .idea/vcs.xml | 6 + .idea/workspace.xml | 97 ++++ lib/api.dart | 8 + lib/sdk.dart | 8 + lib/src/api/Logs/default_logger.dart | 54 ++ lib/src/api/Logs/event_builder.dart | 7 + lib/src/api/Logs/log_record_builder.dart | 13 + lib/src/api/Logs/logg_tracer.dart | 25 + lib/src/api/Logs/logger.dart | 6 + lib/src/api/Logs/logger_builder.dart | 8 + lib/src/api/Logs/logger_provider.dart | 17 + lib/src/api/Logs/readable_log_record.dart | 21 + lib/src/api/Logs/severity.dart | 86 ++++ lib/src/sdk/Logs/.DS_Store | Bin 0 -> 6148 bytes lib/src/sdk/Logs/component_registry.dart | 93 ++++ lib/src/sdk/Logs/dataws.dart | 347 +++++++++++++ .../Logs/expoters/log_collector_exporter.dart | 199 ++++++++ .../sdk/Logs/expoters/log_record_expoter.dart | 17 + .../Logs/expoters/log_record_processor.dart | 17 + .../expoters/simple_log_record_processor.dart | 29 ++ lib/src/sdk/Logs/log_limits.dart | 20 + lib/src/sdk/Logs/logg.dart | 98 ++++ lib/src/sdk/Logs/logger_provider.dart | 55 ++ lib/src/sdk/Logs/logging_tracer.dart | 93 ++++ lib/src/sdk/common/export_result.dart | 19 + .../opentelemetry/proto/collector/.DS_Store | Bin 0 -> 6148 bytes .../proto/collector/logs/v1/.DS_Store | Bin 0 -> 6148 bytes .../collector/logs/v1/logs_service.pb.dart | 222 ++++++++ .../logs/v1/logs_service.pbenum.dart | 11 + .../logs/v1/logs_service.pbjson.dart | 90 ++++ .../logs/v1/logs_service.pbserver.dart | 43 ++ .../opentelemetry/proto/logs/v1/logs.pb.dart | 480 ++++++++++++++++++ .../proto/logs/v1/logs.pbenum.dart | 101 ++++ .../proto/logs/v1/logs.pbjson.dart | 160 ++++++ .../proto/logs/v1/logs.pbserver.dart | 14 + .../trace/exporters/collector_exporter.dart | 2 + pub_package.pub.tgz | Bin 0 -> 55174 bytes 37 files changed, 2466 insertions(+) create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 lib/src/api/Logs/default_logger.dart create mode 100644 lib/src/api/Logs/event_builder.dart create mode 100644 lib/src/api/Logs/log_record_builder.dart create mode 100644 lib/src/api/Logs/logg_tracer.dart create mode 100644 lib/src/api/Logs/logger.dart create mode 100644 lib/src/api/Logs/logger_builder.dart create mode 100644 lib/src/api/Logs/logger_provider.dart create mode 100644 lib/src/api/Logs/readable_log_record.dart create mode 100644 lib/src/api/Logs/severity.dart create mode 100644 lib/src/sdk/Logs/.DS_Store create mode 100644 lib/src/sdk/Logs/component_registry.dart create mode 100644 lib/src/sdk/Logs/dataws.dart create mode 100644 lib/src/sdk/Logs/expoters/log_collector_exporter.dart create mode 100644 lib/src/sdk/Logs/expoters/log_record_expoter.dart create mode 100644 lib/src/sdk/Logs/expoters/log_record_processor.dart create mode 100644 lib/src/sdk/Logs/expoters/simple_log_record_processor.dart create mode 100644 lib/src/sdk/Logs/log_limits.dart create mode 100644 lib/src/sdk/Logs/logg.dart create mode 100644 lib/src/sdk/Logs/logger_provider.dart create mode 100644 lib/src/sdk/Logs/logging_tracer.dart create mode 100644 lib/src/sdk/common/export_result.dart create mode 100644 lib/src/sdk/proto/opentelemetry/proto/collector/.DS_Store create mode 100644 lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/.DS_Store create mode 100644 lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pb.dart create mode 100644 lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbenum.dart create mode 100644 lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbjson.dart create mode 100644 lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbserver.dart create mode 100644 lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pb.dart create mode 100644 lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbenum.dart create mode 100644 lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbjson.dart create mode 100644 lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbserver.dart create mode 100644 pub_package.pub.tgz diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..35eb1ddf --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 00000000..584dd768 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1714635632768 + + + + \ No newline at end of file diff --git a/lib/api.dart b/lib/api.dart index 17c57b8a..1d441fd9 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -33,3 +33,11 @@ export 'src/api/trace/trace_id.dart' show TraceId; export 'src/api/trace/trace_state.dart' show TraceState; export 'src/api/trace/tracer.dart' show Tracer; export 'src/api/trace/tracer_provider.dart' show TracerProvider; +export 'src/api//Logs/event_builder.dart'; +export 'src/api/Logs/log_record_builder.dart'; +export 'src/api/Logs/logger_builder.dart'; +export 'src/api/Logs/logger_provider.dart'; +export 'src/api/Logs/logger.dart'; +export 'src/api/Logs/severity.dart'; +export 'src/api/Logs/readable_log_record.dart'; +export 'src/api/Logs/logg_tracer.dart'; diff --git a/lib/sdk.dart b/lib/sdk.dart index 3e94fa4a..3dd254ef 100644 --- a/lib/sdk.dart +++ b/lib/sdk.dart @@ -28,3 +28,11 @@ export 'src/sdk/trace/span_processors/batch_processor.dart' export 'src/sdk/trace/span_processors/simple_processor.dart' show SimpleSpanProcessor; export 'src/sdk/trace/tracer_provider.dart' show TracerProviderBase; +export 'src/sdk/Logs/expoters/log_record_expoter.dart'; +export 'src/sdk/Logs/expoters/log_collector_exporter.dart'; + +export 'src/sdk/Logs/expoters/log_record_processor.dart'; +export 'src/sdk/Logs/expoters/simple_log_record_processor.dart'; +export 'src/sdk/Logs/logger_provider.dart'; +export 'src/sdk/Logs/log_limits.dart'; +export 'src/sdk/Logs/logg.dart'; diff --git a/lib/src/api/Logs/default_logger.dart b/lib/src/api/Logs/default_logger.dart new file mode 100644 index 00000000..55d6f1d2 --- /dev/null +++ b/lib/src/api/Logs/default_logger.dart @@ -0,0 +1,54 @@ +// import 'package:opentelemetry/api.dart'; +// +// class DefaultLogger implements Logger { +// static final DefaultLogger instanceWithDomain = DefaultLogger(true); +// static final DefaultLogger instanceNoDomain = DefaultLogger(false); +// static final NoopLogRecordBuilder noopLogRecordBuilder = NoopLogRecordBuilder(); +// +// final bool hasDomain; +// +// DefaultLogger(this.hasDomain); +// +// static Logger getInstance(bool hasDomain) { +// return hasDomain ? instanceWithDomain : instanceNoDomain; +// } +// +// @override +// EventBuilder eventBuilder(String name) { +// if (!hasDomain) { +// // log error +// } +// return noopLogRecordBuilder; +// } +// +// @override +// LogRecordBuilder logRecordBuilder() { +// return noopLogRecordBuilder; +// } +// +// static class NoopLogRecordBuilder implements EventBuilder { +// @override +// NoopLogRecordBuilder setTimestamp(DateTime timestamp) => this; +// +// @override +// NoopLogRecordBuilder setObservedTimestamp(DateTime observed) => this; +// +// @override +// NoopLogRecordBuilder setSpanContext(SpanContext context) => this; +// +// @override +// NoopLogRecordBuilder setSeverity(Severity severity) => this; +// +// @override +// NoopLogRecordBuilder setBody(dynamic body) => this; +// +// @override +// NoopLogRecordBuilder setAttributes(Map attributes) => this; +// +// @override +// NoopLogRecordBuilder setData(Map attributes) => this; +// +// @override +// void emit() {} +// } +// } diff --git a/lib/src/api/Logs/event_builder.dart b/lib/src/api/Logs/event_builder.dart new file mode 100644 index 00000000..2410aa74 --- /dev/null +++ b/lib/src/api/Logs/event_builder.dart @@ -0,0 +1,7 @@ +import 'package:opentelemetry/api.dart'; + + +abstract class EventBuilder extends LogRecordBuilder { + EventBuilder setData(Map attributes); +} + diff --git a/lib/src/api/Logs/log_record_builder.dart b/lib/src/api/Logs/log_record_builder.dart new file mode 100644 index 00000000..6a8fe333 --- /dev/null +++ b/lib/src/api/Logs/log_record_builder.dart @@ -0,0 +1,13 @@ + + +import 'package:opentelemetry/api.dart'; +import 'package:opentelemetry/src/api/Logs/severity.dart'; +abstract class LogRecordBuilder { + LogRecordBuilder setTimestamp(DateTime timestamp); + LogRecordBuilder setObservedTimestamp(DateTime observed); + LogRecordBuilder setSpanContext(SpanContext context); + LogRecordBuilder setSeverity(Severity severity); + LogRecordBuilder setBody(dynamic body); + LogRecordBuilder setAttributes(Map attributes); + void emit(); +} diff --git a/lib/src/api/Logs/logg_tracer.dart b/lib/src/api/Logs/logg_tracer.dart new file mode 100644 index 00000000..bff3526f --- /dev/null +++ b/lib/src/api/Logs/logg_tracer.dart @@ -0,0 +1,25 @@ +import '../../../api.dart' as api; +import 'package:fixnum/fixnum.dart'; + +abstract class LogTracer { + /// Starts a new [api.Span] without setting it as the current span in this + /// tracer's context. + /// + /// + api.ReadableLogRecord setLogAndEmit( + api.Attribute body, + DateTime observedTimestamp, + api.Severity severity, + String name, + {api.Context? context, + api.SpanKind kind = api.SpanKind.internal, + List attributes = const [], + List links = const [], + Int64? startTime}); + + + api.ReadableLogRecord setLogg(String name, + api.Context context, + List attributes, + int startTime); +} diff --git a/lib/src/api/Logs/logger.dart b/lib/src/api/Logs/logger.dart new file mode 100644 index 00000000..af91b939 --- /dev/null +++ b/lib/src/api/Logs/logger.dart @@ -0,0 +1,6 @@ + +import 'package:opentelemetry/api.dart'; + +abstract class Logger { + LogRecordBuilder logRecordBuilder(); +} \ No newline at end of file diff --git a/lib/src/api/Logs/logger_builder.dart b/lib/src/api/Logs/logger_builder.dart new file mode 100644 index 00000000..0968a012 --- /dev/null +++ b/lib/src/api/Logs/logger_builder.dart @@ -0,0 +1,8 @@ +import 'package:opentelemetry/api.dart'; + +abstract class LoggerBuilder { + LoggerBuilder setSchemaUrl(String schemaUrl); + LoggerBuilder setInstrumentationVersion(String instrumentationVersion); + LoggerBuilder setIncludeTraceContext(bool includeTraceContext); + LoggerBuilder setAttributes(Map attributes); +} \ No newline at end of file diff --git a/lib/src/api/Logs/logger_provider.dart b/lib/src/api/Logs/logger_provider.dart new file mode 100644 index 00000000..3149ed2f --- /dev/null +++ b/lib/src/api/Logs/logger_provider.dart @@ -0,0 +1,17 @@ +import 'package:opentelemetry/api.dart'; + + + +abstract class LoggerProvider { + LogTracer getLogger(String name, + String version, String schemaUrl, List attributes); + /// Flush all registered span processors. + void forceFlush(); + + /// Stop all registered span processors. + void shutdown(); +} + + + + diff --git a/lib/src/api/Logs/readable_log_record.dart b/lib/src/api/Logs/readable_log_record.dart new file mode 100644 index 00000000..4d712eb1 --- /dev/null +++ b/lib/src/api/Logs/readable_log_record.dart @@ -0,0 +1,21 @@ +import 'dart:ffi'; + +import 'package:opentelemetry/api.dart' as api; +import 'package:opentelemetry/sdk.dart' as sdk; +import '../../sdk/common/attributes.dart'; + +import 'package:opentelemetry/src/sdk/Logs/component_registry.dart'; + + +abstract class ReadableLogRecord { + sdk.Resource get resource; + late final DateTime observedTimestamp; + late final DateTime recordTime; + late final api.Severity severity; + late final api.Attribute body; + Attributes get attributes; + sdk.InstrumentationScope get instrumentationScope; + api.SpanContext get spanContext; + + +} \ No newline at end of file diff --git a/lib/src/api/Logs/severity.dart b/lib/src/api/Logs/severity.dart new file mode 100644 index 00000000..c0aed584 --- /dev/null +++ b/lib/src/api/Logs/severity.dart @@ -0,0 +1,86 @@ + +import 'dart:ffi'; + +enum Severity { + trace, + trace2, + trace3, + trace4, + debug, + debug2, + debug3, + debug4, + info, + info2, + info3, + info4, + warn, + warn2, + warn3, + warn4, + error, + error2, + error3, + error4, + fatal, + fatal2, + fatal3, + fatal4 +} + +extension SeverityDescription on Severity { + String get description { + switch (this) { + case Severity.trace: + return "TRACE"; + case Severity.trace2: + return "TRACE2"; + case Severity.trace3: + return "TRACE3"; + case Severity.trace4: + return "TRACE4"; + case Severity.debug: + return "DEBUG"; + case Severity.debug2: + return "DEBUG2"; + case Severity.debug3: + return "DEBUG3"; + case Severity.debug4: + return "DEBUG4"; + case Severity.info: + return "INFO"; + case Severity.info2: + return "INFO2"; + case Severity.info3: + return "INFO3"; + case Severity.info4: + return "INFO4"; + case Severity.warn: + return "WARN"; + case Severity.warn2: + return "WARN2"; + case Severity.warn3: + return "WARN3"; + case Severity.warn4: + return "WARN4"; + case Severity.error: + return "ERROR"; + case Severity.error2: + return "ERROR2"; + case Severity.error3: + return "ERROR3"; + case Severity.error4: + return "ERROR4"; + case Severity.fatal: + return "FATAL"; + case Severity.fatal2: + return "FATAL2"; + case Severity.fatal3: + return "FATAL3"; + case Severity.fatal4: + return "FATAL4"; + default: + return ""; + } + } +} diff --git a/lib/src/sdk/Logs/.DS_Store b/lib/src/sdk/Logs/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4d8e8bd22f54f994d4fcb6241306dec1984c4e4c GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8-BN@c6g>vK7HqBfgO?EN3mDOZN=-=7V9b^zH9{%msxRc5_&m<+ zZotwWJc-yD*nG3|v%B*__J=XX-AUME%wmiQXowt@C4%Oqu9^u(rK%VZE@#4%EHV2e3H3-dV{@7 zDdV8h{opDZ6+>(DOeVP>C8Ja&MBxZRZm**xl!YrNNtmfzPdh|Qw1(F9bb5T$u@8Fv zS;wB9>~}%$AI@eiv9-H*dNF*8pA-3}x#U2*k`03uyo0h(){B=Wu}mJoSLIdlgv0b0L get props => [name, version, schemaUrl]; +} + +class ComponentRegistry { + final Map _componentByName = {}; + final Map> _componentByNameVersion = {}; + final Map> _componentByNameSchema = {}; + final Map>> _componentByNameVersionSchema = {}; + final List _allComponents = []; + + final T Function(InstrumentationScopeInfo) _builder; + + ComponentRegistry(this._builder); + + T get(String name, [String? version, String? schemaUrl]) { + if (version != null && schemaUrl != null) { + if (!_componentByNameVersionSchema.containsKey(name)) { + _componentByNameVersionSchema[name] = {}; + } + if (!_componentByNameVersionSchema[name]!.containsKey(version)) { + _componentByNameVersionSchema[name]![version] = {}; + } + if (!_componentByNameVersionSchema[name]![version]!.containsKey(schemaUrl)) { + _componentByNameVersionSchema[name]![version]![schemaUrl] = _buildComponent(InstrumentationScopeInfo( + name: name, + version: version, + schemaUrl: schemaUrl, + )); + } + return _componentByNameVersionSchema[name]![version]![schemaUrl]!; + } else if (version != null) { + if (!_componentByNameVersion.containsKey(name)) { + _componentByNameVersion[name] = {}; + } + if (!_componentByNameVersion[name]!.containsKey(version)) { + _componentByNameVersion[name]![version] = _buildComponent(InstrumentationScopeInfo( + name: name, + version: version, + )); + } + return _componentByNameVersion[name]![version]!; + } else if (schemaUrl != null) { + if (!_componentByNameSchema.containsKey(name)) { + _componentByNameSchema[name] = {}; + } + if (!_componentByNameSchema[name]!.containsKey(schemaUrl)) { + _componentByNameSchema[name]![schemaUrl] = _buildComponent(InstrumentationScopeInfo( + name: name, + schemaUrl: schemaUrl, + )); + } + return _componentByNameSchema[name]![schemaUrl]!; + } else { + if (!_componentByName.containsKey(name)) { + _componentByName[name] = _buildComponent(InstrumentationScopeInfo(name: name)); + } + return _componentByName[name]!; + } + } + + T _buildComponent(InstrumentationScopeInfo scope) { + final component = _builder(scope); + _allComponents.add(component); + return component; + } + + List getComponents() { + return List.from(_allComponents); + } +} + diff --git a/lib/src/sdk/Logs/dataws.dart b/lib/src/sdk/Logs/dataws.dart new file mode 100644 index 00000000..b05816b7 --- /dev/null +++ b/lib/src/sdk/Logs/dataws.dart @@ -0,0 +1,347 @@ +// import 'package:opentelemetry/api.dart' as api; +// import 'package:opentelemetry/sdk.dart' as sdk; +// import 'package:opentelemetry/src/sdk/Logs/component_registry.dart'; +// +// +// class ReadableLogRecord { +// sdk.Resource resource; +// InstrumentationScopeInfo instrumentationScopeInfo; +// DateTime timestamp; +// DateTime? observedTimestamp; +// api.SpanContext? spanContext; +// api.Severity? severity; +// AttributeValue? body; +// Map attributes; +// +// ReadableLogRecord({ +// required this.resource, +// required this.instrumentationScopeInfo, +// required this.timestamp, +// this.observedTimestamp, +// this.spanContext, +// this.severity, +// this.body, +// required this.attributes, +// }); +// } +// +// abstract class LogRecordProcessor { +// void onEmit(ReadableLogRecord logRecord); +// ExportResult forceFlush({Duration? explicitTimeout}); +// ExportResult shutdown({Duration? explicitTimeout}); +// } +// +// extension LogRecordProcessorExtension on LogRecordProcessor { +// ExportResult forceFlush() => forceFlush(explicitTimeout: null); +// ExportResult shutdown() => shutdown(explicitTimeout: null); +// } +// +// abstract class LogRecordExporter { +// ExportResult export(List logRecords, {Duration? explicitTimeout}); +// void shutdown({Duration? explicitTimeout}); +// ExportResult forceFlush({Duration? explicitTimeout}); +// } +// +// extension LogRecordExporterExtension on LogRecordExporter { +// ExportResult export(List logRecords) => export(logRecords, explicitTimeout: null); +// void shutdown() => shutdown(explicitTimeout: null); +// ExportResult forceFlush() => forceFlush(explicitTimeout: null); +// } +// +// class InMemoryLogRecordExporter implements LogRecordExporter { +// List finishedLogRecords = []; +// bool isRunning = true; +// +// List getFinishedLogRecords() { +// return finishedLogRecords; +// } +// +// @override +// ExportResult export(List logRecords, {Duration? explicitTimeout}) { +// if (!isRunning) { +// return ExportResult.failure; +// } +// finishedLogRecords.addAll(logRecords); +// return ExportResult.success; +// } +// +// @override +// void shutdown({Duration? explicitTimeout}) { +// finishedLogRecords.clear(); +// isRunning = false; +// } +// +// @override +// ExportResult forceFlush({Duration? explicitTimeout}) { +// if (!isRunning) { +// return ExportResult.failure; +// } +// return ExportResult.success; +// } +// } +// +// class MultiLogRecordExporter implements LogRecordExporter { +// List logRecordExporters; +// +// MultiLogRecordExporter({required this.logRecordExporters}); +// +// @override +// ExportResult export(List logRecords, {Duration? explicitTimeout}) { +// var result = ExportResult.success; +// logRecordExporters.forEach((exporter) { +// result.mergeResultCode(exporter.export(logRecords, explicitTimeout: explicitTimeout)); +// }); +// return result; +// } +// +// @override +// void shutdown({Duration? explicitTimeout}) { +// logRecordExporters.forEach((exporter) { +// exporter.shutdown(explicitTimeout: explicitTimeout); +// }); +// } +// +// @override +// ExportResult forceFlush({Duration? explicitTimeout}) { +// var result = ExportResult.success; +// logRecordExporters.forEach((exporter) { +// result.mergeResultCode(exporter.forceFlush(explicitTimeout: explicitTimeout)); +// }); +// return result; +// } +// } +// +// class NoopLogRecordExporter implements LogRecordExporter { +// static final instance = NoopLogRecordExporter(); +// +// @override +// ExportResult export(List logRecords, {Duration? explicitTimeout}) { +// return ExportResult.success; +// } +// +// @override +// void shutdown({Duration? explicitTimeout}) {} +// +// @override +// ExportResult forceFlush({Duration? explicitTimeout}) { +// return ExportResult.success; +// } +// } +// +// class BatchLogRecordProcessor implements LogRecordProcessor { +// BatchWorker worker; +// +// BatchLogRecordProcessor({ +// required LogRecordExporter logRecordExporter, +// Duration scheduleDelay = const Duration(seconds: 5), +// Duration exportTimeout = const Duration(seconds: 30), +// int maxQueueSize = 2048, +// int maxExportBatchSize = 512, +// void Function(List)? willExportCallback, +// }) : worker = BatchWorker( +// logRecordExporter: logRecordExporter, +// scheduleDelay: scheduleDelay, +// exportTimeout: exportTimeout, +// maxQueueSize: maxQueueSize, +// maxExportBatchSize: maxExportBatchSize, +// willExportCallback: willExportCallback, +// ) { +// worker.start(); +// } +// +// @override +// void onEmit(ReadableLogRecord logRecord) { +// worker.emit(logRecord: logRecord); +// } +// +// @override +// ExportResult forceFlush({Duration? explicitTimeout}) { +// forceFlush(timeout: explicitTimeout); +// return ExportResult.success; +// } +// +// void forceFlush({Duration? timeout}) { +// worker.forceFlush(explicitTimeout: timeout); +// } +// +// @override +// ExportResult shutdown({Duration? explicitTimeout}) { +// worker.cancel(); +// worker.shutdown(explicitTimeout: explicitTimeout); +// return ExportResult.success; +// } +// } +// +// class BatchWorker extends Thread { +// LogRecordExporter logRecordExporter; +// Duration scheduleDelay; +// int maxQueueSize; +// int maxExportBatchSize; +// Duration exportTimeout; +// void Function(List)? willExportCallback; +// int halfMaxQueueSize; +// final cond = NSCondition(); +// List logRecordList = []; +// OperationQueue queue; +// +// BatchWorker({ +// required this.logRecordExporter, +// required this.scheduleDelay, +// required this.exportTimeout, +// required this.maxQueueSize, +// required this.maxExportBatchSize, +// required this.willExportCallback, +// }) : halfMaxQueueSize = maxQueueSize >> 1, +// queue = OperationQueue() +// ..name = 'BatchWorker Queue' +// ..maxConcurrentOperationCount = 1; +// +// void emit(ReadableLogRecord logRecord) { +// cond.lock(); +// if (logRecordList.length == maxQueueSize) { +// // TODO: record a counter for dropped logs +// cond.unlock(); +// return; +// } +// +// // TODO: record a gauge for referenced logs +// logRecordList.add(logRecord); +// if (logRecordList.length >= halfMaxQueueSize) { +// cond.broadcast(); +// } +// cond.unlock(); +// } +// +// @override +// void main() { +// do { +// autoreleasepool(() { +// List logRecordsCopy; +// cond.lock(); +// if (logRecordList.length < maxExportBatchSize) { +// do { +// cond.wait(until: DateTime.now().add(scheduleDelay)); +// } while (logRecordList.isEmpty); +// } +// logRecordsCopy = List.from(logRecordList); +// logRecordList.clear(); +// cond.unlock(); +// exportBatch(logRecordList: logRecordsCopy, explicitTimeout: exportTimeout); +// }); +// } while (true); +// } +// +// void forceFlush({Duration? explicitTimeout}) { +// List logRecordsCopy; +// cond.lock(); +// logRecordsCopy = List.from(logRecordList); +// logRecordList.clear(); +// cond.unlock(); +// +// exportBatch(logRecordList: logRecordsCopy, explicitTimeout: explicitTimeout); +// } +// +// void shutdown({Duration? explicitTimeout}) { +// final timeout = Duration( +// milliseconds: explicitTimeout != null ? explicitTimeout.inMilliseconds : double.infinity.toInt(), +// ); +// forceFlush(explicitTimeout: timeout); +// logRecordExporter.shutdown(explicitTimeout: timeout); +// } +// +// void exportBatch({required List logRecordList, Duration? explicitTimeout}) { +// final exportOperation = BlockOperation(() { +// exportAction(logRecordList: logRecordList, explicitTimeout: explicitTimeout); +// }); +// final timeoutTimer = DispatchSource.makeTimerSource(queue: DispatchQueue.global()); +// timeoutTimer.setEventHandler(() => exportOperation.cancel()); +// final maxTimeOut = Duration( +// milliseconds: explicitTimeout != null ? explicitTimeout.inMilliseconds : double.infinity.toInt(), +// ); +// timeoutTimer.schedule(deadline: DateTime.now().add(maxTimeOut), leeway: Duration(milliseconds: 1)); +// timeoutTimer.activate(); +// queue.addOperation(exportOperation); +// queue.waitUntilAllOperationsAreFinished(); +// timeoutTimer.cancel(); +// } +// +// void exportAction({required List logRecordList, Duration? explicitTimeout}) { +// for (var i = 0; i < logRecordList.length; i += maxExportBatchSize) { +// final logRecordToExport = logRecordList.sublist(i, i + maxExportBatchSize).toList(); +// willExportCallback?.call(logRecordToExport); +// logRecordExporter.export(logRecordToExport, explicitTimeout: explicitTimeout); +// } +// } +// } +// +// class MultiLogRecordProcessor implements LogRecordProcessor { +// List logRecordProcessors; +// +// MultiLogRecordProcessor({required this.logRecordProcessors}); +// +// @override +// ExportResult forceFlush({Duration? explicitTimeout}) { +// var result = ExportResult.success; +// logRecordProcessors.forEach((processor) { +// result.mergeResultCode(processor.forceFlush(explicitTimeout: explicitTimeout)); +// }); +// return result; +// } +// +// @override +// ExportResult shutdown({Duration? explicitTimeout}) { +// var result = ExportResult.success; +// logRecordProcessors.forEach((processor) { +// result.mergeResultCode(processor.shutdown(explicitTimeout: explicitTimeout)); +// }); +// return result; +// } +// +// @override +// void onEmit(ReadableLogRecord logRecord) { +// logRecordProcessors.forEach((processor) { +// processor.onEmit(logRecord); +// }); +// } +// } +// +// class NoopLogRecordProcessor implements LogRecordProcessor { +// static final noopLogRecordProcessor = NoopLogRecordProcessor(); +// +// @override +// void onEmit(ReadableLogRecord logRecord) {} +// +// @override +// ExportResult forceFlush({Duration? explicitTimeout}) { +// return ExportResult.success; +// } +// +// @override +// ExportResult shutdown({Duration? explicitTimeout}) { +// return ExportResult.success; +// } +// } +// +// class SimpleLogRecordProcessor implements LogRecordProcessor { +// LogRecordExporter logRecordExporter; +// +// SimpleLogRecordProcessor({required this.logRecordExporter}); +// +// @override +// void onEmit(ReadableLogRecord logRecord) { +// logRecordExporter.export([logRecord], explicitTimeout: null); +// } +// +// @override +// ExportResult forceFlush({Duration? explicitTimeout}) { +// return logRecordExporter.forceFlush(explicitTimeout: explicitTimeout); +// } +// +// @override +// ExportResult shutdown({Duration? explicitTimeout}) { +// logRecordExporter.shutdown(explicitTimeout: explicitTimeout); +// return ExportResult.success; +// } +// } +// +// diff --git a/lib/src/sdk/Logs/expoters/log_collector_exporter.dart b/lib/src/sdk/Logs/expoters/log_collector_exporter.dart new file mode 100644 index 00000000..15118c81 --- /dev/null +++ b/lib/src/sdk/Logs/expoters/log_collector_exporter.dart @@ -0,0 +1,199 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:fixnum/fixnum.dart'; +import 'package:http/http.dart' as http; +import 'package:logging/logging.dart'; + +import '../../../../api.dart' as api; +import '../../../../sdk.dart' as sdk; + +import '../../proto/opentelemetry/proto/collector/logs/v1/logs_service.pb.dart' +as pb_logs_service; +import '../../proto/opentelemetry/proto/common/v1/common.pb.dart' as pb_common; +import '../../proto/opentelemetry/proto/resource/v1/resource.pb.dart' +as pb_resource; +import '../../proto/opentelemetry/proto/logs/v1/logs.pb.dart' as pb_logs; +import '../../proto/opentelemetry/proto/logs/v1/logs.pbenum.dart' as pg_logs_enum; + + +class LogCollectorExporter implements sdk.LogRecordExporter { + final Logger _log = Logger('opentelemetry.CollectorExporter'); + + final Uri uri; + final http.Client client; + final Map headers; + var _isShutdown = false; + + LogCollectorExporter(this.uri, + {http.Client? httpClient, this.headers = const {}}) + : client = httpClient ?? http.Client(); + + @override + void export(List logRecords) { + if (_isShutdown) { + return; + } + + if (logRecords.isEmpty) { + return; + } + + unawaited(_send(uri, logRecords)); + } + + Future _send( + Uri uri, + List logRecords, + ) async { + try { + final body = pb_logs_service.ExportLogsServiceRequest( + resourceLogs: _logsToProtobuf(logRecords)); + + // final headers = {'Content-Type': 'application/json'} + // ..addAll(this.headers); + // final json = jsonEncode(logRecords); + final headers = {'Content-Type': 'application/x-protobuf'} + ..addAll(this.headers); + + await client.post(uri, body: body.writeToBuffer(), headers: headers); + + } catch (e) { + + _log.warning('Failed to export ${logRecords.length} spans.', e); + } + } + @override + void forceFlush() { + return; + } + + @override + void shutdown() { + _isShutdown = true; + client.close(); + } + + /// Group and construct the protobuf equivalent of the given list of [api.Span]s. + /// Spans are grouped by a trace provider's [sdk.Resource] and a tracer's + /// [sdk.InstrumentationScope]. + Iterable _logsToProtobuf( + List logRecords) { + // use a map of maps to group spans by resource and instrumentation library + final rsm = + >>{}; + for (final logRecord in logRecords) { + final il = rsm[logRecord.resource] ?? + >{}; + print(il); + + il[logRecord.instrumentationScope] = + il[logRecord.instrumentationScope] ?? [] + ..add(_spanToProtobuf(logRecord)); + print("il = ${il}"); + rsm[logRecord.resource] = il; + } + + + final rss = []; + for (final il in rsm.entries) { + // for each distinct resource, construct the protobuf equivalent + final attrs = []; + for (final attr in il.key.attributes.keys) { + attrs.add(pb_common.KeyValue( + key: attr, + value: _attributeValueToProtobuf(il.key.attributes.get(attr)!))); + } + + final rs = pb_logs.ResourceLogs( + resource: pb_resource.Resource(attributes: attrs)); + // for each distinct instrumentation library, construct the protobuf equivalent + for (final ils in il.value.entries) { + rs.scopeLogs.add(pb_logs.ScopeLogs( + logRecords: ils.value, + scope: pb_common.InstrumentationScope( + name: ils.key.name, version: ils.key.version))); + } + rss.add(rs); + } + return rss; + } + + pb_logs.LogRecord _spanToProtobuf(api.ReadableLogRecord log) { + + return pb_logs.LogRecord( + timeUnixNano: Int64(log.recordTime.microsecondsSinceEpoch), + severityNumber: pg_logs_enum.SeverityNumber.valueOf(log.severity.index), + body: _attributeONEValueToProtobuf(log.body), + attributes: log.attributes.keys.map((key) => pb_common.KeyValue( + key: key, + value: _attributeValueToProtobuf(log.attributes.get(key)!))), + spanId: log.spanContext.spanId.get(), + traceId: log.spanContext.traceId.get(), + observedTimeUnixNano: Int64(log.observedTimestamp.microsecondsSinceEpoch) + ); + + } + pb_common.AnyValue _attributeONEValueToProtobuf(Object value){ + switch (value.runtimeType) { + case String: + return pb_common.AnyValue(stringValue: value as String); + case bool: + return pb_common.AnyValue(boolValue: value as bool); + case double: + return pb_common.AnyValue(doubleValue: value as double); + case int: + return pb_common.AnyValue(intValue: Int64(value as int)); + } + return pb_common.AnyValue(); + } + pb_common.AnyValue _attributeValueToProtobuf(Object value) { + switch (value.runtimeType) { + case String: + return pb_common.AnyValue(stringValue: value as String); + case bool: + return pb_common.AnyValue(boolValue: value as bool); + case double: + return pb_common.AnyValue(doubleValue: value as double); + case int: + return pb_common.AnyValue(intValue: Int64(value as int)); + case List: + final list = value as List; + if (list.isNotEmpty) { + switch (list[0].runtimeType) { + case String: + final values = [] as List; + for (final str in list) { + values.add(pb_common.AnyValue(stringValue: str)); + } + return pb_common.AnyValue( + arrayValue: pb_common.ArrayValue(values: values)); + case bool: + final values = [] as List; + for (final b in list) { + values.add(pb_common.AnyValue(boolValue: b)); + } + return pb_common.AnyValue( + arrayValue: pb_common.ArrayValue(values: values)); + case double: + final values = [] as List; + for (final d in list) { + values.add(pb_common.AnyValue(doubleValue: d)); + } + return pb_common.AnyValue( + arrayValue: pb_common.ArrayValue(values: values)); + case int: + final values = [] as List; + for (final i in list) { + values.add(pb_common.AnyValue(intValue: i)); + } + return pb_common.AnyValue( + arrayValue: pb_common.ArrayValue(values: values)); + } + } + } + return pb_common.AnyValue(); + } + + +} diff --git a/lib/src/sdk/Logs/expoters/log_record_expoter.dart b/lib/src/sdk/Logs/expoters/log_record_expoter.dart new file mode 100644 index 00000000..37b8cc2a --- /dev/null +++ b/lib/src/sdk/Logs/expoters/log_record_expoter.dart @@ -0,0 +1,17 @@ +import 'package:opentelemetry/api.dart' as api; +import 'package:opentelemetry/sdk.dart' as sdk; +import 'package:opentelemetry/src/sdk/Logs/component_registry.dart'; +import 'package:opentelemetry/src/api/Logs/readable_log_record.dart'; +import 'package:opentelemetry/src/sdk/common/export_result.dart'; + +abstract class LogRecordExporter { + export(List logRecords); + void shutdown(); + forceFlush(); +} + +extension LogRecordExporterExtension on LogRecordExporter { + export(List logRecords) => export(logRecords); + void shutdown() => shutdown(); + forceFlush() => forceFlush(); +} diff --git a/lib/src/sdk/Logs/expoters/log_record_processor.dart b/lib/src/sdk/Logs/expoters/log_record_processor.dart new file mode 100644 index 00000000..66679f3e --- /dev/null +++ b/lib/src/sdk/Logs/expoters/log_record_processor.dart @@ -0,0 +1,17 @@ +import 'package:opentelemetry/api.dart' as api; +import 'package:opentelemetry/sdk.dart' as sdk; +import 'package:opentelemetry/src/sdk/Logs/component_registry.dart'; +import 'package:opentelemetry/src/api/Logs/readable_log_record.dart'; +import 'package:opentelemetry/src/sdk/common/export_result.dart'; + +abstract class LogRecordProcessor { + + void onEmit(ReadableLogRecord logRecord); + ExportResult forceFlush(); + ExportResult shutdown(); +} +extension LogRecordProcessorExtension on LogRecordProcessor { + ExportResult forceFlush() => forceFlush(); + ExportResult shutdown() => shutdown(); +} + diff --git a/lib/src/sdk/Logs/expoters/simple_log_record_processor.dart b/lib/src/sdk/Logs/expoters/simple_log_record_processor.dart new file mode 100644 index 00000000..3987c4aa --- /dev/null +++ b/lib/src/sdk/Logs/expoters/simple_log_record_processor.dart @@ -0,0 +1,29 @@ +import 'package:opentelemetry/api.dart' as api; +import 'package:opentelemetry/sdk.dart' as sdk; +import 'package:opentelemetry/src/sdk/Logs/component_registry.dart'; +import 'package:opentelemetry/src/api/Logs/readable_log_record.dart'; +import 'package:opentelemetry/src/sdk/common/export_result.dart'; +import 'package:opentelemetry/src/sdk/Logs/expoters/log_record_expoter.dart'; +import 'package:opentelemetry/src/sdk/Logs/expoters/log_record_processor.dart'; + +class SimpleLogRecordProcessor implements LogRecordProcessor { + LogRecordExporter logRecordExporter; + + SimpleLogRecordProcessor({required this.logRecordExporter}); + + @override + void onEmit(ReadableLogRecord logRecord) { + logRecordExporter.export([logRecord]); + } + + @override + ExportResult forceFlush() { + return logRecordExporter.forceFlush(); + } + + @override + ExportResult shutdown() { + logRecordExporter.shutdown(); + return ExportResult.success; + } +} diff --git a/lib/src/sdk/Logs/log_limits.dart b/lib/src/sdk/Logs/log_limits.dart new file mode 100644 index 00000000..40b725e2 --- /dev/null +++ b/lib/src/sdk/Logs/log_limits.dart @@ -0,0 +1,20 @@ +import 'dart:ffi'; + +import 'package:opentelemetry/api.dart' as api; +import 'package:opentelemetry/sdk.dart' as sdk; +import 'package:opentelemetry/src/sdk/Logs/component_registry.dart'; + +class LogLimits { + static const int defaultMaxAttributeCount = 128; + static const int defaultMaxAttributeLength = 4294967296; + + final int maxAttributeCount; + final int maxAttributeLength; + + + LogLimits( + {this.maxAttributeCount = defaultMaxAttributeCount, + this.maxAttributeLength = defaultMaxAttributeLength}); + + +} diff --git a/lib/src/sdk/Logs/logg.dart b/lib/src/sdk/Logs/logg.dart new file mode 100644 index 00000000..ed827e4f --- /dev/null +++ b/lib/src/sdk/Logs/logg.dart @@ -0,0 +1,98 @@ +import 'dart:ffi'; + +import 'package:fixnum/fixnum.dart'; +import 'package:meta/meta.dart'; + +import '../../../api.dart' as api; +import '../../../sdk.dart' as sdk; +import '../common/attributes.dart'; +import '../common/limits.dart' show applyAttributeLimits; + +/// A representation of a single operation within a trace. + +class Logg implements api.ReadableLogRecord{ + final api.SpanContext _spanContext; + final api.SpanId _parentSpanId; + final List _processors; + final sdk.TimeProvider _timeProvider; + final sdk.Resource _resource; + final sdk.LogLimits _limits; + final sdk.InstrumentationScope _instrumentationScope; + final Attributes _attributes = Attributes.empty(); + + final String _name; + int _droppedSpanAttributes = 0; + int _droppedSpanEvents = 0; + + @override + final api.Attribute body; + + @override + final DateTime observedTimestamp; + @override + final DateTime recordTime; + @override + final api.Severity severity; + + + Logg( + this.body, + this.recordTime, + this.observedTimestamp, + this.severity, + this._name, + this._spanContext, + this._parentSpanId, + this._processors, + this._timeProvider, + this._resource, + this._instrumentationScope, + this._limits, + ); + + @override + api.SpanId get parentSpanId => _parentSpanId; + + @override + api.SpanContext get spanContext => _spanContext; + + + @override + // TODO: implement attributes + Attributes get attributes => _attributes; + + @override + // TODO: implement instrumentationScope + sdk.InstrumentationScope get instrumentationScope => _instrumentationScope; + + @override + // TODO: implement resource + sdk.Resource get resource => _resource; + + @override + set body(api.Attribute? _body) { + // TODO: implement body + } + + @override + set observedTimestamp(DateTime? _observedTimestamp) { + // TODO: implement observedTimestamp + } + + @override + set severity(api.Severity? _severity) { + // TODO: implement severity + } + + @override + set spanContext(api.SpanContext? _spanContext) { + // TODO: implement spanContext + } + + @override + set recordTime(DateTime _recordTime) { + this.recordTime = _recordTime; + } + + +} diff --git a/lib/src/sdk/Logs/logger_provider.dart b/lib/src/sdk/Logs/logger_provider.dart new file mode 100644 index 00000000..a56a8005 --- /dev/null +++ b/lib/src/sdk/Logs/logger_provider.dart @@ -0,0 +1,55 @@ +// Copyright 2021-2022 Workiva. +// Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information + +import 'package:meta/meta.dart'; +import 'package:opentelemetry/src/api/Logs/logger_provider.dart'; +import 'package:opentelemetry/src/sdk/Logs/log_limits.dart'; +import 'package:opentelemetry/src/sdk/Logs/logging_tracer.dart'; + +import './logg.dart'; +import '../../../api.dart' as api; +import '../../../sdk.dart' as sdk; + +class LoggerTraceProviderBase implements api.LoggerProvider{ + @protected + final Map tracers = {}; + + @protected + late final List processors; + + @protected + late final sdk.Resource resource; + @protected + final sdk.Sampler sampler; + + @protected + final api.IdGenerator idGenerator; + + @protected + final sdk.LogLimits logLimits; + @override + void forceFlush() { + // TODO: implement forceFlush + } + + LoggerTraceProviderBase(this.logLimits, { this.processors = const [],resource, + this.idGenerator = const sdk.IdGenerator(), + this.sampler = const sdk.ParentBasedSampler(sdk.AlwaysOnSampler()) + }): resource = resource ?? sdk.Resource([]); + @override + api.LogTracer getLogger(String name,String version , String schemaUrl , List attributes) { + // TODO: implement getLogger + + return LoggTracer(processors, resource, sdk.DateTimeTimeProvider(), + sdk.InstrumentationScope(name, version, schemaUrl, attributes), + idGenerator, + sampler, + logLimits); + + } + + @override + void shutdown() { + // TODO: implement shutdown + } +} diff --git a/lib/src/sdk/Logs/logging_tracer.dart b/lib/src/sdk/Logs/logging_tracer.dart new file mode 100644 index 00000000..c46f7968 --- /dev/null +++ b/lib/src/sdk/Logs/logging_tracer.dart @@ -0,0 +1,93 @@ +// Copyright 2021-2022 Workiva. +// Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information + +import 'package:fixnum/fixnum.dart'; +import 'package:meta/meta.dart'; + +import '../../../api.dart' as api; +import '../../../sdk.dart' as sdk; +import '../common/limits.dart' show applyLinkLimits; + +/// An interface for creating [api.Span]s and propagating context in-process. +class LoggTracer implements api.LogTracer { + final List _processors; + final sdk.Resource _resource; + final sdk.TimeProvider _timeProvider; + final sdk.InstrumentationScope _instrumentationScope; + final sdk.LogLimits _limits; + final api.IdGenerator _idGenerator; + final sdk.Sampler _sampler; + + + @protected + const LoggTracer( + this._processors, + this._resource, + this._timeProvider, + this._instrumentationScope, + this._idGenerator, + this._sampler, + this._limits); + + @override + api.ReadableLogRecord setLogAndEmit( + api.Attribute body, + DateTime observedTimestamp, + api.Severity severity, + String name, + {api.Context? context, + api.SpanKind kind = api.SpanKind.internal, + List attributes = const [], + List links = const [], + Int64? startTime}) { + context ??= api.Context.current; + startTime ??= _timeProvider.now; + + // If a valid, active Span is present in the context, use it as this Span's + // parent. If the Context does not contain an active parent Span, create + // a root Span with a new Trace ID and default state. + // See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#determining-the-parent-span-from-a-context + final spanId = api.SpanId.fromIdGenerator(_idGenerator); + final traceState = context.spanContext.traceState; + final traceId = context.spanContext.isValid + ? context.spanContext.traceId + : api.TraceId.fromIdGenerator(_idGenerator); + final parentSpanId = context.spanContext.isValid + ? context.spanContext.spanId + : api.SpanId.root(); + + final samplerResult = + _sampler.shouldSample(context, traceId, name, kind, attributes, links); + final traceFlags = (samplerResult.decision == sdk.Decision.recordAndSample) + ? api.TraceFlags.sampled + : api.TraceFlags.none; + final spanContext = + api.SpanContext(traceId, spanId, traceFlags, traceState); + + final logg = sdk.Logg(body, + observedTimestamp, + observedTimestamp, + severity, + name, + spanContext, + parentSpanId, + _processors, + _timeProvider, + _resource, + _instrumentationScope, + _limits); + + for (var i = 0; i < _processors.length; i++) { + _processors[i].onEmit(logg); + } + + return logg; + } + @override + api.ReadableLogRecord setLogg(String name, api.Context context, List attributes, int startTime) { + // TODO: implement setLogg + context ??= api.Context.current; + + throw UnimplementedError(); + } +} diff --git a/lib/src/sdk/common/export_result.dart b/lib/src/sdk/common/export_result.dart new file mode 100644 index 00000000..e7014d88 --- /dev/null +++ b/lib/src/sdk/common/export_result.dart @@ -0,0 +1,19 @@ +enum ExportResult { + /// The export operation finished successfully. + success, + /// The export operation finished with an error. + failure, +} + +extension ExportResultExtension on ExportResult { + /// Merges the current result code with other result code + /// - Parameter newResultCode: the result code to merge with + ExportResult mergeResultCode(ExportResult newResultCode) { + // If both results are success then return success. + if (this == ExportResult.success && newResultCode == ExportResult.success) { + return ExportResult.success; + } else { + return ExportResult.failure; + } + } +} diff --git a/lib/src/sdk/proto/opentelemetry/proto/collector/.DS_Store b/lib/src/sdk/proto/opentelemetry/proto/collector/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..50f486dd5ec550f2ca08242efac8ca0ee800e62c GIT binary patch literal 6148 zcmeH~F$w}f3`G;&V!>uh%V|7-Hy9Q@!Ct^Zun`4C>p8kVnIJe?i^vZof0CK7>??LQ zBBJAMzZMxpq=%cz%0gp`ypyAx&JhV_f8j3ht;B=96)--iS@&7q~Le>xC+1b}uZyJ79K1T}(S!u1*@b}wNT4AwulZp2{}%pf{%=~Ck^l+( z83FA!(`Lj=#ohY$dRE^>)z$?L_2URHKLJSWDqh0fu%B!J&7q|#Dlq;CI0gn1_$q-1 D43QGZ literal 0 HcmV?d00001 diff --git a/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/.DS_Store b/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0? resourceLogs, + }) { + final $result = create(); + if (resourceLogs != null) { + $result.resourceLogs.addAll(resourceLogs); + } + return $result; + } + ExportLogsServiceRequest._() : super(); + factory ExportLogsServiceRequest.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ExportLogsServiceRequest.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ExportLogsServiceRequest', package: const $pb.PackageName(_omitMessageNames ? '' : 'opentelemetry.proto.collector.logs.v1'), createEmptyInstance: create) + ..pc<$4.ResourceLogs>(1, _omitFieldNames ? '' : 'resourceLogs', $pb.PbFieldType.PM, subBuilder: $4.ResourceLogs.create) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + ExportLogsServiceRequest clone() => ExportLogsServiceRequest()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + ExportLogsServiceRequest copyWith(void Function(ExportLogsServiceRequest) updates) => super.copyWith((message) => updates(message as ExportLogsServiceRequest)) as ExportLogsServiceRequest; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ExportLogsServiceRequest create() => ExportLogsServiceRequest._(); + ExportLogsServiceRequest createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static ExportLogsServiceRequest getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static ExportLogsServiceRequest? _defaultInstance; + + /// An array of ResourceLogs. + /// For data coming from a single resource this array will typically contain one + /// element. Intermediary nodes (such as OpenTelemetry Collector) that receive + /// data from multiple origins typically batch the data before forwarding further and + /// in that case this array will contain multiple elements. + @$pb.TagNumber(1) + $core.List<$4.ResourceLogs> get resourceLogs => $_getList(0); +} + +class ExportLogsServiceResponse extends $pb.GeneratedMessage { + factory ExportLogsServiceResponse({ + ExportLogsPartialSuccess? partialSuccess, + }) { + final $result = create(); + if (partialSuccess != null) { + $result.partialSuccess = partialSuccess; + } + return $result; + } + ExportLogsServiceResponse._() : super(); + factory ExportLogsServiceResponse.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ExportLogsServiceResponse.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ExportLogsServiceResponse', package: const $pb.PackageName(_omitMessageNames ? '' : 'opentelemetry.proto.collector.logs.v1'), createEmptyInstance: create) + ..aOM(1, _omitFieldNames ? '' : 'partialSuccess', subBuilder: ExportLogsPartialSuccess.create) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + ExportLogsServiceResponse clone() => ExportLogsServiceResponse()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + ExportLogsServiceResponse copyWith(void Function(ExportLogsServiceResponse) updates) => super.copyWith((message) => updates(message as ExportLogsServiceResponse)) as ExportLogsServiceResponse; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ExportLogsServiceResponse create() => ExportLogsServiceResponse._(); + ExportLogsServiceResponse createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static ExportLogsServiceResponse getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static ExportLogsServiceResponse? _defaultInstance; + + /// The details of a partially successful export request. + /// + /// If the request is only partially accepted + /// (i.e. when the server accepts only parts of the data and rejects the rest) + /// the server MUST initialize the `partial_success` field and MUST + /// set the `rejected_` with the number of items it rejected. + /// + /// Servers MAY also make use of the `partial_success` field to convey + /// warnings/suggestions to senders even when the request was fully accepted. + /// In such cases, the `rejected_` MUST have a value of `0` and + /// the `error_message` MUST be non-empty. + /// + /// A `partial_success` message with an empty value (rejected_ = 0 and + /// `error_message` = "") is equivalent to it not being set/present. Senders + /// SHOULD interpret it the same way as in the full success case. + @$pb.TagNumber(1) + ExportLogsPartialSuccess get partialSuccess => $_getN(0); + @$pb.TagNumber(1) + set partialSuccess(ExportLogsPartialSuccess v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasPartialSuccess() => $_has(0); + @$pb.TagNumber(1) + void clearPartialSuccess() => clearField(1); + @$pb.TagNumber(1) + ExportLogsPartialSuccess ensurePartialSuccess() => $_ensure(0); +} + +class ExportLogsPartialSuccess extends $pb.GeneratedMessage { + factory ExportLogsPartialSuccess({ + $fixnum.Int64? rejectedLogRecords, + $core.String? errorMessage, + }) { + final $result = create(); + if (rejectedLogRecords != null) { + $result.rejectedLogRecords = rejectedLogRecords; + } + if (errorMessage != null) { + $result.errorMessage = errorMessage; + } + return $result; + } + ExportLogsPartialSuccess._() : super(); + factory ExportLogsPartialSuccess.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ExportLogsPartialSuccess.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ExportLogsPartialSuccess', package: const $pb.PackageName(_omitMessageNames ? '' : 'opentelemetry.proto.collector.logs.v1'), createEmptyInstance: create) + ..aInt64(1, _omitFieldNames ? '' : 'rejectedLogRecords') + ..aOS(2, _omitFieldNames ? '' : 'errorMessage') + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + ExportLogsPartialSuccess clone() => ExportLogsPartialSuccess()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + ExportLogsPartialSuccess copyWith(void Function(ExportLogsPartialSuccess) updates) => super.copyWith((message) => updates(message as ExportLogsPartialSuccess)) as ExportLogsPartialSuccess; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ExportLogsPartialSuccess create() => ExportLogsPartialSuccess._(); + ExportLogsPartialSuccess createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static ExportLogsPartialSuccess getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static ExportLogsPartialSuccess? _defaultInstance; + + /// The number of rejected log records. + /// + /// A `rejected_` field holding a `0` value indicates that the + /// request was fully accepted. + @$pb.TagNumber(1) + $fixnum.Int64 get rejectedLogRecords => $_getI64(0); + @$pb.TagNumber(1) + set rejectedLogRecords($fixnum.Int64 v) { $_setInt64(0, v); } + @$pb.TagNumber(1) + $core.bool hasRejectedLogRecords() => $_has(0); + @$pb.TagNumber(1) + void clearRejectedLogRecords() => clearField(1); + + /// A developer-facing human-readable message in English. It should be used + /// either to explain why the server rejected parts of the data during a partial + /// success or to convey warnings/suggestions during a full success. The message + /// should offer guidance on how users can address such issues. + /// + /// error_message is an optional field. An error_message with an empty value + /// is equivalent to it not being set. + @$pb.TagNumber(2) + $core.String get errorMessage => $_getSZ(1); + @$pb.TagNumber(2) + set errorMessage($core.String v) { $_setString(1, v); } + @$pb.TagNumber(2) + $core.bool hasErrorMessage() => $_has(1); + @$pb.TagNumber(2) + void clearErrorMessage() => clearField(2); +} + +class LogsServiceApi { + $pb.RpcClient _client; + LogsServiceApi(this._client); + + $async.Future export($pb.ClientContext? ctx, ExportLogsServiceRequest request) => + _client.invoke(ctx, 'LogsService', 'Export', request, ExportLogsServiceResponse()) + ; +} + + +const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); +const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbenum.dart b/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbenum.dart new file mode 100644 index 00000000..66479890 --- /dev/null +++ b/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbenum.dart @@ -0,0 +1,11 @@ +// +// Generated code. Do not modify. +// source: opentelemetry/proto/collector/logs/v1/logs_service.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + diff --git a/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbjson.dart b/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbjson.dart new file mode 100644 index 00000000..aec875cb --- /dev/null +++ b/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbjson.dart @@ -0,0 +1,90 @@ +// +// Generated code. Do not modify. +// source: opentelemetry/proto/collector/logs/v1/logs_service.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +import '../../../common/v1/common.pbjson.dart' as $0; +import '../../../logs/v1/logs.pbjson.dart' as $4; +import '../../../resource/v1/resource.pbjson.dart' as $1; + +@$core.Deprecated('Use exportLogsServiceRequestDescriptor instead') +const ExportLogsServiceRequest$json = { + '1': 'ExportLogsServiceRequest', + '2': [ + {'1': 'resource_logs', '3': 1, '4': 3, '5': 11, '6': '.opentelemetry.proto.logs.v1.ResourceLogs', '10': 'resourceLogs'}, + ], +}; + +/// Descriptor for `ExportLogsServiceRequest`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List exportLogsServiceRequestDescriptor = $convert.base64Decode( + 'ChhFeHBvcnRMb2dzU2VydmljZVJlcXVlc3QSTgoNcmVzb3VyY2VfbG9ncxgBIAMoCzIpLm9wZW' + '50ZWxlbWV0cnkucHJvdG8ubG9ncy52MS5SZXNvdXJjZUxvZ3NSDHJlc291cmNlTG9ncw=='); + +@$core.Deprecated('Use exportLogsServiceResponseDescriptor instead') +const ExportLogsServiceResponse$json = { + '1': 'ExportLogsServiceResponse', + '2': [ + {'1': 'partial_success', '3': 1, '4': 1, '5': 11, '6': '.opentelemetry.proto.collector.logs.v1.ExportLogsPartialSuccess', '10': 'partialSuccess'}, + ], +}; + +/// Descriptor for `ExportLogsServiceResponse`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List exportLogsServiceResponseDescriptor = $convert.base64Decode( + 'ChlFeHBvcnRMb2dzU2VydmljZVJlc3BvbnNlEmgKD3BhcnRpYWxfc3VjY2VzcxgBIAEoCzI/Lm' + '9wZW50ZWxlbWV0cnkucHJvdG8uY29sbGVjdG9yLmxvZ3MudjEuRXhwb3J0TG9nc1BhcnRpYWxT' + 'dWNjZXNzUg5wYXJ0aWFsU3VjY2Vzcw=='); + +@$core.Deprecated('Use exportLogsPartialSuccessDescriptor instead') +const ExportLogsPartialSuccess$json = { + '1': 'ExportLogsPartialSuccess', + '2': [ + {'1': 'rejected_log_records', '3': 1, '4': 1, '5': 3, '10': 'rejectedLogRecords'}, + {'1': 'error_message', '3': 2, '4': 1, '5': 9, '10': 'errorMessage'}, + ], +}; + +/// Descriptor for `ExportLogsPartialSuccess`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List exportLogsPartialSuccessDescriptor = $convert.base64Decode( + 'ChhFeHBvcnRMb2dzUGFydGlhbFN1Y2Nlc3MSMAoUcmVqZWN0ZWRfbG9nX3JlY29yZHMYASABKA' + 'NSEnJlamVjdGVkTG9nUmVjb3JkcxIjCg1lcnJvcl9tZXNzYWdlGAIgASgJUgxlcnJvck1lc3Nh' + 'Z2U='); + +const $core.Map<$core.String, $core.dynamic> LogsServiceBase$json = { + '1': 'LogsService', + '2': [ + {'1': 'Export', '2': '.opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest', '3': '.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse', '4': {}}, + ], +}; + +@$core.Deprecated('Use logsServiceDescriptor instead') +const $core.Map<$core.String, $core.Map<$core.String, $core.dynamic>> LogsServiceBase$messageJson = { + '.opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest': ExportLogsServiceRequest$json, + '.opentelemetry.proto.logs.v1.ResourceLogs': $4.ResourceLogs$json, + '.opentelemetry.proto.resource.v1.Resource': $1.Resource$json, + '.opentelemetry.proto.common.v1.KeyValue': $0.KeyValue$json, + '.opentelemetry.proto.common.v1.AnyValue': $0.AnyValue$json, + '.opentelemetry.proto.common.v1.ArrayValue': $0.ArrayValue$json, + '.opentelemetry.proto.common.v1.KeyValueList': $0.KeyValueList$json, + '.opentelemetry.proto.logs.v1.ScopeLogs': $4.ScopeLogs$json, + '.opentelemetry.proto.common.v1.InstrumentationScope': $0.InstrumentationScope$json, + '.opentelemetry.proto.logs.v1.LogRecord': $4.LogRecord$json, + '.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse': ExportLogsServiceResponse$json, + '.opentelemetry.proto.collector.logs.v1.ExportLogsPartialSuccess': ExportLogsPartialSuccess$json, +}; + +/// Descriptor for `LogsService`. Decode as a `google.protobuf.ServiceDescriptorProto`. +final $typed_data.Uint8List logsServiceDescriptor = $convert.base64Decode( + 'CgtMb2dzU2VydmljZRKNAQoGRXhwb3J0Ej8ub3BlbnRlbGVtZXRyeS5wcm90by5jb2xsZWN0b3' + 'IubG9ncy52MS5FeHBvcnRMb2dzU2VydmljZVJlcXVlc3QaQC5vcGVudGVsZW1ldHJ5LnByb3Rv' + 'LmNvbGxlY3Rvci5sb2dzLnYxLkV4cG9ydExvZ3NTZXJ2aWNlUmVzcG9uc2UiAA=='); + diff --git a/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbserver.dart b/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbserver.dart new file mode 100644 index 00000000..a3f62f37 --- /dev/null +++ b/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbserver.dart @@ -0,0 +1,43 @@ +// +// Generated code. Do not modify. +// source: opentelemetry/proto/collector/logs/v1/logs_service.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:async' as $async; +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +import 'logs_service.pb.dart' as $5; +import 'logs_service.pbjson.dart'; + +export 'logs_service.pb.dart'; + +abstract class LogsServiceBase extends $pb.GeneratedService { + $async.Future<$5.ExportLogsServiceResponse> export($pb.ServerContext ctx, $5.ExportLogsServiceRequest request); + + $pb.GeneratedMessage createRequest($core.String methodName) { + switch (methodName) { + case 'Export': return $5.ExportLogsServiceRequest(); + default: throw $core.ArgumentError('Unknown method: $methodName'); + } + } + + $async.Future<$pb.GeneratedMessage> handleCall($pb.ServerContext ctx, $core.String methodName, $pb.GeneratedMessage request) { + switch (methodName) { + case 'Export': return this.export(ctx, request as $5.ExportLogsServiceRequest); + default: throw $core.ArgumentError('Unknown method: $methodName'); + } + } + + $core.Map<$core.String, $core.dynamic> get $json => LogsServiceBase$json; + $core.Map<$core.String, $core.Map<$core.String, $core.dynamic>> get $messageJson => LogsServiceBase$messageJson; +} + diff --git a/lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pb.dart b/lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pb.dart new file mode 100644 index 00000000..41c2b406 --- /dev/null +++ b/lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pb.dart @@ -0,0 +1,480 @@ +// +// Generated code. Do not modify. +// source: opentelemetry/proto/logs/v1/logs.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; + +import '../../common/v1/common.pb.dart' as $0; +import '../../resource/v1/resource.pb.dart' as $1; +import 'logs.pbenum.dart'; + +export 'logs.pbenum.dart'; + +/// LogsData represents the logs data that can be stored in a persistent storage, +/// OR can be embedded by other protocols that transfer OTLP logs data but do not +/// implement the OTLP protocol. +/// +/// The main difference between this message and collector protocol is that +/// in this message there will not be any "control" or "metadata" specific to +/// OTLP protocol. +/// +/// When new fields are added into this message, the OTLP request MUST be updated +/// as well. +class LogsData extends $pb.GeneratedMessage { + factory LogsData({ + $core.Iterable? resourceLogs, + }) { + final $result = create(); + if (resourceLogs != null) { + $result.resourceLogs.addAll(resourceLogs); + } + return $result; + } + LogsData._() : super(); + factory LogsData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory LogsData.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'LogsData', package: const $pb.PackageName(_omitMessageNames ? '' : 'opentelemetry.proto.logs.v1'), createEmptyInstance: create) + ..pc(1, _omitFieldNames ? '' : 'resourceLogs', $pb.PbFieldType.PM, subBuilder: ResourceLogs.create) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + LogsData clone() => LogsData()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + LogsData copyWith(void Function(LogsData) updates) => super.copyWith((message) => updates(message as LogsData)) as LogsData; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static LogsData create() => LogsData._(); + LogsData createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static LogsData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static LogsData? _defaultInstance; + + /// An array of ResourceLogs. + /// For data coming from a single resource this array will typically contain + /// one element. Intermediary nodes that receive data from multiple origins + /// typically batch the data before forwarding further and in that case this + /// array will contain multiple elements. + @$pb.TagNumber(1) + $core.List get resourceLogs => $_getList(0); +} + +/// A collection of ScopeLogs from a Resource. +class ResourceLogs extends $pb.GeneratedMessage { + factory ResourceLogs({ + $1.Resource? resource, + $core.Iterable? scopeLogs, + $core.String? schemaUrl, + }) { + final $result = create(); + if (resource != null) { + $result.resource = resource; + } + if (scopeLogs != null) { + $result.scopeLogs.addAll(scopeLogs); + } + if (schemaUrl != null) { + $result.schemaUrl = schemaUrl; + } + return $result; + } + ResourceLogs._() : super(); + factory ResourceLogs.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ResourceLogs.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ResourceLogs', package: const $pb.PackageName(_omitMessageNames ? '' : 'opentelemetry.proto.logs.v1'), createEmptyInstance: create) + ..aOM<$1.Resource>(1, _omitFieldNames ? '' : 'resource', subBuilder: $1.Resource.create) + ..pc(2, _omitFieldNames ? '' : 'scopeLogs', $pb.PbFieldType.PM, subBuilder: ScopeLogs.create) + ..aOS(3, _omitFieldNames ? '' : 'schemaUrl') + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + ResourceLogs clone() => ResourceLogs()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + ResourceLogs copyWith(void Function(ResourceLogs) updates) => super.copyWith((message) => updates(message as ResourceLogs)) as ResourceLogs; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ResourceLogs create() => ResourceLogs._(); + ResourceLogs createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static ResourceLogs getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static ResourceLogs? _defaultInstance; + + /// The resource for the logs in this message. + /// If this field is not set then resource info is unknown. + @$pb.TagNumber(1) + $1.Resource get resource => $_getN(0); + @$pb.TagNumber(1) + set resource($1.Resource v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasResource() => $_has(0); + @$pb.TagNumber(1) + void clearResource() => clearField(1); + @$pb.TagNumber(1) + $1.Resource ensureResource() => $_ensure(0); + + /// A list of ScopeLogs that originate from a resource. + @$pb.TagNumber(2) + $core.List get scopeLogs => $_getList(1); + + /// The Schema URL, if known. This is the identifier of the Schema that the resource data + /// is recorded in. To learn more about Schema URL see + /// https://opentelemetry.io/docs/specs/otel/schemas/#schema-url + /// This schema_url applies to the data in the "resource" field. It does not apply + /// to the data in the "scope_logs" field which have their own schema_url field. + @$pb.TagNumber(3) + $core.String get schemaUrl => $_getSZ(2); + @$pb.TagNumber(3) + set schemaUrl($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasSchemaUrl() => $_has(2); + @$pb.TagNumber(3) + void clearSchemaUrl() => clearField(3); +} + +/// A collection of Logs produced by a Scope. +class ScopeLogs extends $pb.GeneratedMessage { + factory ScopeLogs({ + $0.InstrumentationScope? scope, + $core.Iterable? logRecords, + $core.String? schemaUrl, + }) { + final $result = create(); + if (scope != null) { + $result.scope = scope; + } + if (logRecords != null) { + $result.logRecords.addAll(logRecords); + } + if (schemaUrl != null) { + $result.schemaUrl = schemaUrl; + } + return $result; + } + ScopeLogs._() : super(); + factory ScopeLogs.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory ScopeLogs.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ScopeLogs', package: const $pb.PackageName(_omitMessageNames ? '' : 'opentelemetry.proto.logs.v1'), createEmptyInstance: create) + ..aOM<$0.InstrumentationScope>(1, _omitFieldNames ? '' : 'scope', subBuilder: $0.InstrumentationScope.create) + ..pc(2, _omitFieldNames ? '' : 'logRecords', $pb.PbFieldType.PM, subBuilder: LogRecord.create) + ..aOS(3, _omitFieldNames ? '' : 'schemaUrl') + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + ScopeLogs clone() => ScopeLogs()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + ScopeLogs copyWith(void Function(ScopeLogs) updates) => super.copyWith((message) => updates(message as ScopeLogs)) as ScopeLogs; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static ScopeLogs create() => ScopeLogs._(); + ScopeLogs createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static ScopeLogs getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static ScopeLogs? _defaultInstance; + + /// The instrumentation scope information for the logs in this message. + /// Semantically when InstrumentationScope isn't set, it is equivalent with + /// an empty instrumentation scope name (unknown). + @$pb.TagNumber(1) + $0.InstrumentationScope get scope => $_getN(0); + @$pb.TagNumber(1) + set scope($0.InstrumentationScope v) { setField(1, v); } + @$pb.TagNumber(1) + $core.bool hasScope() => $_has(0); + @$pb.TagNumber(1) + void clearScope() => clearField(1); + @$pb.TagNumber(1) + $0.InstrumentationScope ensureScope() => $_ensure(0); + + /// A list of log records. + @$pb.TagNumber(2) + $core.List get logRecords => $_getList(1); + + /// The Schema URL, if known. This is the identifier of the Schema that the log data + /// is recorded in. To learn more about Schema URL see + /// https://opentelemetry.io/docs/specs/otel/schemas/#schema-url + /// This schema_url applies to all logs in the "logs" field. + @$pb.TagNumber(3) + $core.String get schemaUrl => $_getSZ(2); + @$pb.TagNumber(3) + set schemaUrl($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasSchemaUrl() => $_has(2); + @$pb.TagNumber(3) + void clearSchemaUrl() => clearField(3); +} + +/// A log record according to OpenTelemetry Log Data Model: +/// https://github.com/open-telemetry/oteps/blob/main/text/logs/0097-log-data-model.md +class LogRecord extends $pb.GeneratedMessage { + factory LogRecord({ + $fixnum.Int64? timeUnixNano, + SeverityNumber? severityNumber, + $core.String? severityText, + $0.AnyValue? body, + $core.Iterable<$0.KeyValue>? attributes, + $core.int? droppedAttributesCount, + $core.int? flags, + $core.List<$core.int>? traceId, + $core.List<$core.int>? spanId, + $fixnum.Int64? observedTimeUnixNano, + }) { + final $result = create(); + if (timeUnixNano != null) { + $result.timeUnixNano = timeUnixNano; + } + if (severityNumber != null) { + $result.severityNumber = severityNumber; + } + if (severityText != null) { + $result.severityText = severityText; + } + if (body != null) { + $result.body = body; + } + if (attributes != null) { + $result.attributes.addAll(attributes); + } + if (droppedAttributesCount != null) { + $result.droppedAttributesCount = droppedAttributesCount; + } + if (flags != null) { + $result.flags = flags; + } + if (traceId != null) { + $result.traceId = traceId; + } + if (spanId != null) { + $result.spanId = spanId; + } + if (observedTimeUnixNano != null) { + $result.observedTimeUnixNano = observedTimeUnixNano; + } + return $result; + } + LogRecord._() : super(); + factory LogRecord.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory LogRecord.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + + static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'LogRecord', package: const $pb.PackageName(_omitMessageNames ? '' : 'opentelemetry.proto.logs.v1'), createEmptyInstance: create) + ..a<$fixnum.Int64>(1, _omitFieldNames ? '' : 'timeUnixNano', $pb.PbFieldType.OF6, defaultOrMaker: $fixnum.Int64.ZERO) + ..e(2, _omitFieldNames ? '' : 'severityNumber', $pb.PbFieldType.OE, defaultOrMaker: SeverityNumber.SEVERITY_NUMBER_UNSPECIFIED, valueOf: SeverityNumber.valueOf, enumValues: SeverityNumber.values) + ..aOS(3, _omitFieldNames ? '' : 'severityText') + ..aOM<$0.AnyValue>(5, _omitFieldNames ? '' : 'body', subBuilder: $0.AnyValue.create) + ..pc<$0.KeyValue>(6, _omitFieldNames ? '' : 'attributes', $pb.PbFieldType.PM, subBuilder: $0.KeyValue.create) + ..a<$core.int>(7, _omitFieldNames ? '' : 'droppedAttributesCount', $pb.PbFieldType.OU3) + ..a<$core.int>(8, _omitFieldNames ? '' : 'flags', $pb.PbFieldType.OF3) + ..a<$core.List<$core.int>>(9, _omitFieldNames ? '' : 'traceId', $pb.PbFieldType.OY) + ..a<$core.List<$core.int>>(10, _omitFieldNames ? '' : 'spanId', $pb.PbFieldType.OY) + ..a<$fixnum.Int64>(11, _omitFieldNames ? '' : 'observedTimeUnixNano', $pb.PbFieldType.OF6, defaultOrMaker: $fixnum.Int64.ZERO) + ..hasRequiredFields = false + ; + + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + LogRecord clone() => LogRecord()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + LogRecord copyWith(void Function(LogRecord) updates) => super.copyWith((message) => updates(message as LogRecord)) as LogRecord; + + $pb.BuilderInfo get info_ => _i; + + @$core.pragma('dart2js:noInline') + static LogRecord create() => LogRecord._(); + LogRecord createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static LogRecord getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static LogRecord? _defaultInstance; + + /// time_unix_nano is the time when the event occurred. + /// Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. + /// Value of 0 indicates unknown or missing timestamp. + @$pb.TagNumber(1) + $fixnum.Int64 get timeUnixNano => $_getI64(0); + @$pb.TagNumber(1) + set timeUnixNano($fixnum.Int64 v) { $_setInt64(0, v); } + @$pb.TagNumber(1) + $core.bool hasTimeUnixNano() => $_has(0); + @$pb.TagNumber(1) + void clearTimeUnixNano() => clearField(1); + + /// Numerical value of the severity, normalized to values described in Log Data Model. + /// [Optional]. + @$pb.TagNumber(2) + SeverityNumber get severityNumber => $_getN(1); + @$pb.TagNumber(2) + set severityNumber(SeverityNumber v) { setField(2, v); } + @$pb.TagNumber(2) + $core.bool hasSeverityNumber() => $_has(1); + @$pb.TagNumber(2) + void clearSeverityNumber() => clearField(2); + + /// The severity text (also known as log level). The original string representation as + /// it is known at the source. [Optional]. + @$pb.TagNumber(3) + $core.String get severityText => $_getSZ(2); + @$pb.TagNumber(3) + set severityText($core.String v) { $_setString(2, v); } + @$pb.TagNumber(3) + $core.bool hasSeverityText() => $_has(2); + @$pb.TagNumber(3) + void clearSeverityText() => clearField(3); + + /// A value containing the body of the log record. Can be for example a human-readable + /// string message (including multi-line) describing the event in a free form or it can + /// be a structured data composed of arrays and maps of other values. [Optional]. + @$pb.TagNumber(5) + $0.AnyValue get body => $_getN(3); + @$pb.TagNumber(5) + set body($0.AnyValue v) { setField(5, v); } + @$pb.TagNumber(5) + $core.bool hasBody() => $_has(3); + @$pb.TagNumber(5) + void clearBody() => clearField(5); + @$pb.TagNumber(5) + $0.AnyValue ensureBody() => $_ensure(3); + + /// Additional attributes that describe the specific event occurrence. [Optional]. + /// Attribute keys MUST be unique (it is not allowed to have more than one + /// attribute with the same key). + @$pb.TagNumber(6) + $core.List<$0.KeyValue> get attributes => $_getList(4); + + @$pb.TagNumber(7) + $core.int get droppedAttributesCount => $_getIZ(5); + @$pb.TagNumber(7) + set droppedAttributesCount($core.int v) { $_setUnsignedInt32(5, v); } + @$pb.TagNumber(7) + $core.bool hasDroppedAttributesCount() => $_has(5); + @$pb.TagNumber(7) + void clearDroppedAttributesCount() => clearField(7); + + /// Flags, a bit field. 8 least significant bits are the trace flags as + /// defined in W3C Trace Context specification. 24 most significant bits are reserved + /// and must be set to 0. Readers must not assume that 24 most significant bits + /// will be zero and must correctly mask the bits when reading 8-bit trace flag (use + /// flags & LOG_RECORD_FLAGS_TRACE_FLAGS_MASK). [Optional]. + @$pb.TagNumber(8) + $core.int get flags => $_getIZ(6); + @$pb.TagNumber(8) + set flags($core.int v) { $_setUnsignedInt32(6, v); } + @$pb.TagNumber(8) + $core.bool hasFlags() => $_has(6); + @$pb.TagNumber(8) + void clearFlags() => clearField(8); + + /// A unique identifier for a trace. All logs from the same trace share + /// the same `trace_id`. The ID is a 16-byte array. An ID with all zeroes OR + /// of length other than 16 bytes is considered invalid (empty string in OTLP/JSON + /// is zero-length and thus is also invalid). + /// + /// This field is optional. + /// + /// The receivers SHOULD assume that the log record is not associated with a + /// trace if any of the following is true: + /// - the field is not present, + /// - the field contains an invalid value. + @$pb.TagNumber(9) + $core.List<$core.int> get traceId => $_getN(7); + @$pb.TagNumber(9) + set traceId($core.List<$core.int> v) { $_setBytes(7, v); } + @$pb.TagNumber(9) + $core.bool hasTraceId() => $_has(7); + @$pb.TagNumber(9) + void clearTraceId() => clearField(9); + + /// A unique identifier for a span within a trace, assigned when the span + /// is created. The ID is an 8-byte array. An ID with all zeroes OR of length + /// other than 8 bytes is considered invalid (empty string in OTLP/JSON + /// is zero-length and thus is also invalid). + /// + /// This field is optional. If the sender specifies a valid span_id then it SHOULD also + /// specify a valid trace_id. + /// + /// The receivers SHOULD assume that the log record is not associated with a + /// span if any of the following is true: + /// - the field is not present, + /// - the field contains an invalid value. + @$pb.TagNumber(10) + $core.List<$core.int> get spanId => $_getN(8); + @$pb.TagNumber(10) + set spanId($core.List<$core.int> v) { $_setBytes(8, v); } + @$pb.TagNumber(10) + $core.bool hasSpanId() => $_has(8); + @$pb.TagNumber(10) + void clearSpanId() => clearField(10); + + /// Time when the event was observed by the collection system. + /// For events that originate in OpenTelemetry (e.g. using OpenTelemetry Logging SDK) + /// this timestamp is typically set at the generation time and is equal to Timestamp. + /// For events originating externally and collected by OpenTelemetry (e.g. using + /// Collector) this is the time when OpenTelemetry's code observed the event measured + /// by the clock of the OpenTelemetry code. This field MUST be set once the event is + /// observed by OpenTelemetry. + /// + /// For converting OpenTelemetry log data to formats that support only one timestamp or + /// when receiving OpenTelemetry log data by recipients that support only one timestamp + /// internally the following logic is recommended: + /// - Use time_unix_nano if it is present, otherwise use observed_time_unix_nano. + /// + /// Value is UNIX Epoch time in nanoseconds since 00:00:00 UTC on 1 January 1970. + /// Value of 0 indicates unknown or missing timestamp. + @$pb.TagNumber(11) + $fixnum.Int64 get observedTimeUnixNano => $_getI64(9); + @$pb.TagNumber(11) + set observedTimeUnixNano($fixnum.Int64 v) { $_setInt64(9, v); } + @$pb.TagNumber(11) + $core.bool hasObservedTimeUnixNano() => $_has(9); + @$pb.TagNumber(11) + void clearObservedTimeUnixNano() => clearField(11); +} + + +const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); +const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); diff --git a/lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbenum.dart b/lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbenum.dart new file mode 100644 index 00000000..53d665af --- /dev/null +++ b/lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbenum.dart @@ -0,0 +1,101 @@ +// +// Generated code. Do not modify. +// source: opentelemetry/proto/logs/v1/logs.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:core' as $core; + +import 'package:protobuf/protobuf.dart' as $pb; + +/// Possible values for LogRecord.SeverityNumber. +class SeverityNumber extends $pb.ProtobufEnum { + static const SeverityNumber SEVERITY_NUMBER_UNSPECIFIED = SeverityNumber._(0, _omitEnumNames ? '' : 'SEVERITY_NUMBER_UNSPECIFIED'); + static const SeverityNumber SEVERITY_NUMBER_TRACE = SeverityNumber._(1, _omitEnumNames ? '' : 'SEVERITY_NUMBER_TRACE'); + static const SeverityNumber SEVERITY_NUMBER_TRACE2 = SeverityNumber._(2, _omitEnumNames ? '' : 'SEVERITY_NUMBER_TRACE2'); + static const SeverityNumber SEVERITY_NUMBER_TRACE3 = SeverityNumber._(3, _omitEnumNames ? '' : 'SEVERITY_NUMBER_TRACE3'); + static const SeverityNumber SEVERITY_NUMBER_TRACE4 = SeverityNumber._(4, _omitEnumNames ? '' : 'SEVERITY_NUMBER_TRACE4'); + static const SeverityNumber SEVERITY_NUMBER_DEBUG = SeverityNumber._(5, _omitEnumNames ? '' : 'SEVERITY_NUMBER_DEBUG'); + static const SeverityNumber SEVERITY_NUMBER_DEBUG2 = SeverityNumber._(6, _omitEnumNames ? '' : 'SEVERITY_NUMBER_DEBUG2'); + static const SeverityNumber SEVERITY_NUMBER_DEBUG3 = SeverityNumber._(7, _omitEnumNames ? '' : 'SEVERITY_NUMBER_DEBUG3'); + static const SeverityNumber SEVERITY_NUMBER_DEBUG4 = SeverityNumber._(8, _omitEnumNames ? '' : 'SEVERITY_NUMBER_DEBUG4'); + static const SeverityNumber SEVERITY_NUMBER_INFO = SeverityNumber._(9, _omitEnumNames ? '' : 'SEVERITY_NUMBER_INFO'); + static const SeverityNumber SEVERITY_NUMBER_INFO2 = SeverityNumber._(10, _omitEnumNames ? '' : 'SEVERITY_NUMBER_INFO2'); + static const SeverityNumber SEVERITY_NUMBER_INFO3 = SeverityNumber._(11, _omitEnumNames ? '' : 'SEVERITY_NUMBER_INFO3'); + static const SeverityNumber SEVERITY_NUMBER_INFO4 = SeverityNumber._(12, _omitEnumNames ? '' : 'SEVERITY_NUMBER_INFO4'); + static const SeverityNumber SEVERITY_NUMBER_WARN = SeverityNumber._(13, _omitEnumNames ? '' : 'SEVERITY_NUMBER_WARN'); + static const SeverityNumber SEVERITY_NUMBER_WARN2 = SeverityNumber._(14, _omitEnumNames ? '' : 'SEVERITY_NUMBER_WARN2'); + static const SeverityNumber SEVERITY_NUMBER_WARN3 = SeverityNumber._(15, _omitEnumNames ? '' : 'SEVERITY_NUMBER_WARN3'); + static const SeverityNumber SEVERITY_NUMBER_WARN4 = SeverityNumber._(16, _omitEnumNames ? '' : 'SEVERITY_NUMBER_WARN4'); + static const SeverityNumber SEVERITY_NUMBER_ERROR = SeverityNumber._(17, _omitEnumNames ? '' : 'SEVERITY_NUMBER_ERROR'); + static const SeverityNumber SEVERITY_NUMBER_ERROR2 = SeverityNumber._(18, _omitEnumNames ? '' : 'SEVERITY_NUMBER_ERROR2'); + static const SeverityNumber SEVERITY_NUMBER_ERROR3 = SeverityNumber._(19, _omitEnumNames ? '' : 'SEVERITY_NUMBER_ERROR3'); + static const SeverityNumber SEVERITY_NUMBER_ERROR4 = SeverityNumber._(20, _omitEnumNames ? '' : 'SEVERITY_NUMBER_ERROR4'); + static const SeverityNumber SEVERITY_NUMBER_FATAL = SeverityNumber._(21, _omitEnumNames ? '' : 'SEVERITY_NUMBER_FATAL'); + static const SeverityNumber SEVERITY_NUMBER_FATAL2 = SeverityNumber._(22, _omitEnumNames ? '' : 'SEVERITY_NUMBER_FATAL2'); + static const SeverityNumber SEVERITY_NUMBER_FATAL3 = SeverityNumber._(23, _omitEnumNames ? '' : 'SEVERITY_NUMBER_FATAL3'); + static const SeverityNumber SEVERITY_NUMBER_FATAL4 = SeverityNumber._(24, _omitEnumNames ? '' : 'SEVERITY_NUMBER_FATAL4'); + + static const $core.List values = [ + SEVERITY_NUMBER_UNSPECIFIED, + SEVERITY_NUMBER_TRACE, + SEVERITY_NUMBER_TRACE2, + SEVERITY_NUMBER_TRACE3, + SEVERITY_NUMBER_TRACE4, + SEVERITY_NUMBER_DEBUG, + SEVERITY_NUMBER_DEBUG2, + SEVERITY_NUMBER_DEBUG3, + SEVERITY_NUMBER_DEBUG4, + SEVERITY_NUMBER_INFO, + SEVERITY_NUMBER_INFO2, + SEVERITY_NUMBER_INFO3, + SEVERITY_NUMBER_INFO4, + SEVERITY_NUMBER_WARN, + SEVERITY_NUMBER_WARN2, + SEVERITY_NUMBER_WARN3, + SEVERITY_NUMBER_WARN4, + SEVERITY_NUMBER_ERROR, + SEVERITY_NUMBER_ERROR2, + SEVERITY_NUMBER_ERROR3, + SEVERITY_NUMBER_ERROR4, + SEVERITY_NUMBER_FATAL, + SEVERITY_NUMBER_FATAL2, + SEVERITY_NUMBER_FATAL3, + SEVERITY_NUMBER_FATAL4, + ]; + + static final $core.Map<$core.int, SeverityNumber> _byValue = $pb.ProtobufEnum.initByValue(values); + static SeverityNumber? valueOf($core.int value) => _byValue[value]; + + const SeverityNumber._($core.int v, $core.String n) : super(v, n); +} + +/// LogRecordFlags represents constants used to interpret the +/// LogRecord.flags field, which is protobuf 'fixed32' type and is to +/// be used as bit-fields. Each non-zero value defined in this enum is +/// a bit-mask. To extract the bit-field, for example, use an +/// expression like: +/// +/// (logRecord.flags & LOG_RECORD_FLAGS_TRACE_FLAGS_MASK) +class LogRecordFlags extends $pb.ProtobufEnum { + static const LogRecordFlags LOG_RECORD_FLAGS_DO_NOT_USE = LogRecordFlags._(0, _omitEnumNames ? '' : 'LOG_RECORD_FLAGS_DO_NOT_USE'); + static const LogRecordFlags LOG_RECORD_FLAGS_TRACE_FLAGS_MASK = LogRecordFlags._(255, _omitEnumNames ? '' : 'LOG_RECORD_FLAGS_TRACE_FLAGS_MASK'); + + static const $core.List values = [ + LOG_RECORD_FLAGS_DO_NOT_USE, + LOG_RECORD_FLAGS_TRACE_FLAGS_MASK, + ]; + + static final $core.Map<$core.int, LogRecordFlags> _byValue = $pb.ProtobufEnum.initByValue(values); + static LogRecordFlags? valueOf($core.int value) => _byValue[value]; + + const LogRecordFlags._($core.int v, $core.String n) : super(v, n); +} + + +const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names'); diff --git a/lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbjson.dart b/lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbjson.dart new file mode 100644 index 00000000..69ac8640 --- /dev/null +++ b/lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbjson.dart @@ -0,0 +1,160 @@ +// +// Generated code. Do not modify. +// source: opentelemetry/proto/logs/v1/logs.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +import 'dart:convert' as $convert; +import 'dart:core' as $core; +import 'dart:typed_data' as $typed_data; + +@$core.Deprecated('Use severityNumberDescriptor instead') +const SeverityNumber$json = { + '1': 'SeverityNumber', + '2': [ + {'1': 'SEVERITY_NUMBER_UNSPECIFIED', '2': 0}, + {'1': 'SEVERITY_NUMBER_TRACE', '2': 1}, + {'1': 'SEVERITY_NUMBER_TRACE2', '2': 2}, + {'1': 'SEVERITY_NUMBER_TRACE3', '2': 3}, + {'1': 'SEVERITY_NUMBER_TRACE4', '2': 4}, + {'1': 'SEVERITY_NUMBER_DEBUG', '2': 5}, + {'1': 'SEVERITY_NUMBER_DEBUG2', '2': 6}, + {'1': 'SEVERITY_NUMBER_DEBUG3', '2': 7}, + {'1': 'SEVERITY_NUMBER_DEBUG4', '2': 8}, + {'1': 'SEVERITY_NUMBER_INFO', '2': 9}, + {'1': 'SEVERITY_NUMBER_INFO2', '2': 10}, + {'1': 'SEVERITY_NUMBER_INFO3', '2': 11}, + {'1': 'SEVERITY_NUMBER_INFO4', '2': 12}, + {'1': 'SEVERITY_NUMBER_WARN', '2': 13}, + {'1': 'SEVERITY_NUMBER_WARN2', '2': 14}, + {'1': 'SEVERITY_NUMBER_WARN3', '2': 15}, + {'1': 'SEVERITY_NUMBER_WARN4', '2': 16}, + {'1': 'SEVERITY_NUMBER_ERROR', '2': 17}, + {'1': 'SEVERITY_NUMBER_ERROR2', '2': 18}, + {'1': 'SEVERITY_NUMBER_ERROR3', '2': 19}, + {'1': 'SEVERITY_NUMBER_ERROR4', '2': 20}, + {'1': 'SEVERITY_NUMBER_FATAL', '2': 21}, + {'1': 'SEVERITY_NUMBER_FATAL2', '2': 22}, + {'1': 'SEVERITY_NUMBER_FATAL3', '2': 23}, + {'1': 'SEVERITY_NUMBER_FATAL4', '2': 24}, + ], +}; + +/// Descriptor for `SeverityNumber`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List severityNumberDescriptor = $convert.base64Decode( + 'Cg5TZXZlcml0eU51bWJlchIfChtTRVZFUklUWV9OVU1CRVJfVU5TUEVDSUZJRUQQABIZChVTRV' + 'ZFUklUWV9OVU1CRVJfVFJBQ0UQARIaChZTRVZFUklUWV9OVU1CRVJfVFJBQ0UyEAISGgoWU0VW' + 'RVJJVFlfTlVNQkVSX1RSQUNFMxADEhoKFlNFVkVSSVRZX05VTUJFUl9UUkFDRTQQBBIZChVTRV' + 'ZFUklUWV9OVU1CRVJfREVCVUcQBRIaChZTRVZFUklUWV9OVU1CRVJfREVCVUcyEAYSGgoWU0VW' + 'RVJJVFlfTlVNQkVSX0RFQlVHMxAHEhoKFlNFVkVSSVRZX05VTUJFUl9ERUJVRzQQCBIYChRTRV' + 'ZFUklUWV9OVU1CRVJfSU5GTxAJEhkKFVNFVkVSSVRZX05VTUJFUl9JTkZPMhAKEhkKFVNFVkVS' + 'SVRZX05VTUJFUl9JTkZPMxALEhkKFVNFVkVSSVRZX05VTUJFUl9JTkZPNBAMEhgKFFNFVkVSSV' + 'RZX05VTUJFUl9XQVJOEA0SGQoVU0VWRVJJVFlfTlVNQkVSX1dBUk4yEA4SGQoVU0VWRVJJVFlf' + 'TlVNQkVSX1dBUk4zEA8SGQoVU0VWRVJJVFlfTlVNQkVSX1dBUk40EBASGQoVU0VWRVJJVFlfTl' + 'VNQkVSX0VSUk9SEBESGgoWU0VWRVJJVFlfTlVNQkVSX0VSUk9SMhASEhoKFlNFVkVSSVRZX05V' + 'TUJFUl9FUlJPUjMQExIaChZTRVZFUklUWV9OVU1CRVJfRVJST1I0EBQSGQoVU0VWRVJJVFlfTl' + 'VNQkVSX0ZBVEFMEBUSGgoWU0VWRVJJVFlfTlVNQkVSX0ZBVEFMMhAWEhoKFlNFVkVSSVRZX05V' + 'TUJFUl9GQVRBTDMQFxIaChZTRVZFUklUWV9OVU1CRVJfRkFUQUw0EBg='); + +@$core.Deprecated('Use logRecordFlagsDescriptor instead') +const LogRecordFlags$json = { + '1': 'LogRecordFlags', + '2': [ + {'1': 'LOG_RECORD_FLAGS_DO_NOT_USE', '2': 0}, + {'1': 'LOG_RECORD_FLAGS_TRACE_FLAGS_MASK', '2': 255}, + ], +}; + +/// Descriptor for `LogRecordFlags`. Decode as a `google.protobuf.EnumDescriptorProto`. +final $typed_data.Uint8List logRecordFlagsDescriptor = $convert.base64Decode( + 'Cg5Mb2dSZWNvcmRGbGFncxIfChtMT0dfUkVDT1JEX0ZMQUdTX0RPX05PVF9VU0UQABImCiFMT0' + 'dfUkVDT1JEX0ZMQUdTX1RSQUNFX0ZMQUdTX01BU0sQ/wE='); + +@$core.Deprecated('Use logsDataDescriptor instead') +const LogsData$json = { + '1': 'LogsData', + '2': [ + {'1': 'resource_logs', '3': 1, '4': 3, '5': 11, '6': '.opentelemetry.proto.logs.v1.ResourceLogs', '10': 'resourceLogs'}, + ], +}; + +/// Descriptor for `LogsData`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List logsDataDescriptor = $convert.base64Decode( + 'CghMb2dzRGF0YRJOCg1yZXNvdXJjZV9sb2dzGAEgAygLMikub3BlbnRlbGVtZXRyeS5wcm90by' + '5sb2dzLnYxLlJlc291cmNlTG9nc1IMcmVzb3VyY2VMb2dz'); + +@$core.Deprecated('Use resourceLogsDescriptor instead') +const ResourceLogs$json = { + '1': 'ResourceLogs', + '2': [ + {'1': 'resource', '3': 1, '4': 1, '5': 11, '6': '.opentelemetry.proto.resource.v1.Resource', '10': 'resource'}, + {'1': 'scope_logs', '3': 2, '4': 3, '5': 11, '6': '.opentelemetry.proto.logs.v1.ScopeLogs', '10': 'scopeLogs'}, + {'1': 'schema_url', '3': 3, '4': 1, '5': 9, '10': 'schemaUrl'}, + ], + '9': [ + {'1': 1000, '2': 1001}, + ], +}; + +/// Descriptor for `ResourceLogs`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List resourceLogsDescriptor = $convert.base64Decode( + 'CgxSZXNvdXJjZUxvZ3MSRQoIcmVzb3VyY2UYASABKAsyKS5vcGVudGVsZW1ldHJ5LnByb3RvLn' + 'Jlc291cmNlLnYxLlJlc291cmNlUghyZXNvdXJjZRJFCgpzY29wZV9sb2dzGAIgAygLMiYub3Bl' + 'bnRlbGVtZXRyeS5wcm90by5sb2dzLnYxLlNjb3BlTG9nc1IJc2NvcGVMb2dzEh0KCnNjaGVtYV' + '91cmwYAyABKAlSCXNjaGVtYVVybEoGCOgHEOkH'); + +@$core.Deprecated('Use scopeLogsDescriptor instead') +const ScopeLogs$json = { + '1': 'ScopeLogs', + '2': [ + {'1': 'scope', '3': 1, '4': 1, '5': 11, '6': '.opentelemetry.proto.common.v1.InstrumentationScope', '10': 'scope'}, + {'1': 'log_records', '3': 2, '4': 3, '5': 11, '6': '.opentelemetry.proto.logs.v1.LogRecord', '10': 'logRecords'}, + {'1': 'schema_url', '3': 3, '4': 1, '5': 9, '10': 'schemaUrl'}, + ], +}; + +/// Descriptor for `ScopeLogs`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List scopeLogsDescriptor = $convert.base64Decode( + 'CglTY29wZUxvZ3MSSQoFc2NvcGUYASABKAsyMy5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbW1vbi' + '52MS5JbnN0cnVtZW50YXRpb25TY29wZVIFc2NvcGUSRwoLbG9nX3JlY29yZHMYAiADKAsyJi5v' + 'cGVudGVsZW1ldHJ5LnByb3RvLmxvZ3MudjEuTG9nUmVjb3JkUgpsb2dSZWNvcmRzEh0KCnNjaG' + 'VtYV91cmwYAyABKAlSCXNjaGVtYVVybA=='); + +@$core.Deprecated('Use logRecordDescriptor instead') +const LogRecord$json = { + '1': 'LogRecord', + '2': [ + {'1': 'time_unix_nano', '3': 1, '4': 1, '5': 6, '10': 'timeUnixNano'}, + {'1': 'observed_time_unix_nano', '3': 11, '4': 1, '5': 6, '10': 'observedTimeUnixNano'}, + {'1': 'severity_number', '3': 2, '4': 1, '5': 14, '6': '.opentelemetry.proto.logs.v1.SeverityNumber', '10': 'severityNumber'}, + {'1': 'severity_text', '3': 3, '4': 1, '5': 9, '10': 'severityText'}, + {'1': 'body', '3': 5, '4': 1, '5': 11, '6': '.opentelemetry.proto.common.v1.AnyValue', '10': 'body'}, + {'1': 'attributes', '3': 6, '4': 3, '5': 11, '6': '.opentelemetry.proto.common.v1.KeyValue', '10': 'attributes'}, + {'1': 'dropped_attributes_count', '3': 7, '4': 1, '5': 13, '10': 'droppedAttributesCount'}, + {'1': 'flags', '3': 8, '4': 1, '5': 7, '10': 'flags'}, + {'1': 'trace_id', '3': 9, '4': 1, '5': 12, '10': 'traceId'}, + {'1': 'span_id', '3': 10, '4': 1, '5': 12, '10': 'spanId'}, + ], + '9': [ + {'1': 4, '2': 5}, + ], +}; + +/// Descriptor for `LogRecord`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List logRecordDescriptor = $convert.base64Decode( + 'CglMb2dSZWNvcmQSJAoOdGltZV91bml4X25hbm8YASABKAZSDHRpbWVVbml4TmFubxI1ChdvYn' + 'NlcnZlZF90aW1lX3VuaXhfbmFubxgLIAEoBlIUb2JzZXJ2ZWRUaW1lVW5peE5hbm8SVAoPc2V2' + 'ZXJpdHlfbnVtYmVyGAIgASgOMisub3BlbnRlbGVtZXRyeS5wcm90by5sb2dzLnYxLlNldmVyaX' + 'R5TnVtYmVyUg5zZXZlcml0eU51bWJlchIjCg1zZXZlcml0eV90ZXh0GAMgASgJUgxzZXZlcml0' + 'eVRleHQSOwoEYm9keRgFIAEoCzInLm9wZW50ZWxlbWV0cnkucHJvdG8uY29tbW9uLnYxLkFueV' + 'ZhbHVlUgRib2R5EkcKCmF0dHJpYnV0ZXMYBiADKAsyJy5vcGVudGVsZW1ldHJ5LnByb3RvLmNv' + 'bW1vbi52MS5LZXlWYWx1ZVIKYXR0cmlidXRlcxI4Chhkcm9wcGVkX2F0dHJpYnV0ZXNfY291bn' + 'QYByABKA1SFmRyb3BwZWRBdHRyaWJ1dGVzQ291bnQSFAoFZmxhZ3MYCCABKAdSBWZsYWdzEhkK' + 'CHRyYWNlX2lkGAkgASgMUgd0cmFjZUlkEhcKB3NwYW5faWQYCiABKAxSBnNwYW5JZEoECAQQBQ' + '=='); + diff --git a/lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbserver.dart b/lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbserver.dart new file mode 100644 index 00000000..118d7f5f --- /dev/null +++ b/lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbserver.dart @@ -0,0 +1,14 @@ +// +// Generated code. Do not modify. +// source: opentelemetry/proto/logs/v1/logs.proto +// +// @dart = 2.12 + +// ignore_for_file: annotate_overrides, camel_case_types, comment_references +// ignore_for_file: constant_identifier_names +// ignore_for_file: deprecated_member_use_from_same_package, library_prefixes +// ignore_for_file: non_constant_identifier_names, prefer_final_fields +// ignore_for_file: unnecessary_import, unnecessary_this, unused_import + +export 'logs.pb.dart'; + diff --git a/lib/src/sdk/trace/exporters/collector_exporter.dart b/lib/src/sdk/trace/exporters/collector_exporter.dart index 07f12ffd..510bcaa4 100644 --- a/lib/src/sdk/trace/exporters/collector_exporter.dart +++ b/lib/src/sdk/trace/exporters/collector_exporter.dart @@ -68,9 +68,11 @@ class CollectorExporter implements sdk.SpanExporter { for (final span in spans) { final il = rsm[span.resource] ?? >{}; + print("li = ${il}"); il[span.instrumentationScope] = il[span.instrumentationScope] ?? [] ..add(_spanToProtobuf(span)); + print("li updated = ${il}"); rsm[span.resource] = il; } diff --git a/pub_package.pub.tgz b/pub_package.pub.tgz new file mode 100644 index 0000000000000000000000000000000000000000..8e7867b5bd957d8701ea757b0a1603d66a82516e GIT binary patch literal 55174 zcmX_nbwE_z7cGsnlypjmbP3Xebc29&w}c=djHGmT4N{WQ9Yc2`B{6h&=iE1bzxUps zbLZZfbI&<@?Y-AphbHm`LdSbPYXsz@_9eI1^3&W6p20n4u=$%1F3S3ZHWUb+;|6xZ z>+!G*GKHrCktYWEzeaCJW@Je^=lENGo}l50ipH+LfIdn+3H#&NSnFJqAs_~F;%GFN z(Y3U)9j580>*%M;P2A1M$W-VaHY`QKJl|e5&e?`THoOvN4XN%xWmEf}A1hYN>kmNY z_2`vkoeVEjXi7KK0+lW|2w=?|%IHIAL1bTLwLV_mx(5LJphqxpB>~%4s~i>gb?=4^ zGpw~rJae6yAj2MUU_HCQt}_dsnp*6(+UPl`2Lx~?Zh^v}K&79HW!h$SPjvOEk?Xw2 zBPHRJ3DEuwz-WNSGQb5j`VTkGYKD-+=a~(dDrnRRx=EZ z1OZ<78F6#Le=NR|GidSfEiXtmZ}VagJc^3W&(C+dRHcOO;(1ZVv#BTgQP{UspO1g} z`jQ(A2v+;quJv)sP+Q%OVHIav81qfo>`d;Sab8vB%y&@zJ*gT-a(QW-DGseVqP;qf zR7g9Z)nT`_<3;p{->>1qRa=-EA~{;>Nz6|?=;xCECDG>XHS8}UCNBQX&*$nQxLw40 z0@~*9>fv*>BOvBCfNKIoKYzV?c%SULN6iupjq)oO)t>DCy_r(&+U;F>7QoC#808J6 zUhuPx7tKnO84v9Y^dlkf?q8-^M8q{l(5V%q^tJq9{b8bcr_)k6gxO_uB~J8PuMFV1 z#QV&BfJ6#{#53o>!?>t5+%byIFqcd&IN z-QN{YiF}_HjxQ~{uBe|>1pW7m{@zs0Vg@q45 z6CmMl&(9;^)o(6Q<;1llfs9uW=lsHZ5Nqx=q&~C&cB}r))b+V?#$KonriVs!2&yos zSUjcXkp(G6NR zgXLo=`PnhE%V5)K&=HOSb}rBdZ@0+;OQu%`LtLeDU!|G532JSPoLy z5T)glNvNiJ>=x2^M9>kG9E)a~q`f!!!&qvj_vb7b9cN$ExbvrG5vt-V`Pp@xKL^_3 zD+P*XU8jn4eiK= z;yw&KW{aOYrZo8*xo`K*j`7QysNKc(h$U|CxB6lY(U!hz2keD9ICi~AtEgAYIDdJC zIwP_zw9fASGVD zGZ1d?r!)$AO~MqrUo}Z7-lmg)hVln6hKQizT&xd&lm^OXTQh)EBm=T-+akIs%Ww6()ZJH2{3SvdjSnzPW+(t?&>3 z7iuzLhuH>vARs^g6i7ibu~uzT&+1R)Bsw|%-fK$)K3B(*)t&zKCfHnR*QD54QdQ3u zLorY_A0eOcRHeMf40~ZUBb(qP&eslK&)lIR%P)t#XJ8qi=EyxMvL-3 zVT4fsgd&QnWs1;)#Ix==kiaAQM__7au+)IMy*jtxI^xKljC?mOS;5RuStmDr&88nN z+azRBDdYxvgo^jjp#oimtj{!{yaEcC?>ufkt=)V}2HGyHOxm?{Rsyq_xd)IurIQ26 zGh8hyqH@TrgtYOU*F?m05ZV>;K!-j2s%rz(aYHY0uzOOkc&)U-y$ zIuM3=>U*{`)ZgFf8BmvJ_xYtCpIh>8NfjLRL1g1a?bB?=2gx0*C>at zu9ZunI*rF>3^8|IpJ!9;%kHOehB5YfYEDSu)?o} zuwoo6g2P7Z1&A^of_Y14>c^pCjSp%`L`=T9FAnHSa~D<=r@1iG>!R-Tie8u81gFG0 znjyB2CEr|x-ZInS71Q*0H*`h}%u`3_w&tE@843n;Fd4>J0&E08!ggj;bv%fqSPIEw zp-HZyo;~wz|AnPiukubUyL@)QI|Srgmygta9|{IgbI^8rF$iBLQPHGOmc)C%wyr8} zdFH~!z?Bia_`K2-tmA6g(pb~q#K`1Jco1^^i!Mam?ARyh43#@&u6KP7>m;qQ(zK?h z?OEs%@#T61=N$DE9nvl;%~u`+0WAzhMag^w(KcD~SK$^lN(JMw&hP0eUI~5!&uT;| zowo!oVrnW*9i~TBn0CwJv~{51hh;u1bxE5d4AKv=rIL;B4F>khy-T;u??wt^C8RxK zuI^R%d-gh#&fM2O)M{9j%`}Vq*BITnK-N<5G@h=!mMdyp3aN7NOOkVJlNas9H)w^1 z!SReA^WuJ-(zlV`G8HbSk5+T?zH8d6qKudBkItq_z}uYdkJ@JJuM{49a(eZ7c>-_4 zyw_4GDWO5-aW1%JAirZ`Jnx6QesP*U?J`t%@x@L8jzvZmi(gt3iC6|cZ7Y|_9a`oh z6+2~kg?&vqeNE0dU4vk;i}m7@j`m?=9vNd8v5$-&Z>ShiGg~GL=40ZA_+`&Ad}wgn zB+zNa_aefP_%x8idYkNqf#uu~+KPL|c^fbjwfA%`8rT0_7unKu{)t`_t9BV%IC&q1 zo4HbXsS8;q4p|{!ynrH|MqO0BWP=!qCW%xid@BV@qfmuFBu|m5<6X;XAh#%CU0v!h zi-{P4pfqwKWlKTY0W1EeH*cz#ma3>DYY%$EX!AyM8IF@&y--4rQBB{zA8I^JlcJsT zDootOcugx+{qm}F>f-{+051iR7dyMfmUjeszRBJD(5vrNzdrL9cyp*SuBe$Qd@FWz zVt7>4q*fFl$!bl94S!MjZBn%u#xZrVKh_|#xYyZ)w@W*RGfkC^WizPG?L@yow40LE z*DP={x~w~t5fj#=tiEU5!ahzx+Ds%XH>|2=OV%Gq~}ZJuT`~6&Kw=PDZ?F%z3*awlT12x z;}T|CO;{YK3%Uyms=f<-Y@&OCDjZp=*kOITFHqzYYe1U)9N872tn?YX>a|@E_LtAv zDctz07N$q3N^ev&O>cC~c7$<#@t%p-UvKm744BKsiTTow@a8FM3v%L3=BeP|wwjSr zBvGBcUwZiqAM3#6Z_M`QZwf>wgO=>e@5gY=|4tOac0qJFDvx{QO zl)l4&DcwkWmXEPdG}xL9y)w8V)x#`o@FgVuKnTJKcZ%C$_e@78Y~&J9{3{ZefxF$N zP9ek3W19z=h>8jTClGdCeAXO3|7jgL#ORyL@<_;EGwk0vT^zY_WEh$iP8@FhiaSV- zD8STUsyYg_M5EjJIcc%c*E{5$tfKeThdi>@tWNtn9Br%k0#ptG$r)y|K*l=`O~}Ml zTtv&FtRZKvOfHQ-vC~D6rVFcIj@yTQnx!)-@@O6+Xl`7Xdmm6)QkkwU$QTbueyeUI?jl4We!vjLgvLy`LQ>HU%_pdJX(ELkIR=p( z3jLz0$&AU(6+5y&344Ce?=!x1uzE!{Ic=ccR9Cy~?T)|JzY%gQsm9j&hUmQ~MquST4jcvr>pRrr>h?6ipCR8KG zHUar@nWXBbXOq_1X&B82q7wiwbLs$J7V#?h#m3bs7>!Z@D-3e`*SEr1X$g4e!%ZD^ zV3Fnplug;fOWx2MKnHhiXWrl72^tsC)o})$TBzE1J?rN=h$g=E^Ic&%Bi8Xm7)Wvc=6_8e^DOla4yF72*Mr-?y!|J z>G;l-JG&vpzg~h*UfjeQ@1gl2iJFz&MCngEkq-tHQF||^|8hqiRm=dQi75|G{z!*&8F^G23|;h!)@I38L+M*g zjEs+PLL5n{yv6NAsADn5FK2!O?sue4+}$s3l;=I1kwy205;@}05_(^IEVc4dElE$% zEl~RI`PkM4)9*Hvh8bfIBmV&?A2*~%iaDu)60I4S#4ut7P$9r@4f(Nw?7lB?3gj>T zfk`L^(8C*yrc1|vn%o=H}N+kJE=!>yY}#fv9# zW677E+8O;o810orernrA^#SjzR6w+ofd3g@ki$$IUS820BH(qQ?@WVMVZRJ#E)zfnU`_}~8YTl>O?b@!@X(NnR zqa8bOjW-G_U*e1%vA7VO9S84ZGUEf+)9CzhKQo=uN*uoTdS~bM%Q#$gctaKcL1E~V zzaKB&y9^PGau0Vqrqw?xlguD7!Czazk9=6+5s>*s1^72d^W-%bfXrC{;}&30R=5rD znnpZ9olffw3}B!q+C6|y4`{xEI?lS?0M{7}@K%8O#}nAKY&vmWq7eBtL4WMDf zA5cUzxdGkwPj zS+*#0rmvo5cbEJrQrL>(X5_CqL&cz&lk(O)&f-OB{V9RKv+(%L-8PrknWdP)ac61M zDm{@W(z%scOVsyWAMkVSeu6^?F9LaA3x$Slge-!(xN0v5t<+J9Xq8ALrk2vlEbvUz zcR79!D*ZK@ir-w|=x9p3JefcFq~<0qOywSs*lkygC1lOuJKSvggnTlbgl-SWH=p>1 z@un=ocQ2rb)DG0n#jOC|FT|@xVQN~ZKoXMH3BXT&{0{yN+W%JJ{!!xCni&G*Z%QO1 zfdLra=*n`D%6iUNqTS-3S4x#%XXK9?l$V|qOfl~UJ!D!XP-nuQ#3%^wXS6|lkGOYi z;9cV-)-coek2YbL1N9_0j&eVi)He#R60s}1tzx9eC^BW1@k*=-3zF*Z9Qs8sJ@{*v zg$GJL7>$bMEVn#=JM6E)-b38`qD-215YaPDk-oVa_ai+fHTf||d{oZ16>@>yVM^YS zD7qF|6_uaE+DYWKS_)CbR0Bt@y8w6h2Q~eD=i(Nm(W5mOlO3R(|HK z59Gk}lxKy0vkz)-#C;KgBR#uF>X-&wM^^e+LydQgwcb?q3f{dR!)?!~a@Af);_}T5 zMtcSC`E9cean)R}xU$PyS`Td_`XyCIb~ew-hhc&CWO}T*v|Tqd6&t-8(^y;22T{j2 zez+7$@z1ePP!+E|)+5MHpw$QXMLGE>;eaFZ2u5Fn!w!T6*0>6=qGCRS=5B8ea%;S< zU=#W1b^tQccuz799Ckzit_rjhz#ibj!#lsDXmaWF%hdj6lZ+mS1qKA{vpr=-K!yLI zkNHEaRj1BnK*$6@9<5tZv<>0Sy?b(LoGPiW2W|zvr@?6Kufb}7(bvIppdv*aU`G|7 zxP-VQBz}>}(XBqh_OFSL)Qf!c*Xs<-qFV8Hv+vocJaR>T6B?dbdta!hhB*_<{o8Im z^o;!}p)qvaYJ8hj_0VTE4Yt4S)*jl(yGy?bP6Ch*dxA!*`))x?*9|v-5w7h$sN&}b zn27+*M{}Uja0UiZ3g~`@8q{jI)QK8#0unx9`!p_UV#;KZr$ECx-~%*be;5YQ+KGQ4 z8yN&~astW71~5YhmIOd|3_T?dcng0h8A)p#aLCs6^U@oEqqOIH+&!J)Y`{~hpytZnjM!WqQn1_LWY&h9~PE~731)V3~89+=(p#NLoW zg+~l$2e7pN=gZRo{GR{^9J`0uFW+@8;E4bn34C;D`0|vhnad5cs6c+LF@H`ok1%~z zX_+vaQhf(=`4w^wy@H+g$mqh@KSSM4d0#<+iuug9FdLD7v}>r{1(fZ+li(4O?I}M3 zvXZQRwrMn$p;O2D9!oua1-vW+KEc7kFz5r{2-HsMWt0747b4gQt=Toz-=*`J1Xbl;ZP-iwAW9P7GW+Qw?|H^=$QMGZ zXO1M_A*hCR@FMNE*iyzmPK~DeqK99@!T?VH5n`ET>)AwzAImf!Eh!Dv?oX_i)DFDO z8gG^|@HxrA8&@_FQsIphqt7Qb;!n8ER#jtzBHKIVa#i?Me1pReMVknH=4Y69zb4jK z5K0C;ToRkO^*g0w!wl|zb5K%Q5bh9IfCbmUPftU*OTRWw#>XZ$rpBU;YoP8WfSA+6 zO5v^hLJHY;%7ocysaIcoNHJNeO?PBAs7yBo+D`9Z)y4d@kl(?Pbrl>mKN=N~f6Dsk z^yJ3v`Zy@HC~)RHDCdGPtFO$uJ4qTDtqjOW>SG99(GBE;HuU6nVfoMOT6Aw;KN3oC z3wC4%6M{j0589(tcN!uXeoIum<%-FDP)Oozv14@r`=>hp-itzqF&pKU)pDl06F!mG z5>7k@6t+x*9!HC{$SIPhk|E#R8d#q@9+K$!hHywp0$OX*O`1My)3&ZH|3Qsl!X|nn zeU+|{kCRxxpeG@#D#>6|Ht}vVDEg5dY_sM%?H#F3E1GXMj67UQb=YOOrrn&i9%v{?4 z!7PvI59+v69s!zHMMPG;8(RnR`WnYYweR@kJ-0gLxWf5EmXXOu9c9xQkLhm`-V9yg zBzpsLih*kIYGo|n$4&d8o7bGi^Q(Ep8~@)Jr-gZW(KD{y=-{T0V_~W=rdY?DtwwV0q{2l(P$p zSMvyQBdDm0vKj|6RVv_+-~)J7nEi#F!UN{h!^AN#mqFzRGr?3|1f0AMSAGj3e0_>5 z0ug_+theHDhe0b2F9BX!b|C%*WP=xuE99I`fIb|qTq?{mo*EU!tE!&RYvdbC{=-oi zsCLQj_+5;GwLU}FljG3mQV^Pe-dIRSgW!6^Qr-Glt%jpPyY}rjR~ko z_@|gG!)V0#>z?3r_6Vp#w_^3g7WnUH{ujQL^9I>%&y5{`3Ffz)8*q1?-O(jN9LkX* zQS1%P*G4F>jFti4BBItR;v`46Cz%^vtJ+tjZg)SsTdqYEd$A1RpEzO>i}^gd%9>K& zQ&?ScTYklx@q3OaxIR`HEot<4w#CIF&+;1fTCSGNdS))geLZR>ee$yOOQ#dl-;H)L zHhukQ8>qV|);D)W#rGnYGbV`1TAT(^s6N;IBb;29I(2b&N+Ur;ElRPAMD|J)393t% z@>S#)^iJ?+^t~RkaoNl@duw?OVM%(z9QjugV<~^Q1T-ZN;ix-v1%V@B$Spuo@2vF* zVn;371Ff{HwilfO@BBZ^fMl=P-y#2d#?WE*3I-yJYXqpG#k}Av^al81ph5-wq@28f z8uWNPLTAt6Wh2B#egMRR8nF#g&9B#UfY0jf9-RXasSUA5j_dn(wQN%&2}%E+YhBdL z%8H{Jm_ImphWsxD%xwJ|4E!#i{GYdgVu1O*OXJGoah=E0`~aTagPM=3ff1R~5g?H1 z15^?X4ukff2qB%~ct|eqe|2JwfT9hwMnH@K|4RL$AyC;Ca^whz7Qz0$k|>P;s9!8? z6jkAbcWv<33O&$cKz_pk2%MqCr2xa<7dOGl=&5`tm7L$;1o{zt{r}f7SkD0b-k*8I zxl>{87c}HxyZcJ)G&%&muFmYV<$_Z_e><>f~@9JeTUwzuj=m1=!A`BOK_6k)43q>`I;iT|FqkhF?FE}=o|{x-4Bp=dOVoS9!Nj|!?JiofP#t&C?WdVb|LZLDVk(>E{@lqL$N@D z%N%8K@>=l9BXkTuP(To&M_=(iXF~@!O(E=|g9K&iS%K6%M?CcM%1EyIysB67tIA`i zi`Sk}XMfQ#`gh^0qz`Yp*YO2AL48!#1iDNU^9v#9RF2Zq2(5lUG*_pFK9zC>@tiIp z?{B_Y_j&Vd9O4r&{x^nIOwz{Vj{1efdB#B?l~9^6X%%>OqPwifO1TI@KxutU$AfS=gRcjR{aMsY1tzbshHCdFqyxV7(x2i`Yyi*TDfS_ zlmL;(%AyWHpMYoy^u??#!}kHUyZK}PibmtP-34(pA21k)L4KctQc!BQBv|#Jh6tae zVTT^|&!GR6D6NB_+ihf}K~P0Y1H6^#0a{onZXiU&?c{*`FDFo$kYDtHY3i-k<5W59{Z^zCyc zynIyxvaM^AjR1$QfJ`NThX-zd{_#Tp#OL?KV~)$>N!+)T7Y=dEk!caY^f&*A!Ghz? zyqyii{`tfFKBIaa2`i+Q_NMZe+csM zp;r5wAkw4Blc6ZKI5GWDjQlGsWB!~-1_?0*ew@Lp*h;}hw^Z_1_3Qd;(tYyXulrvM zz2x?ieTxj!rgscMX}S*PUPRVq?R4*44&N-^upJj8*-NuB9KDu3R*4d2vq?ykMzi1& zd-BJ)T#9ShBcuRXtkMZ>{mMyc^YU083aICMd18R_WMR63%Kly*tuHS~_?8@nh22 zL}@Ic*7;yWky%HHjedj7R917% zAoRxF9=y%G`<}E4M&_tRPP?d<2iyO)h&Ff?avj_J=Lx39Q~UICa@Uq9K^W_=Sx-S= zAX1K!kyVG?qR?acDk~+1qWyQr9(REc9M^n{`UVVxx9EPc1_`}y9TYWMmdh2l-Z;h# z_Q`LaHRSElkKtfrPe)mN^geDLP|VFI!Iu^ob@S%tMspjSZTl^kSe`*zYM)naX!r*U zOnnt$l$ROQ^m}rm^k;Zu4YREAqH@pofh`;v9or3^b)RJAs`M202FODi%WND~%9aLso)m`;ypmYTsV!lIy$-6KWK9axOG@=Z>bQ|C^MjVk2T` z-H1`++}?@Bq`g z0SvEw8p}4}`MQbl8R~Ei2EqA*-@8wc{YQ!IP8$dyaf-Qz@2rROSq-z&gm=cZ&Eal* z9MkJ!Vv3{y&w)y-0O6QAOohem-j+?p@o)RUo#MLuU)fc&fr1URkNjU&(fuQZWcF_- z(X2`HEtQXLhQ@yXN@^ikF2?PC)=UWbeVf}%G-2JNz9|1?t zIsmL`8UcV;R$6X=X57yt4-n{q1Q;fI##;+(B>ykZ?p;H63$j-9Z-ZEkb06Yqz|Eyl z1=Z^yAw<#FeMeat^vT?l{S3d|U%NpiRGuUJ33G_qE$kkCAd*kb#(s}g7OH!EX9>OO zW7z7dnUY9}2Qn*)8UT*}(vbQGAiTm*!6+?1FEw_ASZd6D zP+=J$_E0I5S>ZVjXlXqHEU4mY_h1y?jItw~H4&Y!ANkGtSh03I-+3+V1_+%$vT{@> zj?wVgeco50#7+xQlqNs4j_WM5MdrN!efBqS7ws{4$KU_04ET~>B74JMNj5%QbGts7 z@P3~=Z}!8pa0m~k%fQsnmyrES9x5~)M|I`N^xfkd7s8o<4byL^;&tY~^HhW{9E$rw zdK$5%3$bY#hgnkv@}yOH77>@Cj7ig6`QCQDRhhNz4eF$Hv!I^Sqcn5eTmfFtK$!Tr27Cu+`aZmdC&39a48%vLMWO30V(JWI|Sa08K{9i5&o0=YUmAq#SmDuYC9W3}HyUITP_oSR zZN9-ZXpW!A*%(~|?5UluN^!ZeJ?^yjR{NyaYqeJIR8@8HQ0UjxyYP+)&aAbfAXN|K zEm6IOl2XaOnLjd)r^G`lNGF?ZD+84CIWB%dsi3>)aFWI_0w~4Npj8)2=+D??j3okm zftO9fV#&&Dfi_r!`I%FY({IcNpKL9C`V-NOW~-~Nu)V_wwFQ&kL=-%%29SmPYB+o0 zIMYRe$rm9`{6c3R3DkmAVzI%;h9$3IyeM2*%=9B?7bSG82hr$f3%2}tjKrRonH`Mx z@ zM$?a!FMv^u5e5W~R}dwoLk%TSz9nyITQKrm6a7``55~Uw`zf?>1S7R%&5Hbn@opI0 zB<1ZN>@69~GY!5(e!$%`d;A=R(xlG5B)4Sitk8B)Lt*?4`Bmt`W6V1nB=aHd&&r5r zMK-v7$9=tPo5{R74g!k8(A4`$KkGmR@ z8bPa!hlM9yWA^4;iwXMf8W$0>Dst&Q<4IY3WW+LtD@hz_QCdItVOpA3_SUM_p(+LX zp7yVz4awYVbFKK8ZOqthM#rmNVwKgMzsDO(S*TBHyyNbU{J}tfPd9j8moV|E_yy`} zNE8X1&#X-OzB#coRHpq`;06_zNSNf;aC_@m_0TZrnil!xl%ci3D?y$59%R%cXQgmr zG^Pc{H_5iV=p$RvW5}8cy~Hz^LZ(lXlxkDGCXHrnCYc?5oKM7rA$^ri$o8o&QEi~b z7z+ZY@0vF!mgo#urn@Bm)j>)-F$-tdp1j2k)(ux8vp2Ss0=n7|o7kDsF!gu5^fBrN zXRJ-A*fh4M&UvmJUs?s>(mk#n!DH{d zH;Xrnhv^QMjLk2d3g--GG3&eKr13>Pknqss3sAy2R{4-O>cX{?6TcrS;od!!zm#%D zA(*J443D)px8SD9I+!8ZKHBRb{-`<`f~sIW<&#C@s&9@ra-gwP!$-?_K6;$iS9&Mb z-Jx!^saSaUtbisJ(J$4{Bz9VNre>j=epEH5eymDu+7zjo^iN!Z76Q{#Z8D*B7 z%u+TA-g~X8^$@@H(p&bYP{ZTQ%PDy`ydVj|`r`-XG;`pm;3!DwF*c?H(89HSjI9q9 zxuIcSM^;(@b+S7F8ffsgz{51xbBW3cINyUi?DSe5CLqAl@y;fwzW&*Z_3Z9gLfm2r zPv=^Hhh~6RCE$MGus1ZRZy?4iQvM>URj=W+`HDhFb8Bpq-iU4dnl~Q9qwFpyUXsMY zNy1ykHaPJwVNbMm8u!d_0(f?{PBD8mRh%KJi*$_s^Jge?qRP7@wcJJUHwZj*6Y$d z`D+A>WbFR&%nvp45OiG>1LzRgKErvQ7+50#TzrMimml7lY+5&102q9OH z=~>X5XCZ^@@@G){>fArRU_uWN9W^iynsnslH+K`JSZbRHF_X46u(r*6Ws@MHw5LF` zO~fQ^uW?RB#-`To>hcZwR^jSo4AnS-1l{iZXVb(~c+Ec3Ta2J9l<(J7A))GwBhiH*lydIRzyA)8v3M!{^gApe)k}pvZ0!2RPw%%`@;u ziVET#u!QXAvB`+E?>Ozm`Sa9dDJG~fO|CPlHwA%z7w&V!Cci<9R&kmvx0mz7qX?d7 zT_o$L^kK!=_{2h&h8TNg`jcO%Y>0*U*xq4VVB1eOCkUy+DHBr&i=*f!Srl`W#a0d z4W<7K%%HT)$Hw~GwZG2R z5c&P<#8g^|(iuSwIS*4sW6-Eq$7?*VmnI&VSNsiYIO2WsN(DyoKM;B3S&9V?%)W-V zOaygaB3qP-%dKY1xO~$?!OLx_K#91P`1_1c9i?lERMQ00`*jC`8$=QQ8AQ|IJVPiR z$8SJ@q6x@{OYJ|*pIs_fj^V*al^X`rYkioQ2M*xM`n9zT6t4Ed_W@T+Vc!r+xl2oq z((M=l?48uj&WU9&L5E19e>|r+H?t~>dv2C^KvD4QRt1L#C6fp7es&5azAN;0ub=Wc zEn%JDY7%RFNPMC}c^{4Rcp+HNN|DH$8B0G*5u#2(RyAln&9~1C~)|Q5Y4<&MHmj7uyqSHIrJi2`Ifh{X2D;xAT4~=`0=zM`^>YG@iIfvf$Xfv^( zD!WfCj`bqw_s-2N?}JH2;WH>1<=?6_MLzGsi8^?L6tpE#0lX6G{^a;q}BhVz0Zv?U(DDfr|72kj#q(_UjrUBMN-u7r=kKNNf_-}<~rxdTSmj437Og(dEOhaMw zwH2CAAmV+{N=gTyhx;#Etm8gF+u>T=gGpK0zaZDTg4{Sa>bp2RpHB5?Kf74LjTHbm z+CUX>5W2oMf%CM7piBPN-GVaNqWI!BX++KVQ*z_d3aNBf;n@sqetv#VpM+RVkM^r+ zBb-XKj=r%{_ubRTL@K9XuH+tZU|h$)_t6~Imq0ssoWni;{(JGO=ABM3U~!FWBpjLj z3dw4kBHU0|FgVpCg4qOf;>X{#okp?7z!Qwv{a{Zy+{76boH+xMW|?;U{;(+$Iw_Xp5%jA}?{J zym*Nz7KWb0f6cBu?h&fdB4@~$|wiP`53%;uBG?Z^s8RI$iYpEILbSjMm?Q?On2zi78O`jSr2BA$Va z!?S1DUzzj#qZO~&nOg~vPpQKsS&KXbu66Y);iUW=+@f-l2S8K*p_UK@9Pew1;MViQ zdciZ(W8m_<$Kx5K^IupImffjb_A+J8Hp7IyI8iu)yg{VgQnSKlm9y9U-cO@2Q@Z-rX51^NU!A4@fP z1_MtcAngX&CCyU*I4rReEdDsKC@~J4$KKKa&#`K|G>7Wo7&f^zkX4M;8TK}Su5HV6 zf_}95>#IvJTK`(U>sR*n8wTTDA@1(I{J$12xA6~Bhu=KW#*e?~kD<~PESq|THd_0d zq)24ZK`WUf7X8G!*!iUr6*ZF^KtM1x`zfl$(ixpnrY3kuF%Ttb`H2wcW%gi3l$4g4Km5CxQ^#?5HV8) zl0C6J-!NTM`%UHPe6LToh(g_MTM0;1kP}5#1#TY)qo}Au_e`;)KR$d6K3ta5;?2Zn ztA4I5m9<)wSuR4+RVT)hM7Rt_FW0k5A^X%_=_DB`wuCE=awH*3#@#<(mH`%*=oAC!f>f*5j1btv_m_;n-=~Kg=E|h%bS&l_bZcj$bZerf!8$uMQs}o_ zqF&~bg-NBJF`DOw52Mno{S6orge)$1!@eBFQ(#A%hTye~a2fV5(;G4}1|1I1Rnlu# z`o}}w;Jf^L3^hKi5eN_+jwAXtTuV@?)Y0@Uq8cH`6m2y}Zr7hc^U0;2HO^?vlv3fJ zy}I~|ux|(|u34NnsgOav{>fXWO+_axR-LUx)bU*EuC0juA1UM;VO`Qhy|`*QG*s1_ zr#V5|2HbRP4P7|oVmp~9akYO{@wD9qy?LC%PqX`YJV!ZA5=I9T@b>ZP?uE^0SwyhydOndOx(--J?am3rf1y$H|({ z$mHqyq~@QtlMHWA5@)fs_(nzfMmZerEY46{bbfSyP^Q!ojAmrG7t@$Bfe~Qv+ZEB* zGIeZ*6F;`7qbg+mWc+X;86u#JAtgQAEsTLmq^R+dKiZz$FPQ&erT|QDY=yz6q!Bt= zfs%=KMxLGnuUCJ*=hBIg|NJ5XCQ_e2neOVS;!XeGteHI4BjgY{f z1^rDzl79RCtczOjzz}UTJk=Vgp(mWwmH0sm$!~+Q>l2^`Nd%x7F~BF>y-R3)sOTez?f$88ae5bG z)tPh&wf1eCayqz#%Hz2|NhEIojp?<(Z=sgIfD1eY<^aEsU@k|D!`I%>OU}t|mWTJj zvR~&_LL)Tj7`TpMjIH&}7N|!@^}E#UDB)N=zZ;LEkryLq864vi*E$Ei^Vn`AlP|^U z@0=EFYJc~LXL`}xEM~vy6=!e4f8_9H6g>RSwqixB-(!P@`@N;_@kn1==bo)$E+uo^ zAk&cAdJ({-biWhr1KI6ALKp+);L`1hIpAv|UKI?}o4*B(1h76po!gsR8_TXC@^~}H zAh}&5%d!c&iL=$`DMwa*4e$N7B6?-oonMwcngz<3uyp+VtYYtLNxG;F8pu9B}<|0@`^5 z_ANIh<_rXmfp(%hv29@X0SJFiep8GdrQ%`s7K#<;QNufeq5cju%e9YU>lJ}V8z6Fw z^r6kL5S>G$TEE3YfQQ;Dhi1#%SLy{P0AYSqYkW^NIKtw z02Ned6++6j0LNQglZL3iYd{X3BmYg}Joyg1t_=K_BOCvT^o2xec|haML4{ETyu)K@ z06uLWNSFYpTN@DmfBvd`qPw5hB+hHON+6v&VrJ@oP`lM-{e*3F+{^!wSo&)U&%7AAWu3$tTq6Ft z$Ng1BkH4=ULkypO4&4$Xf1%FXc8)(~bzSaz6C&9uM^(;3YP=eHxLS1vz>umzmUTlg z_p1PT_ei_XS&2SP$rLTt>C_0`@2WL_GVtbD_q`&s= z%Ug=O@zo+?+51?z!S z&9%!E;1mQKphMR3SO1{!a=;5leA|e;6eyVXJ7gaHy?XrG+_A|+&Y=pD=hKY{wY9fp zVmPjZ3@*q&^Nf}OZ!Nfh{Ju#SdR8~8z0VWR*)4KIMbW~b8e2_uG|6OP#IY1&z^tg2 zgrYo~aiwLYQQ>VSm;5$dD*LQZDRsatzK7hc%b_(Gzo}U)K~}9fj_EBYgAHVevb16& zm!(tu5Pr%8RW0;vR$=?QPud}3{9aQ~>$$HqYE zGQ+5KgZdW@BsEw}zh0=&^=1&jc{|w75A-cUnofBHCQ58<<Zh8FsP2V&_v>Wk_nIBzx39B;`UXkKeWgY% z;!R}f(p+W9x5d`Euj9QprgAa$JYJ>SlTZy!hdWXS2n*<(oLdmN4$$Bfrpd0|d}sThowSgoRs=r^HBor^f4|8O*yhOmprx7{Iyx4dPW(Izq?XC6hIN2ig9 zMNOt0X1Fi~KOhm&mwU_55r7x@qHcz|Q5-TG9#l~C|q-WNhMM{q$Oakk2@ zn4MhKtBJt1bi<8`fh=Y`rrQ???rI`(NYE6irt9DefC6 z5?=0)z%^VvWJjIz16&?LwV>{lt9ldFIRv2#p4Bsqji6vfg46W4hU6+?S}JzkYRycH zp%nxvca4VNmXzUyDlV4suPE=rC}`ZHNC#yCgJE_L-2ALZ10*0S_p;{oe*_6LgmPYHqrMv;nX0rq^E@PUGY6DWHzp#?~d(cD`8;~Q`vMe{|=K`r`wy_+mV zFz<0ZPw?w@Uk2hXbbzix;x@u3yhD2`oy$+t@x_XyXl$76EpGI?N&V!m^Cx;Lu5r-z zpO-UAz{`FS`0~HqH5*vY!epiZdN5glG+3=|phIwR{qqAb)iZOImr@P6dJ$_}Y`te= zApshQUw78_++*UsagXj$yvn+7O~xagKdYk-w#QwQIc)3G3d9$^Xu%3Txlt(5L$%)Y zl&hM!>0cdeTL!H@Jd%`Ah;@nx@zYLQ{pC$8DH!{~951{s9k!>U6*BLv_HL=ne20>n zQc)#TPM1%=xZEyTLRgm2a;2<=45OHe_FesE9c?D1qPhlimAL* zP1ON@jt+KqGfmzf*^wDhpIxp!awLuT$DSJh^H<%M0;jMk|Q(CD#GLy24Y+lJsmsW$g(Dx?+4|K1Va>20B8`qI46C{6Uz;ROn7+xf*#L%b`qHGb=<2z(i`G`6bdpZ9x^u4P|?%SP!(h~!rJ=k z^lsmliI$dALoG`VvVd5>`R&*i=MWlmu+uX|x#gi@(Oo8s`KClP;y4g)E|j=sOPFc` z#+Fo~x1159H;S)W=fqM}XC8&%*n4xmDdrpZfnU-F4HfqCshVV;y0M-ruyAzX+IP8@<*4Zg%=}$Y$u< z=%9{-v|>V1G;I3~?F?;t0|hhl^|70V$_R$PD8j0edC0Y50#oqDBXT8lp#0+vDVbK| zGMy@`I(AZvOM!56B!(OrDSWcc`V>V&A?m1Y#J|XvynIB{L0^9ktK%OwSMYJQS_KeV z`5&}U8{-ak{=OuOm(XO>b~GJpH#Mz^@V$+qPtY%@cUjoi#9 zhsD6-eabzTP({nR!Dy0fre^B({Ig8yt;!bV@*4xz(@B!>b-p?$MgNSXHaoNqtSedO zZ@x6sG&;AtaPV;`#8EKG92Dvig!GKs=W`R9?vE&~cQQ?ChBDk=0|=+rb9}kJGbEiV z%%Ui(a>y2<(6w|=*2$hE*{kaKM<3oK52Z{`XX`#Fs?Aoxdg1?s00F6+=eS zFx)qII8k6!8L9&pI>G7K0gv>9GM3w8ebI2G{xvoKXYL{ejlDi8;c5lMj8Z;k#YE?| zYks<)jVVvOdL-)<1PpOw3z10`0#ML93an@ag%opEHPF7LI3#WF^?Ab z!*+VNZG9r*9L(wj%-VW20(t-Sa9=?^+|cpL3D{uF7s~!vLH)a!|Bl8@pcqsfY4iao zr4o34GQE-g2S^ny{JQ`{Ma49P=?Gv8V{St8=A@%g_2Uk?bmVMy@r}w(u<0rwS-%j` zrM_eh7Mgl5M`=e!(==9je5@GT=c7Zyg}|;&b(M1#sg>6-ufN*L@0EmHLI;fkx|@#K)SB0W@` z|L*b?|EVHzkANJ5${#m?M-bs7Ff17~UI0=DgchLlutTVo4&6KU5m0XIl-G&VzTQjt z%<3pa=Tw}JcB1hE(k=gu#31#X4kwBA#pJIXaRkm7cX9P+1dSj2VF6!=RVNQuJQwsi z$w?UY^8F)%6)UtQlq-{cl;cs`yfl}mVoW(2Rz?xI`Y`GM*?(!SYz`L5JYFp)A)i&l zeP`56^F&j!h^El`oh8xh2bYKT510eEr*L#iBFzmOWgqI;Re+-ytml z{2;@pL`59n5r95|+%Z@GS-M~n z6GIxiLg$&~r=CvUYz)0jw}Vbel&Q>*&=N+^iIFv0T3^p92SQ>HQc7_+)4S2nbu0($*ETaLQ6|b8Pg1s{T&KVrI&!8K)Hdjp_On+bQw-X>TN>&&rlp$EMtk^{}6hG!>lzQd(lPe{Y{BoPnTs`2v1J9oZ~h5< zV?YH0noC|eqk(cjC2vfjeRtM2Vkw`L@lJ&EI#C^^;m}O=Ej170kC_$V{Ypcjz5B$r zNZYT)@SA8fX*?|^=OdJ>8}QQ_;zuLE9{O_wwZxN;P^M<(2E6m1d1iC<3zUb1&NFqZ z|1Hiwu5Cs5Kp)5*sQpIP^QCsS5t!3l=QspaiU3TL=gFq&q2Kv-%nN+w_dWF+oguUB zHZopkxqWG8^8-6P&FK*MqmY)nFk-WkFI7!0&$X&$1rtygE(=i0Q+y!iab|DjZ^rtv z2PME8swY5D;Qj$z4=oQ)c|99}fmaSk?-KYt0^JoFjh<^Ulx0YON^~fTV=;iPF=;ZcNVr9J@Qc!Vt;s#`9C7)6sV5JWTpZR?lE^>In8QBi@*DyAD}CSHGug8f=K}s z0QgWoNZ4`*tekzFi|%jo6Ns>`t~>#aK%Y)Ek8%>AJM@Y_RA+Sn({`_1k?k?wFlc4P zNzNIlhAln-D4>J+d%zz59`yGPq!c{y1d01}+yxXF3T;OOI85)5c#aN;Vh*lJ$_KY< zYGwWS(Qz?`raaFl<)kwx)xFDrG>EO|SK~PFXWbY|c&!!YkMR_BMvPgW0L#*A1LBejT>nO14>@I&Moo?z6OjLGJP5(nePO-Gu` zQw`^i$Xms#{e7br8&Jh?PAmMa`kmxsvj5}0*zUB)Ib43 zXw1Q!-KiY_9KmSqgTh`T7|wQ2#Kd8zjzEOx1jisWl^`62?HbQxX|c--wo$jZ9ZR+J zdD8xZT0d7&PG6lLOxq=7XsqZN9W+u6Cv;eKAqdtXas3;PRwL}nBZBVPij-U_$>j){ zv$RvfDth)lTZ`Q^*Hs5 zqK#=?*@XPG5>iBBIKo{?pMZ!p8at; z6Q|#|C+yqWBlN0lff5$dG>^Ng@NPiiZ2V28U z(9G&DbobiAh;$;f{SY@H5qX0w*$kmL0l{WaYqkRb+7_wvMu7 zb+V9O7vq}Q<|PG=J}*?W}|n`5|NqnK*@!S4FOTN9D9@fSmHh3*&J9qeP^ zQkPDp?=dtz`imom9Fs;9DyjqzI~*(ngM4@{!Z2dKN2K!vPf_ft3|(m~+N^UkM->(# z)Q)nzFK%*n;PYqXv)2p=JEb;x$9F27zsEY zAxJqeF!w^Z@fz6*ZYO;6BC?Rn*x(;4PxgV6&eQv+)ie^T9_Q1DDep%Fkm^QP0jDG1 zeZm^H+j7r*G|@P=1w-!6eoXlKukofkIt`|Z#EQ0kYkBs~_q4q#*rP-?*zUnRjp?6eyhbhr3T7(m;eGK&>ulg3rR__57RX*twq6LI_b%=0|D@Iw zIId9NIp>FrYnNqi9&vOD3`8Du3Ix=~<{FMdP%sE3AcmMYGA9 z&Oh{%QQ^I&%H(`tX*x^mU2lG6chs3I{S@P74f--(wotck?&k6jH7#pfLDaE1!eayF z74tXsuJ1y`*}s8Y*QCfC)m_tz`1|NsDZUc2wvk1=-812+R?0SQSWG=6OR`>;9p&%! zq)ufbFn6nrqvxFBh7VYZvP_xr|HFVi(WXqMK~qk|i29w1tKzL=>HI}i>fqG-&_rjL z>Kr$GeI6+mE(vMHwU~4b5{saHJbWp4QA%*a<%==i&*^{CiA( zS*xO&haoX!t$fD{jfSY;IfABRB0^&x40^I()>5G5D>NPB#8VF%TM4Um3YziE%4zb1 z0q*~2uD%0SZJU4I=H)=qB;7ausZZe6x9h*EOxH0xC!sRtUuT`^&2a=wo4IA@RnEQE z)NK5*NMhkI{fbLPi02JK$`2FEv+tHKO=vti71SDNVpfTa6DJ2VQK>du(l>*a3OA@$ zjE9M%)v4UkmR@#Sg%MvfAf{ZW>mxJ3;eQJFS8=HPn74`1iT+Z%F!kzU>;wG1H2*t2 z{`_ioQ+_lZIt1aru=xRH3qKBC)-=~$_d)Pa{W-Coy?KKugS}dK4P?U~P0HA_)`o|w zR6nU*jQ0+@6RYaJ56Ihe**MT0G)boz5Qf@3Z5e`S7A*}qe?nWO=bd{75_oEZ#H^DY z!Lm6OvK)b2y8-B8;qv4}E+Q#tYL4*Q&yU`bvQ`m8XU?qvBWoy0ouD$K&rO)|Qq7Jr zk;SQ28Vr+FgmauF-qt44yyrgaq?}yS);y-^M)^Dajh6AkvL~FiveQO6ciU9yE;u5h z%kf6%`H}j$vXB!hzT;n^*hj`k1m>79U#`W_Y=cZzZ5UovvzMSC1Ug4}ji`mn_`Cl| z_LcYj!1Uu#906XvL@L2lBa73wMrn8)wV z$qyP)_B?0X)cEqh2ol6?a0%2cdTCl|GJOFRotx0`mdaJfe~m8_TM@07dHIii3c*kk z{+q1v0MyI9I|9g_-9cko79o}YW%vCb<4XP@Cjp=JpC)u)<&b86z1}YqR&~wRqxx!dtvbfL@(0XwKl~6X+y-6<|Ux%?3Q% zRqpfN!;pzAr$7~YS~46|ss?axdSx^SI~cq)62XG zc;`*FF9^STA*NDKAQseDjab+6+{{n*(I2R-hOPn#TE~E=&|4NrH9YiQ@MhVlU|H({ zJ$sK=Xqs6VB70WRX+{Vwa<&0OXad21;(p$j0w3S~=6dyu9C1V4HWm!()Bultqi=i3 z4pdQu9RL-bbttdwHS{vsO1e0=$j%TyY@yW%v#PQcHI)Nr*40|mPoVz>5u_FX&nD{* zul>4)OK8`?0UDa{D#@K|>-FqE-+}C5MkWFC*R+}1xrSS^F@uJcf3MQj=Mh+4_!C`! z);bcv6?;gvd0~mi0B_OYmPiwcAZb# z5qtt;FdYV0fF!arFI4`sQ(#lI7BgTH&3WLupQu2}^-t-5obzA?c8h9|3#!c8~wWOT4aj!`EQK|5l}7-%6di*LHvd&^{-D zmR+j*`hsZz?OM#`0@rJf+(giZmhtq_YhX3hJY6jbX#Hub8@PQ6a!Ja7eR=~D85%e$ zRP9Vh_ng7RN{#s$%Z5#eZh;J8V$h+sk!8sB!{O_-%xg*)SAp;D{7T60>e6%*fRR$+AW~3!8>D0Yd^~|X zn#2Enctl&2O4TAg)nlJO$_RV54CRw+btzR|BE(GbDzWcDIQzb)JJj^Nl~~B@sW?dI0Ydd8 z>qBzv8~PKeVbmtNzN>>6JJ*5V9D+nFva%+(vMN}zx(KLsh6h(8x2nCv^sU$BIduLA ze2YvlndNJ)_^H7Lg|BZT`EfWcF5F^vBR<7GF}PLCRK`X>W9VzQb$KgFHU7xOPd>!G zue!L^!K3{f<^T~@BIo%_lNoiOWv9$mr)L*BSK#FYh0We6 zR-I%SqW-iB82Iw3V)NHG0xP%8VL|OW328~NX=OlQFqb*rxA4vu*xqgU%suXF4rT1?vy^9K;0=aeJ<5>oWfZM)>LiCHHLI(L^lU>?(&yu> zo&@~@ot6vxx-(z78jJSqMT%CrW#S>{#E{76dxeTIpU3Lrmf0kNhWt0?6O3R*uhD^Q z*__MwG*#4PLy{*!5br<8v{kHdeiPVg6`j!RqLA*J)q6#nm+>nco`lg&h0ZD)f$frIFKi@$j)Z*1ZVh3#8wtjMjYW*6@LK;gasKQlFE=&(7?bgF>RrP9Dd@+g~%y z{&4qUv;3hr`Xi+L@rR>~W9oA~J{{r%4kElz{-rVFn|7H}WpbYRsUU3QPYLNox_vf! zo1Pt(Z)+r+bmiZCn2scZ7tW~=Q?X1?5qK23?n+`v|N7&B$(2HnoEDZ<{%KsMw6B_q z&w5GuQgi&;z{EQjUW)KHJ*$km0w(roIgM+9D7_(snK?N~mvS%+%Z!h=mov}! z8UtI03U;sLbvhiAsbs~4J;RYUNg8TWk1CIYqUF|2Nl(KTn*dqOyzuSnm;ePLV%<<2 z1J@7GfQ<>zzYn^e5H4t^(gG-h_R)eFZb2}QkO9FikqOXg-Qz?FAS(oh@cpMRfBg_A z3it$Fk>R&dY0HUUpIhEyX&h2{X3aK?PU0$T?$HquJ>*C)qH4q6f8{mmrx+z_-Dqy5 z!P9Pxxx#Z}AWEd30+cN$Iz8PQu$;K527vB2WEdXAM#nWYI7R z%LG68d;478fjc{YLLN=Qke7RKptmToseu^rS|<2eZv~oH0tx`#yLo#HJs+g3xt7&85$bmYz}|f#wi$+b#SDBa3;qw3 zW10qRUPoDC8)_;?0Mtu+fA-C(Y-Q?VjZ6%>Ne4k4){PScc9AnVVBI<#}}b4A2_4=4Y2G0wX3ri zYyZtbV3r4zya7W-h+K2Q*6T>_4)Dwx>*z3$dQCfhUkto{V-INku?0?ni-`kABY5eZ ziH$sf%Aq~D|8~h@ra`>e%l@Ku_YhFWEHosdM7;ia&XKpB1uC&%nN@+98i?09RJ~Zu z0lIRv&>TI%GhlD;n#|=4;F<>m9eZ`*I~yjCYdI}|CX`F6IRTISCyTX88fZUznfMLt zc|ylXuT3*Zvta~q20cw+sz>A+ECj{u_QA7Nd(VJ}U}Gxud=Z#x!0x5iXbm)pW~F;G)6*-{(~i-5|6JzV@Z;wAnsyWxmhPyg zapHoI-hK(K(TUU|`-kmr7t#}|>KATXx%a0S=I=65Bw=(d`5`J9-5 zoCo`_$A5!u8xXhOu4Qu0Hd9U?wmX*we@lXd&c76Q2La)Z_MzUE{Ipedtigv(;LIGX ziEuOdiBHkBV^21}XpaSFw%lcigim#+oX=;R@O)7Fswr>s?ldzv4!Bg8mFyn(>B7Z% zY_u7F<4!ZA6g50*W*A?#ZmOLr`BV(?1xjGn)^uoFn|vj9k+|3Fk6bVkQZ)YV38uGM zOqFBUpPM2pvi(Ro(nRo=oLDq-%IukV2{IXxtsMO+?t+=YYBAM@5k+NGD;85Z!NxFi zo}AuJv*^=MMw68=%C}ar8;%gxO9!PE&IL7EQ`V_K&KF{_ggoUE6;NKD^6q$|cEJ3H z$oh|H4)|=brH|%&kYbNMCln&t_p&B0xfmK1M*M0)W;;Cs+J!nOHYgf3=KN~$K`Gt( zlG;^OcGZ%9(5Z07yKe=$l!tg$C9@MQqu-yz&Vao{N|-d~RIFeG8tlDW1;N(1|6(^Y zH4M0h^8(fi2EOrQmSCG#MN$g6n#cwSV<8TfrVh)cZKO9qe=|jnU73n^TeI5aDdQ;z zxwf|(dFEyQ35@;sRyPgR<)R;D9`ez2VOX6T*)&UR&#@s$>m%fp*}stn*JHE=tQntW z@`*Cy)Vc>MC#DrdO#*68>L0!Fa{fJe@2rt+Z_OhAWE6WrA*(GEN{rLXNb|0__7Nqk z{rxOWRvXx#5%Bv_#V9^bZz{14ikGr<57>)${XWspAvMG)miU0QIZdXLcrwqiGNNsL zb0wC?%UZBH!r!j6ws1}A&6p1=IVYl^_-(gnjd`6NnjrKX~FMbP`EI;p9 zI7t>SbzLIg^nO$1Cse!?B)UqH@A(!w#OMm+pQP#=#QyA5no`sJ!S1Ppk8AMpTDgE7 z-=E}BXJ7B(G0OHP)1x+*m5@DrHxpDjcyKsz#j!4<$;i#|CYfhQ2180z7@Y@0>qFSS zZls3#h(bvG9EPOCjIuuQA@axf>R6KzcrYmR&nD_ zIVK1{BgH5dX-s~XO>nT6B&TJ~p?R1mi~d^kNJ;iagPI1GY6~XM4n8^|L>(RTYY=6e zggaF)0fLgElzJ>PE6<1Yu!~9bIkh!8bPLqrK_gm1c^QHAxZ)-}8qq|}jAS@m>->luGdTqm_6?^ofnQOVTF|teFI!MPXVzD5T#G$=KELcjc=q1y43>g+( zxs8#w6{Y_0UEiX=rHWz`u8q5QiY2k!JHME_+v+enYd;1t+@O4-Z%X>4P8~^0wO@&7 zkM_K_Yd}#Z@=f{<`FhY2lINhzDeQwWnc^G|jp=210_|v~1SY(HSj{h^Qr&}SypnGz zTU^F$KTa33G-MRfWSHjmy-07uMH#T1DYfk-xxeYwL3y_w|zBALE-6JbhjBlf1 z!ofX!5S|1C@ZLx+@N1NiAJEw7GSVwwNY1>`wC9dSJov@I>5o1Xx+JGFXgusDkYrSXgGD)*FeXbsX-@JV?=9cwI=M!Ikq-G(W*aFizfSEdKa`9!vc za~fH^fAcSnm|NgIL%?7w9eLr~PVaQd)?+DO1&u9j~)ysLyW7JWqYX!m^HnU=yByzP9z`kk>T z5+#K8cV@4kK0QuKOVxqy!uIguw93dpeXj{cRK-yvT}#UmT|`bfUy>bP2q z^8sP|?+4%GS*`;-D#Q3BL)9H1w{)u8P0kZVu{JpHCxUmCP_QxWtyl~ z*p#uCV8NHSTo}Tm5kB=kQ$Kgg(?a6sx6ZIn0&;0=s#M49VKuo{G*#Mb4g$$aG;!td z9yKI)|Dxu=ieGVd21`@2+3zT2=ziji(+fp$Hq4(Z8Q&5rOdX+e;5I1&S}#=iVX*HL~!0t2@-$>;KS(fn78ceI^XAq=893!-o=Ho&v*YbjnP= zz{?l}S;=)wQH9J;@;hsX&ec zbnzm<(-5BulQ_;s+zy8E;7(Bd+pcd~V{|ucJvFWoK{edbqi6aTTz{oo5BXabBusQ2 zsOSC1@u^Z|1?f_caq>{Jc!;T8uOp|)A`c`C9x<7*H}$GL?es7O6aIQy8F2!w9p&Z) zR&g^5IWu`y|1=fa-#)slzAF483+6FdYjYO6<#S$qV!~aw{{FRXv0A6%)ajj4!Vc|t}%g9R-*yuY;g@f><&^NDC}uhr`Ci+kM}I=W1*{q6|THOgLFIJs(2 z9%v=?G6A<9bS@HrMjgK|?qzMk?`^I8xq$?fflZ66#d;*XpDuc`p5n-kzaYiWK9cr3 z&7Z8jHH&?&U#fRGhT1yr`m)9=8(i;ZGrU}L8$ZRyAdim+2$_Nf_Q_U$O*HU1#=tV~ zVi5I(#9%rYsG`bqK36}7%{{s#Z&>L2oss&xACLA$P-*Ol==#VR3>(Tfu)8$Qwd>iq z8?8D!7b&tQ20m5tfB*WF!Od+%iDkfeYKo<~?-gjRN&Srbvu_wi%_uw&9{=|{4=O%8 z1`JR7znagrfh*qaTa#-!?UgwOJMTE=GGbf(8Qc&^zr>g6;k&Pj5%-TjHA?GQSewv- zH(K?guHv!-hU)y97Sgg><{#n+{wNT*;D5Y1BRX?h(Q~)T3-Hr{b@K&zxY&C1pFDqG z@jT>>@0jX~c_h##K?yx06Xp6dPgKF0C`EV~F9S*+G zM$CM7YEUHH&Vq>FQj_oWBjmVX#{9GU14lXMNG{7{u}Mh4o~`%AM&{Y{H$^AQteeGB zwVelRVoFkU6>~4KC~xIvyN{Vvj|8}XbM_;q6r9OQWmwG9c(9t~Yhc_szNDdCV_W(3 z!`QPdeP%EM;7~FVgvrS#sfJ4jVK!+Sm;R!m`B2d8zwM;0hFj5Q_LNcX%15m%(gRI< zeupUuW``>UJ*$)b`qGCZeq{KO<=aZ-<2{v&S!gyFNnPR9;Q^F7g{v`&E~_o%H~>= z*MP%Y&hk^6_!MA2o8qb&S^2WX@RR-B znXWU9ouu#NL#++QCm-b**a?3~R)n6ybKXwz_Vb-WSy(opnh%dN2cmU>Bu)HT+J5#T zWN7{&0%IfIX#K!Q&mHt53=9Im%g_X=o`at^X822g?K(ByNFn&4PF1QDM< z17q|LfcIq~6fl(idj;wn^Z${)B!3T<%iA>u_!bWIy9DmRnxa|fpb>e@bWkaZ!=^y| zY;ej7FNc}!y)Zpj!wd3d-2t#V^DZ{TnUFyeKz=qA zFjaj0yQFoHvgH@LC6MI?g&CkTOnpnHq@cD0vA|XZLT|~zK`H}l-=-BZMOm~VF?A@} zQjn1}>_>2R@*wo0U*0{ii6dL50nrN%6bV3T0_8QpP6K^TxPRexz=KaPIR8MM@o0;{ zUPIsZGl+p90SM%HI7?VVR`>tY_}i~cYNab759fLC!PJMJ>=fT@#p|6oD}Fp>NRu|X z{BW`V!(KwGKXSUaaj>c7WXMZXV_b`-vFa-l!|Z!;Z{=VExD2}Z<)wI?~`&*J2^ z3Lf^z9^6y38Q?3jR$*wz{Xb3a7Qg!#GPz@ne-2=LCR?c{#0mpMcsmj}ia~lW_p}9O zw!-KrLuKIxK{vBsqU3x@zl^ju%I4%Iya92b8xi!saU32_CDUgr^$-rs_*D0i*ibw^ z{FLQN+mz4*D*|J7W0Is)SJf``?Y|0^EzGG%JciKuyS46~%7Z(!qB*y=rq-pOCxZ#I znEjc78*ElbI= zC}D`G@S@lx^M0<=M}M-O`&NZrH9M1w zgLcYw5x-3XQ>qM2{6oEl#}V#$ek$tZs-PC<6#U6A%Fyz~zGpv8?lwFAk-R}t1ygCo z*H40rU;^hyE;cckUJ+I#FfHDBB3^yvTJkHRp}wSQRBb#>vD!a0mf>VYttX@DJ0=io zL{=|c5e+?EP3i;c<&Q6=u`McQDufTdioY4i(hoAU49qu{8Q_VAa{r!rSD}cr=f>t?6T5W}#(wN+3GRFVR1S@O|VqUeD1r5QbkU zPIG9aehj^!#Tb3-lR)Gm%_pE`3cbp6E_f489c>*wKk2vluws_oR+EijF*%QqRcmo~ zv4p4v>M@n}1s?DFI2~j+q6qq60b$2%m`%fv%{ODzd7X7l-1=#q1k#2|X6Aty{UJP3 zm($UsPFHHwA6cII@Xb`^lE*wy&Y~O}WUbdiKyPzJ*x6@(4sl^Hk-eRlGs+j8E9F2! z_(T%(8ULL$Huqkx6r9N-tifTm-&Q5lK7XR<=uU=r<~rf-+t?DZe1BS};Llyh3S9BG zd!rnY(m~8E&F>fNIMX}+y?sX?61viz3L5fHNcS=LCrwpGTV!2D9B(?{k(<%d2~VXp z<(`uy$vIhP9Pd{3PrKZ)j?ZRW7s0U3@fq^OxJh}s4}&m|OU$0mEWB)+)x!11y|yQO z2dm(RM8w~`_PK#FWWOMJaz%+;tW@fcNdCy^$0C}RF&KOp9Hz{c;ziUc^0J}tj>v7s zx09(Ti}zuD3(SA)3p$AtbYX`!OIROT-w15%7lkpRXP`}={fH;faqNyrZ%Pnpu*j+| zsNsI-GQdWqY-6i?ii;@i)W0??w#5(Sj%n{1sT7tbs&I};h~8ImQ6h1k zqQiYf5sDym`c87ZshU^e{q?)j|W?qoqWOEH;ruPh1;dBS(s`D)cXZ|1sH{Am~Ff z#u_5Gub4JJI!2TUFZ%S;-UZc@*${iaaHa%1dPNQ?IevKSZ^W3eKTZ9LVG;pfeyh{> z603^7RTJ!r=lA)xEZ&!%YoCM@^d5_lp3Ygo7!5T@E)FILv>U%!@}4D$vB5}rwzf_< zHmv5)?YjwSrX5X2qi#N6D%8QfXlS%sU=FW~i*r1)8@5w_R1#lWoalCTgUd|GWzuge zaKs1ceo{t=z_blcP|u^rVdSXf+v4E4?oBCJ_3kH&BDp=?q~c- zk@QE^v+oh^;~8d~BmW$*TBIme4|fd6zA}F-LDl?ea?fseWV}5RTUkF#Q#t4XbLCVo zB?U4iG@q5;Y!t?vWDe?!K9AI-N_In@CtlA-;Viq5R~swE(iZp~lik+EZ>5O_Z|ymoR;0_+@m(yCqKZLxb*?U&|`b3`n-3Q!uE-De==P(`>?BFT>4YO z0jAtyXI|45X;!+I=YnV;v~xa8P|STSn_{|HwGisoo@oUO7u<-ot|Y!&r-hPe?aS?p z0BgC2)FD6X6I+7uJ)F`?FHM}qGH0hz>uJhZDpT|++@z5I4b2OYkUH*Ql4xW06cXcP zS!Sdonb)-A$I%kFYB3pE7prEQv#eS#CqdPhU(;)VudAn}S9Z*wfo1)z&7Q#9%^r=? z&vUD%0?x;(PFza|WD8`Ma?NBDF>59|6?!R8l_63iM9o*wn)9`a@qC(H*x!_TS#`j5 z7J3;|e(Fr8SSRXR{#1mLALrCYwrb{qFms@DD|(ON@xH-~e0F3s^6RfjcmBb*UXAhu zbycY5pF9Pb(enmMx5mE`Iw7IE?n$UFHj~BW6ewhd=7tbl3%5D$MX#|QIzu}A8hu`C zN#!H|HTdh%z)^|L=ZyiyqMuhyn=4>v_G{)N*uWqtJ zAX6$&vpFwVfnLmr#_%fh2Y=3B;qNb=PmBEmukj4vKN?*dx@L+!y{Ufw*SfNri=8xk zkb{vh%USPD+?$JHF#J8`*RNy?R};#ZO9tp+UWBQIEqnQHuLc5wCZA@W#YVqKfS{A8hF0v_>VK`x;*DQ#E{7eIF7v34>EgP&dOs=VkKRnnZf&11E6uLFQ8|dS zes5HX@TMTL3>Ai;9ldWY^UlVbJhG1qGCkAB^xY_1OvRMAc6tcrc`rjK=$G6HLT84j zc<_+skw9WJ#SQQj%=ktTJHD*ZF`@5y^$OQ?qB0 z_cPv4Ltv$?DUU;?5-5rOu3y+0lbj&{@uNs$pnY5``EN8U-|D|F;PH4T0AMO+z*G3Gg$+yc=MlIe>oT!Hw6DnHqh)NR6u&$nXN9AZuUx zBq>?|n+Anv==GF20QkKJy^CjiO}8=pin3HO0qq`mHpf%zKHU+gkg`aeyZ-iJjW0m{ zWyRF8kP|e=j$4gLClDr2;~P)$Z@Qadr<51bD(=-w>{fHvME&r!LWMGE9h>F6lSp|! z-K6n|BsyuStj3gldD35Z&!=Wzr$!X!_XthPvIyKe5_0H;3dzk10jA zdb0`MM^&wM!F3#B@-hkvxP~0>=RZ1G(2ci6FsnIZ`eJkS&;^#Fw7gwt~_pH0uUTf_^DB{ma z1#Pf#Z#p-8F{8<%;yCy{>!1m8E!WoHqVnV5B(~;qD#B@{5of8TS#{FqXE&Ob9iY)yL|qSf#*(m(>$6bMvH2N z8^^f@{a&@3T>{Q=Gfqs?hBBtCV>X?sS%Fb(nfcxXbHdiGq-!0m9PbvYdq!ex+mue- z&s2qL@4V47#)_Iy=81o=P1zGM>v(@)|3?u4=NZzQZk)7oJhN6kOx;oI$-pCYzdylL z7~^V1+nKWW(AYNCSkieMAhCw8diF4Vf2iZe)mp-8d{>w4UDEClb@xw_GX<*iynNM|Uz2nE8-y%K zt8*85osbX^AQCAXVEiD1mB3z#r3jn?Cy&-Zexm|0>Lmd!>NzE%Y&PHR+vQ zwf9{=&LKb{NW-%X70O@(GFH3DS*lN+*Ok(n>D#!^A{~D2+{X1;f}n(jv&q1!qX)>)REH;TAY0>3Q*R9bwpy&L?;DVZ~}oy zfo7^iDa={Y?SlbLrB~=$A~8nuO;|L06B_e_J*Xn3WTZl=wops@(~b2x{fEc0yXtnG zjT-fr{l+{phpW>fZNYzdw^3_lQPI|4mD(?^MapY#h}KJms5$h6$ya(`9ycz(dTGV_ zc?GPq2qL0X%gr(A$jcizqy_$=LKm)g_;!3`z&sKhYi=>%4bs>?NCqxYX&qkf^y~QTyXV7qpniKT$Qb*nE%0^{>>`W@MV|f z)waD^DDa@fFRjA-rVqLcecY0w4%Lm#E}jSNlOdy%>+>=VZWs5SCA=?oOo+H`xBQB| zBujKC60IRou;1r_718cqlJl+Gz<;B=eMa%OT!0@dWCBPz4BzIg9Cl_r@5c#R?tNi7 z-D((qCNY9QTy8Dkt~$86V)bT2oH7y4HsxHI+SDL*b=1sscinH_2%VhyU&cM*^{ZE3 zw05i;QF*Px7ueK5z@li3w6#)9nZoRQAA<4YXsv#y7+Jq}!}r&9S)aaT(>z^T3c^|sFHap>%JMbxa5Wg)LI{JcJU zy{a$gExrLg7(F9~qjWpoI~WDJXXiWOx|WP3Ee(|t=EBLnei!>bM;9)!wFCUkA=mzT zS!(HcM0f_S%(2;Aex8Zh?h&Nd=U{nezPbNCUJLhm?DqA1Eb+CwS#hUHw!S&o_(xwa zlEX>q<^y$uZb!^_}I_`;KyvUKU|05N?oGx6g6=wos# z^WEyMQJdTL(x46AE#l8C7rlm{sXGp3`up0)q*kH!AI0tme(~uPZcoT6eqQb&+tNE4 zeiE8tX1o1@qVX!`bk&Ip`763S#t-P*NYWnUp-RQ7IFc(9KR0Y4ZE9df=n=I;a_mf! z9x~L>={Ph7ClE!xEg(qR(fhiCFp_zjT~4t zyQ&@1Fzy;#uSr)9y%D;gEvjE(ez*=XcT&I)xA>sasEe9c+1*t+_}Sfp6}j2woG*q( zH-4iz__^lO3UfjEo<{_^<`=vc9~P9Y1s6*V6NynT-6}QNSI^Ii(_8}`ex7b_U@j)8 zWNA}hsvlDw3;Jd)PEXw$<-gqg-n~i@YXPMQOQp5ISp(laYCoj2pR9EF7a&mqwib{p z1$kTxU^JEaxxu0m^ySyqsYQi``T_VM!J7fOo-etr-wkcLx8LqZ1A)C80dK<@gt zL1xDVY}-_K_?>lzNf|O}Ivew_O(HnwC-^l&?d~LPR+-XFn_%1MW7$0DVGp%~-xMhz z8AkdumAqK&+iTtm_hpFQ;b&TT9ASLnf-k>{<9*qM9QYcn%iXI@}^`WTwUmrDh z0^$Xr+Z^{l{`B+ZXV_tnKOCl4+Xi6Vbe^K;XAORyKs4B|=& z3QPVowRM#dIl$mi*nsPZ^(#dXQMPtm5+{DW$I%8(+3{tzD5sLd6Fqg9fP%P~dEWsS zvC8ODO7|s&xi=Y{wjVowg=$%~_J?-DR|nc+K(pMzWeE3`8~%5&&ZqKJd*p#-@%nnW zo2_Ew#mCal03JpQ*&ZP~NIX|%<%R&8y72Dc8+9cRq7h;?Jd3l=+|DjPB7}BF%F%+S zn?BiAj|eRaXVO8%M5_eB>kk}Zml=!?LG?0xtVAK*Qtgor&yVW`cM6q<9B{<7-NIORjU^zm5dB91SScKl!fhdy<(Syu{2 zdrzHi_ydW${L~0M7jD#N1}k}}Pm}l_iASkQ8-k-G1n2Wr>I`@ql6{(|$pG~>V7C-@ z3q!;n=0IWKUgv|mFOF9k#{q0|WYyU{>_aeSXw(-Qh0!!urI<1GB>IIOTk^ShSbhGz z5$~CwTKrdM=3ydax}M>spv5?Ee&j@ET^%@kYH54$EU1F~-0jtX<@ zHk<;F>j2LoRA^NvQmYqSy^2tpw67) z5q&A#x;LL%0VX|vCQRu+fz`>2b& z7WdUNf`PQ?(|+G#RQ;m}%1+!vz(vT9o+%IgEnfx#J7Diot4C5EK)>9}-vg<_G%VQ@ z+8)g@i4hfDCjy%}T)Nv%IioQmiNLtUJ_UTQpWCL4LhBpTSQ9M(|5J^wLE`062|4$G z+;!wvE|34KpNxvR;-TYc6H_x~JGh&uQ>8n8+gW==`>wV3zh<%}DJSIt}8q-BQ+#(V&7E&>cpys(|N_oj|>ta`GmRstd+9;AfUd4!Xkq} z&?qrd>87z;^iM+guLYnEiia=?pClc~ZmG>lQI)E;8rrPW8w)&PqSq&5G%H4bwOqD9 zItgQTJSmHow41xJTr0cIPk`c!^v2Y0flRPaNN=%Q^xU8k8KG4;*7}L5FeQC)ZW%?X zP)?^%->6lwm`w+kyeE`p-ET9QJ>Hw;Q~K!?{5yeyO-Bs|<47?*+%ck~Z+pua)-Nia8d<5(v)+KHfN4AWH9q`( ziQ=cMaq+-sQwQn9S0!Lp{7X5~BB!3c3r3kJtSEWaOa!zM>&A+X}0`Rs(SvXiUSbvlWrIc7_kepi@=?Kvn5o;1Le z2}xqazb3+1Z*UFhbQINuJHtKwF7telD}VqKa|7oZgqd`_YHd*4$!o+eO|3 zdJ5(*7m^8a0nLK+B}YSk3CvtN35pLhm*1$i!3|1d@jye&xTPrpH>Gy7ZD3cMi2qgj zJlgLZ8DJh2YF_L7p0YRtjxsPj!9nvP+v+<04ocu?zPh3kS}_Bz>1-8A+CWqn0>hf4 zr_NL=>_&Rf=vx~CN0e>(3X*8A+||To*h>*BhW*bjr4A7s6#^Fqw8|}1?F0r%4|HT9 ze}uQHnU_G?_23Sfb`&vQt-9ZNrNe$iM-sla<+?xAwLRAJ0wCjuyWGge7=AZWg_6wm;_A{ z*lDhwxZLTlm}C*-D{jJ%v^y|@sMQo($vB-9T!?x`k?adx`zbQgH{#c7kKXk{O@}6S zoY%J+m=Hf+G*egwhX!1h28fuSdH5wJ{il?R7Ro2t_=je(K-+<5yyBrpTqk9KmU^yV zP!XlOEXspg{r8Wq@(qkHJv*CdYivAQOPsenA2#9Qa5*TL=g#%7m_>O})b&%n)}l*+ zKIkaCx$a{!gsTmKHGy5fm`#;Z{7^R-c65VJT#c(Y}~OBf?c|)Z!|! z$e?vmYgy@nh-JFAJz1No@+|?85DHL(Osq=&nb=5}n`(fvl}IHVHoXAP`=1Pnv_blW z=}{FjsmdeFI07T|I^aH5j(N*-YxN)Qn=Vc2PehVrR_y*{f2WSm12$6EH_&lvx(3Ty ztjPe5ktFa|tHT;>;t&i4)r-4 zNP$5JY}jN}-EovmaB9dUkUHfjG5exSbnR`MfeaEsaE~-MYZxaZe3!u(wwZKW`W#4h zf{o6ZjuIc4ng9yYTf00DAsv+`j-Kw}9?L%uR1~$R15|iE5`f#FkRtKSI~5A)OvH}_ zman4u{8y@l8RVK@1>Z-h2$`{&=1_pM<|^MdV-)3PSIUrVwmJ(K{Xg1wfX9&MLZ&ES(n?-{uTdo8?ppc`Qt~IE}oi|)L zZ{2Du^z+%$uiV3_iADz*!Kg=IYl%;Aq7pIje|Nz#@jyB&j`#}KL1SyN?u^UG2$WM) zq$ITCc}5^{e=8zI6u1Jn-4dae2;*#?t`F@-u*~Nj59Y~aF~x^29xwuEWmqo~*i2d# zJP2rHbp@F7mlLB64&HLELj6j*>7nA`Q>-`_Q9IOSGu$+Tx)> zN5bCMUG+B2cBlW#bR>Whb}d^Dqmsk(6p!X(#fKKA>i>m1C|WT`GW&YPg3-VtKUqK3 zfw8TugSrV*&@9OfX^bSl2nxC>A9s`2a%4YN%(C-06Gs8Gz}?PM2Z50bMBp`K=5ia8 zRrncKqzUfv8?Q0gQn3yc52a!6IV>BZi+gyIL(Cwrxu&)rogWP1Hcc5mKs<@p1bFPO zxNrYY<)oUoi$av-e+=VAHoX7b@REfVcB*!(=#`>c zO$i+KzL9W8%2i-F5L~})#v!fbTZ>DbnDev^^`YzMNP0cqq$|tc=h$|4StItkjQzI zH*1X-63siXqKR0X{!e|Q$N*+e~#D+m1feR3%=P;b7-32wY$P#4x-;vHes z?8kg-h@Tel5(vDHR*XWwxurD&7MXkwVacvKgJhk_X6mFI3rrT8hX4**JdJ)r6+cQG z)c3SR0vMau7)U0$=P3{sHhEzHbz3t!pMIJh(Y}X^@V#p$UC^u{#EQ^lYe>C)XsQyD zui=xJD5Ci$0z>DB8&oe{ZXsll_sLa>qOx5IRPW&P_@5SbG%`(aVyro(F^g@Pd!!{P zVO@%55_udvh;y{a)>og*_&P#A98^D~hlcDvzLbO1!^5MIoK7(gvSTQT?Mn&{ z%41vcx*jt)_>)^>L1u-L6U+_Ro2HnC*Lan_r0ws$0-v|zfs!7X6a4)X<``ZfBh_NR6DMpZ zJxe=YlYSMZ3)|=_8cPXznB-PtKHd`JisFn?2-*>jrYq=TQs^{9M*H<^o!{-{su=>; zGB*yI%=In}&m(O*(aXnJn9NWIQZ~fCD{)-&J@-l0?V~+Q;`fG3>mQk{gl4rWxUTZ- za9@zbY8EQ|GC|NFjeXVL+^yf=v46VaCfAX#fviLdJ@WeynQ5uK#yqlQay*U@@YsXp zX6fT?EQ5wP|E+s+yD2-skxlz5cO^bnF57HM1m_GQ#t;Ysf;I z;*35ZML-`nlApn{>?Gtlk3I`exN5_jw-&Of)NcN5@_e|f>E(zQsBvgXaFP|&Ow^?_ zzzS6`k8#|XCZE9^vAWfocr4|D;&DitB2*fki8S04bL}E zxUS`RGXH{jf;-D6c1>*11O!8L*q6xj8qptb|ML4-Bv3XsNA#dS8AdC@+QU5~LLNrL zhW(SuGgtMpHm#6GMYQ*$!o+L#d&CJ2T*3~KL~2fdrC;4QhV9BgT#34X#lRRMSCxQX z1fKglkt&Y^w%SXZeveQz=GRKccd#6`M~do2xE$ux`xNZ7593>#rqLsEs+2*STUxHS zhWSVe22`-A5PL1=kFDN&GR^QsU}Ue-3U=bdgG1~GEn#m|<@Y^fKgpo&usi5! z=(9_an5;nB+Ai3|udIVF4%NNYdnr{AWP3BKfX#(g^f+NE>K(`yY715@zj4Mr8Mb44 zxg%Cg;blUB#Lu5?+DxrOHNhkP8smgHwiaiZd-R?u{d;$elEz)!ucXJHY+jexd*6^D z9mWDo3mx+!wzsxuAVRTos%{$oS{!XM4)1Ood8xs)Y4fcy#K`#jb>-MFs2P25aVl8) zZ~AbBV~N-#pEaqG+wkH8s>a3JlE?8a#Ldy$l9X<>pSpJKDH$h{Ww_(p$}W|u36~pQ zx?7ghKPOMM4?{Ib1_(ysva&S)yIVP-i|Wv2Vj*?bbo%>TC(rsw32&_f`3Y>3*`!Nz zZdS+uQemYs+J=sRHDWyCb^dgPRJo`-W1S2N_phP@4!I8Fx|DCI!!=(=(2--w0yFwr!GMa z?YU}&3gY6`fRa-hx^kmbaQ18J!TYB;^0do?lr{~KM{UP3@oXP*8Cqs>#B3rPt|VVI z0}G04Axt$_`z$83spHi!FQCZgEYRLqTNTQ*xG6F_JvXbN^*w&@z$9IqqE@YebQ?W> zq}+Yve@xY1EqgL&GpmGB$;If_ykrIC)x&!j;c-SGN^mSpVq~KfE=J=J-xtYjgV*y|q1im3eVw%ab^bIe~jN1z$MVZVOMZaqccZVL6f+ zCF;L?#EMOhdte+!w%PN-3(GAzP=}qqBzovCwm$@>Otp-E(ZnP*@>JU@qZsB3MFc=`t;TfcBrI93P{Em{7}NYJQtQd$W7qDAo;NxE zrBj~Dy_`b%e5bpf;WB3p-?Tc6>9#;~9kG<^pY~55l9Vku-QQynk}F?zk^-#8y5pBE zaIIw%6WOFF_ise;AR>h9oC}`%_Vlgs0yjx&UC`B6=76z)-GHk36m?Gxp`o+ki-Uzg zetmJ=SS&~nLr-YNFhFmav-@m4Ms)+zPYRyVnJxYT6( z0py#Pq}III(G=cko&k>mJcKbPdrUINzf!G?QB}xY8x#*XV7rE=`tUkFD8cJ4_Lcb; zabc6SWmz%&6v{al>O^ovYbu0~PwpLueLdJCmRpPN2UOfi4kLFTmbU0)nB^IdGYpR> zoxDRIgIxjQ$B=y&yZ{=b*@95FREUi*1TcAN9<-N(k#Y`Qki{Y zm&#IQVLco4@1Kl9y3hvyy?%*Cd1-N)KIrEv2&TSsmxeR4*W_9rPE_7na6CMjRRm+b z*K1hH`K&b^V=>C;Jq$O_-Cy4yT7%D$j-ZC5VUg2*MV^RpFP{ z1RH}>teS~!)LSPhcrPi`o57!^CmGLudyEEO0gqOqMg@sTag7 z`&-Ig)_#g*PWn4#Q=!JJKHzS}1!itEtI->Y{rf8~UlnK9%HJ(#Qci&!p5gI&R0X62 zomXEt1Co%R2=pFHHkB}c(Y&Pp5|Zs&+<?lf4td0Sji<02# z)hN&k6CNxhlS`Mi_}^x;Kl2)%&8D~tJt0X`r;DQ9Jy=3YQA(yYB7_mJq=`wKHmDrH zGAD%XT09raA|@2)hZq-|Oa|Z#v`gmG>rN6#)4MmC7;dCD*3zd^nBf%;WFg*rYK4iy z4(HeKG%PfKAv6|1+ga|zC(siVE!q||TUff@jJ_X}TjH;jdT?_hQAJXNoDy1~c)e)g7c^!GK>hyo0)P zX{&DM55w*lcA}^3wd|Z41eOUmE7|J^2P4Jr=0w)$R!tPQxEe$aI5&>wePwZ@i(NoF zuakVBAL2h+c4Br0_}7{5^0sM_%9Ip?a@hj{5c0L6hhY#*IdgULL)iwsF>Y=@hY=T{ zye*YCaQF)ck~#kQ-yQ115i~HX!kn?CQh~-(fKb7N;$aGcx^$N?Fii1^v3f#}LUu|Z zZT5@>jnvSGrf}ZWo|tOoKOLpqMp!DvI-OBZTm2F*4<>wji<`SmCNPiJxoX5?rVfC{ zY2R`RjX_>ez*%!iN&mZWf1Xd7UV+V2h0vQEGt?ffXyC-uu#%I_{LYgY?X@#w5iU`SF!j@qbM z;vk>8qo|0BF1M@8L`qX!?M;^Iwv0h6DgM~yruC1D_dFlCbt}DdQ6}~E6Sxt$f~rgL zFVkQnIUiv>n8gfQjM8#WC^Kpug5VXyaJlT1 z8b!|o%R*T{t{Ro(DGqi=vlGqx$zmt;%h?%fw=fjPP9gu!LkqThY>w`HZ9|Pd%KM0B zCMHIvZIv;0b-;PpZ<*J_FcV7v4qDH)zbV3OG7iy|jBtYlLjzCSh$>uUI%E7raO>-bJRy}-b$lb%E%&gky?zO9^KLCYS2KzG zbiUGk{ZEl&ZIdOml(esk#JV?0FEm?(h@uSpX7=N9OGEWmwBUM8nHIaHC#+GjU#`$P zD_Tqpos$`By8C=o$(i7`JQg_k{fbWOd?LZ~(Kqoc$>5C{Q>ct-9!JyT4Kyv&qS1aR zLQ()bBOoMXJY-6&g?$*f&V>z1xCO%Gg5MWc*$NI{Jz_@JtBq^0i5~!&Dz{_n4FG~B0@UrhzvQnrPMvD z>>NOaY%J+LKyhw8M?0V7*Q5R6Vk{bBo$FT-TP4u05=-Dkt0kWz(5PW2l z=5d!{wLK>Md^vM{CzRRzMn>batnVF1(%KEkR#A^4?okS;LhGB=#yUMm1)+HP2+94L z;Cg(+*U{wVlEcXPe6-r7>j9e)4tfKKa0j=#zC|093zx^ph}ys%!+J(Lgt5#R?3Bm5 zw&KMr)$x|m2FTnR&IH$kelJAQga@B*azeYSprp15$25j`gyH}s%!UM3+AoPPCFW3i zO!7rP5Gw`rLmobJi~L6eef2*B$f_M)QOB@yBGEed9x-!hi-*#%HhQpq3!INjXKWxm z9SWD1)u0K|cs#F9cTm|rQZBP&w?zsDT8DE2qkXMLqmSF94pz$&D&$uQ=w$F2j3wJ` zZ&hF0jdz-_yG%lRboA7Tq(Q5N5-G@wQ;ri;6WPZ{QAs_a%lTn|giPZ5{~rJ_Dj(YXo1DV^8jf zI3!@_1MkY*wE9e@mB$GUsTd_PwY?g)r7i8HL>o#v5sm2w^dj`mCrS|ftP*A!fS{ZZ z-}&)g-nLdHAUR-Bq-~>P?=!F#*sW$YKx@5|boGi;KS6%W(d~q12KnGV1Cj)1Yq3-~ z>4_vgT)(+L-&Ap8*<4@YY5-4+PDe`K08<}@38A4WQ6JFGZI4A)hiq^SMxpU!Kg5PL zr}tb)R$scQYQUI3Rl@CmVvzs*Y*vqgh{d1{7k)xOlN9f{W<^k6ihq8SCeHj^Nahwi z2}Z7eQC0(tiBW$Bm<`$10~ks95xx*z89SysCn41MRjI-Wir^CJnHY08;<+_BYEHIM z4EkSArJ`(TJcx}GMm7dE!;l+}W%rY$muZosQDmBO%S$oyiUOC>zlH;oG^bf9pvq_{ zyE4Lge8ZRE*v+7|D&VYP?BWyv3yqWB)Yrg>B2j87)y}6-uXj zZ6`_BWMh7Pl0phso@>I{zv*SGv}#-mvf#? zdxYVz&>(*dNpYA_%*S}iN+4zf<&oB=2!n7}VPoAL3>RUX9ZCSVW%O=|-}jN2e`4@h z7p{Qd4Ehj;O4|LzK)a)jclEqwh=45^8wp$b&>6}Hf|cY?6LPU(G?es_+VsJWbehE+ zS$hR3G36o++K$LQB*63g=r>a9tbj$G>YOruVY|FwUrn$UdCkm{oM=Vv@WrX=^8IW{ z-6jU+o%rO0dlVyW1Z_=d*BMeXBC!}q645fOa_tQw=-cR!rmZR+PHnKs9Qh;sVQL z1G{GS<4Th}7xa3`|4DC^jO#yV5oF-IuU2tY0#~SNH!JfP*d5m-WuxF(IILdc(U z64F1DAGs&RTx2XpvqN8j1V+dvX5hktSI9ZRx4GS^NPtN5R;x}(oN9^k#^>*#4Oy_b zs=T0=kejK7wtEN0=go7fgmO6@{Z3NwI+o({QIMw55zxfRw)mYe-%xJNpD(EC6d`eI z{CZ|1WCqTC>_JeB>LVjv0}wA2n%c-`XUP-@5=QP=bwA5C4IF( z&v19m(sNl0#6L0dU!NzfL}ka4rz+(XjZ6G)mtOyJ?wV}0C~<%j98 zE!*>()__`|)3~=H{4(6+7*bor@suEuCvHf|_!b3}b#9s%uJKS5R*1kMqhp=l0e&vd ze!^e*qD^n+r%<0uwW!!Ap5_bh%C9Aa!19?0AjZouRq1S0XqZY~8LSKm<#(34v{`o% zf$)8(Y1miS{;Uj=CRxr4_>5?yO6ixAp|<}AE$_sO;dCTli6!27xO3QAOi6Z#)8Z<@ zYB_NJGD7BgjAOVtYrVG2$uiy#+l=F%&P8Ls%kz&?&00(PlCqpqb^k6YO$kB1@weE_ z0-FYgt&uO7y)43lZJw$?+s)>`s2xG`nQv-^?a?Y?Bf{_A|q}_YRgRT+!D)!N}1bGCNq2OPkY^D{`nKcwUfV%!9>Dp zE$Iqd+ou}hZf_pfo25zm66pd?4^*N&il6wi-|C)O@vs*d2D2&SuW|Db*X${Rqs)Z@*M*~Rer zA=j2#NA3_{M%MM&6F+eX8>~VC5PUDv0eCMlp1xZAx1cSHmf}QkLJIkl@Le_4zD}Sr zW^Kl=en@v8;J{722gq^B=mpRRAxt`bC(=@U`=ut3y!JRV6ng$n}|_he1k3yIbPs~q)h z(Mp$Th5_eVPp78qlaNh?Eepr!^j6&!%U1jk=tJ5TjDM8)Jzei{#`z~?5PmDyZC|!r z#|(c(6jd*KSF_l49;2T3HxYu3x*x{@rDfT%)Pj1FXHkFi{|@4ae9RX%`HQ2}?>PL$ zu}h!R4Bhn!q=yRnz1u6iZTLl98QUFHKa#o++v9DoheK@#aiB;_YF`%XDf+Tp23IpG zEaJ-L5?YS_hbUS=iHI+_oupJzl+TG7z%M}vT^&#-@$2umsFeZxR^bWRd-dFSk^LOz z-u6%6f?amrwtl0JP*j|!f9&4#!A5Aa@1hMi;;9JG)M%sFF17)JN=rZCKsMaTTU&cn zBG%SHFJDNv{OOH~MH;VK34inZLHAs}-3taN*n>o!W$&UWIBzWl!<{Y$4<}AcHUhWkNeYlm;%Uz& zHj+0!Z&AQwmL}`3r0#R`2;cB@$_yi`1{d-LU)OPp1V7&*yg@dUdb&JQD4E zqb3ueyT05>ciDJk5iIzlz#1|_*#PAfLeVzO(m_$GP&ckZfuU3l8d#rjh6_Y(uy(vwD9&3|s-4o&}F|oxdBRiUa{`llF%bZ_$UJ zCv&A`54l5E-#>mMjAd^IQ$XUYpSHp~`%hY_GXSucDXcmIg`|S?B1!04O6BcJ2h5WetMe-C!E&MHH< z{Pv7h8MV$!U*2;p(wZ;havVNIRSg4M55Yh_o)~D&EWgBCl?o4H1`l62*jWjrnva4W z*s@bNpUX2K(@G5f*g)B)qgvkK(Zh9L1h2suVHwYbEhaVVlUA&QAw6LlDrKG$#R(MM zK}Hj5Et?a*gQ(-toS3lRzDw&6D%$4eH4SAhfaGzGfqa~{-8qhERmhq6)2Y#BY2)0CLiPe-%=A&@0$9cyc+A#t;?R-2vEq-a zJ$6Te9zp{^&htpt4T^2%Ep84$;yU2N?*tc`2~SToai%LKm!`PUTXZf@*zapj=%~~6 z2*^*QKdin|2t&H3>>J?jJkKuwAU|pOdEz&IVE36gPhr)sb#W-S;r!z$kL~muTYQ?d1g-zjQQtGCA2%COTs%3JD}04x`BnoUI#(APyb?=%;VJJ$s!!L zH#qrm<38Vfu=%yduH3ELv5;9|9M)0|{FsN_osq($DvQ4O(Ev!#?FR5vlUA+5F=*!} zE<*K$TPq?KEM<`S66HGw#Yg9&=%M5UK7U}O$ur*ORCXp5#3croZ#!qn+spWS_iNcO zdXtW$GG4QK$}yXF z^KH--V^_Gup7_7ofs0~=P=EGMnu)hnx9>X|36*48!ONCh-#QWxx(?_MxH7+9>2xM7 zTA&=nUu_>%9N8a-u!osJ)=Y^b7N5St+2w?tP?SUMRa_8RKm6AP{V*=2eu)P13F*~0Q{RH_8aC|Cr=K6Mf)7<4x*_){$TIgt7< zJM5u|(RV4DjON8rP3Z6unAl1YVQrslPki^J^V>;AanT(}EOArSNX~GkkYpE-XsXB( zM9PlcSXY3uH(G3q?C68@fT!9+(0K?l25Z3cEyeUiq=>8nfcfZ$VFvFCz>u`$)&fK{ zvkpw(6Be!9lJWfJ|LCjUJq;P`~`?6nI}fAm=h@Nup0O{&hC z1ByNb0jk={+SYbraB*oxHz8JDC2EGoAH}^YF64@m(_b*^R(}g{w=l`9wo|3wGS(87 z2|hw#U1YUNjP0A*zNAnu&<)^BNlCj=0k}HIq!O~?wlYpRY;oti?z`t7_ABj;vkx-= z#!SM&iNxDCi3VwR14wtp$qXNgx5`A(hk0qkE&0B%?0p(_5)C6;+g1yrNFPrC8ZCc@ zNEhh$J{i3M4Qf)?ehif4CjdpBpC$wBL|A@Pd%$! zem@-P@t%nxfbsBQ?7JuG(IyvQQb+HxmU+*Xi&qjEb}zbso5usA$73uGccC2ao+R>c?ysgNMH*9(n8FE1v&+}&uh9c@h{cN|f?q^?Cd zX0KICl8s?wB@^bZ=0zIXh7ieH5ZW2|I7;6nGl*Zlg1dlbe%CZm+)%tU7{w(Nit+kxUjB_Q+%Wmf#k)ex=$Z9m0>fy{f;6QKK_Uwenw z`h{0tnC5sFO92_BM$BNNGnY(o&E(#F-mv3m4s4f1e@+=hW?%0FHr`)CH&|e)w*N23 zlO7S?x0zq;dgm66)z?+;0f&_)`Z!Fy0E2N;)NjB4Ueg_u12$$P8+43_s>gb-U8 z^ZQSno#_RdcJN7=515eo`7??ZZ0~oxT?`T47;_bWhISM|z16g)%U=8O1+z`P`>kFJ zI(=c@x6QsO{txuun~nsX0fk3fy!c}y1UMS&Ef z3`TM-C4#^#A}Ate@+K#4txQQ=6~OGvGH1dDf6u3Q`f2l5-K(_85#uq-QEPnNUbp&! z#6l*=YQh^fqS4anZ=3l-7fn}0Bk?gZ3JzC;LfMGAIAJU zot1K)BWWTR|0v%Ke*bu+FM8H!@!Fq1E?tGbugSM0CQZL4g0=ieCv9TvlxXTfg;dVa z8Dox$+BSAHiZu}fPFXryZBEBz+K0>}1x2cVw6i${`(&=dYrc;1Bb6H%U=NH*o2*`w z$MrgG1g$~&zWde6z60&Z*tOr`KKD+HHgxNj!!zNcW{OvQ7)fG1sHv$BG)Btb*kqPq z#GQexw}70sbRvu;B~etr-5M>Nq>|3A3@!;my)k9>bxT)uU0=CdPzR3q-L;nk1@*8qyz5~=J z6}y#Fk~tp8Bd2OPx#QbmjbZAFhZ7l8dH*Pit0R)@=U{75zgae|}^ zr7dB6;=)&|92$j|04Rs*0HD4qkyV(oL~x=t?^mUc%TS8Jki*?&Sgyn*&^)9U^3(XO zA}5_uMQi+mMTI8W&Te*`7-8^9eHbRx=po8mfEw;HFX zr@aBv6)tv=b$5i-N>zkj8*{o4uzVX@rt&XjoRF6k&3EwA8zJ87dBvwm-9^kdt{N|` z@?@~h^154w9e38GIiAM^hf;*CJr5EhD{`s|k^(bj}+2oq-++ixSoeLJiJksno>}B*eVM$*)&oO~|A8{D{|W0e6_f zgxm^iFE_O7Oh&-e8$Vr=OyC2Hs(WNt$>{RaiPi58iH?wH<%(2Cva#CStAH7v22XUo(Ld}=LX6m#&fK5Dq%^44( zA>f1?z*z9*_d~!ClfVB52#WyzFoel`Kp^1f`ad4jpiOD=hh)hSiqHeVu6>n;0aWO~ zUjW|5fR?PJQ$X4`V;)(A>bG*Tl2ip-sYyXS}o2sIrG)YF#1`Zk%U-uh(daS zwlJSD^0ly)%-hZV{YW<8^sq;TJ9QRNT=YLzoWz?0!w)6(`D@e+`w`k@NzpTOUXhmvRTUKi>A?6RNBI7jVF z#JqusKSwUIGqAw+;&-z2amUv22?=7j53u0=Nrw9=u8zKM5a$6F&gpr88W9wLmGn=> zUozmn&6$}Q;0I!L|F!cIr;vEmqf5~UIDz@um`OkIJ3HiBXpaz5A{o?`V$y41;}YxJ z&%=+jnaA%l!OZVrBytlfG4VPWoH-*$!MZ+cVonwgq(dbLj5i+;W3yonnVEwio|!N> zK0MQ-(6R0!B?!tnH!R1dYu?B7~;z7&*w3;JfH{Nd{o749w!p!^Z@ zL4Rifjv{{ygg&AbbR+avEM@94PvJa| z>2xv2KaFS6WiIh{;>wnC-!F0;=vBs%TW@u(J1UQ+vZYn%efPk;9Hnw=#!6;oRcSf; z$T#B#mz*_*ii|y}r|<-*PtJ5PeV4q5>%D6;m&ViJ)=UxFB)p|SX7aEuAWrEMT<-xq zIg< zk^dikieLYW*!?H3|6(ra|2bdICjK9mk{-4EA3SRfN&3?YTSE3%;~a%WpI_}jbMpBg zIl6X-45ryo4sT#m(t|dIOwM5d`k>uZGR#s{zwbI&1O4TL zW?<>t>ER7c&m9kGoB3~DbNRRFA*(|XY$tgsoe8r6ocdIF`moj^*ek12@a)r}WsHZG z@YGFkZ`ZcaShz#}h;N6j!JqV?a*Y|#zA$=(AtNz_;!dhVt)MQwp=#fuw^Z{>(hT~W z1rcKP_%5*j`YyS8bWnSWxdF?2ZQBZb)v(qWA22j*Bc2zg?S0rUtQ^S9mZJq%-TeWvNG(a=!z zRo(pe*z`uSZ(F`b$dT?Aji2kCxbJW|w8xhzsYjwlF|U8Ekdtg@^z7t*Kn}T)MYB4D z$gbZ#8!$L4-~Bq%7>KxH+bJ1EcuZbcx;Ux~Ino0cT1!S2JGn*vP2XbZX+Mth>Kbp( zmLY(Vi84AQcyLPcDy_s|UfFM1=)rvCGL$mt3B4DLu)JoN!2@?R(0?^_#{*)fPtbcf z?u^LR#yf4maKk=jBWAmoyusJmV8Z7&>{MNh4S;_{w0BJT=lXq)KE?8XcfCpRu+YEa+C-Hvi;^l(>s#&Xo&@cJzq9qW7jPsA)^=#T!(m(q%wu@Srt zK!0os*V4_HA^X;j&j~~{P|2syiggQFfixO-V5N(NuIc4A)T@c|J@k+eL}AgV&!HiP zQG@}83ewQATWn(p~*T=xF|y%q02QQ=(4Vat}zXhp5H&h)b3I~v5se$J{ea$HX~%j z!We^?nij3&bHb3{f3Hr8M>_(*DOh!G2(&H1m}(bu&=0?1plut4i4#XG-HaP5)QH#Y zg=Pj}8Ii_|?MrrZ0bhNlB22iki%oiEs_EaEl8|YVFAWx9qD{&vi&;R{EM$a%v!lRz z@ajWo65c;>+2N?KO^Q@k;`lnm6G8FtwS-^%SmWf1qNos@QnP{a0q@;j&rP#N%99gxX_nr;1E(N z@_QAX+h{6P2HNVIr;c@Z)N|&r<>a){+&$i_ zHcyWl)syEwi1yHIT|bYh5(G?l_^>Lg_4;vrhAQ3bht+rdR$Ce4&D8Z1x}K|qnJ?sjCCVr#tS<+q-x57Ewi*jcHxrqM$Qg(huR%#+KoXZCjZUAfhVJ0HICc&a@@b;xz*p z3J(?c$~_Fp_kh#`B%fO$_Xh@Lj<@uDIe|*KXJuz*b60Wb+{Mhuar>(Y@)Tti81d#* zok~nY7!ANARL=#dJ7pEckcg!hs6XYAoM#k02w2pJ)AFkdJ zgvzp*Bc>2Dead{+Ph!ke%1t3{KuPS=XWo)O!ySI{JXl!LiE+Wq8wG2}L@Nl0WqRC! z2Qhd&eGfcGPfDn2po_y{>z+ZEO89T-#CZ%UykPAbq+RUTwdWr>X^pgh!chw@&c%*f zcm8oxXhHWU962kvyDe_mtoescP(15r8Z%Mzcb(26RR7;{A<^ImRvp{*{5JerX1sGJ z)&6H-w?=4YftJ6wW_v+(pxsZgID`Ffwp=dc6Z@Z~q{ROBNvEjwFD!o_P6sBg|B(G} zwouL{_P@(Wdi&q(W~rFTC-FZXe~McFuxhKwNs_>pyP( z(^SLu;5ugJ|6oHXB>tb4lM?>#NvF8=FL=O*(Sh0dzg)3YPWZoNqzL}6ST1EZllb3{ zKgF$odZFUsb*-|k6Z#kDs{68)wJp%tvy;0wm96OPBU%javLTOzyMMnzV8M?Qg zIm8P-@7Ov(L)4*V-k6@zgK>O@xAN^Vxjye-YxN9xVO!rY1}2Ok0rln9a=PwqdSDJo z-+(B7F)HtBIO^*pM+3(2)86snYXDm}J*>2W&_1X5$ll)Grf>6UcX+jaQeW>4pJ9#b z|KXXPXPR=W1gdUKMV&|P$b=@gM#K#e>4DL2-D7}L%V~8w7^TI;TM&o{=AGGrj$vTY zdziPr0VTY#2XotHfl#qB&o<3L+92K0pai1AGvUoi#f-1sy5)Ie(_7yt=3<&p{W_hS zZDnQxUY(S0B;+c31?VsfZgN?~AT;h67KDXH!p+N}+utKb>D)T{jYlu;r129&2l^&O zCv^4GiZrDwpFgb#kShU)BiNsoZMOkKNypk0o=0b(>pCkV7|;R1PyuDlu&ry;*aP&m z#(fD~7^CoJHM%QvS~u1eb%B8Q*wQ1H^=g&6@4=DXGl$jmjq(uMoq|@Z}A5i?7v_FisgKw0DAOk^7?=1?mt=oQ_ctD{}fBvDSi(1XMQDx!s<^ z^EUiPk)I;IuPQ>pt3o}$64$&#E}niiZhKazC+iz7%@+C(2KWQBV_kwIJaUaMzQ*c{ z(72q!XrV({R9*z3!oX1}bRd*X-q;=y&x$R%DW3@}+KjPhdSs%aR7_-CiLz=igw}bg zu8KgyHvmC$b8Db)-yw9%^z`Z?(=%m_*DNwKf#u81lEm!m!G65rNEv%*)`KG@;?v6(GnEO&VR+YXs z{{Qx_Wk+ooivCI#BN3zsL3m6-E$K+3RxDb&peuw>1~N<}9wP$NR%rgczP95RPC@{s zD)C+A={UZzopW<@jt`ID*0UnAAnp@u=viV7a(Xg~M5x;|ltn zZz!3{leB`#L*nXT4@xu+*A$0u?}#=$c&c*I8*h#-+An{d@w zB4O5nZlmm|$ln#FhD~=xXtG%OKetP1CnGjxl!twRDU0#Wk0VuZff8kRsfBeVA|9_hIzXHs}e@boo{?B7R*BA%#$A4N)*Zlui zh-u?L_ua;aPPb(efNtOP{r{S?e`f!8n{_q*<2E}c|ECc9zvDk~Vh<|BhlkcrQh7@d zZ&MEgF$*kqx($-kgR-Jb!EXdzL;Om=oaQ<>H7rGi*c5?|DHgn7l_kN9Z_s^pIWSNg zc_$BJfV$EG<8{5P8B~sr4>deKFhL`V9YGT$nC)=Z1D7ugK~N0N#nRY> z^s&Gh^&FSR8m!;^WjH6zWPL{`RUEiBsuFt8F#@j9{1_%CAp&gTBR#%;@uQb!B0{aI zaGQDF)`RKu@ozqyYfNvc`2W(0pIUzWU+)0_hnfEiFoXX~Z71RX3&(-{_}^_c%>O@y zm_Glb-srmK2cR-o3jV*+?4Q~H8_lEqk9wu|9~ciuzozDLbJeGY@=Tslt&o~)@(ST?yl6}c0zhUJ~7T)dU6>q^#x zW~}2AY(I|rG-HHqV0jhm{i>e=sXa@O>WS6QJyiE_r+yEHrr;MW8G-+WmW2Oiq&=@P z2js_p4Y%o<@xKr=_^;HKh5xQG4xEAi?mKmZ|BA2#{MYWZ4gYHyOyB>nIs0ehzq;E# z;(u=#{8xzG2L6)@OZh;nKOUa`(-55=#i$TZ06zzvE*WUJjfh^FLo>kTFM*!$oy(y` wV&z-UqPp=60>R(z!^dHd*8z&p+3++^{=RL1lQCn)jFrXy0@CP;tpK_R0C&dKG5`Po literal 0 HcmV?d00001 From 2c5a1a6352773f891b91629af21ca5c306eca638 Mon Sep 17 00:00:00 2001 From: provRushabhShah Date: Thu, 16 May 2024 10:56:07 +0530 Subject: [PATCH 2/5] some refactoring --- lib/src/api/Logs/logg_tracer.dart | 13 +---- lib/src/api/Logs/readable_log_record.dart | 9 +++- lib/src/api/common/attribute.dart | 4 ++ .../Logs/expoters/log_collector_exporter.dart | 8 +-- lib/src/sdk/Logs/logg.dart | 52 ++++++++++++++----- lib/src/sdk/Logs/logging_tracer.dart | 32 ++++-------- lib/src/sdk/common/limits.dart | 21 ++++++++ 7 files changed, 89 insertions(+), 50 deletions(-) diff --git a/lib/src/api/Logs/logg_tracer.dart b/lib/src/api/Logs/logg_tracer.dart index bff3526f..f54bc930 100644 --- a/lib/src/api/Logs/logg_tracer.dart +++ b/lib/src/api/Logs/logg_tracer.dart @@ -1,25 +1,16 @@ import '../../../api.dart' as api; import 'package:fixnum/fixnum.dart'; - abstract class LogTracer { /// Starts a new [api.Span] without setting it as the current span in this /// tracer's context. /// /// - api.ReadableLogRecord setLogAndEmit( - api.Attribute body, - DateTime observedTimestamp, - api.Severity severity, + api.ReadableLogRecord setLog( + DateTime? observedTimestamp, String name, {api.Context? context, api.SpanKind kind = api.SpanKind.internal, List attributes = const [], List links = const [], Int64? startTime}); - - - api.ReadableLogRecord setLogg(String name, - api.Context context, - List attributes, - int startTime); } diff --git a/lib/src/api/Logs/readable_log_record.dart b/lib/src/api/Logs/readable_log_record.dart index 4d712eb1..864b5e8c 100644 --- a/lib/src/api/Logs/readable_log_record.dart +++ b/lib/src/api/Logs/readable_log_record.dart @@ -11,11 +11,16 @@ abstract class ReadableLogRecord { sdk.Resource get resource; late final DateTime observedTimestamp; late final DateTime recordTime; - late final api.Severity severity; - late final api.Attribute body; + late final api.Severity? severity; + api.Attribute get body; Attributes get attributes; sdk.InstrumentationScope get instrumentationScope; api.SpanContext get spanContext; + void setAttribute(api.Attribute attribute); + void setBody(api.Attribute attribute); + void setSevarity(api.Severity severity); + void emit(); + } \ No newline at end of file diff --git a/lib/src/api/common/attribute.dart b/lib/src/api/common/attribute.dart index 2f95d205..e3cd0a3e 100644 --- a/lib/src/api/common/attribute.dart +++ b/lib/src/api/common/attribute.dart @@ -6,6 +6,10 @@ class Attribute { final String key; final Object value; + String get id => key; + String get val => key; + Attribute.empty(this.key, String this.value); + /// Create an Attribute from a String value. Attribute.fromString(this.key, String this.value); diff --git a/lib/src/sdk/Logs/expoters/log_collector_exporter.dart b/lib/src/sdk/Logs/expoters/log_collector_exporter.dart index 15118c81..98d0a76d 100644 --- a/lib/src/sdk/Logs/expoters/log_collector_exporter.dart +++ b/lib/src/sdk/Logs/expoters/log_collector_exporter.dart @@ -123,11 +123,11 @@ class LogCollectorExporter implements sdk.LogRecordExporter { return pb_logs.LogRecord( timeUnixNano: Int64(log.recordTime.microsecondsSinceEpoch), - severityNumber: pg_logs_enum.SeverityNumber.valueOf(log.severity.index), - body: _attributeONEValueToProtobuf(log.body), + severityNumber: pg_logs_enum.SeverityNumber.valueOf(log.severity!.index), + body: _attributeONEValueToProtobuf(log.body.val), attributes: log.attributes.keys.map((key) => pb_common.KeyValue( - key: key, - value: _attributeValueToProtobuf(log.attributes.get(key)!))), + key: key, + value: _attributeValueToProtobuf(log.attributes.get(key)!))), spanId: log.spanContext.spanId.get(), traceId: log.spanContext.traceId.get(), observedTimeUnixNano: Int64(log.observedTimestamp.microsecondsSinceEpoch) diff --git a/lib/src/sdk/Logs/logg.dart b/lib/src/sdk/Logs/logg.dart index ed827e4f..b3379ffb 100644 --- a/lib/src/sdk/Logs/logg.dart +++ b/lib/src/sdk/Logs/logg.dart @@ -6,7 +6,7 @@ import 'package:meta/meta.dart'; import '../../../api.dart' as api; import '../../../sdk.dart' as sdk; import '../common/attributes.dart'; -import '../common/limits.dart' show applyAttributeLimits; +import '../common/limits.dart' show applyAttributeLimitsForLog; /// A representation of a single operation within a trace. @@ -20,26 +20,24 @@ class Logg implements api.ReadableLogRecord{ final sdk.InstrumentationScope _instrumentationScope; final Attributes _attributes = Attributes.empty(); + api.Attribute? _body; + final String _name; int _droppedSpanAttributes = 0; int _droppedSpanEvents = 0; - @override - final api.Attribute body; @override final DateTime observedTimestamp; @override final DateTime recordTime; @override - final api.Severity severity; + api.Severity? severity; Logg( - this.body, this.recordTime, this.observedTimestamp, - this.severity, this._name, this._spanContext, this._parentSpanId, @@ -70,19 +68,35 @@ class Logg implements api.ReadableLogRecord{ sdk.Resource get resource => _resource; @override - set body(api.Attribute? _body) { - // TODO: implement body + get body { + if (this._body != null){ + return this._body!; + } + return api.Attribute.empty("", ""); } + @override + void setAttribute(api.Attribute attribute) { + //Don't want to have any attribute + if (_limits.maxAttributeCount == 0) { + _droppedSpanAttributes++; + return; + } + + final obj = _attributes.get(attribute.key); + // If current attributes.length is equal or greater than maxNumAttributes and + // key is not in current map, drop it. + if (_attributes.length >= _limits.maxAttributeLength && obj == null) { + _droppedSpanAttributes++; + return; + } + _attributes.add(applyAttributeLimitsForLog(attribute, _limits)); + } @override set observedTimestamp(DateTime? _observedTimestamp) { // TODO: implement observedTimestamp } - @override - set severity(api.Severity? _severity) { - // TODO: implement severity - } @override set spanContext(api.SpanContext? _spanContext) { @@ -93,6 +107,20 @@ class Logg implements api.ReadableLogRecord{ set recordTime(DateTime _recordTime) { this.recordTime = _recordTime; } + @override + void setBody(api.Attribute attribute){ + this._body = attribute; + } + @override + void setSevarity(api.Severity severity){ + this.severity = severity; + } + @override + void emit() { + for (var i = 0; i < _processors.length; i++) { + _processors[i].onEmit(this); + } + } } diff --git a/lib/src/sdk/Logs/logging_tracer.dart b/lib/src/sdk/Logs/logging_tracer.dart index c46f7968..87a1616d 100644 --- a/lib/src/sdk/Logs/logging_tracer.dart +++ b/lib/src/sdk/Logs/logging_tracer.dart @@ -6,6 +6,7 @@ import 'package:meta/meta.dart'; import '../../../api.dart' as api; import '../../../sdk.dart' as sdk; +import './logg.dart'; import '../common/limits.dart' show applyLinkLimits; /// An interface for creating [api.Span]s and propagating context in-process. @@ -17,10 +18,11 @@ class LoggTracer implements api.LogTracer { final sdk.LogLimits _limits; final api.IdGenerator _idGenerator; final sdk.Sampler _sampler; + Logg? logg; @protected - const LoggTracer( + LoggTracer( this._processors, this._resource, this._timeProvider, @@ -30,16 +32,15 @@ class LoggTracer implements api.LogTracer { this._limits); @override - api.ReadableLogRecord setLogAndEmit( - api.Attribute body, - DateTime observedTimestamp, - api.Severity severity, + setLog( + DateTime? observedTimestamp, String name, {api.Context? context, api.SpanKind kind = api.SpanKind.internal, List attributes = const [], List links = const [], - Int64? startTime}) { + Int64? startTime}) + { context ??= api.Context.current; startTime ??= _timeProvider.now; @@ -64,10 +65,9 @@ class LoggTracer implements api.LogTracer { final spanContext = api.SpanContext(traceId, spanId, traceFlags, traceState); - final logg = sdk.Logg(body, - observedTimestamp, - observedTimestamp, - severity, + logg = sdk.Logg( + observedTimestamp ?? DateTime.now(), + observedTimestamp ?? DateTime.now(), name, spanContext, parentSpanId, @@ -77,17 +77,7 @@ class LoggTracer implements api.LogTracer { _instrumentationScope, _limits); - for (var i = 0; i < _processors.length; i++) { - _processors[i].onEmit(logg); - } - return logg; - } - @override - api.ReadableLogRecord setLogg(String name, api.Context context, List attributes, int startTime) { - // TODO: implement setLogg - context ??= api.Context.current; - - throw UnimplementedError(); + return logg!; } } diff --git a/lib/src/sdk/common/limits.dart b/lib/src/sdk/common/limits.dart index 139167f4..69de5afa 100644 --- a/lib/src/sdk/common/limits.dart +++ b/lib/src/sdk/common/limits.dart @@ -74,6 +74,27 @@ api.Attribute applyAttributeLimits(api.Attribute attr, sdk.SpanLimits limits) { return attr; } +@protected +api.Attribute applyAttributeLimitsForLog(api.Attribute attr, sdk.LogLimits limits) { + // if maxNumAttributeLength is less than zero, then it has unlimited length. + if (limits.maxAttributeLength < 0) return attr; + + if (attr.value is String) { + attr = api.Attribute.fromString( + attr.key, + applyAttributeLengthLimit( + attr.value as String, limits.maxAttributeLength)); + } else if (attr.value is List) { + final listString = attr.value as List; + for (var j = 0; j < listString.length; j++) { + listString[j] = applyAttributeLengthLimit( + listString[j], limits.maxAttributeLength); + } + attr = api.Attribute.fromStringList(attr.key, listString); + } + return attr; +} + /// Truncate just strings which length is longer than configuration. /// Reference: https://github.com/open-telemetry/opentelemetry-java/blob/14ffacd1cdd22f5aa556eeda4a569c7f144eadf2/sdk/common/src/main/java/io/opentelemetry/sdk/internal/AttributeUtil.java#L80 @protected From f3a0398923bb4b1074f3fe6bfc0329a69e99029c Mon Sep 17 00:00:00 2001 From: provRushabhShah Date: Fri, 17 May 2024 15:20:45 +0530 Subject: [PATCH 3/5] added unit test cases for Logexpoter,collector,provider --- .idea/workspace.xml | 194 ++++++++++++----- .../Logs/expoters/log_collector_exporter.dart | 5 +- .../Logs/expoters/log_record_processor.dart | 4 +- .../expoters/simple_log_record_processor.dart | 14 +- lib/src/sdk/Logs/logger_provider.dart | 16 +- .../datetime_time_provider.dart | 5 + test/unit/mocks.dart | 8 + test/unit/sdk/Logs/log_expoter_test.dart | 196 ++++++++++++++++++ test/unit/sdk/Logs/log_processor_test.dart | 45 ++++ test/unit/sdk/Logs/log_provider_test.dart | 57 +++++ 10 files changed, 483 insertions(+), 61 deletions(-) create mode 100644 test/unit/sdk/Logs/log_expoter_test.dart create mode 100644 test/unit/sdk/Logs/log_processor_test.dart create mode 100644 test/unit/sdk/Logs/log_provider_test.dart diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 584dd768..a4a692eb 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,43 +5,30 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -50,17 +37,17 @@