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..a4a692eb --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + "keyToString": { + "RunOnceActivity.OpenProjectViewOnStart": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.cidr.known.project.marker": "true", + "cidr.known.project.marker": "true", + "dart.analysis.tool.window.visible": "false", + "last_opened_file_path": "/Users/rushabhshah/Downloads/Flutter OTeL/opentelemetry-dart/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1", + "show.migrate.to.gradle.popup": "false" + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1714635632768 + + + + + + + + file://$PROJECT_DIR$/lib/src/sdk/Logs/expoters/simple_log_record_processor.dart + 25 + + + file://$PROJECT_DIR$/lib/src/sdk/Logs/expoters/log_collector_exporter.dart + 67 + + + file://$PROJECT_DIR$/lib/src/sdk/trace/span_processors/simple_processor.dart + 31 + + + file://$PROJECT_DIR$/lib/src/sdk/trace/span_processors/simple_processor.dart + 19 + + + file://$PROJECT_DIR$/lib/src/sdk/Logs/expoters/log_collector_exporter.dart + 73 + + + file://$PROJECT_DIR$/lib/src/sdk/trace/exporters/collector_exporter.dart + 239 + + + file://$PROJECT_DIR$/lib/src/sdk/trace/exporters/collector_exporter.dart + 240 + + + file://$PROJECT_DIR$/test/unit/sdk/Logs/log_expoter_test.dart + 128 + + + file://$PROJECT_DIR$/test/unit/sdk/exporters/collector_exporter_test.dart + 166 + + + file://$PROJECT_DIR$/lib/src/sdk/Logs/expoters/log_collector_exporter.dart + 51 + + + file://$PROJECT_DIR$/lib/src/sdk/Logs/expoters/log_collector_exporter.dart + 49 + + + file://$PROJECT_DIR$/test/unit/sdk/Logs/log_expoter_test.dart + 188 + + + file://$PROJECT_DIR$/test/unit/sdk/Logs/log_expoter_test.dart + 178 + + + file://$PROJECT_DIR$/test/unit/sdk/Logs/log_expoter_test.dart + 190 + + + file://$PROJECT_DIR$/lib/src/sdk/Logs/expoters/log_collector_exporter.dart + 33 + + + file://$PROJECT_DIR$/lib/src/sdk/trace/exporters/collector_exporter.dart + 48 + + + + + \ 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/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..f54bc930 --- /dev/null +++ b/lib/src/api/Logs/logg_tracer.dart @@ -0,0 +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 setLog( + DateTime? observedTimestamp, + String name, + {api.Context? context, + api.SpanKind kind = api.SpanKind.internal, + List attributes = const [], + List links = const [], + Int64? 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..864b5e8c --- /dev/null +++ b/lib/src/api/Logs/readable_log_record.dart @@ -0,0 +1,26 @@ +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; + 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/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/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/.DS_Store b/lib/src/sdk/Logs/.DS_Store new file mode 100644 index 00000000..4d8e8bd2 Binary files /dev/null and b/lib/src/sdk/Logs/.DS_Store differ diff --git a/lib/src/sdk/Logs/component_registry.dart b/lib/src/sdk/Logs/component_registry.dart new file mode 100644 index 00000000..33c4b2fd --- /dev/null +++ b/lib/src/sdk/Logs/component_registry.dart @@ -0,0 +1,93 @@ +import 'dart:collection'; + +/// Holds information about the instrumentation library specified when creating an instance of +/// TracerSdk using TracerProviderSdk. +class InstrumentationScopeInfo { + final String name; + final String? version; + final String? schemaUrl; + + /// Creates a new empty instance of InstrumentationScopeInfo. + + /// Creates a new instance of InstrumentationScopeInfo. + /// - Parameters: + /// - name: name of the instrumentation library + /// - version: version of the instrumentation library (e.g., "semver:1.0.0"), might be null + InstrumentationScopeInfo({ + required this.name, + this.version, + this.schemaUrl, + }); + + @override + List 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..69152299 --- /dev/null +++ b/lib/src/sdk/Logs/expoters/log_collector_exporter.dart @@ -0,0 +1,200 @@ +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: sdk.DateTimeTimeProvider().getInt64Time(log.recordTime) , + 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)!))), + spanId: log.spanContext.spanId.get(), + traceId: log.spanContext.traceId.get(), + observedTimeUnixNano: sdk.DateTimeTimeProvider().getInt64Time(log.observedTimestamp) + ); + + } + 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..22f328fa --- /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); + void forceFlush(); + void 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..5dde4572 --- /dev/null +++ b/lib/src/sdk/Logs/expoters/simple_log_record_processor.dart @@ -0,0 +1,35 @@ +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; + bool _isShutdown = false; + + + SimpleLogRecordProcessor({required this.logRecordExporter}); + + @override + void onEmit(ReadableLogRecord logRecord) { + if (_isShutdown) { + return; + } + logRecordExporter.export([logRecord]); + } + + @override + void forceFlush() { + logRecordExporter.forceFlush(); + } + + @override + void shutdown() { + forceFlush(); + logRecordExporter.shutdown(); + _isShutdown = true; + } +} 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..b3379ffb --- /dev/null +++ b/lib/src/sdk/Logs/logg.dart @@ -0,0 +1,126 @@ +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 applyAttributeLimitsForLog; + +/// 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(); + + api.Attribute? _body; + + final String _name; + int _droppedSpanAttributes = 0; + int _droppedSpanEvents = 0; + + + @override + final DateTime observedTimestamp; + @override + final DateTime recordTime; + @override + api.Severity? severity; + + + Logg( + this.recordTime, + this.observedTimestamp, + 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 + 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 spanContext(api.SpanContext? _spanContext) { + // TODO: implement spanContext + } + + @override + 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/logger_provider.dart b/lib/src/sdk/Logs/logger_provider.dart new file mode 100644 index 00000000..b55d24c4 --- /dev/null +++ b/lib/src/sdk/Logs/logger_provider.dart @@ -0,0 +1,59 @@ +// 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() { + for (var i = 0; i < processors.length; i++) { + processors[i].forceFlush(); + } + } + + @override + void shutdown() { + for (var i = 0; i < processors.length; i++) { + processors[i].shutdown(); + } + } + + 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); + + } +} diff --git a/lib/src/sdk/Logs/logging_tracer.dart b/lib/src/sdk/Logs/logging_tracer.dart new file mode 100644 index 00000000..87a1616d --- /dev/null +++ b/lib/src/sdk/Logs/logging_tracer.dart @@ -0,0 +1,83 @@ +// 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 './logg.dart'; +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; + Logg? logg; + + + @protected + LoggTracer( + this._processors, + this._resource, + this._timeProvider, + this._instrumentationScope, + this._idGenerator, + this._sampler, + this._limits); + + @override + setLog( + DateTime? observedTimestamp, + 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); + + logg = sdk.Logg( + observedTimestamp ?? DateTime.now(), + observedTimestamp ?? DateTime.now(), + name, + spanContext, + parentSpanId, + _processors, + _timeProvider, + _resource, + _instrumentationScope, + _limits); + + + return logg!; + } +} 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/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 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 00000000..50f486dd Binary files /dev/null and b/lib/src/sdk/proto/opentelemetry/proto/collector/.DS_Store differ 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 00000000..5008ddfc Binary files /dev/null and b/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/.DS_Store differ diff --git a/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pb.dart b/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pb.dart new file mode 100644 index 00000000..871a1baa --- /dev/null +++ b/lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pb.dart @@ -0,0 +1,222 @@ +// +// 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:async' as $async; +import 'dart:core' as $core; + +import 'package:fixnum/fixnum.dart' as $fixnum; +import 'package:protobuf/protobuf.dart' as $pb; + +import '../../../logs/v1/logs.pb.dart' as $4; + +class ExportLogsServiceRequest extends $pb.GeneratedMessage { + factory ExportLogsServiceRequest({ + $core.Iterable<$4.ResourceLogs>? 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/time_providers/datetime_time_provider.dart b/lib/src/sdk/time_providers/datetime_time_provider.dart index fe9c9851..f965bc17 100644 --- a/lib/src/sdk/time_providers/datetime_time_provider.dart +++ b/lib/src/sdk/time_providers/datetime_time_provider.dart @@ -10,4 +10,9 @@ class DateTimeTimeProvider implements TimeProvider { Int64 get now => Int64(DateTime.now().microsecondsSinceEpoch) * TimeProvider.nanosecondsPerMicrosecond; + + Int64? getInt64Time(DateTime dateTime){ + Int64(dateTime.microsecondsSinceEpoch) * + TimeProvider.nanosecondsPerMicrosecond; + } } 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 00000000..8e7867b5 Binary files /dev/null and b/pub_package.pub.tgz differ diff --git a/test/unit/mocks.dart b/test/unit/mocks.dart index 8c5919c2..bfb5709c 100644 --- a/test/unit/mocks.dart +++ b/test/unit/mocks.dart @@ -3,8 +3,11 @@ import 'package:http/http.dart' as http; import 'package:mocktail/mocktail.dart'; +import 'package:opentelemetry/src/api/Logs/readable_log_record.dart'; import 'package:opentelemetry/src/api/context/context.dart'; import 'package:opentelemetry/src/api/trace/span.dart'; +import 'package:opentelemetry/src/sdk/Logs/expoters/log_record_expoter.dart'; +import 'package:opentelemetry/src/sdk/Logs/expoters/log_record_processor.dart'; import 'package:opentelemetry/src/sdk/trace/exporters/span_exporter.dart'; import 'package:opentelemetry/src/sdk/trace/read_only_span.dart'; import 'package:opentelemetry/src/sdk/trace/span_processors/span_processor.dart'; @@ -15,3 +18,8 @@ class MockSpan extends Mock implements Span{} class MockReadOnlySpan extends Mock implements ReadOnlySpan{} class MockSpanExporter extends Mock implements SpanExporter{} class MockSpanProcessor extends Mock implements SpanProcessor{} + +class MockReadableLog extends Mock implements ReadableLogRecord{} +class MockLogRecordExpoter extends Mock implements LogRecordExporter{} +class MockLogProcessop extends Mock implements LogRecordProcessor{} + diff --git a/test/unit/sdk/Logs/log_expoter_test.dart b/test/unit/sdk/Logs/log_expoter_test.dart new file mode 100644 index 00000000..e719f4e6 --- /dev/null +++ b/test/unit/sdk/Logs/log_expoter_test.dart @@ -0,0 +1,198 @@ +// 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 + +@TestOn('vm') +import 'dart:ffi'; +import 'dart:typed_data'; + +import 'package:mocktail/mocktail.dart'; +import 'package:logging/logging.dart'; +import 'package:opentelemetry/api.dart' as api; +import 'package:opentelemetry/sdk.dart' as sdk; +import 'package:opentelemetry/src/sdk/common/limits.dart'; +import 'package:opentelemetry/src/sdk/proto/opentelemetry/proto/collector/trace/v1/trace_service.pb.dart' +as pb_trace_service; + +import 'package:opentelemetry/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pb.dart' +as pb_log_service; + +import 'package:opentelemetry/src/sdk/proto/opentelemetry/proto/common/v1/common.pb.dart' +as pb_common; +import 'package:opentelemetry/src/sdk/proto/opentelemetry/proto/resource/v1/resource.pb.dart' +as pb_resource; +import 'package:opentelemetry/src/sdk/proto/opentelemetry/proto/trace/v1/trace.pb.dart' +as pb; + +import 'package:opentelemetry/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pb.dart' as pb_logs; +import 'package:opentelemetry/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbenum.dart' as pg_logs_enum; + +import 'package:opentelemetry/src/sdk/trace/span.dart'; +import 'package:test/test.dart'; + +import '../../mocks.dart'; + +void main() { + late MockHttpClient mockClient; + final uri = + Uri.parse('https://h.wdesk.org/s/opentelemetry-collector/v1/traces'); + + setUp(() { + mockClient = MockHttpClient(); + }); + + tearDown(() { + reset(mockClient); + }); + + test('sends logs', () { + final resource = + sdk.Resource([api.Attribute.fromString('service.name', 'bar')]); + final instrumentationLibrary = sdk.InstrumentationScope( + 'library_name', 'library_version', 'url://schema', []); + final limits = sdk.SpanLimits(maxNumAttributeLength: 5); + final logLimit = sdk.LogLimits(maxAttributeCount: 10); + final log1 = sdk.Logg(DateTime.now(), + DateTime.now(), + "log1", + api.SpanContext(api.TraceId([1, 2, 3]), api.SpanId([10, 11, 12]), + api.TraceFlags.none, api.TraceState.empty()), + api.SpanId([4, 5, 6]), + [], + sdk.DateTimeTimeProvider(), + resource, + instrumentationLibrary, + logLimit) + ..setAttribute(api.Attribute.fromString('foo', 'bar')) + ..setBody(api.Attribute.fromString('body', 'bodyVal')) + ..setSevarity(api.Severity.debug3) + ..emit(); + final log2 = sdk.Logg(DateTime.now(), + DateTime.now(), + "log2", + api.SpanContext(api.TraceId([1, 2, 3]), api.SpanId([10, 11, 12]), + api.TraceFlags.none, api.TraceState.empty()), + api.SpanId([4, 5, 6]), + [], + sdk.DateTimeTimeProvider(), + resource, + instrumentationLibrary, + logLimit) + ..setAttribute(api.Attribute.fromString('foo', 'bar')) + ..setSevarity(api.Severity.debug3) + ..setBody(api.Attribute.fromString('body', 'bodyVal')) + ..emit(); + + + sdk.LogCollectorExporter(uri, httpClient: mockClient).export([log1,log2]); + + final expected = pb_log_service.ExportLogsServiceRequest( + resourceLogs: [pb_logs.ResourceLogs( + resource: pb_resource.Resource(attributes: [ + pb_common.KeyValue( + key: 'service.name', + value: pb_common.AnyValue(stringValue: 'bar')) + ]), + scopeLogs: [pb_logs.ScopeLogs( + logRecords: [ + pb_logs.LogRecord( + timeUnixNano : sdk.DateTimeTimeProvider().getInt64Time(log1.recordTime) , + severityNumber: pg_logs_enum.SeverityNumber.valueOf(log1.severity!.index ), + attributes: [ pb_common.KeyValue( + key: 'foo', + value: pb_common.AnyValue(stringValue: 'bar'))], + traceId : [1, 2, 3], + spanId : [10, 11, 12], + body: pb_common.AnyValue(stringValue: 'body'), + observedTimeUnixNano: sdk.DateTimeTimeProvider().getInt64Time(log1.observedTimestamp), + ),pb_logs.LogRecord( + timeUnixNano : sdk.DateTimeTimeProvider().getInt64Time(log2.recordTime) , + severityNumber: pg_logs_enum.SeverityNumber.valueOf(log2.severity!.index ), + attributes: [ pb_common.KeyValue( + key: 'foo', + value: pb_common.AnyValue(stringValue: 'bar'))], + traceId : [1, 2, 3], + spanId : [10, 11, 12], body: pb_common.AnyValue(stringValue: 'body'), + + observedTimeUnixNano: sdk.DateTimeTimeProvider().getInt64Time(log2.observedTimestamp), + )], + scope: pb_common.InstrumentationScope( + name: 'library_name', version: 'library_version')) + ] + )] + ); + final verifyResult = verify(() => mockClient.post(uri, + body: captureAny(named: 'body'), + headers: {'Content-Type': 'application/x-protobuf'})) + ..called(1); + final captured = verifyResult.captured; + + final traceRequest = pb_log_service.ExportLogsServiceRequest.fromBuffer( + captured[0] as Uint8List); + expect(traceRequest, equals(expected)); + + }); + test('does not send log when shutdown', () { + + final logLimit = sdk.LogLimits(maxAttributeCount: 10); + + final log1 = sdk.Logg(DateTime.now(), + DateTime.now(), + "log1", + api.SpanContext(api.TraceId([1, 2, 3]), api.SpanId([10, 11, 12]), + api.TraceFlags.none, api.TraceState.empty()), + api.SpanId([4, 5, 6]), + [], + sdk.DateTimeTimeProvider(), + sdk.Resource([]), + sdk.InstrumentationScope( + 'library_name', 'library_version', 'url://schema', []), + logLimit) + ..emit(); + + sdk.LogCollectorExporter(uri, httpClient: mockClient) + ..shutdown() + ..export([log1]); + + verify(() => mockClient.close()).called(1); + verifyNever(() => mockClient.post(uri, + body: anything, headers: {'Content-Type': 'application/x-protobuf'})); + }); + test('supplies HTTP headers', () { + final resource = + sdk.Resource([api.Attribute.fromString('service.name', 'bar')]); + final instrumentationLibrary = sdk.InstrumentationScope( + 'library_name', 'library_version', 'url://schema', []); + final limits = sdk.SpanLimits(maxNumAttributeLength: 5); + final logLimit = sdk.LogLimits(maxAttributeCount: 10); + final log1 = sdk.Logg(DateTime.now(), + DateTime.now(), + "log1", + api.SpanContext(api.TraceId([1, 2, 3]), api.SpanId([10, 11, 12]), + api.TraceFlags.none, api.TraceState.empty()), + api.SpanId([4, 5, 6]), + [], + sdk.DateTimeTimeProvider(), + resource, + instrumentationLibrary, + logLimit) + ..setAttribute(api.Attribute.fromString('foo', 'bar')) + ..setSevarity(api.Severity.debug3) + ..emit(); + + final suppliedHeaders = { + 'header-param-key-1': 'header-param-value-1', + 'header-param-key-2': 'header-param-value-2', + }; + final expectedHeaders = { + 'Content-Type': 'application/x-protobuf', + ...suppliedHeaders, + }; + + sdk.LogCollectorExporter(uri, httpClient: mockClient, headers: suppliedHeaders) + .export([log1]); + + verify(() => mockClient.post(uri, body: anything, headers: expectedHeaders)) + .called(1); + }); + +} diff --git a/test/unit/sdk/Logs/log_processor_test.dart b/test/unit/sdk/Logs/log_processor_test.dart new file mode 100644 index 00000000..bbb860e2 --- /dev/null +++ b/test/unit/sdk/Logs/log_processor_test.dart @@ -0,0 +1,45 @@ +// 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 + +@TestOn('vm') +import 'package:mocktail/mocktail.dart'; +import 'package:opentelemetry/sdk.dart' as sdk; +import 'package:opentelemetry/src/api/Logs/readable_log_record.dart'; +import 'package:test/test.dart'; + + +import '../../mocks.dart'; + +void main() { + late sdk.LogRecordExporter exporter; + late sdk.LogRecordProcessor processor; + late ReadableLogRecord logRecord; + + setUp(() { + exporter = MockLogRecordExpoter(); + processor = sdk.SimpleLogRecordProcessor(logRecordExporter: exporter); + logRecord = MockReadableLog(); + }); + + test('executes export', () { + processor.onEmit(logRecord); + + verify(() => exporter.export([logRecord])).called(1); + }); + + test('flushes exporter on forced flush', () { + processor.forceFlush(); + + verify(() => exporter.forceFlush()).called(1); + }); + + test('does not export if shut down', () { + processor + ..shutdown() + ..onEmit(logRecord); + + verify(() => exporter.shutdown()).called(1); + verify(() => exporter.forceFlush()).called(1); + verifyNever(() => exporter.export([logRecord])); + }); +} diff --git a/test/unit/sdk/Logs/log_provider_test.dart b/test/unit/sdk/Logs/log_provider_test.dart new file mode 100644 index 00000000..c3711cd4 --- /dev/null +++ b/test/unit/sdk/Logs/log_provider_test.dart @@ -0,0 +1,57 @@ +@TestOn('vm') +import 'package:fixnum/src/int64.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:opentelemetry/sdk.dart' as sdk; + +import 'package:opentelemetry/src/sdk/time_providers/time_provider.dart'; + +import 'package:opentelemetry/src/sdk/trace/read_only_span.dart'; +import 'package:opentelemetry/src/sdk/trace/span_processors/span_processor.dart'; +import 'package:opentelemetry/src/sdk/trace/tracer_provider.dart'; +import 'package:opentelemetry/src/sdk/Logs/logger_provider.dart'; + +import 'package:test/test.dart'; + +import 'package:mocktail/mocktail.dart'; + +import '../../mocks.dart'; + + +void main() { + + + test('tracerProvider custom span processors', () { + final mockProcessor1 = MockLogProcessop(); + final mockProcessor2 = MockLogProcessop(); + final logLimit = sdk.LogLimits(maxAttributeCount: 10); + + final provider = + LoggerTraceProviderBase( logLimit , processors: [mockProcessor1, mockProcessor2]); + + expect(provider.processors, [mockProcessor1, mockProcessor2]); + }); + + test('tracerProvider force flushes all processors', () { + final mockProcessor1 = MockLogProcessop(); + final mockProcessor2 = MockLogProcessop(); + final logLimit = sdk.LogLimits(maxAttributeCount: 10); + + LoggerTraceProviderBase( logLimit , processors: [mockProcessor1, mockProcessor2]) + .forceFlush(); + + verify(mockProcessor1.forceFlush).called(1); + verify(mockProcessor2.forceFlush).called(1); + }); + + test('tracerProvider shuts down all processors', () { + final mockProcessor1 = MockLogProcessop(); + final mockProcessor2 = MockLogProcessop(); + final logLimit = sdk.LogLimits(maxAttributeCount: 10); + + LoggerTraceProviderBase( logLimit , processors: [mockProcessor1, mockProcessor2]) + .shutdown(); + + verify(mockProcessor1.shutdown).called(1); + verify(mockProcessor2.shutdown).called(1); + }); +} \ No newline at end of file