├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yaml └── workflows │ ├── dart_ci.yaml │ └── publish.yaml ├── .gitignore ├── .gitmodules ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── NOTICE ├── README.md ├── analysis_options.yaml ├── aviary.yaml ├── build.yaml ├── example ├── attach_detach_context │ ├── README.md │ └── attach_detach_context.dart ├── main.dart ├── sampling.dart ├── stream_context │ ├── README.md │ └── stream_context.dart └── w3c_context_propagation.dart ├── lib ├── api.dart ├── sdk.dart ├── src │ ├── api │ │ ├── common │ │ │ ├── attribute.dart │ │ │ ├── resource_attributes.dart │ │ │ └── semantic_attributes.dart │ │ ├── context │ │ │ ├── context.dart │ │ │ ├── context_manager.dart │ │ │ ├── map_context.dart │ │ │ ├── noop_context_manager.dart │ │ │ ├── zone_context.dart │ │ │ └── zone_context_manager.dart │ │ ├── exporters │ │ │ └── span_exporter.dart │ │ ├── instrumentation_library.dart │ │ ├── logs │ │ │ ├── log_record.dart │ │ │ ├── logger.dart │ │ │ ├── logger_provider.dart │ │ │ └── noop │ │ │ │ ├── noop_logger.dart │ │ │ │ └── noop_logger_provider.dart │ │ ├── metrics │ │ │ ├── counter.dart │ │ │ ├── meter.dart │ │ │ ├── meter_key.dart │ │ │ ├── meter_provider.dart │ │ │ └── noop │ │ │ │ ├── noop_counter.dart │ │ │ │ ├── noop_meter.dart │ │ │ │ └── noop_meter_provider.dart │ │ ├── open_telemetry.dart │ │ ├── propagation │ │ │ ├── extractors │ │ │ │ └── text_map_getter.dart │ │ │ ├── injectors │ │ │ │ └── text_map_setter.dart │ │ │ ├── noop_text_map_propagator.dart │ │ │ ├── text_map_propagator.dart │ │ │ └── w3c_trace_context_propagator.dart │ │ ├── span_processors │ │ │ └── span_processor.dart │ │ └── trace │ │ │ ├── id_generator.dart │ │ │ ├── nonrecording_span.dart │ │ │ ├── noop_tracer.dart │ │ │ ├── noop_tracer_provider.dart │ │ │ ├── span.dart │ │ │ ├── span_context.dart │ │ │ ├── span_event.dart │ │ │ ├── span_id.dart │ │ │ ├── span_link.dart │ │ │ ├── span_status.dart │ │ │ ├── trace_flags.dart │ │ │ ├── trace_id.dart │ │ │ ├── trace_state.dart │ │ │ ├── tracer.dart │ │ │ └── tracer_provider.dart │ ├── experimental_api.dart │ ├── experimental_sdk.dart │ └── sdk │ │ ├── common │ │ ├── attributes.dart │ │ ├── instrumentation_scope.dart │ │ └── limits.dart │ │ ├── instrumentation_library.dart │ │ ├── metrics │ │ ├── counter.dart │ │ ├── meter.dart │ │ └── meter_provider.dart │ │ ├── platforms │ │ └── web │ │ │ ├── time_providers │ │ │ └── web_time_provider.dart │ │ │ └── trace │ │ │ └── web_tracer_provider.dart │ │ ├── proto │ │ └── opentelemetry │ │ │ └── proto │ │ │ ├── collector │ │ │ ├── logs │ │ │ │ └── v1 │ │ │ │ │ ├── logs_service.pb.dart │ │ │ │ │ ├── logs_service.pbenum.dart │ │ │ │ │ ├── logs_service.pbjson.dart │ │ │ │ │ └── logs_service.pbserver.dart │ │ │ └── trace │ │ │ │ └── v1 │ │ │ │ ├── trace_service.pb.dart │ │ │ │ ├── trace_service.pbenum.dart │ │ │ │ ├── trace_service.pbjson.dart │ │ │ │ └── trace_service.pbserver.dart │ │ │ ├── common │ │ │ └── v1 │ │ │ │ ├── common.pb.dart │ │ │ │ ├── common.pbenum.dart │ │ │ │ ├── common.pbjson.dart │ │ │ │ └── common.pbserver.dart │ │ │ ├── logs │ │ │ └── v1 │ │ │ │ ├── logs.pb.dart │ │ │ │ ├── logs.pbenum.dart │ │ │ │ ├── logs.pbjson.dart │ │ │ │ └── logs.pbserver.dart │ │ │ ├── resource │ │ │ └── v1 │ │ │ │ ├── resource.pb.dart │ │ │ │ ├── resource.pbenum.dart │ │ │ │ ├── resource.pbjson.dart │ │ │ │ └── resource.pbserver.dart │ │ │ └── trace │ │ │ └── v1 │ │ │ ├── trace.pb.dart │ │ │ ├── trace.pbenum.dart │ │ │ ├── trace.pbjson.dart │ │ │ └── trace.pbserver.dart │ │ ├── resource │ │ └── resource.dart │ │ ├── time_providers │ │ ├── datetime_time_provider.dart │ │ └── time_provider.dart │ │ └── trace │ │ ├── exporters │ │ ├── collector_exporter.dart │ │ ├── console_exporter.dart │ │ └── span_exporter.dart │ │ ├── id_generator.dart │ │ ├── read_only_span.dart │ │ ├── read_write_span.dart │ │ ├── sampling │ │ ├── always_off_sampler.dart │ │ ├── always_on_sampler.dart │ │ ├── parent_based_sampler.dart │ │ ├── sampler.dart │ │ └── sampling_result.dart │ │ ├── span.dart │ │ ├── span_limits.dart │ │ ├── span_processors │ │ ├── batch_processor.dart │ │ ├── simple_processor.dart │ │ └── span_processor.dart │ │ ├── tracer.dart │ │ └── tracer_provider.dart └── web_sdk.dart ├── package.sh ├── pubspec.yaml ├── scripts ├── attach_copyright.sh └── copyright_notice.txt └── test ├── api ├── context │ └── context_test.dart └── open_telemetry_test.dart ├── integration ├── api │ └── propagation │ │ └── w3c_trace_context_propagator_test.dart └── sdk │ ├── span_test.dart │ └── tracer_test.dart ├── sdk └── trace │ └── span_processors │ ├── batch_processor_test.dart │ └── simple_processor_test.dart └── unit ├── api ├── context │ ├── map_context_test.dart │ └── zone_context_test.dart ├── logs │ └── noop │ │ └── noop_logger_provider_test.dart ├── metrics │ └── noop_meter_provider_test.dart ├── propagation │ └── w3c_trace_context_propagator_test.dart ├── span_context_test.dart └── trace_state_test.dart ├── mocks.dart └── sdk ├── exporters ├── collector_exporter_test.dart └── console_exporter_test.dart ├── id_generator_test.dart ├── metrics └── meter_provider_test.dart ├── platforms └── web │ ├── web_time_provider_test.dart │ └── web_trace_provider_test.dart ├── sampling ├── always_off_sampler_test.dart ├── always_on_sampler_test.dart └── parent_based_sampler_test.dart ├── span_id_test.dart ├── span_limits_test.dart ├── span_test.dart ├── trace └── tracer_test.dart ├── trace_id_test.dart └── trace_provider_test.dart /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Code owners file. 2 | # This file controls who is tagged for review for any given pull request. 3 | 4 | # For anything not explicitly taken by someone else: 5 | * @blakeroberts-wk 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: Bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Steps to reproduce** 14 | If possible, provide a recipe for reproducing the error. 15 | 16 | **What did you expect to see?** 17 | A clear and concise description of what you expected to see. 18 | 19 | **What did you see instead?** 20 | A clear and concise description of what you saw instead. 21 | 22 | **What version and what artifacts are you using?** 23 | Artifacts: (e.g., `opentelemetry-api`, `opentelemetry-sdk`, which exporters, etc) 24 | Version: (e.g., `v0.4.0`, `1eb551b`, etc) 25 | How did you reference these artifacts? (excerpt from your `pubspec.lock`, `pubspec.yaml`, etc) 26 | 27 | **Environment** 28 | Dart Version: (e.g., "2.18.0) 29 | OS: (e.g., "Ubuntu 20.04") 30 | 31 | 32 | **Additional context** 33 | Add any other context about the problem here. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: Feature Request 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Which problem is this PR solving? 2 | 3 | Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. 4 | 5 | Fixes # (issue) 6 | 7 | ## Short description of the change 8 | 9 | 10 | ## How Has This Been Tested? 11 | 12 | Please describe the tests that you ran to verify your change. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration 13 | 14 | 15 | ## Checklist: 16 | 17 | - [ ] Unit tests have been added 18 | - [ ] Documentation has been updated -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "pub" 4 | directory: / 5 | groups: 6 | pub: 7 | patterns: 8 | - "*" 9 | schedule: 10 | interval: weekly 11 | - package-ecosystem: "github-actions" 12 | directory: / 13 | groups: 14 | github-actions: 15 | patterns: 16 | - "*" 17 | schedule: 18 | interval: weekly -------------------------------------------------------------------------------- /.github/workflows/dart_ci.yaml: -------------------------------------------------------------------------------- 1 | name: Dart CI 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - "master" 7 | - "test_consume_**" 8 | pull_request: 9 | branches: 10 | - "**" 11 | concurrency: 12 | group: opentelemetry-coverage-${{ github.ref }}-1 13 | cancel-in-progress: true 14 | permissions: 15 | contents: read 16 | issues: write 17 | pull-requests: write 18 | 19 | jobs: 20 | test-dartv2: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v4 24 | with: 25 | submodules: true 26 | - uses: dart-lang/setup-dart@v1 27 | with: 28 | sdk: 2.19.6 29 | - run: sudo apt install -y protobuf-compiler 30 | - run: make init format analyze test 31 | - name: Generate Coverage 32 | run: dart test --coverage=./coverage 33 | - name: Activate Coverage Package 34 | run: dart pub global activate coverage 35 | - name: Format Coverage 36 | run: dart pub global run coverage:format_coverage --packages=.dart_tool/package_config.json --report-on=lib --lcov -o ./coverage/lcov.info -i ./coverage 37 | - name: Activate RemoveFromCoverage Package 38 | run: dart pub global activate remove_from_coverage 39 | - name: Ignore Files For Coverage 40 | run: dart pub global run remove_from_coverage:remove_from_coverage -f coverage/lcov.info -r 'lib\/src\/sdk\/proto\/opentelemetry\/proto\/.+' 41 | - name: Package Artifacts 42 | run: ./package.sh 43 | 44 | test-dartv3: 45 | runs-on: ubuntu-latest 46 | steps: 47 | - uses: actions/checkout@v4 48 | with: 49 | submodules: true 50 | - uses: dart-lang/setup-dart@v1 51 | with: 52 | sdk: 3.2.0 53 | - run: sudo apt install -y protobuf-compiler 54 | - run: make init format analyze test 55 | -------------------------------------------------------------------------------- /.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | name: Publish to pub.dev 2 | 3 | on: 4 | push: 5 | tags: 6 | # Releases 7 | - '[0-9]+.[0-9]+.[0-9]+' 8 | # Release Candidates 9 | - '[0-9]+.[0-9]+.[0-9]+-rc[0-9]+' 10 | 11 | permissions: 12 | contents: write 13 | id-token: write 14 | pull-requests: write 15 | 16 | jobs: 17 | create-sbom-release-asset: 18 | name: Create SBOM Release Asset 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | - name: Publish SBOM to Release Assets 23 | uses: anchore/sbom-action@v0 24 | with: 25 | path: ./ 26 | format: cyclonedx-json 27 | publish: 28 | name: Publish to pub.dev 29 | runs-on: ubuntu-latest 30 | steps: 31 | - uses: actions/checkout@v4 32 | - uses: dart-lang/setup-dart@v1 33 | with: 34 | sdk: stable 35 | - name: Install dependencies 36 | run: dart pub get 37 | - name: Publish - dry run 38 | run: dart pub publish --dry-run --skip-validation 39 | - name: Publish 40 | run: dart pub publish -f 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .dart_tool 2 | .packages 3 | pubspec.lock 4 | .tool-versions 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/src/sdk/proto/opentelemetry-proto"] 2 | path = lib/src/sdk/proto/opentelemetry-proto 3 | url = git@github.com:open-telemetry/opentelemetry-proto.git 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | init: 2 | git submodule init 3 | # Pull opentelemetry-proto at the stored commit. 4 | # To upgrade, execute `git submodule update --remote --merge` 5 | # and commit the result. 6 | git submodule update 7 | dart pub get 8 | # Generate mocks for unit tests. For config, see build.yaml. 9 | dart run build_runner build --delete-conflicting-outputs 10 | dart pub global activate protoc_plugin 21.1.2 11 | cd lib/src/sdk/proto && \ 12 | protoc --proto_path opentelemetry-proto --dart_out . \ 13 | opentelemetry-proto/opentelemetry/proto/common/v1/common.proto \ 14 | opentelemetry-proto/opentelemetry/proto/collector/trace/v1/trace_service.proto \ 15 | opentelemetry-proto/opentelemetry/proto/collector/logs/v1/logs_service.proto \ 16 | opentelemetry-proto/opentelemetry/proto/logs/v1/logs.proto \ 17 | opentelemetry-proto/opentelemetry/proto/resource/v1/resource.proto \ 18 | opentelemetry-proto/opentelemetry/proto/trace/v1/trace.proto 19 | ./scripts/attach_copyright.sh 20 | 21 | analyze: 22 | @dart analyze 23 | 24 | format: 25 | @find ./lib -name '*.dart' -not -path './lib/src/sdk/proto/opentelemetry/*' | xargs dart format --fix 26 | @find ./test/ -name '*.dart' | xargs dart format --fix 27 | @./scripts/attach_copyright.sh 28 | 29 | test: 30 | @dart test ./test \ 31 | --chain-stack-traces \ 32 | --platform vm \ 33 | --platform chrome 34 | 35 | changelog: 36 | # requires the ruby gem: gem install github_changelog_generator 37 | # requires the env var CHANGELOG_GITHUB_TOKEN set to a GitHub token with repo scope 38 | git fetch --tags 39 | git checkout $(shell git describe --tags `git rev-list --tags --max-count=1`) 40 | github_changelog_generator -u Workiva -p opentelemetry-dart 41 | 42 | .PHONY: init format analyze test 43 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | opentelemetry 2 | Copyright 2021-2022 Workiva Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | The opentelemetry-dart software uses a repository with separate copyright 17 | notices and/or license terms. Your use of the source code for the these 18 | software repositories is subject to the terms and conditions of the following 19 | licenses: 20 | 21 | opentelemetry-proto: https://github.com/open-telemetry/opentelemetry-proto 22 | Licensed under the Apache 2.0 license: https://github.com/open-telemetry/opentelemetry-proto/blob/main/LICENSE 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenTelemetry for Dart 2 | 3 | This repository is the Dart implementation of the [OpenTelemetry project](https://opentelemetry.io/). All contributions and designs should follow the [OpenTelemetry specification](https://github.com/open-telemetry/opentelemetry-specification). 4 | 5 | ## Project Status 6 | 7 | | Signal | Status | 8 | | - | - | 9 | | Traces | Beta | 10 | | Metrics | Alpha | 11 | | Logs | Unimplemented | 12 | 13 | ## Getting Started 14 | 15 | This section will show you how to initialize the OpenTelemetry SDK, capture a span, and propagate context. 16 | 17 | ### Initialize the OpenTelemetry SDK 18 | 19 | ```dart 20 | import 'package:opentelemetry/sdk.dart' 21 | show 22 | BatchSpanProcessor, 23 | CollectorExporter, 24 | ConsoleExporter, 25 | SimpleSpanProcessor, 26 | TracerProviderBase; 27 | import 'package:opentelemetry/api.dart' 28 | show registerGlobalTracerProvider, globalTracerProvider; 29 | 30 | void main(List args) { 31 | final tracerProvider = TracerProviderBase(processors: [ 32 | BatchSpanProcessor( 33 | CollectorExporter(Uri.parse('https://my-collector.com/v1/traces'))), 34 | SimpleSpanProcessor(ConsoleExporter()) 35 | ]); 36 | 37 | registerGlobalTracerProvider(tracerProvider); 38 | final tracer = globalTracerProvider.getTracer('instrumentation-name'); 39 | } 40 | ``` 41 | 42 | ### Capture a Span 43 | 44 | ```dart 45 | import 'package:opentelemetry/api.dart' show StatusCode, globalTracerProvider; 46 | 47 | void main(List args) { 48 | final tracer = globalTracerProvider.getTracer('instrumentation-name'); 49 | 50 | final span = tracer.startSpan('main'); 51 | try { 52 | // do some work 53 | span.addEvent('some work'); 54 | } catch (e, s) { 55 | span 56 | ..setStatus(StatusCode.error, e.toString()) 57 | ..recordException(e, stackTrace: s); 58 | rethrow; 59 | } finally { 60 | span.end(); 61 | } 62 | } 63 | ``` 64 | 65 | ### Propagate Context 66 | 67 | ### Intra-process 68 | 69 | In order to parent spans, context must be propagated. Propagation can be achieved by manually passing an instance of `Context` or by using Dart [`Zones`](https://dart.dev/libraries/async/zones). 70 | 71 | See the [attach detach context example](./example/attach_detach_context)for more information. 72 | 73 | ### Inter-process 74 | 75 | In order to parent spans between processes, context can be serialized and deserialized using a `TextMapPropagator`, `TextMapSetter`, and `TextMapGetter`. 76 | 77 | See the [W3C context propagation example](./example/w3c_context_propagation.dart) for more information. 78 | 79 | #### High Resolution Timestamps 80 | 81 | A tracer provider can register a web-specific time provider that uses the browser's [performance API](https://developer.mozilla.org/en-US/docs/Web/API/Performance/now) instead of [DateTime](https://api.dart.dev/stable/dart-core/DateTime-class.html) when recording timestamps for a span's start timestamp, end timestamp, and span events. 82 | 83 | ```dart 84 | import 'package:opentelemetry/web_sdk.dart' as web_sdk; 85 | 86 | final tracerProvider = 87 | web_sdk.WebTracerProvider(timeProvider: web_sdk.WebTimeProvider()); 88 | ``` 89 | 90 | Important Note: Span timestamps may be inaccurate if the executing system is suspended for sleep. See [https://github.com/open-telemetry/opentelemetry-js/issues/852](https://github.com/open-telemetry/opentelemetry-js/issues/852) for more information. 91 | 92 | ## Contributing 93 | 94 | In order to generate protobuf definitions, you must have [protoc](https://github.com/protocolbuffers/protobuf/releases) installed and available in your path. 95 | 96 | ### Publishing New Versions 97 | 98 | Only Workiva maintainers can publish new versions of opentelemetry-dart. See [Publishing opentelemetry-dart](https://github.com/Workiva/Observability/blob/master/doc/publishing_opentelemetry_dart.md) 99 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:workiva_analysis_options/v2.yaml 2 | analyzer: 3 | exclude: 4 | - lib/src/sdk/proto 5 | -------------------------------------------------------------------------------- /aviary.yaml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | exclude: 4 | - ^lib/src/sdk/proto/ 5 | -------------------------------------------------------------------------------- /build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | -------------------------------------------------------------------------------- /example/attach_detach_context/README.md: -------------------------------------------------------------------------------- 1 | # Attach Detach Context Example 2 | 3 | This example demonstrates context propagation using the attach/detach context APIs. 4 | 5 | The example produces two traces represented by the following diagram: 6 | 7 | ```mermaid 8 | flowchart LR 9 | r1[Root 1 Span] --> c[Child Span] 10 | c --> g1[Grandchild 1 Span] 11 | c --> g2[Grandchild 2 Span] 12 | r2[Root 2 Span] 13 | ``` 14 | -------------------------------------------------------------------------------- /example/attach_detach_context/attach_detach_context.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/api.dart'; 5 | import 'package:opentelemetry/sdk.dart' 6 | show ConsoleExporter, SimpleSpanProcessor, TracerProviderBase; 7 | 8 | void main() { 9 | final tp = TracerProviderBase( 10 | processors: [SimpleSpanProcessor(ConsoleExporter())]), 11 | tracer = tp.getTracer('instrumentation-name'); 12 | 13 | // Attach the root span to the current context (the root context) making the 14 | // span the current span until it is detached. 15 | final rootToken = Context.attach( 16 | contextWithSpan(Context.current, tracer.startSpan('root-1')..end())); 17 | 18 | // Starting a child span will automatically parent the span to the span held 19 | // by the attached context. 20 | final child1 = tracer.startSpan('child')..end(); 21 | final context = contextWithSpan(Context.current, child1); 22 | 23 | // Starting a span doesn't automatically attach the span. So to make the 24 | // parent span actually parent a span, its context needs to be attached. 25 | final childToken = Context.attach(context); 26 | tracer.startSpan('grandchild-1').end(); 27 | if (!Context.detach(childToken)) { 28 | throw Exception('Failed to detach context'); 29 | } 30 | 31 | // Alternatively, manually specifying the desired parent context avoids the 32 | // need to attach and detach the context. 33 | tracer.startSpan('grandchild-2', context: context).end(); 34 | 35 | if (!Context.detach(rootToken)) { 36 | throw Exception('Failed to detach context'); 37 | } 38 | 39 | // Since the previous root span context was detached, spans will no longer be 40 | // automatically parented. 41 | tracer.startSpan('root-2').end(); 42 | } 43 | -------------------------------------------------------------------------------- /example/main.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'dart:async'; 5 | 6 | import 'package:opentelemetry/api.dart'; 7 | import 'package:opentelemetry/sdk.dart'; 8 | 9 | /// Applications use a tracer to create sets of spans that constitute a trace. 10 | /// There are several components needed to get a tracer: 11 | 12 | /// An exporter is needed to send ended spans to a backend such as the dev 13 | /// console. 14 | final exporter = ConsoleExporter(); 15 | 16 | /// A processor is needed to handle starting and ending spans. The 17 | /// [SimpleSpanProcessor] doesn't do any processing and immediately forwards 18 | /// ended spans to the exporter. This is in contrast to the [BatchSpanProcessor] 19 | /// which will batch spans together before forwarding them to the exporter. 20 | final processor = SimpleSpanProcessor(exporter); 21 | 22 | /// Finally, a [TracerProvider] is configured with any number of processors. 23 | /// [TracerProviderBase] is suitable for applications run in the VM whereas 24 | /// a WebTracerProvider is suited for applications transpiled to JavaScript to 25 | /// run in a browser. 26 | final provider = TracerProviderBase(processors: [processor]); 27 | 28 | // The [TracerProvider] is the mechanism used to get a [Tracer]. 29 | final tracer = provider.getTracer('instrumentation-name'); 30 | 31 | /// Demonstrates creating a trace with a parent and child span. 32 | void main() async { 33 | // The current active context is available via a static getter. 34 | var context = Context.current; 35 | 36 | // A trace starts with a root span which has no parent. 37 | final parentSpan = tracer.startSpan('parent-span'); 38 | 39 | // A new context can be created in order to propagate context manually. 40 | context = contextWithSpan(context, parentSpan); 41 | 42 | // The [traceContext] and [traceContextSync] functions will automatically 43 | // propagate context, capture errors, and end the span. 44 | await traceContext('child-span', (_) { 45 | tracer.startSpan('grandchild-span').end(); 46 | return Future.delayed(Duration(milliseconds: 100)); 47 | }, context: context, tracer: tracer); 48 | 49 | // Spans must be ended or they will not be exported. 50 | parentSpan.end(); 51 | } 52 | -------------------------------------------------------------------------------- /example/sampling.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:collection/collection.dart'; 5 | import 'package:opentelemetry/api.dart' 6 | show 7 | Attribute, 8 | Context, 9 | SpanKind, 10 | SpanLink, 11 | TraceId, 12 | registerGlobalTracerProvider, 13 | spanContextFromContext; 14 | import 'package:opentelemetry/sdk.dart' 15 | show 16 | ConsoleExporter, 17 | Decision, 18 | ParentBasedSampler, 19 | ReadOnlySpan, 20 | ReadWriteSpan, 21 | Sampler, 22 | SamplingResult, 23 | SimpleSpanProcessor, 24 | TracerProviderBase; 25 | 26 | final Attribute samplingOffAttribute = 27 | Attribute.fromInt('sampling.priority', 0); 28 | 29 | class SpanSamplingPrioritySampler implements Sampler { 30 | @override 31 | SamplingResult shouldSample( 32 | Context parentContext, 33 | TraceId traceId, 34 | String name, 35 | SpanKind spanKind, 36 | List attributes, 37 | List links) { 38 | final decision = attributes.firstWhereOrNull((element) => 39 | element.key == 'sampling.priority' && element.value == 0) != 40 | null 41 | ? Decision.recordOnly 42 | : Decision.recordAndSample; 43 | 44 | return SamplingResult( 45 | decision, attributes, spanContextFromContext(parentContext).traceState); 46 | } 47 | 48 | @override 49 | String get description => 'SpanSamplingPrioritySampler'; 50 | } 51 | 52 | class PrintingSpanProcessor extends SimpleSpanProcessor { 53 | PrintingSpanProcessor(super.exporter); 54 | 55 | @override 56 | void onStart(ReadWriteSpan span, Context parentContext) { 57 | print('Span started: ${span.name}'); 58 | super.onStart(span, parentContext); 59 | } 60 | 61 | @override 62 | void onEnd(ReadOnlySpan span) { 63 | print('Span ended: ${span.name}'); 64 | super.onEnd(span); 65 | } 66 | 67 | @override 68 | void shutdown() { 69 | print('Shutting down'); 70 | super.shutdown(); 71 | } 72 | 73 | @override 74 | void forceFlush() {} 75 | } 76 | 77 | void main(List args) async { 78 | final sampler = ParentBasedSampler(SpanSamplingPrioritySampler()); 79 | final tp = TracerProviderBase( 80 | processors: [PrintingSpanProcessor(ConsoleExporter())], sampler: sampler); 81 | registerGlobalTracerProvider(tp); 82 | 83 | final tracer = tp.getTracer('instrumentation-name'); 84 | 85 | tracer.startSpan('span-not-sampled', attributes: [ 86 | samplingOffAttribute, 87 | ]).end(); 88 | tracer.startSpan('span-sampled').end(); 89 | 90 | tp.shutdown(); 91 | } 92 | -------------------------------------------------------------------------------- /example/stream_context/README.md: -------------------------------------------------------------------------------- 1 | # Stream Context Propagation Example 2 | 3 | This example demonstrates context propagation over a `Stream` or `StreamController`. 4 | 5 | The example produces three traces represented by the following diagram: 6 | 7 | ```mermaid 8 | flowchart LR 9 | subgraph a[Zone A] 10 | direction LR 11 | ap[Zone A Parent Span] --> ac[Zone A Child Span] 12 | r[New Root Span] 13 | ec[Event Child Span] 14 | end 15 | ep[Event Parent Span] --> ec 16 | ``` 17 | 18 | Note: When registering a stream listener, A stream listener callback is executed in the Zone where the callback was registered. This can lead to long running traces if the stream gets an event long after it was registered. To avoid this issue, the `trace` and `traceSync` functions will attach and detach the span they create before and after invoking the callback given to them. 19 | -------------------------------------------------------------------------------- /example/stream_context/stream_context.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'dart:async'; 5 | 6 | import 'package:opentelemetry/api.dart'; 7 | import 'package:opentelemetry/sdk.dart' 8 | show ConsoleExporter, SimpleSpanProcessor, TracerProviderBase; 9 | 10 | mixin EventContext { 11 | final Context context = Context.current; 12 | } 13 | 14 | class MyEvent with EventContext { 15 | MyEvent(); 16 | } 17 | 18 | void main() async { 19 | final tp = TracerProviderBase( 20 | processors: [SimpleSpanProcessor(ConsoleExporter())]), 21 | tracer = tp.getTracer('instrumentation-name'); 22 | 23 | final controller = StreamController(); 24 | 25 | traceSync('zone-a-parent', () { 26 | tracer.startSpan('zone-a-child').end(); 27 | 28 | controller.stream.listen((e) { 29 | tracer.startSpan('new-root').end(); 30 | tracer.startSpan('event-child', context: e.context).end(); 31 | }); 32 | }, tracer: tracer); 33 | 34 | traceSync('event-parent', () => controller.add(MyEvent()), tracer: tracer); 35 | 36 | await controller.close(); 37 | } 38 | -------------------------------------------------------------------------------- /example/w3c_context_propagation.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/api.dart'; 5 | import 'package:opentelemetry/sdk.dart' 6 | show ConsoleExporter, SimpleSpanProcessor, TracerProviderBase; 7 | 8 | class MapSetter implements TextMapSetter { 9 | @override 10 | void set(Map carrier, String key, String value) { 11 | carrier[key] = value; 12 | } 13 | } 14 | 15 | class MapGetter implements TextMapGetter { 16 | @override 17 | String? get(Map? carrier, String key) { 18 | return (carrier == null) ? null : carrier[key]; 19 | } 20 | 21 | @override 22 | Iterable keys(Map carrier) { 23 | return carrier.keys.map((key) => key.toString()); 24 | } 25 | } 26 | 27 | void main(List args) async { 28 | final tp = 29 | TracerProviderBase(processors: [SimpleSpanProcessor(ConsoleExporter())]); 30 | registerGlobalTracerProvider(tp); 31 | 32 | final tmp = W3CTraceContextPropagator(); 33 | registerGlobalTextMapPropagator(tmp); 34 | 35 | final span = tp.getTracer('instrumentation-name').startSpan('test-span-0'); 36 | final carrier = {}; 37 | tmp.inject(contextWithSpan(Context.current, span), carrier, MapSetter()); 38 | await test(carrier); 39 | span.end(); 40 | } 41 | 42 | Future test(Map carrier) async { 43 | globalTracerProvider 44 | .getTracer('instrumentation-name') 45 | .startSpan('test-span-1', 46 | context: globalTextMapPropagator.extract( 47 | Context.current, carrier, MapGetter())) 48 | .end(); 49 | } 50 | -------------------------------------------------------------------------------- /lib/api.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | export 'src/api/common/attribute.dart' show Attribute; 5 | export 'src/api/common/resource_attributes.dart' show ResourceAttributes; 6 | export 'src/api/common/semantic_attributes.dart' show SemanticAttributes; 7 | export 'src/api/context/context.dart' 8 | show 9 | Context, 10 | ContextKey, 11 | contextWithSpan, 12 | contextWithSpanContext, 13 | spanContextFromContext, 14 | spanFromContext, 15 | zone; 16 | export 'src/api/context/context_manager.dart' 17 | show globalContextManager, registerGlobalContextManager; 18 | export 'src/api/exporters/span_exporter.dart' show SpanExporter; 19 | export 'src/api/instrumentation_library.dart' show InstrumentationLibrary; 20 | export 'src/api/open_telemetry.dart' 21 | show 22 | globalTextMapPropagator, 23 | globalTracerProvider, 24 | registerGlobalTextMapPropagator, 25 | registerGlobalTracerProvider, 26 | trace, 27 | traceContext, 28 | traceSync, 29 | traceContextSync; 30 | export 'src/api/propagation/extractors/text_map_getter.dart' show TextMapGetter; 31 | export 'src/api/propagation/injectors/text_map_setter.dart' show TextMapSetter; 32 | export 'src/api/propagation/text_map_propagator.dart' show TextMapPropagator; 33 | export 'src/api/propagation/w3c_trace_context_propagator.dart' 34 | show W3CTraceContextPropagator; 35 | export 'src/api/span_processors/span_processor.dart' show SpanProcessor; 36 | export 'src/api/trace/id_generator.dart' show IdGenerator; 37 | export 'src/api/trace/span.dart' show Span, SpanKind; 38 | export 'src/api/trace/span_context.dart' show SpanContext; 39 | export 'src/api/trace/span_event.dart' show SpanEvent; 40 | export 'src/api/trace/span_id.dart' show SpanId; 41 | export 'src/api/trace/span_link.dart' show SpanLink; 42 | export 'src/api/trace/span_status.dart' show SpanStatus, StatusCode; 43 | export 'src/api/trace/trace_flags.dart' show TraceFlags; 44 | export 'src/api/trace/trace_id.dart' show TraceId; 45 | export 'src/api/trace/trace_state.dart' show TraceState; 46 | export 'src/api/trace/tracer.dart' show Tracer; 47 | export 'src/api/trace/tracer_provider.dart' show TracerProvider; 48 | -------------------------------------------------------------------------------- /lib/sdk.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | export 'src/sdk/instrumentation_library.dart' show InstrumentationLibrary; 5 | export 'src/sdk/common/attributes.dart' show Attributes; 6 | export 'src/sdk/common/instrumentation_scope.dart' show InstrumentationScope; 7 | export 'src/sdk/resource/resource.dart' show Resource; 8 | export 'src/sdk/time_providers/datetime_time_provider.dart' 9 | show DateTimeTimeProvider; 10 | export 'src/sdk/time_providers/time_provider.dart' show TimeProvider; 11 | export 'src/sdk/trace/exporters/span_exporter.dart' show SpanExporter; 12 | export 'src/sdk/trace/exporters/collector_exporter.dart' show CollectorExporter; 13 | export 'src/sdk/trace/exporters/console_exporter.dart' show ConsoleExporter; 14 | export 'src/sdk/trace/id_generator.dart' show IdGenerator; 15 | export 'src/sdk/trace/sampling/always_off_sampler.dart' show AlwaysOffSampler; 16 | export 'src/sdk/trace/sampling/always_on_sampler.dart' show AlwaysOnSampler; 17 | export 'src/sdk/trace/sampling/parent_based_sampler.dart' 18 | show ParentBasedSampler; 19 | export 'src/sdk/trace/sampling/sampler.dart' show Sampler; 20 | export 'src/sdk/trace/sampling/sampling_result.dart' 21 | show Decision, SamplingResult; 22 | export 'src/sdk/trace/read_only_span.dart' show ReadOnlySpan; 23 | export 'src/sdk/trace/read_write_span.dart' show ReadWriteSpan; 24 | export 'src/sdk/trace/span_limits.dart' show SpanLimits; 25 | export 'src/sdk/trace/span_processors/span_processor.dart' show SpanProcessor; 26 | export 'src/sdk/trace/span_processors/batch_processor.dart' 27 | show BatchSpanProcessor; 28 | export 'src/sdk/trace/span_processors/simple_processor.dart' 29 | show SimpleSpanProcessor; 30 | export 'src/sdk/trace/tracer_provider.dart' show TracerProviderBase; 31 | -------------------------------------------------------------------------------- /lib/src/api/common/attribute.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | /// A representation of a single piece of metadata attached to trace span. 5 | class Attribute { 6 | final String key; 7 | final Object value; 8 | 9 | /// Create an Attribute from a String value. 10 | Attribute.fromString(this.key, String this.value); 11 | 12 | /// Create an Attribute from a boolean value. 13 | // ignore: avoid_positional_boolean_parameters 14 | Attribute.fromBoolean(this.key, bool this.value); 15 | 16 | /// Create an Attribute from a double-precision floating-point value. 17 | Attribute.fromDouble(this.key, double this.value); 18 | 19 | /// Create an Attribute from an integer value. 20 | Attribute.fromInt(this.key, int this.value); 21 | 22 | /// Create an Attribute from a list of String values. 23 | Attribute.fromStringList(this.key, List this.value); 24 | 25 | /// Create an Attribute from a list of boolean values. 26 | Attribute.fromBooleanList(this.key, List this.value); 27 | 28 | /// Create an Attribute from a list of double-precision floating-point values. 29 | Attribute.fromDoubleList(this.key, List this.value); 30 | 31 | /// Create an Attribute from a list of integer values. 32 | Attribute.fromIntList(this.key, List this.value); 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/api/common/resource_attributes.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | /// Common OpenTelemetry attribute keys for resource information. 5 | /// 6 | /// Keys should follow OpenTelemetry's attribute semantic conventions: 7 | /// https://github.com/open-telemetry/opentelemetry-specification/tree/main/specification/resource/semantic_conventions 8 | class ResourceAttributes { 9 | /// Name of the deployment environment or tier. 10 | static const String deploymentEnvironment = 'deployment.environment'; 11 | 12 | /// Logical name of the service. 13 | static const String serviceName = 'service.name'; 14 | 15 | /// A namespace for `service.name`. 16 | static const String serviceNamespace = 'service.namespace'; 17 | 18 | /// The string ID of the service instance. 19 | static const String serviceInstanceId = 'service.instance.id'; 20 | 21 | /// The version string of the service API or implementation. 22 | static const String serviceVersion = 'service.version'; 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/api/context/context_manager.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'context.dart' show Context; 5 | 6 | /// The [ContextManager] is responsible for managing the current [Context]. 7 | /// Different implementations of [ContextManager] can be registered to use 8 | /// different underlying storage mechanisms. 9 | @Deprecated('This class will be removed in 0.19.0 without replacement.') 10 | class ContextManager { 11 | @Deprecated( 12 | 'This method will be removed in 0.19.0. Use the API global function ' 13 | '[root] instead.') 14 | Context get root => Context.root; 15 | 16 | @Deprecated( 17 | 'This method will be removed in 0.19.0. Use the API global function ' 18 | '[active] instead.') 19 | Context get active => Context.current; 20 | } 21 | 22 | final ContextManager _noopContextManager = ContextManager(); 23 | ContextManager _contextManager = _noopContextManager; 24 | 25 | @Deprecated('This method will be removed in 0.19.0. Use the API global ' 26 | 'function [active] instead.') 27 | ContextManager get globalContextManager => _contextManager; 28 | 29 | @Deprecated('This method will be removed in 0.19.0 without replacement.') 30 | void registerGlobalContextManager(ContextManager contextManager) { 31 | if (_contextManager != _noopContextManager) { 32 | throw StateError( 33 | 'Global context manager is already registered, registerContextManager ' 34 | 'must be called only once.'); 35 | } 36 | 37 | _contextManager = contextManager; 38 | } 39 | -------------------------------------------------------------------------------- /lib/src/api/context/map_context.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:meta/meta.dart'; 5 | 6 | import '../../../api.dart'; 7 | 8 | MapContext createMapContext() => MapContext._(); 9 | 10 | class MapContext implements Context { 11 | final Map _contextMap = {}; 12 | 13 | MapContext._(); 14 | 15 | /// Returns the value from this context identified by [key], or null if no 16 | /// such value is set. 17 | @override 18 | T? getValue(ContextKey key) => _contextMap[key] as T?; 19 | 20 | /// Returns a new context created from this one with the given key/value pair 21 | /// set. 22 | /// 23 | /// If [key] was already set in this context, it will be overridden. The rest 24 | /// of the context values will be inherited. 25 | @override 26 | MapContext setValue(ContextKey key, Object value) { 27 | final newContext = createMapContext(); 28 | newContext._contextMap.addAll(_contextMap); 29 | newContext._contextMap[key] = value; 30 | return newContext; 31 | } 32 | 33 | /// Returns a new [MapContext] created from this one with the given [Span] 34 | /// set. 35 | @override 36 | Context withSpan(Span span) => contextWithSpan(this, span); 37 | 38 | /// Execute a function, this is a no-op for [MapContext]. 39 | @override 40 | R execute(R Function() fn) => fn(); 41 | 42 | /// Get the [Span] attached to this [MapContext], or an invalid, [Span] if no such 43 | /// [Span] exists. 44 | @override 45 | Span get span => spanFromContext(this); 46 | 47 | /// Call [fn] with this [MapContext] and return its result. 48 | @experimental 49 | R run(R Function(Context context) fn) => fn(this); 50 | 51 | /// Get the [SpanContext] from this [MapContext], or an invalid [SpanContext] if no such 52 | /// [SpanContext] exists. 53 | @override 54 | SpanContext get spanContext => spanContextFromContext(this); 55 | } 56 | -------------------------------------------------------------------------------- /lib/src/api/context/noop_context_manager.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' show Context; 5 | import '../../experimental_api.dart' show ContextManager; 6 | import 'map_context.dart' show createMapContext; 7 | 8 | final _root = createMapContext(); 9 | 10 | @Deprecated('This class will be removed in 0.19.0 without replacement.') 11 | class NoopContextManager implements ContextManager { 12 | @override 13 | Context get root => _root; 14 | 15 | @override 16 | Context get active => _root; 17 | } 18 | -------------------------------------------------------------------------------- /lib/src/api/context/zone_context.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | /// The OpenTelemetry SDKs require a mechanism for propagating context and the 5 | /// OpenTelemetry specification outlines the requirements for this context 6 | /// implementation: https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/context/context.md 7 | /// 8 | /// The spec notes that "languages are expected to use the single, widely used 9 | /// Context implementation if one exists for them." Fortunately, the Dart SDK 10 | /// provides just that with [Zone] - a representation of "an environment that 11 | /// remains stable across asynchronous calls." [Zone] also meets the core 12 | /// requirements of immutability and being able to read and write values: 13 | /// 14 | /// - Immutable: a Zone's values are set when the Zone is created and cannot be 15 | /// changed afterwards. 16 | /// - Reading and writing values: a Zone implements the `[]` operator, allowing 17 | /// values to be read directly from it like a [Map], and writing values is 18 | /// possible only by forking another Zone and providing values to add/override 19 | /// (the rest of the values will be inherited from the forked Zone). 20 | /// 21 | /// This library provides a simple abstraction over [Zone] for the purpose of 22 | /// implementing the rest of the Context specification. OpenTelemetry SDKs and 23 | /// instrumentation libraries should use this [ZoneContext] API instead of a [Zone] 24 | /// directly. Other users should usually not interact with Context at all and 25 | /// should instead manipulate it through cross-cutting concerns APIs provided by 26 | /// OpenTelemetry SDKs. 27 | import 'dart:async' show Zone; 28 | 29 | import 'package:meta/meta.dart'; 30 | 31 | import '../../../api.dart'; 32 | 33 | ZoneContext createZoneContext(Zone zone) => ZoneContext._(zone); 34 | 35 | class ZoneContext implements Context { 36 | final Zone _zone; 37 | 38 | ZoneContext._(this._zone); 39 | 40 | /// Returns the value from this context identified by [key], or null if no 41 | /// such value is set. 42 | @override 43 | T? getValue(ContextKey key) => _zone[key]; 44 | 45 | /// Returns a new context created from this one with the given key/value pair 46 | /// set. 47 | /// 48 | /// If [key] was already set in this context, it will be overridden. The rest 49 | /// of the context values will be inherited. 50 | @override 51 | Context setValue(ContextKey key, Object value) => 52 | createZoneContext(_zone.fork(zoneValues: {key: value})); 53 | 54 | /// Returns a new [ZoneContext] created from this one with the given [Span] 55 | /// set. 56 | @override 57 | Context withSpan(Span span) => contextWithSpan(this, span); 58 | 59 | /// Execute a function [fn] within this [ZoneContext] and return its result. 60 | @override 61 | R execute(R Function() fn) => _zone.run(() => fn()); 62 | 63 | /// Call [fn] in this [ZoneContext]'s [Zone] and return its result. 64 | @experimental 65 | R run(R Function(Context context) fn) => _zone.run(() => fn(this)); 66 | 67 | /// Get the [Span] attached to this [ZoneContext], or an invalid, [Span] if no such 68 | /// [Span] exists. 69 | @override 70 | Span get span => spanFromContext(this); 71 | 72 | /// Get the [SpanContext] from this [ZoneContext], or an invalid [SpanContext] if no such 73 | /// [SpanContext] exists. 74 | @override 75 | SpanContext get spanContext => spanContextFromContext(this); 76 | } 77 | -------------------------------------------------------------------------------- /lib/src/api/context/zone_context_manager.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'dart:async'; 5 | 6 | import 'context.dart' show Context; 7 | import 'context_manager.dart' show ContextManager; 8 | import 'zone_context.dart' show createZoneContext; 9 | 10 | @Deprecated('This class will be removed in 0.19.0 without replacement.') 11 | class ZoneContextManager implements ContextManager { 12 | @override 13 | Context get root => createZoneContext(Zone.root); 14 | 15 | @override 16 | Context get active => createZoneContext(Zone.current); 17 | } 18 | -------------------------------------------------------------------------------- /lib/src/api/exporters/span_exporter.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' as api; 5 | 6 | @Deprecated( 7 | 'This class will be moved to the SDK package in 0.19.0. Use [SpanExporter] from SDK instead.') 8 | abstract class SpanExporter { 9 | void export(List spans); 10 | 11 | void forceFlush(); 12 | 13 | void shutdown(); 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/api/instrumentation_library.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | /// Represents versioning metadata for this library within applications 5 | /// which use multiple implementations of OpenTelemetry. 6 | // See https://github.com/open-telemetry/oteps/blob/main/text/0083-component.md#instrumentationlibrary 7 | @Deprecated( 8 | 'This class will be removed in 0.19.0. Use [InstrumentationScope] from the sdk instead.') 9 | abstract class InstrumentationLibrary { 10 | String get name; 11 | String get version; 12 | } 13 | -------------------------------------------------------------------------------- /lib/src/api/logs/log_record.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | enum Severity { 5 | unspecified, 6 | trace, 7 | trace2, 8 | trace3, 9 | trace4, 10 | debug, 11 | debug2, 12 | debug3, 13 | debug4, 14 | info, 15 | info2, 16 | info3, 17 | info4, 18 | warn, 19 | warn2, 20 | warn3, 21 | warn4, 22 | error, 23 | error2, 24 | error3, 25 | error4, 26 | fatal, 27 | fatal2, 28 | fatal3, 29 | fatal4, 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/api/logs/logger.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' as api; 5 | import '../../../sdk.dart' as sdk; 6 | import 'log_record.dart'; 7 | 8 | abstract class Logger { 9 | void emit({ 10 | sdk.Attributes? attributes, 11 | api.Context? context, 12 | dynamic body, 13 | DateTime? observedTimestamp, 14 | Severity? severityNumber, 15 | String? severityText, 16 | DateTime? timeStamp, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/api/logs/logger_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/api.dart'; 5 | import 'package:opentelemetry/src/api/logs/logger.dart'; 6 | 7 | abstract class LoggerProvider { 8 | /// Gets or creates a [Logger] instance. 9 | /// 10 | /// The meter is identified by the combination of [name], [version], 11 | /// [schemaUrl] and [attributes]. The [name] SHOULD uniquely identify the 12 | /// instrumentation scope, such as the instrumentation library 13 | /// (e.g. io.opentelemetry.contrib.mongodb), package, module or class name. 14 | /// The [version] specifies the version of the instrumentation scope if the 15 | /// scope has a version (e.g. a library version). The [schemaUrl] identifies 16 | /// the schema this provider adheres to. The [attributes] specifies 17 | /// attributes to associate with emitted telemetry. 18 | Logger get( 19 | String name, { 20 | String version = '', 21 | String schemaUrl = '', 22 | List attributes = const [], 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /lib/src/api/logs/noop/noop_logger.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/src/api/context/context.dart'; 5 | import 'package:opentelemetry/src/api/logs/log_record.dart'; 6 | import 'package:opentelemetry/src/api/logs/logger.dart'; 7 | import 'package:opentelemetry/src/sdk/common/attributes.dart'; 8 | 9 | class NoopLogger implements Logger { 10 | const NoopLogger(); 11 | 12 | @override 13 | void emit({ 14 | Attributes? attributes, 15 | Context? context, 16 | dynamic body, 17 | DateTime? observedTimestamp, 18 | Severity? severityNumber, 19 | String? severityText, 20 | DateTime? timeStamp, 21 | }) {} 22 | } 23 | -------------------------------------------------------------------------------- /lib/src/api/logs/noop/noop_logger_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/src/api/common/attribute.dart'; 5 | import 'package:opentelemetry/src/api/logs/logger.dart'; 6 | import 'package:opentelemetry/src/api/logs/logger_provider.dart'; 7 | import 'package:opentelemetry/src/api/logs/noop/noop_logger.dart'; 8 | 9 | class NoopLoggerProvider implements LoggerProvider { 10 | @override 11 | Logger get( 12 | String name, { 13 | String version = '', 14 | String schemaUrl = '', 15 | List attributes = const [], 16 | }) => 17 | const NoopLogger(); 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/api/metrics/counter.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/api.dart'; 5 | 6 | abstract class Counter { 7 | /// Records a value with a set of attributes. 8 | /// 9 | /// [value] The increment amount. MUST be non-negative. 10 | /// [attributes] A set of attributes to associate with the value. 11 | /// [context] The explicit context to associate with this measurement. 12 | void add(T value, {List attributes, Context context}); 13 | } 14 | -------------------------------------------------------------------------------- /lib/src/api/metrics/meter.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/src/experimental_api.dart'; 5 | 6 | abstract class Meter { 7 | /// Creates a new [Counter] instrument named [name]. Additional details about 8 | /// this metric can be captured in [description] and units can be specified in 9 | /// [unit]. 10 | /// 11 | /// See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/metrics/api.md#instrument-naming-rule 12 | Counter createCounter(String name, 13 | {String description, String unit}); 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/api/metrics/meter_key.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:collection/collection.dart'; 5 | import 'package:quiver/core.dart'; 6 | import 'package:opentelemetry/api.dart'; 7 | 8 | /// A class that acts as a unique key for a given Meter configuration. 9 | class MeterKey { 10 | final String name; 11 | final String version; 12 | final String schemaUrl; 13 | final List attributes; 14 | 15 | MeterKey(this.name, this.version, this.schemaUrl, this.attributes); 16 | 17 | @override 18 | bool operator ==(Object other) => 19 | other is MeterKey && 20 | name == other.name && 21 | version == other.version && 22 | schemaUrl == other.schemaUrl && 23 | const ListEquality().equals(attributes, other.attributes); 24 | 25 | @override 26 | int get hashCode => hash4(name, version, schemaUrl, attributes); 27 | } 28 | -------------------------------------------------------------------------------- /lib/src/api/metrics/meter_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/api.dart'; 5 | import 'package:opentelemetry/src/experimental_api.dart'; 6 | 7 | /// A registry for creating named [Meter]s. 8 | abstract class MeterProvider { 9 | /// Gets or creates a [Meter] instance. 10 | /// 11 | /// The meter is identified by the combination of [name], [version], 12 | /// [schemaUrl] and [attributes]. The [name] SHOULD uniquely identify the 13 | /// instrumentation scope, such as the instrumentation library 14 | /// (e.g. io.opentelemetry.contrib.mongodb), package, module or class name. 15 | /// The [version] specifies the version of the instrumentation scope if the 16 | /// scope has a version (e.g. a library version). The [schemaUrl] identifies 17 | /// the schema this provider adheres to. The [attributes] specifies 18 | /// attributes to associate with emitted telemetry. 19 | Meter get(String name, 20 | {String version = '', 21 | String schemaUrl = '', 22 | List attributes = const []}); 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/api/metrics/noop/noop_counter.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/api.dart'; 5 | import 'package:opentelemetry/src/experimental_api.dart'; 6 | 7 | /// A no-op instance of a [Counter] 8 | class NoopCounter extends Counter { 9 | @override 10 | void add(T value, {List? attributes, Context? context}) {} 11 | } 12 | -------------------------------------------------------------------------------- /lib/src/api/metrics/noop/noop_meter.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/src/api/metrics/noop/noop_counter.dart'; 5 | import 'package:opentelemetry/src/experimental_api.dart'; 6 | 7 | /// A no-op instance of a [Meter] 8 | class NoopMeter implements Meter { 9 | @override 10 | Counter createCounter(String name, 11 | {String? description, String? unit}) { 12 | return NoopCounter(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/api/metrics/noop/noop_meter_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/api.dart'; 5 | import 'package:opentelemetry/src/experimental_api.dart'; 6 | 7 | /// A noop registry for creating named [Meter]s. 8 | class NoopMeterProvider implements MeterProvider { 9 | static final _noopMeter = NoopMeter(); 10 | 11 | @override 12 | Meter get(String name, 13 | {String version = '', 14 | String schemaUrl = '', 15 | List attributes = const []}) { 16 | return _noopMeter; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/api/propagation/extractors/text_map_getter.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../../api.dart' as api; 5 | 6 | /// Interface that allows a [api.TextMapPropagator] to read propagated fields from a carrier. 7 | abstract class TextMapGetter { 8 | /// Returns all the keys in the given carrier. 9 | Iterable keys(C carrier); 10 | 11 | /// Returns the first value of the given propagation [key] or returns null. 12 | String? get(C carrier, String key); 13 | } 14 | -------------------------------------------------------------------------------- /lib/src/api/propagation/injectors/text_map_setter.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../../api.dart' as api; 5 | 6 | /// Class that allows a [api.TextMapPropagator] to set propagated fields into a carrier. 7 | abstract class TextMapSetter { 8 | /// Sets [value] for [key] on [carrier]. 9 | void set(C carrier, String key, String value); 10 | } 11 | -------------------------------------------------------------------------------- /lib/src/api/propagation/noop_text_map_propagator.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' as api; 5 | 6 | class NoopTextMapPropagator implements api.TextMapPropagator { 7 | @override 8 | api.Context extract( 9 | api.Context context, dynamic carrier, api.TextMapGetter getter) => 10 | context; 11 | 12 | @override 13 | void inject(api.Context context, dynamic carrier, api.TextMapSetter setter) {} 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/api/propagation/text_map_propagator.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' as api; 5 | 6 | /// A class responsible for performing the injection and extraction of a 7 | /// cross-cutting concern value as string key/values pairs into carriers that 8 | /// travel across process boundaries. 9 | /// 10 | /// See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/context/api-propagators.md#textmap-propagator 11 | /// for full specification. 12 | abstract class TextMapPropagator { 13 | void inject(api.Context context, C carrier, api.TextMapSetter setter); 14 | 15 | api.Context extract( 16 | api.Context context, C carrier, api.TextMapGetter getter); 17 | } 18 | -------------------------------------------------------------------------------- /lib/src/api/propagation/w3c_trace_context_propagator.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | import '../../../api.dart' as api; 4 | import '../../experimental_api.dart'; 5 | 6 | class W3CTraceContextPropagator implements api.TextMapPropagator { 7 | static const String _traceVersion = '00'; 8 | static const String _traceParentHeaderKey = 'traceparent'; 9 | static const String _traceStateHeaderKey = 'tracestate'; 10 | static const String _traceVersionFieldKey = 'version'; 11 | static const String _traceIdFieldKey = 'traceid'; 12 | static const String _parentIdFieldKey = 'parentid'; 13 | static const String _traceFlagsFieldKey = 'traceflags'; 14 | 15 | // See https://www.w3.org/TR/trace-context/#traceparent-header-field-values 16 | // for trace parent header specification. 17 | static final RegExp traceParentHeaderRegEx = 18 | RegExp('^(?<$_traceVersionFieldKey>[0-9a-f]{2})-' 19 | '(?<$_traceIdFieldKey>[0-9a-f]{${api.TraceId.sizeBits}})-' 20 | '(?<$_parentIdFieldKey>[0-9a-f]{${api.SpanId.sizeBits}})-' 21 | '(?<$_traceFlagsFieldKey>[0-9a-f]{${2}})\$'); 22 | 23 | @override 24 | api.Context extract( 25 | api.Context context, dynamic carrier, api.TextMapGetter getter) { 26 | final traceParentHeader = getter.get(carrier, _traceParentHeaderKey); 27 | if (traceParentHeader == null) { 28 | // Carrier did not contain a trace header. Do nothing. 29 | return context; 30 | } 31 | 32 | final parentHeaderMatch = 33 | traceParentHeaderRegEx.firstMatch(traceParentHeader); 34 | 35 | if (parentHeaderMatch == null) { 36 | // Encountered a malformed or unknown trace header. Do nothing. 37 | return context; 38 | } 39 | 40 | final parentHeaderFields = Map.fromIterable( 41 | parentHeaderMatch.groupNames, 42 | key: (element) => element.toString(), 43 | value: (element) => parentHeaderMatch.namedGroup(element)!); 44 | 45 | final traceIdHeader = parentHeaderFields[_traceIdFieldKey]; 46 | final traceId = (traceIdHeader != null) 47 | ? api.TraceId.fromString(traceIdHeader) 48 | : api.TraceId.invalid(); 49 | final parentIdHeader = parentHeaderFields[_parentIdFieldKey]; 50 | final parentId = (parentIdHeader != null) 51 | ? api.SpanId.fromString(parentIdHeader) 52 | : api.SpanId.invalid(); 53 | final traceFlagsHeader = parentHeaderFields[_traceFlagsFieldKey]; 54 | final traceFlags = (traceFlagsHeader != null) 55 | ? int.parse(traceFlagsHeader, radix: 16) 56 | : api.TraceFlags.none; 57 | final traceStateHeader = getter.get(carrier, _traceStateHeaderKey); 58 | final traceState = (traceStateHeader != null) 59 | ? api.TraceState.fromString(traceStateHeader) 60 | : api.TraceState.empty(); 61 | 62 | return api.contextWithSpan( 63 | context, 64 | NonRecordingSpan( 65 | api.SpanContext.remote(traceId, parentId, traceFlags, traceState))); 66 | } 67 | 68 | @override 69 | void inject(api.Context context, dynamic carrier, api.TextMapSetter setter) { 70 | final spanContext = api.spanContextFromContext(context); 71 | 72 | setter 73 | ..set( 74 | carrier, 75 | _traceParentHeaderKey, 76 | '$_traceVersion-${spanContext.traceId.toString()}-' 77 | '${spanContext.spanId.toString()}-' 78 | '${spanContext.traceFlags.toRadixString(16).padLeft(2, '0')}') 79 | ..set(carrier, _traceStateHeaderKey, spanContext.traceState.toString()); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lib/src/api/span_processors/span_processor.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' as api; 5 | 6 | @Deprecated( 7 | 'This class will be moved to the SDK package in 0.19.0. Use [SpanProcessor] from SDK instead.') 8 | abstract class SpanProcessor { 9 | void onStart(api.Span span, api.Context parentContext); 10 | 11 | void onEnd(api.Span span); 12 | 13 | void shutdown(); 14 | 15 | void forceFlush(); 16 | } 17 | -------------------------------------------------------------------------------- /lib/src/api/trace/id_generator.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | /// Generator capable of creating OTel compliant IDs. 5 | abstract class IdGenerator { 6 | /// Generate an ID for a Span. 7 | List generateSpanId(); 8 | 9 | /// Generate an ID for a trace. 10 | List generateTraceId(); 11 | } 12 | -------------------------------------------------------------------------------- /lib/src/api/trace/nonrecording_span.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:fixnum/fixnum.dart'; 5 | 6 | import '../../../api.dart' as api; 7 | 8 | /// A class representing a [api.Span] which should not be sampled or recorded. 9 | /// 10 | /// See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#wrapping-a-spancontext-in-a-span 11 | /// for more information. 12 | /// 13 | class NonRecordingSpan implements api.Span { 14 | final api.SpanId _parentSpanId = api.SpanId.invalid(); 15 | final api.SpanContext _spanContext; 16 | 17 | NonRecordingSpan(this._spanContext); 18 | 19 | @override 20 | void setAttribute(api.Attribute attribute) {} 21 | 22 | @override 23 | void setAttributes(List attributes) {} 24 | 25 | @override 26 | void end({Int64? endTime}) {} 27 | 28 | @override 29 | void setName(String _name) {} 30 | 31 | @override 32 | api.SpanId get parentSpanId => _parentSpanId; 33 | 34 | @override 35 | void setStatus(api.StatusCode status, [String? description]) {} 36 | 37 | @override 38 | api.SpanContext get spanContext => _spanContext; 39 | 40 | @override 41 | void recordException(dynamic exception, 42 | {bool escaped = false, 43 | StackTrace? stackTrace, 44 | List? attributes}) {} 45 | 46 | @override 47 | void addEvent(String name, 48 | {Int64? timestamp, List? attributes}) {} 49 | } 50 | -------------------------------------------------------------------------------- /lib/src/api/trace/noop_tracer.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:fixnum/fixnum.dart'; 5 | 6 | import '../../../api.dart'; 7 | import '../../experimental_api.dart' show NonRecordingSpan; 8 | 9 | /// A [Tracer] class which yields [NonRecordingSpan]s and no-ops for most 10 | /// operations. 11 | class NoopTracer implements Tracer { 12 | @override 13 | Span startSpan(String name, 14 | {Context? context, 15 | SpanKind? kind, 16 | List? attributes, 17 | List? links, 18 | Int64? startTime, 19 | bool newRoot = false}) { 20 | return NonRecordingSpan(context != null 21 | ? spanContextFromContext(context) 22 | : SpanContext.invalid()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/src/api/trace/noop_tracer_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' as api; 5 | import 'noop_tracer.dart'; 6 | 7 | class NoopTracerProvider implements api.TracerProvider { 8 | @override 9 | void forceFlush() {} 10 | 11 | @override 12 | api.Tracer getTracer(String name, 13 | {String version = '', 14 | String schemaUrl = '', 15 | List attributes = const []}) { 16 | return NoopTracer(); 17 | } 18 | 19 | @override 20 | void shutdown() {} 21 | } 22 | -------------------------------------------------------------------------------- /lib/src/api/trace/span.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:fixnum/fixnum.dart'; 5 | 6 | import '../../../api.dart' as api; 7 | 8 | enum SpanKind { 9 | /// Server-side handling of a synchronous RPC or other remote request. 10 | server, 11 | 12 | /// A request to a remote service. 13 | client, 14 | 15 | /// An initiator of an asynchronous request. 16 | producer, 17 | 18 | /// A handler of an asynchronous producer request. 19 | consumer, 20 | 21 | /// An internal operation within an application, as opposed to an operation with remote parents or children. 22 | internal 23 | } 24 | 25 | /// A representation of a single operation within a trace. 26 | /// 27 | /// Examples of a span might include remote procedure calls or in-process 28 | /// function calls to sub-components. A trace has a single, top-level "root" 29 | /// span that in turn may haze zero or more child Spans, which in turn may have 30 | /// children. 31 | /// 32 | /// Warning: methods may be added to this interface in minor releases. 33 | abstract class Span { 34 | /// The context associated with this span. 35 | /// 36 | /// This context is an immutable, serializable identifier for this span that 37 | /// can be used to create new child spans and remains usable even after this 38 | /// span ends. 39 | api.SpanContext get spanContext; 40 | 41 | /// The parent span id. 42 | api.SpanId get parentSpanId; 43 | 44 | /// Sets the name of the [Span]. 45 | void setName(String name); 46 | 47 | /// Sets the status to the [Span]. 48 | /// 49 | /// If used, this will override the default [Span] status. Default status code 50 | /// is [api.StatusCode.unset]. 51 | /// 52 | /// Only the value of the last call will be recorded, and implementations are 53 | /// free to ignore previous calls. 54 | void setStatus(api.StatusCode status, [String description]); 55 | 56 | /// Sets a single attribute. 57 | void setAttribute(api.Attribute attribute); 58 | 59 | /// Sets multiple attributes. 60 | void setAttributes(List attributes); 61 | 62 | /// Records a [api.SpanEvent]. 63 | void addEvent(String name, 64 | {Int64? timestamp, List attributes}); 65 | 66 | /// Marks the end of this span's execution. 67 | void end({Int64 endTime}); 68 | 69 | /// Record metadata about an exception occurring during this span. 70 | void recordException(dynamic exception, 71 | {bool escaped, StackTrace stackTrace, List attributes}); 72 | } 73 | -------------------------------------------------------------------------------- /lib/src/api/trace/span_context.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' as api; 5 | 6 | /// Representation of the context of an individual span. 7 | class SpanContext { 8 | final api.TraceId traceId; 9 | final api.SpanId spanId; 10 | final int traceFlags; 11 | final api.TraceState traceState; 12 | final bool isRemote; 13 | 14 | bool get isValid => spanId.isValid && traceId.isValid; 15 | 16 | /// Construct a [SpanContext]. 17 | SpanContext(this.traceId, this.spanId, this.traceFlags, this.traceState) 18 | : isRemote = false; 19 | 20 | /// Construct a [SpanContext] representing an operation which originated from 21 | /// a remote source. 22 | SpanContext.remote( 23 | this.traceId, this.spanId, this.traceFlags, this.traceState) 24 | : isRemote = true; 25 | 26 | /// Construct an invalid [SpanContext]. 27 | SpanContext.invalid() 28 | : spanId = api.SpanId.invalid(), 29 | traceId = api.TraceId.invalid(), 30 | traceFlags = api.TraceFlags.none, 31 | traceState = api.TraceState.empty(), 32 | isRemote = false; 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/api/trace/span_event.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:fixnum/fixnum.dart'; 5 | 6 | import '../../../api.dart' as api; 7 | 8 | /// A representation of a collection of metadata attached to a trace span. 9 | class SpanEvent { 10 | final Int64 timestamp; 11 | 12 | /// The name of the event. 13 | final String name; 14 | 15 | /// The attributes of the event. 16 | final Iterable attributes; 17 | 18 | /// Count of attributes of the event that were dropped due to collection limits 19 | final int droppedAttributesCount; 20 | 21 | SpanEvent({ 22 | required this.timestamp, 23 | required this.name, 24 | required this.attributes, 25 | this.droppedAttributesCount = 0, 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /lib/src/api/trace/span_id.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' as api; 5 | 6 | /// Class representing an ID for a single [api.Span]. 7 | /// See https://www.w3.org/TR/trace-context/#parent-id for full specification. 8 | class SpanId { 9 | static const sizeBits = 16; 10 | static const sizeBytes = 8; 11 | 12 | List _id; 13 | 14 | SpanId(this._id); 15 | SpanId.fromIdGenerator(api.IdGenerator generator) 16 | : _id = generator.generateSpanId(); 17 | SpanId.fromString(String id) : _id = [] { 18 | id = id.padLeft(api.SpanId.sizeBits, '0'); 19 | 20 | for (var i = 0; i < id.length; i += 2) { 21 | _id.add(int.parse('${id[i]}${id[i + 1]}', radix: 16)); 22 | } 23 | } 24 | SpanId.invalid() : this(List.filled(sizeBytes, 0)); 25 | SpanId.root() : this([]); 26 | 27 | /// Retrieve this SpanId as a list of byte values. 28 | List get() => _id; 29 | 30 | /// Whether this ID represents a valid [api.Span]. 31 | bool get isValid => _id.isEmpty || !_id.every((i) => i == 0); 32 | 33 | /// Retrieve this SpanId as a human-readable ID. 34 | @override 35 | String toString() => 36 | _id.map((x) => x.toRadixString(16).padLeft(2, '0')).join(); 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/api/trace/span_link.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' as api; 5 | 6 | class SpanLink { 7 | final api.SpanContext context; 8 | final List attributes; 9 | final int droppedAttributes; 10 | 11 | SpanLink(this.context, 12 | {this.attributes = const [], this.droppedAttributes = 0}); 13 | } 14 | -------------------------------------------------------------------------------- /lib/src/api/trace/span_status.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | /// The set of canonical status codes. 5 | enum StatusCode { 6 | /// The default status. 7 | unset, 8 | 9 | /// The operation contains an error. 10 | error, 11 | 12 | /// The operation has been validated by an Application developers or 13 | /// Operator to have completed successfully. 14 | ok, 15 | } 16 | 17 | /// A representation of the status of a Span. 18 | class SpanStatus { 19 | StatusCode code = StatusCode.unset; 20 | String description = ''; 21 | } 22 | -------------------------------------------------------------------------------- /lib/src/api/trace/trace_flags.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | /// A class which controls tracing flags for sampling, trace level, and so forth. 5 | /// See https://www.w3.org/TR/trace-context/#trace-flags for full specification. 6 | abstract class TraceFlags { 7 | static const int none = 0x0; 8 | static const int sampled = 0x1 << 0; 9 | } 10 | -------------------------------------------------------------------------------- /lib/src/api/trace/trace_id.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' as api; 5 | 6 | /// Class representing an ID for a single Trace. 7 | /// See https://www.w3.org/TR/trace-context/#trace-id for full specification. 8 | class TraceId { 9 | static const sizeBits = 32; 10 | static const sizeBytes = 16; 11 | 12 | List _id; 13 | 14 | TraceId(this._id); 15 | TraceId.fromIdGenerator(api.IdGenerator generator) 16 | : _id = generator.generateTraceId(); 17 | TraceId.fromString(String id) : _id = [] { 18 | id = id.padLeft(TraceId.sizeBits, '0'); 19 | 20 | for (var i = 0; i < id.length; i += 2) { 21 | _id.add(int.parse('${id[i]}${id[i + 1]}', radix: 16)); 22 | } 23 | } 24 | TraceId.invalid() : this(List.filled(sizeBytes, 0)); 25 | 26 | /// Retrieve this TraceId as a list of byte values. 27 | List get() => _id; 28 | 29 | /// Whether this ID represents a valid Trace. 30 | bool get isValid => !_id.every((i) => i == 0); 31 | 32 | /// Retrieve this SpanId as a human-readable ID. 33 | @override 34 | String toString() => 35 | _id.map((x) => x.toRadixString(16).padLeft(2, '0')).join(); 36 | } 37 | -------------------------------------------------------------------------------- /lib/src/api/trace/trace_state.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | /// Representation of the state of a trace. 5 | /// 6 | /// See W3C documentation: https://www.w3.org/TR/trace-context/#tracestate-header 7 | class TraceState { 8 | static const int _MAX_KEY_VALUE_PAIRS = 32; 9 | static const int _KEY_MAX_SIZE = 256; 10 | static const int _VALUE_MAX_SIZE = 256; 11 | static final RegExp validKeyRegex = RegExp( 12 | r'^[a-z][\w\-*/]{0,255}$|^[a-z0-9][\w\-*/]{0,239}@[\w\-*/]{0,13}$'); 13 | static final RegExp validValueRegex = 14 | RegExp(r'^[\w"@#$%^&*()+\-./:;<>?\[\]\\`{|\}]{1,256}$'); 15 | final Map _state = {}; 16 | 17 | TraceState.empty(); 18 | 19 | TraceState.fromString(String traceState) { 20 | final stateElements = traceState.split(','); 21 | 22 | // Incoming state doesn't contain valid matchings of comma-separated 23 | // "key=value,key=value" pairs. Note: an invalid value with both a = and 24 | // a comma will still be converted, incorrectly. 25 | if (!stateElements.every((element) => element.contains('='))) { 26 | return; 27 | } 28 | 29 | for (final element in stateElements) { 30 | final entry = element.split('='); 31 | if (entry.length == 2) { 32 | put(entry.first, entry.last); 33 | } 34 | } 35 | } 36 | 37 | static TraceState getDefault() => TraceState.empty(); 38 | 39 | /// Determine if the given key is valid. 40 | /// 41 | /// Key is an opaque string up to 256 characters printable. It MUST begin 42 | /// with a lowercase letter, and can only contain lowercase letters a-z, 43 | /// digits 0-9, underscores _, dashes -, asterisks *, and forward slashes /. 44 | /// For multi-tenant vendor scenarios, an at sign (@) can be used to prefix 45 | /// the vendor name. The tenant id (before the '@') is limited to 240 46 | /// characters and the vendor id is limited to 13 characters. If in the 47 | /// multi-tenant vendor format, then the first character may additionally 48 | /// be numeric. 49 | static bool _isValidKey(String key) { 50 | if (key.length > _KEY_MAX_SIZE || key.isEmpty) { 51 | return false; 52 | } 53 | 54 | final match = validKeyRegex.matchAsPrefix(key); 55 | 56 | return (match != null) && (match.group(0) == key); 57 | } 58 | 59 | /// Determine if the given value is valid. 60 | /// 61 | /// Value an is opaque string up to 256 characters printable ASCII RFC0020 62 | /// characters (i.e., the range 0x20 to 0x7E) except comma , and =. 63 | static bool _isValidValue(String value) { 64 | if (value.length > _VALUE_MAX_SIZE || value.isEmpty) { 65 | return false; 66 | } 67 | 68 | final match = validValueRegex.matchAsPrefix(value); 69 | 70 | return (match != null) && (match.group(0) == value); 71 | } 72 | 73 | String get(String key) => _state[key] ?? ''; 74 | 75 | /// Adds a key value pair to the TraceState. 76 | /// 77 | /// Key is an opaque string up to 256 characters printable. It MUST begin 78 | /// with a lowercase letter, and can only contain lowercase letters a-z, 79 | /// digits 0-9, underscores _, dashes -, asterisks *, and forward slashes /. 80 | /// For multi-tenant vendor scenarios, an at sign (@) can be used to prefix 81 | /// the vendor name. The tenant id (before the '@') is limited to 240 82 | /// characters and the vendor id is limited to 13 characters. If in the 83 | /// multi-tenant vendor format, then the first character may additionally 84 | /// be numeric. 85 | /// 86 | /// Value is opaque string up to 256 characters printable ASCII RFC0020 87 | /// characters (i.e., the range 0x20 to 0x7E) except comma , and =. 88 | void put(String key, String value) { 89 | if (_isValidKey(key) && 90 | _isValidValue(value) && 91 | size < _MAX_KEY_VALUE_PAIRS) { 92 | _state[key] = value; 93 | } 94 | } 95 | 96 | /// Removes a key value pair from the TraceState. 97 | /// 98 | /// Key is an opaque string up to 256 characters printable. It MUST begin 99 | /// with a lowercase letter, and can only contain lowercase letters a-z, 100 | /// digits 0-9, underscores _, dashes -, asterisks *, and forward slashes /. 101 | /// For multi-tenant vendor scenarios, an at sign (@) can be used to prefix 102 | /// the vendor name. The tenant id (before the '@') is limited to 240 103 | /// characters and the vendor id is limited to 13 characters. If in the 104 | /// multi-tenant vendor format, then the first character may additionally 105 | /// be numeric. 106 | /// 107 | /// Value is opaque string up to 256 characters printable ASCII RFC0020 108 | /// characters (i.e., the range 0x20 to 0x7E) except comma , and =. 109 | void remove(String key) { 110 | if (_isValidKey(key)) { 111 | _state.remove(key); 112 | } 113 | } 114 | 115 | @override 116 | String toString() { 117 | if (isEmpty) { 118 | return ''; 119 | } 120 | 121 | final state_entries = _state.entries; 122 | var state = '${state_entries.first.key}=${state_entries.first.value}'; 123 | 124 | state_entries.skip(1).forEach((entry) { 125 | state += ',${entry.key}=${entry.value}'; 126 | }); 127 | 128 | return state; 129 | } 130 | 131 | bool get isEmpty => _state.isEmpty; 132 | 133 | int get size => _state.length; 134 | } 135 | -------------------------------------------------------------------------------- /lib/src/api/trace/tracer.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:fixnum/fixnum.dart'; 5 | 6 | import '../../../api.dart' as api; 7 | 8 | /// An interface for creating [api.Span]s and propagating context in-process. 9 | /// 10 | /// Users may choose to use manual or automatic Context propagation. Because of 11 | /// that, this class offers APIs to facilitate both usages. 12 | /// 13 | /// Warning: methods may be added to this interface in minor releases. 14 | abstract class Tracer { 15 | /// Starts a [api.Span]. 16 | /// 17 | /// The [api.Span] is created with the provided name and as a child of any 18 | /// existing span context found in the passed context. 19 | api.Span startSpan(String name, 20 | {api.Context context, 21 | api.SpanKind kind, 22 | List attributes, 23 | List links, 24 | Int64 startTime}); 25 | } 26 | -------------------------------------------------------------------------------- /lib/src/api/trace/tracer_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' as api; 5 | 6 | /// A registry for creating named [api.Tracer]s. 7 | /// 8 | /// Warning: methods may be added to this interface in minor releases. 9 | abstract class TracerProvider { 10 | /// Returns a Tracer, creating one if one with the given [name] and [version] 11 | /// is not already created. 12 | /// 13 | /// [name] should be the name of the tracer or instrumentation library. 14 | /// [version] should be the version of the tracer or instrumentation library. 15 | api.Tracer getTracer(String name, 16 | {String version, String schemaUrl, List attributes}); 17 | 18 | /// Flush all registered span processors. 19 | void forceFlush(); 20 | 21 | /// Stop all registered span processors. 22 | void shutdown(); 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/experimental_api.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @experimental 5 | library experimental_api; 6 | 7 | import 'package:meta/meta.dart'; 8 | 9 | export 'api/context/context_manager.dart' show ContextManager; 10 | export 'api/context/noop_context_manager.dart' show NoopContextManager; 11 | export 'api/context/zone_context.dart' show ZoneContext; 12 | export 'api/context/zone_context_manager.dart' show ZoneContextManager; 13 | export 'api/metrics/counter.dart' show Counter; 14 | export 'api/metrics/meter_provider.dart' show MeterProvider; 15 | export 'api/metrics/meter.dart' show Meter; 16 | export 'api/metrics/noop/noop_meter.dart' show NoopMeter; 17 | export 'api/trace/nonrecording_span.dart' show NonRecordingSpan; 18 | export 'api/logs/logger.dart' show Logger; 19 | export 'api/logs/log_record.dart' show Severity; 20 | export 'api/logs/logger_provider.dart' show LoggerProvider; 21 | export 'api/logs/noop/noop_logger.dart' show NoopLogger; 22 | export 'api/logs/noop/noop_logger_provider.dart' show NoopLoggerProvider; 23 | -------------------------------------------------------------------------------- /lib/src/experimental_sdk.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @experimental 5 | library experimental_sdk; 6 | 7 | import 'package:meta/meta.dart'; 8 | 9 | export 'sdk/metrics/counter.dart' show Counter; 10 | export 'sdk/metrics/meter_provider.dart' show MeterProvider; 11 | export 'sdk/metrics/meter.dart' show Meter; 12 | export 'sdk/resource/resource.dart' show Resource; 13 | -------------------------------------------------------------------------------- /lib/src/sdk/common/attributes.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart'; 5 | 6 | /// A representation of a collection of metadata attached to a trace span. 7 | class Attributes { 8 | final Map _attributes = {}; 9 | 10 | /// Instantiate an empty Attributes. 11 | Attributes.empty(); 12 | 13 | /// Retrieve the value associated with the Attribute with key [key]. 14 | Object? get(String key) => _attributes[key]; 15 | 16 | /// 17 | int get length => _attributes.length; 18 | 19 | /// Retrieve the keys of all Attributes in this collection. 20 | Iterable get keys => _attributes.keys; 21 | 22 | /// Add an Attribute [attribute]. 23 | /// If an Attribute with the same key already exists, it will be overwritten. 24 | void add(Attribute attribute) { 25 | _attributes[attribute.key] = attribute.value; 26 | } 27 | 28 | /// Add all Attributes in List [attributes]. 29 | /// If an Attribute with the same key already exists, it will be overwritten. 30 | void addAll(List attributes) { 31 | attributes.forEach(add); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/sdk/common/instrumentation_scope.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/api.dart' as api; 5 | 6 | class InstrumentationScope { 7 | final String _name; 8 | final String _version; 9 | final String _schemaUrl; 10 | final List _attributes; 11 | 12 | InstrumentationScope( 13 | this._name, this._version, this._schemaUrl, this._attributes); 14 | 15 | String get name { 16 | return _name; 17 | } 18 | 19 | String get version { 20 | return _version; 21 | } 22 | 23 | String get schemaUrl { 24 | return _schemaUrl; 25 | } 26 | 27 | List get attributes { 28 | return _attributes; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/sdk/common/limits.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | import 'package:meta/meta.dart'; 4 | 5 | import '../../../api.dart' as api; 6 | import '../../../sdk.dart' as sdk; 7 | 8 | /// Applies given [sdk.SpanLimits] to a list of [api.SpanLink]s. 9 | @protected 10 | List applyLinkLimits( 11 | List links, sdk.SpanLimits limits) { 12 | final spanLink = []; 13 | 14 | for (final link in links) { 15 | if (spanLink.length >= limits.maxNumLink) { 16 | break; 17 | } 18 | 19 | if (!link.context.isValid) continue; 20 | 21 | final linkAttributes = []; 22 | 23 | // make sure override duplicated attributes in the list 24 | final attributeMap = {}; 25 | 26 | var droppedAttributes = 0; 27 | for (final attr in link.attributes) { 28 | // if attributes num is already greater than maxNumAttributesPerLink 29 | // and this key doesn't exist in the list, drop it. 30 | if (attributeMap.length >= limits.maxNumAttributesPerLink && 31 | !attributeMap.containsKey(attr.key)) { 32 | droppedAttributes++; 33 | continue; 34 | } 35 | 36 | // apply maxNumAttributeLength limit. 37 | final trimmedAttr = applyAttributeLimits(attr, limits); 38 | 39 | // if this key has been added before, find its index, 40 | // and replace it with new value. 41 | final idx = attributeMap[attr.key]; 42 | if (idx != null) { 43 | linkAttributes[idx] = trimmedAttr; 44 | } else { 45 | // record this new key's index with linkAttributes length, 46 | // and add this new attr in linkAttributes. 47 | attributeMap[attr.key] = linkAttributes.length; 48 | linkAttributes.add(trimmedAttr); 49 | } 50 | } 51 | 52 | spanLink.add(api.SpanLink(link.context, 53 | attributes: linkAttributes, droppedAttributes: droppedAttributes)); 54 | } 55 | return spanLink; 56 | } 57 | 58 | /// Applies given [sdk.SpanLimits] to an [api.Attribute]. 59 | @protected 60 | api.Attribute applyAttributeLimits(api.Attribute attr, sdk.SpanLimits limits) { 61 | // if maxNumAttributeLength is less than zero, then it has unlimited length. 62 | if (limits.maxNumAttributeLength < 0) return attr; 63 | 64 | if (attr.value is String) { 65 | attr = api.Attribute.fromString( 66 | attr.key, 67 | applyAttributeLengthLimit( 68 | attr.value as String, limits.maxNumAttributeLength)); 69 | } else if (attr.value is List) { 70 | final listString = attr.value as List; 71 | for (var j = 0; j < listString.length; j++) { 72 | listString[j] = applyAttributeLengthLimit( 73 | listString[j], limits.maxNumAttributeLength); 74 | } 75 | attr = api.Attribute.fromStringList(attr.key, listString); 76 | } 77 | return attr; 78 | } 79 | 80 | /// Truncate just strings which length is longer than configuration. 81 | /// Reference: https://github.com/open-telemetry/opentelemetry-java/blob/14ffacd1cdd22f5aa556eeda4a569c7f144eadf2/sdk/common/src/main/java/io/opentelemetry/sdk/internal/AttributeUtil.java#L80 82 | @protected 83 | String applyAttributeLengthLimit(String value, int lengthLimit) { 84 | return value.length > lengthLimit ? value.substring(0, lengthLimit) : value; 85 | } 86 | -------------------------------------------------------------------------------- /lib/src/sdk/instrumentation_library.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../api.dart' as api; 5 | 6 | // Represents the instrumentation library. 7 | @Deprecated( 8 | 'This class will be removed in 0.19.0. Use [InstrumentationScope] instead.') 9 | class InstrumentationLibrary implements api.InstrumentationLibrary { 10 | final String _name; 11 | final String _version; 12 | 13 | InstrumentationLibrary(this._name, this._version); 14 | 15 | @override 16 | String get name => _name; 17 | 18 | @override 19 | String get version => _version; 20 | } 21 | -------------------------------------------------------------------------------- /lib/src/sdk/metrics/counter.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/api.dart' as api; 5 | import 'package:opentelemetry/src/experimental_api.dart' as api; 6 | 7 | class Counter implements api.Counter { 8 | @override 9 | void add(T value, {List? attributes, api.Context? context}) { 10 | // TODO: implement add https://github.com/Workiva/opentelemetry-dart/issues/75 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/src/sdk/metrics/meter.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:meta/meta.dart'; 5 | 6 | import '../../../sdk.dart' as sdk; 7 | import '../../experimental_sdk.dart' as sdk; 8 | import '../../experimental_api.dart' as api; 9 | 10 | class Meter implements api.Meter { 11 | final sdk.Resource _resource; // ignore: unused_field 12 | final sdk.InstrumentationScope _instrumentationScope; // ignore: unused_field 13 | 14 | @protected 15 | Meter(this._resource, this._instrumentationScope); 16 | 17 | @override 18 | api.Counter createCounter(String name, 19 | {String? description, String? unit}) { 20 | return sdk.Counter(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/src/sdk/metrics/meter_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:meta/meta.dart'; 5 | import 'package:logging/logging.dart'; 6 | import 'package:quiver/core.dart'; 7 | 8 | import '../../../api.dart' as api; 9 | import '../../experimental_api.dart' as api; 10 | import '../../experimental_sdk.dart' as sdk; 11 | import '../common/instrumentation_scope.dart'; 12 | 13 | class MeterProvider implements api.MeterProvider { 14 | final _logger = Logger('opentelemetry.sdk.metrics.meterprovider'); 15 | 16 | @protected 17 | final Map meters = {}; 18 | 19 | @visibleForTesting 20 | final sdk.Resource resource; 21 | 22 | MeterProvider({sdk.Resource? resource}) 23 | : resource = resource ?? sdk.Resource([]); 24 | 25 | @override 26 | api.Meter get(String name, 27 | {String version = '', 28 | String schemaUrl = '', 29 | List attributes = const []}) { 30 | if (name.isEmpty) { 31 | _logger.warning('Invalid Meter Name', '', StackTrace.current); 32 | } 33 | 34 | return meters.putIfAbsent( 35 | hash3(name, version, schemaUrl), 36 | () => sdk.Meter(resource, 37 | InstrumentationScope(name, version, schemaUrl, attributes))); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/sdk/platforms/web/time_providers/web_time_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'dart:html'; 5 | 6 | import 'package:fixnum/fixnum.dart'; 7 | import 'package:meta/meta.dart'; 8 | 9 | import '../../../time_providers/time_provider.dart'; 10 | 11 | Int64 msToNs(num n, {int? fractionDigits}) { 12 | const nsPerMs = 1000 * 1000; 13 | final whole = n.truncate(); 14 | if (fractionDigits == null) { 15 | final frac = ((n - whole) * nsPerMs).round(); 16 | return Int64(whole * nsPerMs + frac); 17 | } 18 | final frac = 19 | double.parse((n - whole).toStringAsFixed(fractionDigits)) * nsPerMs; 20 | return Int64(whole) * nsPerMs + Int64(frac.round()); 21 | } 22 | 23 | /// Time when navigation started or the service worker was started in 24 | /// nanoseconds. 25 | @experimental 26 | final Int64 timeOrigin = msToNs( 27 | window.performance.timeOrigin ?? window.performance.timing.navigationStart, 28 | fractionDigits: 1); 29 | 30 | /// Converts a high-resolution timestamp from the browser performance API to an 31 | /// Int64 representing nanoseconds since Unix Epoch. 32 | @experimental 33 | Int64 fromDOMHighResTimeStamp(num ts) { 34 | return timeOrigin + msToNs(ts); 35 | } 36 | 37 | /// BrowserTimeProvider retrieves high-resolution timestamps utilizing the 38 | /// `window.performance` API. 39 | /// 40 | /// See [DOMHighResTimeStamp](https://www.w3.org/TR/hr-time/#sec-DOMHighResTimeStamp) 41 | /// for more information. 42 | /// 43 | /// Note that this time may be inaccurate if the executing system is suspended 44 | /// for sleep. See https://github.com/open-telemetry/opentelemetry-js/issues/852 45 | /// for more information. 46 | class WebTimeProvider implements TimeProvider { 47 | /// The current time, in nanoseconds since Unix Epoch. 48 | /// 49 | /// Note that this time may be inaccurate if the executing system is suspended 50 | /// for sleep. See https://github.com/open-telemetry/opentelemetry-js/issues/852 51 | /// for more information. 52 | @override 53 | Int64 get now => fromDOMHighResTimeStamp(window.performance.now()); 54 | } 55 | -------------------------------------------------------------------------------- /lib/src/sdk/platforms/web/trace/web_tracer_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../../../api.dart' as api; 5 | import '../../../../../sdk.dart' as sdk; 6 | import '../../../trace/tracer.dart'; 7 | 8 | /// A [api.TracerProvider] which implements features specific to `dart:html`. 9 | /// 10 | /// Use of [WebTracerProvider] with this provider results in a [api.Tracer] 11 | /// which uses the `window.performance` API for high-precision timestamps 12 | /// on the [api.Span]s it creates. 13 | /// 14 | /// Note that these timestamps may be inaccurate if the executing system is 15 | /// suspended for sleep. 16 | /// See https://github.com/open-telemetry/opentelemetry-js/issues/852 17 | /// for more information. 18 | class WebTracerProvider extends sdk.TracerProviderBase { 19 | final sdk.TimeProvider _timeProvider; 20 | 21 | WebTracerProvider( 22 | {List? processors, 23 | sdk.Resource? resource, 24 | sdk.Sampler? sampler, 25 | sdk.TimeProvider? timeProvider, 26 | api.IdGenerator? idGenerator, 27 | sdk.SpanLimits? spanLimits}) 28 | : _timeProvider = timeProvider ?? sdk.DateTimeTimeProvider(), 29 | super( 30 | processors: processors ?? 31 | [], // Default to a TracerProvider which does not emit traces. 32 | resource: resource ?? sdk.Resource([]), 33 | sampler: sampler ?? sdk.ParentBasedSampler(sdk.AlwaysOnSampler()), 34 | idGenerator: idGenerator ?? sdk.IdGenerator(), 35 | spanLimits: spanLimits ?? sdk.SpanLimits()); 36 | 37 | @override 38 | api.Tracer getTracer(String name, 39 | {String version = '', 40 | String schemaUrl = '', 41 | List attributes = const []}) { 42 | return tracers.putIfAbsent( 43 | '$name@$version', 44 | () => Tracer( 45 | processors, 46 | resource, 47 | sampler, 48 | _timeProvider, 49 | idGenerator, 50 | sdk.InstrumentationScope(name, version, schemaUrl, attributes), 51 | spanLimits)); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbenum.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/collector/logs/v1/logs_service.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names, library_prefixes 12 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 13 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 14 | 15 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbjson.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/collector/logs/v1/logs_service.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names, library_prefixes 12 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 13 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 14 | 15 | import 'dart:convert' as $convert; 16 | import 'dart:core' as $core; 17 | import 'dart:typed_data' as $typed_data; 18 | 19 | import '../../../common/v1/common.pbjson.dart' as $0; 20 | import '../../../logs/v1/logs.pbjson.dart' as $4; 21 | import '../../../resource/v1/resource.pbjson.dart' as $1; 22 | 23 | @$core.Deprecated('Use exportLogsServiceRequestDescriptor instead') 24 | const ExportLogsServiceRequest$json = { 25 | '1': 'ExportLogsServiceRequest', 26 | '2': [ 27 | {'1': 'resource_logs', '3': 1, '4': 3, '5': 11, '6': '.opentelemetry.proto.logs.v1.ResourceLogs', '10': 'resourceLogs'}, 28 | ], 29 | }; 30 | 31 | /// Descriptor for `ExportLogsServiceRequest`. Decode as a `google.protobuf.DescriptorProto`. 32 | final $typed_data.Uint8List exportLogsServiceRequestDescriptor = $convert.base64Decode( 33 | 'ChhFeHBvcnRMb2dzU2VydmljZVJlcXVlc3QSTgoNcmVzb3VyY2VfbG9ncxgBIAMoCzIpLm9wZW' 34 | '50ZWxlbWV0cnkucHJvdG8ubG9ncy52MS5SZXNvdXJjZUxvZ3NSDHJlc291cmNlTG9ncw=='); 35 | 36 | @$core.Deprecated('Use exportLogsServiceResponseDescriptor instead') 37 | const ExportLogsServiceResponse$json = { 38 | '1': 'ExportLogsServiceResponse', 39 | '2': [ 40 | {'1': 'partial_success', '3': 1, '4': 1, '5': 11, '6': '.opentelemetry.proto.collector.logs.v1.ExportLogsPartialSuccess', '10': 'partialSuccess'}, 41 | ], 42 | }; 43 | 44 | /// Descriptor for `ExportLogsServiceResponse`. Decode as a `google.protobuf.DescriptorProto`. 45 | final $typed_data.Uint8List exportLogsServiceResponseDescriptor = $convert.base64Decode( 46 | 'ChlFeHBvcnRMb2dzU2VydmljZVJlc3BvbnNlEmgKD3BhcnRpYWxfc3VjY2VzcxgBIAEoCzI/Lm' 47 | '9wZW50ZWxlbWV0cnkucHJvdG8uY29sbGVjdG9yLmxvZ3MudjEuRXhwb3J0TG9nc1BhcnRpYWxT' 48 | 'dWNjZXNzUg5wYXJ0aWFsU3VjY2Vzcw=='); 49 | 50 | @$core.Deprecated('Use exportLogsPartialSuccessDescriptor instead') 51 | const ExportLogsPartialSuccess$json = { 52 | '1': 'ExportLogsPartialSuccess', 53 | '2': [ 54 | {'1': 'rejected_log_records', '3': 1, '4': 1, '5': 3, '10': 'rejectedLogRecords'}, 55 | {'1': 'error_message', '3': 2, '4': 1, '5': 9, '10': 'errorMessage'}, 56 | ], 57 | }; 58 | 59 | /// Descriptor for `ExportLogsPartialSuccess`. Decode as a `google.protobuf.DescriptorProto`. 60 | final $typed_data.Uint8List exportLogsPartialSuccessDescriptor = $convert.base64Decode( 61 | 'ChhFeHBvcnRMb2dzUGFydGlhbFN1Y2Nlc3MSMAoUcmVqZWN0ZWRfbG9nX3JlY29yZHMYASABKA' 62 | 'NSEnJlamVjdGVkTG9nUmVjb3JkcxIjCg1lcnJvcl9tZXNzYWdlGAIgASgJUgxlcnJvck1lc3Nh' 63 | 'Z2U='); 64 | 65 | const $core.Map<$core.String, $core.dynamic> LogsServiceBase$json = { 66 | '1': 'LogsService', 67 | '2': [ 68 | {'1': 'Export', '2': '.opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest', '3': '.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse', '4': {}}, 69 | ], 70 | }; 71 | 72 | @$core.Deprecated('Use logsServiceDescriptor instead') 73 | const $core.Map<$core.String, $core.Map<$core.String, $core.dynamic>> LogsServiceBase$messageJson = { 74 | '.opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest': ExportLogsServiceRequest$json, 75 | '.opentelemetry.proto.logs.v1.ResourceLogs': $4.ResourceLogs$json, 76 | '.opentelemetry.proto.resource.v1.Resource': $1.Resource$json, 77 | '.opentelemetry.proto.common.v1.KeyValue': $0.KeyValue$json, 78 | '.opentelemetry.proto.common.v1.AnyValue': $0.AnyValue$json, 79 | '.opentelemetry.proto.common.v1.ArrayValue': $0.ArrayValue$json, 80 | '.opentelemetry.proto.common.v1.KeyValueList': $0.KeyValueList$json, 81 | '.opentelemetry.proto.logs.v1.ScopeLogs': $4.ScopeLogs$json, 82 | '.opentelemetry.proto.common.v1.InstrumentationScope': $0.InstrumentationScope$json, 83 | '.opentelemetry.proto.logs.v1.LogRecord': $4.LogRecord$json, 84 | '.opentelemetry.proto.collector.logs.v1.ExportLogsServiceResponse': ExportLogsServiceResponse$json, 85 | '.opentelemetry.proto.collector.logs.v1.ExportLogsPartialSuccess': ExportLogsPartialSuccess$json, 86 | }; 87 | 88 | /// Descriptor for `LogsService`. Decode as a `google.protobuf.ServiceDescriptorProto`. 89 | final $typed_data.Uint8List logsServiceDescriptor = $convert.base64Decode( 90 | 'CgtMb2dzU2VydmljZRKNAQoGRXhwb3J0Ej8ub3BlbnRlbGVtZXRyeS5wcm90by5jb2xsZWN0b3' 91 | 'IubG9ncy52MS5FeHBvcnRMb2dzU2VydmljZVJlcXVlc3QaQC5vcGVudGVsZW1ldHJ5LnByb3Rv' 92 | 'LmNvbGxlY3Rvci5sb2dzLnYxLkV4cG9ydExvZ3NTZXJ2aWNlUmVzcG9uc2UiAA=='); 93 | 94 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/collector/logs/v1/logs_service.pbserver.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/collector/logs/v1/logs_service.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names 12 | // ignore_for_file: deprecated_member_use_from_same_package, library_prefixes 13 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 14 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 15 | 16 | import 'dart:async' as $async; 17 | import 'dart:core' as $core; 18 | 19 | import 'package:protobuf/protobuf.dart' as $pb; 20 | 21 | import 'logs_service.pb.dart' as $5; 22 | import 'logs_service.pbjson.dart'; 23 | 24 | export 'logs_service.pb.dart'; 25 | 26 | abstract class LogsServiceBase extends $pb.GeneratedService { 27 | $async.Future<$5.ExportLogsServiceResponse> export($pb.ServerContext ctx, $5.ExportLogsServiceRequest request); 28 | 29 | $pb.GeneratedMessage createRequest($core.String methodName) { 30 | switch (methodName) { 31 | case 'Export': return $5.ExportLogsServiceRequest(); 32 | default: throw $core.ArgumentError('Unknown method: $methodName'); 33 | } 34 | } 35 | 36 | $async.Future<$pb.GeneratedMessage> handleCall($pb.ServerContext ctx, $core.String methodName, $pb.GeneratedMessage request) { 37 | switch (methodName) { 38 | case 'Export': return this.export(ctx, request as $5.ExportLogsServiceRequest); 39 | default: throw $core.ArgumentError('Unknown method: $methodName'); 40 | } 41 | } 42 | 43 | $core.Map<$core.String, $core.dynamic> get $json => LogsServiceBase$json; 44 | $core.Map<$core.String, $core.Map<$core.String, $core.dynamic>> get $messageJson => LogsServiceBase$messageJson; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/collector/trace/v1/trace_service.pbenum.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/collector/trace/v1/trace_service.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names, library_prefixes 12 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 13 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 14 | 15 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/collector/trace/v1/trace_service.pbjson.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/collector/trace/v1/trace_service.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names, library_prefixes 12 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 13 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 14 | 15 | import 'dart:convert' as $convert; 16 | import 'dart:core' as $core; 17 | import 'dart:typed_data' as $typed_data; 18 | 19 | import '../../../common/v1/common.pbjson.dart' as $0; 20 | import '../../../resource/v1/resource.pbjson.dart' as $1; 21 | import '../../../trace/v1/trace.pbjson.dart' as $2; 22 | 23 | @$core.Deprecated('Use exportTraceServiceRequestDescriptor instead') 24 | const ExportTraceServiceRequest$json = { 25 | '1': 'ExportTraceServiceRequest', 26 | '2': [ 27 | {'1': 'resource_spans', '3': 1, '4': 3, '5': 11, '6': '.opentelemetry.proto.trace.v1.ResourceSpans', '10': 'resourceSpans'}, 28 | ], 29 | }; 30 | 31 | /// Descriptor for `ExportTraceServiceRequest`. Decode as a `google.protobuf.DescriptorProto`. 32 | final $typed_data.Uint8List exportTraceServiceRequestDescriptor = $convert.base64Decode( 33 | 'ChlFeHBvcnRUcmFjZVNlcnZpY2VSZXF1ZXN0ElIKDnJlc291cmNlX3NwYW5zGAEgAygLMisub3' 34 | 'BlbnRlbGVtZXRyeS5wcm90by50cmFjZS52MS5SZXNvdXJjZVNwYW5zUg1yZXNvdXJjZVNwYW5z'); 35 | 36 | @$core.Deprecated('Use exportTraceServiceResponseDescriptor instead') 37 | const ExportTraceServiceResponse$json = { 38 | '1': 'ExportTraceServiceResponse', 39 | '2': [ 40 | {'1': 'partial_success', '3': 1, '4': 1, '5': 11, '6': '.opentelemetry.proto.collector.trace.v1.ExportTracePartialSuccess', '10': 'partialSuccess'}, 41 | ], 42 | }; 43 | 44 | /// Descriptor for `ExportTraceServiceResponse`. Decode as a `google.protobuf.DescriptorProto`. 45 | final $typed_data.Uint8List exportTraceServiceResponseDescriptor = $convert.base64Decode( 46 | 'ChpFeHBvcnRUcmFjZVNlcnZpY2VSZXNwb25zZRJqCg9wYXJ0aWFsX3N1Y2Nlc3MYASABKAsyQS' 47 | '5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbGxlY3Rvci50cmFjZS52MS5FeHBvcnRUcmFjZVBhcnRp' 48 | 'YWxTdWNjZXNzUg5wYXJ0aWFsU3VjY2Vzcw=='); 49 | 50 | @$core.Deprecated('Use exportTracePartialSuccessDescriptor instead') 51 | const ExportTracePartialSuccess$json = { 52 | '1': 'ExportTracePartialSuccess', 53 | '2': [ 54 | {'1': 'rejected_spans', '3': 1, '4': 1, '5': 3, '10': 'rejectedSpans'}, 55 | {'1': 'error_message', '3': 2, '4': 1, '5': 9, '10': 'errorMessage'}, 56 | ], 57 | }; 58 | 59 | /// Descriptor for `ExportTracePartialSuccess`. Decode as a `google.protobuf.DescriptorProto`. 60 | final $typed_data.Uint8List exportTracePartialSuccessDescriptor = $convert.base64Decode( 61 | 'ChlFeHBvcnRUcmFjZVBhcnRpYWxTdWNjZXNzEiUKDnJlamVjdGVkX3NwYW5zGAEgASgDUg1yZW' 62 | 'plY3RlZFNwYW5zEiMKDWVycm9yX21lc3NhZ2UYAiABKAlSDGVycm9yTWVzc2FnZQ=='); 63 | 64 | const $core.Map<$core.String, $core.dynamic> TraceServiceBase$json = { 65 | '1': 'TraceService', 66 | '2': [ 67 | {'1': 'Export', '2': '.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest', '3': '.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse', '4': {}}, 68 | ], 69 | }; 70 | 71 | @$core.Deprecated('Use traceServiceDescriptor instead') 72 | const $core.Map<$core.String, $core.Map<$core.String, $core.dynamic>> TraceServiceBase$messageJson = { 73 | '.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest': ExportTraceServiceRequest$json, 74 | '.opentelemetry.proto.trace.v1.ResourceSpans': $2.ResourceSpans$json, 75 | '.opentelemetry.proto.resource.v1.Resource': $1.Resource$json, 76 | '.opentelemetry.proto.common.v1.KeyValue': $0.KeyValue$json, 77 | '.opentelemetry.proto.common.v1.AnyValue': $0.AnyValue$json, 78 | '.opentelemetry.proto.common.v1.ArrayValue': $0.ArrayValue$json, 79 | '.opentelemetry.proto.common.v1.KeyValueList': $0.KeyValueList$json, 80 | '.opentelemetry.proto.trace.v1.ScopeSpans': $2.ScopeSpans$json, 81 | '.opentelemetry.proto.common.v1.InstrumentationScope': $0.InstrumentationScope$json, 82 | '.opentelemetry.proto.trace.v1.Span': $2.Span$json, 83 | '.opentelemetry.proto.trace.v1.Span.Event': $2.Span_Event$json, 84 | '.opentelemetry.proto.trace.v1.Span.Link': $2.Span_Link$json, 85 | '.opentelemetry.proto.trace.v1.Status': $2.Status$json, 86 | '.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse': ExportTraceServiceResponse$json, 87 | '.opentelemetry.proto.collector.trace.v1.ExportTracePartialSuccess': ExportTracePartialSuccess$json, 88 | }; 89 | 90 | /// Descriptor for `TraceService`. Decode as a `google.protobuf.ServiceDescriptorProto`. 91 | final $typed_data.Uint8List traceServiceDescriptor = $convert.base64Decode( 92 | 'CgxUcmFjZVNlcnZpY2USkQEKBkV4cG9ydBJBLm9wZW50ZWxlbWV0cnkucHJvdG8uY29sbGVjdG' 93 | '9yLnRyYWNlLnYxLkV4cG9ydFRyYWNlU2VydmljZVJlcXVlc3QaQi5vcGVudGVsZW1ldHJ5LnBy' 94 | 'b3RvLmNvbGxlY3Rvci50cmFjZS52MS5FeHBvcnRUcmFjZVNlcnZpY2VSZXNwb25zZSIA'); 95 | 96 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/collector/trace/v1/trace_service.pbserver.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/collector/trace/v1/trace_service.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names 12 | // ignore_for_file: deprecated_member_use_from_same_package, library_prefixes 13 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 14 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 15 | 16 | import 'dart:async' as $async; 17 | import 'dart:core' as $core; 18 | 19 | import 'package:protobuf/protobuf.dart' as $pb; 20 | 21 | import 'trace_service.pb.dart' as $3; 22 | import 'trace_service.pbjson.dart'; 23 | 24 | export 'trace_service.pb.dart'; 25 | 26 | abstract class TraceServiceBase extends $pb.GeneratedService { 27 | $async.Future<$3.ExportTraceServiceResponse> export($pb.ServerContext ctx, $3.ExportTraceServiceRequest request); 28 | 29 | $pb.GeneratedMessage createRequest($core.String methodName) { 30 | switch (methodName) { 31 | case 'Export': return $3.ExportTraceServiceRequest(); 32 | default: throw $core.ArgumentError('Unknown method: $methodName'); 33 | } 34 | } 35 | 36 | $async.Future<$pb.GeneratedMessage> handleCall($pb.ServerContext ctx, $core.String methodName, $pb.GeneratedMessage request) { 37 | switch (methodName) { 38 | case 'Export': return this.export(ctx, request as $3.ExportTraceServiceRequest); 39 | default: throw $core.ArgumentError('Unknown method: $methodName'); 40 | } 41 | } 42 | 43 | $core.Map<$core.String, $core.dynamic> get $json => TraceServiceBase$json; 44 | $core.Map<$core.String, $core.Map<$core.String, $core.dynamic>> get $messageJson => TraceServiceBase$messageJson; 45 | } 46 | 47 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/common/v1/common.pbenum.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/common/v1/common.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names, library_prefixes 12 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 13 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 14 | 15 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/common/v1/common.pbjson.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/common/v1/common.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names, library_prefixes 12 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 13 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 14 | 15 | import 'dart:convert' as $convert; 16 | import 'dart:core' as $core; 17 | import 'dart:typed_data' as $typed_data; 18 | 19 | @$core.Deprecated('Use anyValueDescriptor instead') 20 | const AnyValue$json = { 21 | '1': 'AnyValue', 22 | '2': [ 23 | {'1': 'string_value', '3': 1, '4': 1, '5': 9, '9': 0, '10': 'stringValue'}, 24 | {'1': 'bool_value', '3': 2, '4': 1, '5': 8, '9': 0, '10': 'boolValue'}, 25 | {'1': 'int_value', '3': 3, '4': 1, '5': 3, '9': 0, '10': 'intValue'}, 26 | {'1': 'double_value', '3': 4, '4': 1, '5': 1, '9': 0, '10': 'doubleValue'}, 27 | {'1': 'array_value', '3': 5, '4': 1, '5': 11, '6': '.opentelemetry.proto.common.v1.ArrayValue', '9': 0, '10': 'arrayValue'}, 28 | {'1': 'kvlist_value', '3': 6, '4': 1, '5': 11, '6': '.opentelemetry.proto.common.v1.KeyValueList', '9': 0, '10': 'kvlistValue'}, 29 | {'1': 'bytes_value', '3': 7, '4': 1, '5': 12, '9': 0, '10': 'bytesValue'}, 30 | ], 31 | '8': [ 32 | {'1': 'value'}, 33 | ], 34 | }; 35 | 36 | /// Descriptor for `AnyValue`. Decode as a `google.protobuf.DescriptorProto`. 37 | final $typed_data.Uint8List anyValueDescriptor = $convert.base64Decode( 38 | 'CghBbnlWYWx1ZRIjCgxzdHJpbmdfdmFsdWUYASABKAlIAFILc3RyaW5nVmFsdWUSHwoKYm9vbF' 39 | '92YWx1ZRgCIAEoCEgAUglib29sVmFsdWUSHQoJaW50X3ZhbHVlGAMgASgDSABSCGludFZhbHVl' 40 | 'EiMKDGRvdWJsZV92YWx1ZRgEIAEoAUgAUgtkb3VibGVWYWx1ZRJMCgthcnJheV92YWx1ZRgFIA' 41 | 'EoCzIpLm9wZW50ZWxlbWV0cnkucHJvdG8uY29tbW9uLnYxLkFycmF5VmFsdWVIAFIKYXJyYXlW' 42 | 'YWx1ZRJQCgxrdmxpc3RfdmFsdWUYBiABKAsyKy5vcGVudGVsZW1ldHJ5LnByb3RvLmNvbW1vbi' 43 | '52MS5LZXlWYWx1ZUxpc3RIAFILa3ZsaXN0VmFsdWUSIQoLYnl0ZXNfdmFsdWUYByABKAxIAFIK' 44 | 'Ynl0ZXNWYWx1ZUIHCgV2YWx1ZQ=='); 45 | 46 | @$core.Deprecated('Use arrayValueDescriptor instead') 47 | const ArrayValue$json = { 48 | '1': 'ArrayValue', 49 | '2': [ 50 | {'1': 'values', '3': 1, '4': 3, '5': 11, '6': '.opentelemetry.proto.common.v1.AnyValue', '10': 'values'}, 51 | ], 52 | }; 53 | 54 | /// Descriptor for `ArrayValue`. Decode as a `google.protobuf.DescriptorProto`. 55 | final $typed_data.Uint8List arrayValueDescriptor = $convert.base64Decode( 56 | 'CgpBcnJheVZhbHVlEj8KBnZhbHVlcxgBIAMoCzInLm9wZW50ZWxlbWV0cnkucHJvdG8uY29tbW' 57 | '9uLnYxLkFueVZhbHVlUgZ2YWx1ZXM='); 58 | 59 | @$core.Deprecated('Use keyValueListDescriptor instead') 60 | const KeyValueList$json = { 61 | '1': 'KeyValueList', 62 | '2': [ 63 | {'1': 'values', '3': 1, '4': 3, '5': 11, '6': '.opentelemetry.proto.common.v1.KeyValue', '10': 'values'}, 64 | ], 65 | }; 66 | 67 | /// Descriptor for `KeyValueList`. Decode as a `google.protobuf.DescriptorProto`. 68 | final $typed_data.Uint8List keyValueListDescriptor = $convert.base64Decode( 69 | 'CgxLZXlWYWx1ZUxpc3QSPwoGdmFsdWVzGAEgAygLMicub3BlbnRlbGVtZXRyeS5wcm90by5jb2' 70 | '1tb24udjEuS2V5VmFsdWVSBnZhbHVlcw=='); 71 | 72 | @$core.Deprecated('Use keyValueDescriptor instead') 73 | const KeyValue$json = { 74 | '1': 'KeyValue', 75 | '2': [ 76 | {'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'}, 77 | {'1': 'value', '3': 2, '4': 1, '5': 11, '6': '.opentelemetry.proto.common.v1.AnyValue', '10': 'value'}, 78 | ], 79 | }; 80 | 81 | /// Descriptor for `KeyValue`. Decode as a `google.protobuf.DescriptorProto`. 82 | final $typed_data.Uint8List keyValueDescriptor = $convert.base64Decode( 83 | 'CghLZXlWYWx1ZRIQCgNrZXkYASABKAlSA2tleRI9CgV2YWx1ZRgCIAEoCzInLm9wZW50ZWxlbW' 84 | 'V0cnkucHJvdG8uY29tbW9uLnYxLkFueVZhbHVlUgV2YWx1ZQ=='); 85 | 86 | @$core.Deprecated('Use instrumentationScopeDescriptor instead') 87 | const InstrumentationScope$json = { 88 | '1': 'InstrumentationScope', 89 | '2': [ 90 | {'1': 'name', '3': 1, '4': 1, '5': 9, '10': 'name'}, 91 | {'1': 'version', '3': 2, '4': 1, '5': 9, '10': 'version'}, 92 | {'1': 'attributes', '3': 3, '4': 3, '5': 11, '6': '.opentelemetry.proto.common.v1.KeyValue', '10': 'attributes'}, 93 | {'1': 'dropped_attributes_count', '3': 4, '4': 1, '5': 13, '10': 'droppedAttributesCount'}, 94 | ], 95 | }; 96 | 97 | /// Descriptor for `InstrumentationScope`. Decode as a `google.protobuf.DescriptorProto`. 98 | final $typed_data.Uint8List instrumentationScopeDescriptor = $convert.base64Decode( 99 | 'ChRJbnN0cnVtZW50YXRpb25TY29wZRISCgRuYW1lGAEgASgJUgRuYW1lEhgKB3ZlcnNpb24YAi' 100 | 'ABKAlSB3ZlcnNpb24SRwoKYXR0cmlidXRlcxgDIAMoCzInLm9wZW50ZWxlbWV0cnkucHJvdG8u' 101 | 'Y29tbW9uLnYxLktleVZhbHVlUgphdHRyaWJ1dGVzEjgKGGRyb3BwZWRfYXR0cmlidXRlc19jb3' 102 | 'VudBgEIAEoDVIWZHJvcHBlZEF0dHJpYnV0ZXNDb3VudA=='); 103 | 104 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/common/v1/common.pbserver.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/common/v1/common.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names 12 | // ignore_for_file: deprecated_member_use_from_same_package, library_prefixes 13 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 14 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 15 | 16 | export 'common.pb.dart'; 17 | 18 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/logs/v1/logs.pbserver.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/logs/v1/logs.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names 12 | // ignore_for_file: deprecated_member_use_from_same_package, library_prefixes 13 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 14 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 15 | 16 | export 'logs.pb.dart'; 17 | 18 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/resource/v1/resource.pb.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/resource/v1/resource.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names, library_prefixes 12 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 13 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 14 | 15 | import 'dart:core' as $core; 16 | 17 | import 'package:protobuf/protobuf.dart' as $pb; 18 | 19 | import '../../common/v1/common.pb.dart' as $0; 20 | 21 | /// Resource information. 22 | class Resource extends $pb.GeneratedMessage { 23 | factory Resource({ 24 | $core.Iterable<$0.KeyValue>? attributes, 25 | $core.int? droppedAttributesCount, 26 | }) { 27 | final $result = create(); 28 | if (attributes != null) { 29 | $result.attributes.addAll(attributes); 30 | } 31 | if (droppedAttributesCount != null) { 32 | $result.droppedAttributesCount = droppedAttributesCount; 33 | } 34 | return $result; 35 | } 36 | Resource._() : super(); 37 | factory Resource.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); 38 | factory Resource.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); 39 | 40 | static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Resource', package: const $pb.PackageName(_omitMessageNames ? '' : 'opentelemetry.proto.resource.v1'), createEmptyInstance: create) 41 | ..pc<$0.KeyValue>(1, _omitFieldNames ? '' : 'attributes', $pb.PbFieldType.PM, subBuilder: $0.KeyValue.create) 42 | ..a<$core.int>(2, _omitFieldNames ? '' : 'droppedAttributesCount', $pb.PbFieldType.OU3) 43 | ..hasRequiredFields = false 44 | ; 45 | 46 | @$core.Deprecated( 47 | 'Using this can add significant overhead to your binary. ' 48 | 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' 49 | 'Will be removed in next major version') 50 | Resource clone() => Resource()..mergeFromMessage(this); 51 | @$core.Deprecated( 52 | 'Using this can add significant overhead to your binary. ' 53 | 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' 54 | 'Will be removed in next major version') 55 | Resource copyWith(void Function(Resource) updates) => super.copyWith((message) => updates(message as Resource)) as Resource; 56 | 57 | $pb.BuilderInfo get info_ => _i; 58 | 59 | @$core.pragma('dart2js:noInline') 60 | static Resource create() => Resource._(); 61 | Resource createEmptyInstance() => create(); 62 | static $pb.PbList createRepeated() => $pb.PbList(); 63 | @$core.pragma('dart2js:noInline') 64 | static Resource getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); 65 | static Resource? _defaultInstance; 66 | 67 | /// Set of attributes that describe the resource. 68 | /// Attribute keys MUST be unique (it is not allowed to have more than one 69 | /// attribute with the same key). 70 | @$pb.TagNumber(1) 71 | $core.List<$0.KeyValue> get attributes => $_getList(0); 72 | 73 | /// dropped_attributes_count is the number of dropped attributes. If the value is 0, then 74 | /// no attributes were dropped. 75 | @$pb.TagNumber(2) 76 | $core.int get droppedAttributesCount => $_getIZ(1); 77 | @$pb.TagNumber(2) 78 | set droppedAttributesCount($core.int v) { $_setUnsignedInt32(1, v); } 79 | @$pb.TagNumber(2) 80 | $core.bool hasDroppedAttributesCount() => $_has(1); 81 | @$pb.TagNumber(2) 82 | void clearDroppedAttributesCount() => clearField(2); 83 | } 84 | 85 | 86 | const _omitFieldNames = $core.bool.fromEnvironment('protobuf.omit_field_names'); 87 | const _omitMessageNames = $core.bool.fromEnvironment('protobuf.omit_message_names'); 88 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/resource/v1/resource.pbenum.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/resource/v1/resource.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names, library_prefixes 12 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 13 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 14 | 15 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/resource/v1/resource.pbjson.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/resource/v1/resource.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names, library_prefixes 12 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 13 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 14 | 15 | import 'dart:convert' as $convert; 16 | import 'dart:core' as $core; 17 | import 'dart:typed_data' as $typed_data; 18 | 19 | @$core.Deprecated('Use resourceDescriptor instead') 20 | const Resource$json = { 21 | '1': 'Resource', 22 | '2': [ 23 | {'1': 'attributes', '3': 1, '4': 3, '5': 11, '6': '.opentelemetry.proto.common.v1.KeyValue', '10': 'attributes'}, 24 | {'1': 'dropped_attributes_count', '3': 2, '4': 1, '5': 13, '10': 'droppedAttributesCount'}, 25 | ], 26 | }; 27 | 28 | /// Descriptor for `Resource`. Decode as a `google.protobuf.DescriptorProto`. 29 | final $typed_data.Uint8List resourceDescriptor = $convert.base64Decode( 30 | 'CghSZXNvdXJjZRJHCgphdHRyaWJ1dGVzGAEgAygLMicub3BlbnRlbGVtZXRyeS5wcm90by5jb2' 31 | '1tb24udjEuS2V5VmFsdWVSCmF0dHJpYnV0ZXMSOAoYZHJvcHBlZF9hdHRyaWJ1dGVzX2NvdW50' 32 | 'GAIgASgNUhZkcm9wcGVkQXR0cmlidXRlc0NvdW50'); 33 | 34 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/resource/v1/resource.pbserver.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/resource/v1/resource.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names 12 | // ignore_for_file: deprecated_member_use_from_same_package, library_prefixes 13 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 14 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 15 | 16 | export 'resource.pb.dart'; 17 | 18 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/trace/v1/trace.pbenum.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/trace/v1/trace.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names, library_prefixes 12 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 13 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 14 | 15 | import 'dart:core' as $core; 16 | 17 | import 'package:protobuf/protobuf.dart' as $pb; 18 | 19 | /// SpanFlags represents constants used to interpret the 20 | /// Span.flags field, which is protobuf 'fixed32' type and is to 21 | /// be used as bit-fields. Each non-zero value defined in this enum is 22 | /// a bit-mask. To extract the bit-field, for example, use an 23 | /// expression like: 24 | /// 25 | /// (span.flags & SPAN_FLAGS_TRACE_FLAGS_MASK) 26 | /// 27 | /// See https://www.w3.org/TR/trace-context-2/#trace-flags for the flag definitions. 28 | /// 29 | /// Note that Span flags were introduced in version 1.1 of the 30 | /// OpenTelemetry protocol. Older Span producers do not set this 31 | /// field, consequently consumers should not rely on the absence of a 32 | /// particular flag bit to indicate the presence of a particular feature. 33 | class SpanFlags extends $pb.ProtobufEnum { 34 | static const SpanFlags SPAN_FLAGS_DO_NOT_USE = SpanFlags._(0, _omitEnumNames ? '' : 'SPAN_FLAGS_DO_NOT_USE'); 35 | static const SpanFlags SPAN_FLAGS_TRACE_FLAGS_MASK = SpanFlags._(255, _omitEnumNames ? '' : 'SPAN_FLAGS_TRACE_FLAGS_MASK'); 36 | 37 | static const $core.List values = [ 38 | SPAN_FLAGS_DO_NOT_USE, 39 | SPAN_FLAGS_TRACE_FLAGS_MASK, 40 | ]; 41 | 42 | static final $core.Map<$core.int, SpanFlags> _byValue = $pb.ProtobufEnum.initByValue(values); 43 | static SpanFlags? valueOf($core.int value) => _byValue[value]; 44 | 45 | const SpanFlags._($core.int v, $core.String n) : super(v, n); 46 | } 47 | 48 | /// SpanKind is the type of span. Can be used to specify additional relationships between spans 49 | /// in addition to a parent/child relationship. 50 | class Span_SpanKind extends $pb.ProtobufEnum { 51 | static const Span_SpanKind SPAN_KIND_UNSPECIFIED = Span_SpanKind._(0, _omitEnumNames ? '' : 'SPAN_KIND_UNSPECIFIED'); 52 | static const Span_SpanKind SPAN_KIND_INTERNAL = Span_SpanKind._(1, _omitEnumNames ? '' : 'SPAN_KIND_INTERNAL'); 53 | static const Span_SpanKind SPAN_KIND_SERVER = Span_SpanKind._(2, _omitEnumNames ? '' : 'SPAN_KIND_SERVER'); 54 | static const Span_SpanKind SPAN_KIND_CLIENT = Span_SpanKind._(3, _omitEnumNames ? '' : 'SPAN_KIND_CLIENT'); 55 | static const Span_SpanKind SPAN_KIND_PRODUCER = Span_SpanKind._(4, _omitEnumNames ? '' : 'SPAN_KIND_PRODUCER'); 56 | static const Span_SpanKind SPAN_KIND_CONSUMER = Span_SpanKind._(5, _omitEnumNames ? '' : 'SPAN_KIND_CONSUMER'); 57 | 58 | static const $core.List values = [ 59 | SPAN_KIND_UNSPECIFIED, 60 | SPAN_KIND_INTERNAL, 61 | SPAN_KIND_SERVER, 62 | SPAN_KIND_CLIENT, 63 | SPAN_KIND_PRODUCER, 64 | SPAN_KIND_CONSUMER, 65 | ]; 66 | 67 | static final $core.Map<$core.int, Span_SpanKind> _byValue = $pb.ProtobufEnum.initByValue(values); 68 | static Span_SpanKind? valueOf($core.int value) => _byValue[value]; 69 | 70 | const Span_SpanKind._($core.int v, $core.String n) : super(v, n); 71 | } 72 | 73 | /// For the semantics of status codes see 74 | /// https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#set-status 75 | class Status_StatusCode extends $pb.ProtobufEnum { 76 | static const Status_StatusCode STATUS_CODE_UNSET = Status_StatusCode._(0, _omitEnumNames ? '' : 'STATUS_CODE_UNSET'); 77 | static const Status_StatusCode STATUS_CODE_OK = Status_StatusCode._(1, _omitEnumNames ? '' : 'STATUS_CODE_OK'); 78 | static const Status_StatusCode STATUS_CODE_ERROR = Status_StatusCode._(2, _omitEnumNames ? '' : 'STATUS_CODE_ERROR'); 79 | 80 | static const $core.List values = [ 81 | STATUS_CODE_UNSET, 82 | STATUS_CODE_OK, 83 | STATUS_CODE_ERROR, 84 | ]; 85 | 86 | static final $core.Map<$core.int, Status_StatusCode> _byValue = $pb.ProtobufEnum.initByValue(values); 87 | static Status_StatusCode? valueOf($core.int value) => _byValue[value]; 88 | 89 | const Status_StatusCode._($core.int v, $core.String n) : super(v, n); 90 | } 91 | 92 | 93 | const _omitEnumNames = $core.bool.fromEnvironment('protobuf.omit_enum_names'); 94 | -------------------------------------------------------------------------------- /lib/src/sdk/proto/opentelemetry/proto/trace/v1/trace.pbserver.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | // 5 | // Generated code. Do not modify. 6 | // source: opentelemetry/proto/trace/v1/trace.proto 7 | // 8 | // @dart = 2.12 9 | 10 | // ignore_for_file: annotate_overrides, camel_case_types, comment_references 11 | // ignore_for_file: constant_identifier_names 12 | // ignore_for_file: deprecated_member_use_from_same_package, library_prefixes 13 | // ignore_for_file: non_constant_identifier_names, prefer_final_fields 14 | // ignore_for_file: unnecessary_import, unnecessary_this, unused_import 15 | 16 | export 'trace.pb.dart'; 17 | 18 | -------------------------------------------------------------------------------- /lib/src/sdk/resource/resource.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api.dart' as api; 5 | import '../common/attributes.dart'; 6 | 7 | class Resource { 8 | final Attributes _attributes; 9 | 10 | Resource(List attributes) 11 | : _attributes = Attributes.empty()..addAll(attributes); 12 | 13 | Attributes get attributes => _attributes; 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/sdk/time_providers/datetime_time_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:fixnum/fixnum.dart'; 5 | import 'time_provider.dart'; 6 | 7 | /// DateTimeTimeProvider retrieves timestamps using DateTime. 8 | class DateTimeTimeProvider implements TimeProvider { 9 | @override 10 | Int64 get now => Int64(DateTime.now().microsecondsSinceEpoch) * 1000; 11 | } 12 | -------------------------------------------------------------------------------- /lib/src/sdk/time_providers/time_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:fixnum/fixnum.dart'; 5 | 6 | abstract class TimeProvider { 7 | // The smallest increment that DateTime can report is in microseconds, while 8 | // OpenTelemetry expects time in nanoseconds. 9 | @Deprecated('This constant will be removed in 0.19.0 without replacement.') 10 | static const int nanosecondsPerMicrosecond = 1000; 11 | 12 | // window.performance API reports time in fractional milliseconds, while 13 | // OpenTelemetry expects time in nanoseconds. 14 | @Deprecated('This constant will be removed in 0.19.0 without replacement.') 15 | static const int nanosecondsPerMillisecond = 1000000; 16 | 17 | /// The current time, in nanoseconds since Unix Epoch. 18 | Int64 get now; 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/exporters/console_exporter.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../../sdk.dart' as sdk; 5 | 6 | class ConsoleExporter implements sdk.SpanExporter { 7 | var _isShutdown = false; 8 | 9 | void _printSpans(List spans) { 10 | for (var i = 0; i < spans.length; i++) { 11 | final span = spans[i]; 12 | print({ 13 | 'traceId': '${span.spanContext.traceId}', 14 | 'parentId': '${span.parentSpanId}', 15 | 'name': span.name, 16 | 'id': '${span.spanContext.spanId}', 17 | 'timestamp': span.startTime, 18 | 'duration': span.endTime! - span.startTime, 19 | 'flags': 20 | '${span.spanContext.traceFlags.toRadixString(16).padLeft(2, '0')}', 21 | 'state': '${span.spanContext.traceState}', 22 | 'status': span.status.code 23 | }); 24 | } 25 | } 26 | 27 | @override 28 | void export(List spans) { 29 | if (_isShutdown) { 30 | return; 31 | } 32 | 33 | _printSpans(spans); 34 | } 35 | 36 | @Deprecated( 37 | 'This method will be removed in 0.19.0. Use [SpanProcessor] instead.') 38 | @override 39 | void forceFlush() { 40 | return; 41 | } 42 | 43 | @override 44 | void shutdown() { 45 | _isShutdown = true; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/exporters/span_exporter.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../read_only_span.dart'; 5 | 6 | abstract class SpanExporter { 7 | void export(List spans); 8 | 9 | @Deprecated( 10 | 'This method will be removed in 0.19.0. Use [SpanProcessor] instead.') 11 | void forceFlush(); 12 | 13 | void shutdown(); 14 | } 15 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/id_generator.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'dart:math'; 5 | 6 | import '../../../api.dart' as api; 7 | 8 | /// Generator responsible for generating OTel compatible. 9 | class IdGenerator implements api.IdGenerator { 10 | static final Random _random = Random.secure(); 11 | 12 | static List _generateId(int byteLength) { 13 | final buffer = []; 14 | for (var i = 0; i < byteLength; i++) { 15 | buffer.add(_random.nextInt(256)); 16 | } 17 | return buffer.cast(); 18 | } 19 | 20 | const IdGenerator(); 21 | 22 | @override 23 | List generateSpanId() => _generateId(8); 24 | 25 | @override 26 | List generateTraceId() => _generateId(16); 27 | } 28 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/read_only_span.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:fixnum/fixnum.dart'; 5 | 6 | import '../../../api.dart' as api; 7 | import '../../../sdk.dart' as sdk; 8 | import '../../sdk/common/attributes.dart'; 9 | 10 | /// A representation of the readable portions of a single operation 11 | /// within a trace. 12 | /// 13 | /// Warning: methods may be added to this interface in minor releases. 14 | abstract class ReadOnlySpan { 15 | /// The name of the span. 16 | String get name; 17 | 18 | /// The kind of the span. 19 | api.SpanKind get kind; 20 | 21 | /// The context associated with this span. 22 | /// 23 | /// This context is an immutable, serializable identifier for this span that 24 | /// can be used to create new child spans and remains usable even after this 25 | /// span ends. 26 | api.SpanContext get spanContext; 27 | 28 | /// The parent span id. 29 | api.SpanId get parentSpanId; 30 | 31 | /// The time when the span was started. 32 | Int64 get startTime; 33 | 34 | /// The time when the span was closed, or null if still open. 35 | Int64? get endTime; 36 | 37 | /// The status of the span. 38 | api.SpanStatus get status; 39 | 40 | List get events; 41 | 42 | int get droppedEventsCount; 43 | 44 | /// The instrumentation library for the span. 45 | sdk.InstrumentationScope get instrumentationScope; 46 | 47 | List get links; 48 | 49 | int get droppedLinksCount; 50 | 51 | Attributes get attributes; 52 | 53 | int get droppedAttributes; 54 | 55 | sdk.Resource get resource; 56 | } 57 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/read_write_span.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/api.dart' as api; 5 | import 'package:opentelemetry/sdk.dart' as sdk; 6 | 7 | abstract class ReadWriteSpan implements sdk.ReadOnlySpan, api.Span {} 8 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/sampling/always_off_sampler.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../../api.dart' as api; 5 | import '../../../../sdk.dart' as sdk; 6 | 7 | class AlwaysOffSampler implements sdk.Sampler { 8 | const AlwaysOffSampler(); 9 | 10 | @override 11 | String get description => 'AlwaysOffSampler'; 12 | 13 | @override 14 | sdk.SamplingResult shouldSample( 15 | api.Context context, 16 | api.TraceId traceId, 17 | String spanName, 18 | api.SpanKind spanKind, 19 | List spanAttributes, 20 | List links) { 21 | return sdk.SamplingResult(sdk.Decision.drop, spanAttributes, 22 | api.spanContextFromContext(context).traceState); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/sampling/always_on_sampler.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../../api.dart' as api; 5 | import '../../../../sdk.dart' as sdk; 6 | 7 | class AlwaysOnSampler implements sdk.Sampler { 8 | const AlwaysOnSampler(); 9 | 10 | @override 11 | String get description => 'AlwaysOnSampler'; 12 | 13 | @override 14 | sdk.SamplingResult shouldSample( 15 | api.Context context, 16 | api.TraceId traceId, 17 | String spanName, 18 | api.SpanKind spanKind, 19 | List spanAttributes, 20 | List spanLinks) { 21 | return sdk.SamplingResult(sdk.Decision.recordAndSample, spanAttributes, 22 | api.spanContextFromContext(context).traceState); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/sampling/parent_based_sampler.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../../api.dart' as api; 5 | import '../../../../sdk.dart' as sdk; 6 | 7 | class ParentBasedSampler implements sdk.Sampler { 8 | final sdk.Sampler _root; 9 | final sdk.Sampler _remoteParentSampled; 10 | final sdk.Sampler _remoteParentNotSampled; 11 | final sdk.Sampler _localParentSampled; 12 | final sdk.Sampler _localParentNotSampled; 13 | 14 | const ParentBasedSampler(this._root, 15 | {sdk.Sampler remoteParentSampled = const sdk.AlwaysOnSampler(), 16 | sdk.Sampler remoteParentNotSampled = const sdk.AlwaysOffSampler(), 17 | sdk.Sampler localParentSampled = const sdk.AlwaysOnSampler(), 18 | sdk.Sampler localParentNotSampled = const sdk.AlwaysOffSampler()}) 19 | : _remoteParentSampled = remoteParentSampled, 20 | _remoteParentNotSampled = remoteParentNotSampled, 21 | _localParentSampled = localParentSampled, 22 | _localParentNotSampled = localParentNotSampled; 23 | 24 | @override 25 | String get description => 'ParentBasedSampler{root=${_root.description}}'; 26 | 27 | @override 28 | sdk.SamplingResult shouldSample( 29 | api.Context context, 30 | api.TraceId traceId, 31 | String spanName, 32 | api.SpanKind spanKind, 33 | List spanAttributes, 34 | List spanLinks) { 35 | final parentSpanContext = api.spanContextFromContext(context); 36 | 37 | if (!parentSpanContext.isValid) { 38 | return _root.shouldSample( 39 | context, traceId, spanName, spanKind, spanAttributes, spanLinks); 40 | } 41 | 42 | if (parentSpanContext.isRemote) { 43 | return ((parentSpanContext.traceFlags & api.TraceFlags.sampled) == 44 | api.TraceFlags.sampled) 45 | ? _remoteParentSampled.shouldSample( 46 | context, traceId, spanName, spanKind, spanAttributes, spanLinks) 47 | : _remoteParentNotSampled.shouldSample( 48 | context, traceId, spanName, spanKind, spanAttributes, spanLinks); 49 | } 50 | 51 | return (parentSpanContext.traceFlags & api.TraceFlags.sampled) == 52 | api.TraceFlags.sampled 53 | ? _localParentSampled.shouldSample( 54 | context, traceId, spanName, spanKind, spanAttributes, spanLinks) 55 | : _localParentNotSampled.shouldSample( 56 | context, traceId, spanName, spanKind, spanAttributes, spanLinks); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/sampling/sampler.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../../api.dart' as api; 5 | import '../../../../sdk.dart' as sdk; 6 | 7 | /// Represents an entity which determines whether a [api.Span] should be sampled 8 | /// and sent for collection. 9 | abstract class Sampler { 10 | sdk.SamplingResult shouldSample( 11 | api.Context context, 12 | api.TraceId traceId, 13 | String spanName, 14 | api.SpanKind spanKind, 15 | List spanAttributes, 16 | List spanLinks); 17 | 18 | String get description; 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/sampling/sampling_result.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../../api.dart' as api; 5 | 6 | enum Decision { 7 | drop, 8 | recordOnly, 9 | recordAndSample, 10 | } 11 | 12 | class SamplingResult { 13 | final Decision decision; 14 | final List spanAttributes; 15 | final api.TraceState traceState; 16 | 17 | SamplingResult(this.decision, this.spanAttributes, this.traceState); 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/span_limits.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | class SpanLimits { 5 | static const _DEFAULT_MAXNUM_ATTRIBUTES = 128; 6 | static const _DEFAULT_MAXNUM_EVENTS = 128; 7 | static const _DEFAULT_MAXNUM_LINKS = 128; 8 | static const _DEFAULT_MAXNUM_ATTRIBUTES_PER_EVENT = 128; 9 | static const _DEFAULT_MAXNUM_ATTRIBUTES_PER_LINK = 128; 10 | static const _DEFAULT_MAXNUM_ATTRIBUTES_LENGTH = -1; 11 | 12 | final int _maxNumAttributes; 13 | final int _maxNumEvents; 14 | final int _maxNumLink; 15 | final int _maxNumAttributesPerEvent; 16 | final int _maxNumAttributesPerLink; 17 | final int _maxNumAttributeLength; 18 | 19 | ///setters 20 | ///Set the max number of attributes per span 21 | set maxNumAttributes(int maxNumberOfAttributes) { 22 | if (maxNumberOfAttributes < 0) { 23 | throw ArgumentError('maxNumEvents must be greater or equal to zero'); 24 | } 25 | } 26 | 27 | ///set the max number of events per span 28 | set maxNumEvents(int maxNumEvents) { 29 | if (maxNumEvents < 0) { 30 | throw ArgumentError('maxNumEvents must be greater or equal to zero'); 31 | } 32 | } 33 | 34 | ///set the max number of links per span 35 | set maxNumLink(int maxNumLink) { 36 | if (maxNumLink < 0) { 37 | throw ArgumentError('maxNumEvents must be greater than or equal to zero'); 38 | } 39 | } 40 | 41 | ///set the max number of attributes per event 42 | set maxNumAttributesPerEvent(int maxNumAttributesPerEvent) { 43 | if (maxNumAttributesPerEvent < 0) { 44 | throw ArgumentError('maxNumEvents must be greater than or equal to zero'); 45 | } 46 | } 47 | 48 | ///set the max number of attributes per link 49 | set maxNumAttributesPerLink(int maxNumAttributesPerLink) { 50 | if (maxNumAttributesPerLink < 0) { 51 | throw ArgumentError('maxNumEvents must be greater than or equal to zero'); 52 | } 53 | } 54 | 55 | ///return the maximum allowed attribute value length. 56 | ///This limits only applies to string and string list attribute values. 57 | ///Any string longer than this value will be truncated to this length. 58 | /// 59 | ///default is unlimited. 60 | set maxNumAttributeLength(int maxNumAttributeLength) { 61 | if (maxNumAttributeLength < 0) { 62 | throw ArgumentError('maxNumEvents must be greater than or equal to zero'); 63 | } 64 | } 65 | 66 | ///getters 67 | ///return the max number of attributes per span 68 | int get maxNumAttributes => _maxNumAttributes; 69 | 70 | ///return the max number of events per span 71 | int get maxNumEvents => _maxNumEvents; 72 | 73 | ///return the max number of links per span 74 | int get maxNumLink => _maxNumLink; 75 | 76 | ///return the max number of attributes per event 77 | int get maxNumAttributesPerEvent => _maxNumAttributesPerEvent; 78 | 79 | ///return the max number of attributes per link 80 | int get maxNumAttributesPerLink => _maxNumAttributesPerLink; 81 | 82 | ///return the maximum allowed attribute value length. 83 | ///This limits only applies to string and string list attribute values. 84 | ///Any string longer than this value will be truncated to this length. 85 | /// 86 | ///default is unlimited. 87 | int get maxNumAttributeLength => _maxNumAttributeLength; 88 | 89 | const SpanLimits( 90 | {int maxNumAttributes = _DEFAULT_MAXNUM_ATTRIBUTES, 91 | int maxNumEvents = _DEFAULT_MAXNUM_EVENTS, 92 | int maxNumLink = _DEFAULT_MAXNUM_LINKS, 93 | int maxNumAttributesPerEvent = _DEFAULT_MAXNUM_ATTRIBUTES_PER_EVENT, 94 | int maxNumAttributesPerLink = _DEFAULT_MAXNUM_ATTRIBUTES_PER_LINK, 95 | int maxNumAttributeLength = _DEFAULT_MAXNUM_ATTRIBUTES_LENGTH}) 96 | : _maxNumAttributes = maxNumAttributes, 97 | _maxNumEvents = maxNumEvents, 98 | _maxNumLink = maxNumLink, 99 | _maxNumAttributesPerEvent = maxNumAttributesPerEvent, 100 | _maxNumAttributesPerLink = maxNumAttributesPerLink, 101 | _maxNumAttributeLength = maxNumAttributeLength; 102 | } 103 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/span_processors/batch_processor.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'dart:async'; 5 | import 'dart:math'; 6 | 7 | import 'package:logging/logging.dart'; 8 | 9 | import '../../../api/context/context.dart'; 10 | import '../../../api/trace/trace_flags.dart'; 11 | import '../exporters/span_exporter.dart'; 12 | import '../read_only_span.dart'; 13 | import '../read_write_span.dart'; 14 | import 'span_processor.dart'; 15 | 16 | class BatchSpanProcessor implements SpanProcessor { 17 | static const int _DEFAULT_MAXIMUM_BATCH_SIZE = 512; 18 | static const int _DEFAULT_MAXIMUM_QUEUE_SIZE = 2048; 19 | static const int _DEFAULT_EXPORT_DELAY = 5000; 20 | 21 | final SpanExporter _exporter; 22 | final Logger _log = Logger('opentelemetry.BatchSpanProcessor'); 23 | final int _maxExportBatchSize; 24 | final int _maxQueueSize; 25 | final List _spanBuffer = []; 26 | 27 | late final Timer _timer; 28 | 29 | bool _isShutdown = false; 30 | 31 | BatchSpanProcessor(this._exporter, 32 | {int maxExportBatchSize = _DEFAULT_MAXIMUM_BATCH_SIZE, 33 | int scheduledDelayMillis = _DEFAULT_EXPORT_DELAY}) 34 | : _maxExportBatchSize = maxExportBatchSize, 35 | _maxQueueSize = _DEFAULT_MAXIMUM_QUEUE_SIZE { 36 | _timer = Timer.periodic( 37 | Duration(milliseconds: scheduledDelayMillis), _exportBatch); 38 | } 39 | 40 | @override 41 | void forceFlush() { 42 | if (_isShutdown) { 43 | return; 44 | } 45 | while (_spanBuffer.isNotEmpty) { 46 | _exportBatch(_timer); 47 | } 48 | } 49 | 50 | @override 51 | void onEnd(ReadOnlySpan span) { 52 | if (_isShutdown) { 53 | return; 54 | } 55 | _addToBuffer(span); 56 | } 57 | 58 | @override 59 | void onStart(ReadWriteSpan span, Context parentContext) {} 60 | 61 | @override 62 | void shutdown() { 63 | forceFlush(); 64 | _isShutdown = true; 65 | _timer.cancel(); 66 | _exporter.shutdown(); 67 | } 68 | 69 | void _addToBuffer(ReadOnlySpan span) { 70 | if (_spanBuffer.length >= _maxQueueSize) { 71 | // Buffer is full, drop span. 72 | _log.warning( 73 | 'Max queue size exceeded. Dropping ${_spanBuffer.length} spans.'); 74 | return; 75 | } 76 | 77 | final isSampled = 78 | span.spanContext.traceFlags & TraceFlags.sampled == TraceFlags.sampled; 79 | if (isSampled) { 80 | _spanBuffer.add(span); 81 | } 82 | } 83 | 84 | void _exportBatch(Timer timer) { 85 | if (_spanBuffer.isEmpty) { 86 | return; 87 | } 88 | 89 | final batchSize = min(_spanBuffer.length, _maxExportBatchSize); 90 | final batch = _spanBuffer.sublist(0, batchSize); 91 | _spanBuffer.removeRange(0, batchSize); 92 | 93 | _exporter.export(batch); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/span_processors/simple_processor.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../api/context/context.dart'; 5 | import '../../../api/trace/trace_flags.dart'; 6 | import '../exporters/span_exporter.dart'; 7 | import '../read_only_span.dart'; 8 | import '../read_write_span.dart'; 9 | import 'span_processor.dart'; 10 | 11 | class SimpleSpanProcessor implements SpanProcessor { 12 | final SpanExporter _exporter; 13 | bool _isShutdown = false; 14 | 15 | SimpleSpanProcessor(this._exporter); 16 | 17 | @override 18 | void forceFlush() {} 19 | 20 | @override 21 | void onEnd(ReadOnlySpan span) { 22 | if (_isShutdown) { 23 | return; 24 | } 25 | 26 | final isSampled = 27 | span.spanContext.traceFlags & TraceFlags.sampled == TraceFlags.sampled; 28 | if (isSampled) { 29 | _exporter.export([span]); 30 | } 31 | } 32 | 33 | @override 34 | void onStart(ReadWriteSpan span, Context parentContext) {} 35 | 36 | @override 37 | void shutdown() { 38 | _isShutdown = true; 39 | _exporter.shutdown(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/span_processors/span_processor.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import '../../../../api.dart' as api; 5 | import '../../../../sdk.dart' as sdk; 6 | 7 | abstract class SpanProcessor { 8 | void onStart(sdk.ReadWriteSpan span, api.Context parentContext); 9 | 10 | void onEnd(sdk.ReadOnlySpan span); 11 | 12 | void shutdown(); 13 | 14 | void forceFlush(); 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/tracer.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:fixnum/fixnum.dart'; 5 | import 'package:meta/meta.dart'; 6 | 7 | import '../../../api.dart' as api; 8 | import '../../../sdk.dart' as sdk; 9 | import '../common/limits.dart' show applyLinkLimits; 10 | import 'span.dart'; 11 | 12 | /// An interface for creating [api.Span]s and propagating context in-process. 13 | class Tracer implements api.Tracer { 14 | final List _processors; 15 | final sdk.Resource _resource; 16 | final sdk.Sampler _sampler; 17 | final sdk.TimeProvider _timeProvider; 18 | final api.IdGenerator _idGenerator; 19 | final sdk.InstrumentationScope _instrumentationScope; 20 | final sdk.SpanLimits _limits; 21 | 22 | @protected 23 | const Tracer( 24 | this._processors, 25 | this._resource, 26 | this._sampler, 27 | this._timeProvider, 28 | this._idGenerator, 29 | this._instrumentationScope, 30 | this._limits); 31 | 32 | @override 33 | api.Span startSpan(String name, 34 | {api.Context? context, 35 | api.SpanKind kind = api.SpanKind.internal, 36 | List attributes = const [], 37 | List links = const [], 38 | Int64? startTime, 39 | bool newRoot = false}) { 40 | context ??= api.Context.current; 41 | startTime ??= _timeProvider.now; 42 | 43 | // If a valid, active Span is present in the context, use it as this Span's 44 | // parent. If the Context does not contain an active parent Span, create 45 | // a root Span with a new Trace ID and default state. 46 | // See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#determining-the-parent-span-from-a-context 47 | final psc = newRoot 48 | ? api.SpanContext.invalid() 49 | : api.spanContextFromContext(context); 50 | final traceId = psc.traceId.isValid 51 | ? psc.traceId 52 | : api.TraceId.fromIdGenerator(_idGenerator); 53 | final spanId = api.SpanId.fromIdGenerator(_idGenerator); 54 | final samplerResult = 55 | _sampler.shouldSample(context, traceId, name, kind, attributes, links); 56 | final traceFlags = (samplerResult.decision == sdk.Decision.recordAndSample) 57 | ? api.TraceFlags.sampled 58 | : api.TraceFlags.none; 59 | final spanContext = 60 | api.SpanContext(traceId, spanId, traceFlags, psc.traceState); 61 | 62 | final span = Span( 63 | name, 64 | spanContext, 65 | psc.spanId, 66 | _processors, 67 | _timeProvider, 68 | _resource, 69 | _instrumentationScope, 70 | kind, 71 | applyLinkLimits(links, _limits), 72 | _limits, 73 | startTime) 74 | ..setAttributes(attributes); 75 | 76 | for (var i = 0; i < _processors.length; i++) { 77 | _processors[i].onStart(span, context); 78 | } 79 | 80 | return span; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /lib/src/sdk/trace/tracer_provider.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:meta/meta.dart'; 5 | 6 | import './tracer.dart'; 7 | import '../../../api.dart' as api; 8 | import '../../../sdk.dart' as sdk; 9 | 10 | /// A registry for creating named [api.Tracer]s. 11 | class TracerProviderBase implements api.TracerProvider { 12 | @protected 13 | final Map tracers = {}; 14 | 15 | @protected 16 | final List processors; 17 | 18 | @protected 19 | final sdk.Resource resource; 20 | 21 | @protected 22 | final sdk.Sampler sampler; 23 | 24 | @protected 25 | final api.IdGenerator idGenerator; 26 | 27 | @protected 28 | final sdk.SpanLimits spanLimits; 29 | 30 | final sdk.TimeProvider _timeProvider; 31 | 32 | TracerProviderBase( 33 | {this.processors = 34 | const [], // Default to a TracerProvider which does not emit traces. 35 | resource, 36 | sdk.TimeProvider? timeProvider, 37 | this.sampler = const sdk.ParentBasedSampler(sdk.AlwaysOnSampler()), 38 | this.idGenerator = const sdk.IdGenerator(), 39 | this.spanLimits = const sdk.SpanLimits()}) 40 | : resource = resource ?? sdk.Resource([]), 41 | _timeProvider = timeProvider ?? sdk.DateTimeTimeProvider(); 42 | 43 | List get spanProcessors => processors; 44 | 45 | @override 46 | api.Tracer getTracer(String name, 47 | {String version = '', 48 | String schemaUrl = '', 49 | List attributes = const []}) { 50 | final key = '$name@$version'; 51 | return tracers.putIfAbsent( 52 | key, 53 | () => Tracer( 54 | processors, 55 | resource, 56 | sampler, 57 | _timeProvider, 58 | idGenerator, 59 | sdk.InstrumentationScope(name, version, schemaUrl, attributes), 60 | spanLimits)); 61 | } 62 | 63 | @override 64 | void forceFlush() { 65 | for (var i = 0; i < processors.length; i++) { 66 | processors[i].forceFlush(); 67 | } 68 | } 69 | 70 | @override 71 | void shutdown() { 72 | for (var i = 0; i < processors.length; i++) { 73 | processors[i].shutdown(); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /lib/web_sdk.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | export 'src/sdk/platforms/web/time_providers/web_time_provider.dart' 5 | show fromDOMHighResTimeStamp, timeOrigin, WebTimeProvider; 6 | export 'src/sdk/platforms/web/trace/web_tracer_provider.dart' 7 | show WebTracerProvider; 8 | -------------------------------------------------------------------------------- /package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | mkdir pub_temp 5 | 6 | # Make a copy of the directories we want to publish, with symlinks expanded 7 | [ -d lib ] && cp -R -L lib pub_temp/lib 8 | 9 | # Make a copy of the files we want to publish 10 | [ -f CHANGELOG.md ] && cp CHANGELOG.md pub_temp/ 11 | [ -f LICENSE ] && cp LICENSE pub_temp/ 12 | [ -f NOTICE ] && cp NOTICE pub_temp/ 13 | [ -f README.md ] && cp README.md pub_temp/ 14 | [ -f analysis_options.yaml ] && cp analysis_options.yaml pub_temp/ 15 | [ -f pubspec.yaml ] && cp pubspec.yaml pub_temp/ 16 | 17 | # Generate the final publishable artifact 18 | cd pub_temp 19 | tar czf ../pub_package.pub.tgz . 20 | cd ../ 21 | 22 | # Clean up 23 | rm -rf pub_temp 24 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: opentelemetry 2 | version: 0.18.10 3 | description: A framework for collecting OpenTelemetry traces from applications. 4 | homepage: https://github.com/Workiva/opentelemetry-dart 5 | environment: 6 | sdk: '>=2.19.0 <4.0.0' 7 | 8 | dependencies: 9 | async: '>=2.5.0 <3.0.0' 10 | collection: ^1.15.0 11 | fixnum: '>=1.0.0 <2.0.0' 12 | http: '>=0.13.0 <2.0.0' 13 | logging: ^1.0.0 14 | meta: '>=1.9.1 <2.0.0' 15 | protobuf: ">=2.0.0 <5.0.0" 16 | quiver: '>=3.0.0 <4.0.0' 17 | 18 | dev_dependencies: 19 | build_runner: ^2.3.3 20 | build_test: ^2.2.1 21 | build_web_compilers: '>=3.2.7 <5.0.0' 22 | mocktail: ^1.0.3 23 | remove_from_coverage: ^2.0.0 24 | test: ^1.24.2 25 | workiva_analysis_options: ^1.2.2 26 | -------------------------------------------------------------------------------- /scripts/attach_copyright.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | HERE="$(dirname "$0")" 4 | # Locate and array filenames of all Dart files in this repository which do not contain "Copyright YYYY-YYYY Workiva". 5 | IFS=$'\n' read -r -d '' -a FILES <<<"$(find . -type f -name '*.dart' -print0 | xargs -0 grep -E -L 'Copyright \d+-\d+ Workiva')" 6 | 7 | echo "Scanning files and attaching copyright..." 8 | 9 | for FILE in "${FILES[@]}"; do 10 | mv "$FILE" "$FILE".old 11 | cat "$HERE"/copyright_notice.txt "$FILE".old > "$FILE" 12 | rm "$FILE".old 13 | printf 'Updated: %s\n' "$FILE" 14 | done 15 | 16 | echo "...done." 17 | -------------------------------------------------------------------------------- /scripts/copyright_notice.txt: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | -------------------------------------------------------------------------------- /test/api/context/context_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | 6 | import 'dart:async'; 7 | 8 | import 'package:opentelemetry/api.dart' as api; 9 | import 'package:opentelemetry/sdk.dart' as sdk; 10 | import 'package:opentelemetry/src/experimental_api.dart'; 11 | import 'package:opentelemetry/src/sdk/trace/span.dart'; 12 | import 'package:test/test.dart'; 13 | 14 | void main() { 15 | final testSpanContext = api.SpanContext(api.TraceId([1, 2, 3]), 16 | api.SpanId([7, 8, 9]), api.TraceFlags.none, api.TraceState.empty()); 17 | final testSpan = Span( 18 | 'foo', 19 | testSpanContext, 20 | api.SpanId([4, 5, 6]), 21 | [], 22 | sdk.DateTimeTimeProvider(), 23 | sdk.Resource([]), 24 | sdk.InstrumentationScope( 25 | 'library_name', 'library_version', 'url://schema', []), 26 | api.SpanKind.client, 27 | [], 28 | sdk.SpanLimits(), 29 | sdk.DateTimeTimeProvider().now); 30 | 31 | group('contextWithSpan', () { 32 | test('returns a new Context with the Span', () { 33 | final context = api.contextWithSpan(api.Context.current, testSpan); 34 | expect(api.Context.current, isNot(same(context))); 35 | expect(api.spanFromContext(context), same(testSpan)); 36 | }); 37 | }); 38 | 39 | group('contextWithSpanContext', () { 40 | test('returns a new Context with the SpanContext', () { 41 | final context = 42 | api.contextWithSpanContext(api.Context.current, testSpanContext); 43 | expect(api.Context.current, isNot(same(context))); 44 | expect(api.spanContextFromContext(context), same(testSpanContext)); 45 | }); 46 | }); 47 | 48 | group('spanFromContext', () { 49 | test('returns Span when exists', () { 50 | final context = api.contextWithSpan(api.Context.current, testSpan); 51 | expect(api.spanFromContext(context), same(testSpan)); 52 | }); 53 | 54 | test('returns an invalid Span when Span doesn\'t exist', () { 55 | final context = api.Context.current; 56 | expect(api.spanFromContext(context), isA()); 57 | expect(api.spanContextFromContext(context).isValid, isFalse); 58 | }); 59 | }); 60 | 61 | group('spanContextFromContext', () { 62 | test('returns SpanContext when Span exists', () { 63 | final testContext = api.contextWithSpan(api.Context.current, testSpan); 64 | expect(api.spanContextFromContext(testContext), same(testSpanContext)); 65 | }); 66 | 67 | test('returns an invalid SpanContext when Span doesn\'t exist', () { 68 | expect(api.spanContextFromContext(api.Context.current).isValid, isFalse); 69 | }); 70 | }); 71 | 72 | group('Context.current', () { 73 | test('returns root context', () { 74 | expect(api.Context.current, same(api.Context.root)); 75 | }); 76 | 77 | test('returns attached context', () { 78 | final context = api.Context.root.setValue(api.ContextKey(), 'foo'); 79 | final token = api.Context.attach(context); 80 | expect(api.Context.current, same(context)); 81 | expect(api.Context.detach(token), isTrue); 82 | expect(api.Context.current, same(api.Context.root)); 83 | }); 84 | 85 | test('returns non-root stack attached context', () { 86 | final context1 = api.Context.root.setValue(api.ContextKey(), 'foo'); 87 | final token = api.Context.attach(context1); 88 | Zone.current.run(() { 89 | final context2 = api.Context.root.setValue(api.ContextKey(), 'bar'); 90 | final token = api.Context.attach(context2); 91 | expect(api.Context.current, same(context2)); 92 | expect(api.Context.detach(token), isTrue); 93 | expect(api.Context.current, same(context1)); 94 | }); 95 | expect(api.Context.detach(token), isTrue); 96 | }); 97 | }); 98 | 99 | group('Context.detach', () { 100 | test('returns true on match', () { 101 | final token = api.Context.attach(api.Context.current); 102 | expect(api.Context.detach(token), isTrue); 103 | }); 104 | 105 | test('returns false on mismatch', () { 106 | final token1 = api.Context.attach(api.Context.current); 107 | final token2 = api.Context.attach(api.Context.current); 108 | expect(api.Context.detach(token1), isFalse); 109 | expect(api.Context.detach(token2), isTrue); 110 | }); 111 | 112 | test('returns true on match in nested zone', () { 113 | final token1 = api.Context.attach(api.Context.current); 114 | Zone.current.fork().run(() { 115 | final token2 = api.Context.attach(api.Context.current); 116 | Zone.current.fork().run(() { 117 | expect(api.Context.detach(token2), isTrue); 118 | expect(api.Context.detach(token1), isTrue); 119 | }); 120 | }); 121 | }); 122 | }); 123 | } 124 | -------------------------------------------------------------------------------- /test/api/open_telemetry_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | 6 | import 'package:opentelemetry/api.dart'; 7 | import 'package:opentelemetry/sdk.dart' as sdk; 8 | import 'package:opentelemetry/src/sdk/trace/span.dart' as sdk show Span; 9 | import 'package:opentelemetry/src/sdk/trace/tracer.dart' as sdk show Tracer; 10 | import 'package:test/test.dart'; 11 | 12 | void main() { 13 | final tracer = sdk.Tracer([], 14 | sdk.Resource([]), 15 | sdk.AlwaysOnSampler(), 16 | sdk.DateTimeTimeProvider(), 17 | sdk.IdGenerator(), 18 | sdk.InstrumentationScope('name', 'version', 'url://schema', []), 19 | sdk.SpanLimits()); 20 | 21 | test('trace starts and ends span', () async { 22 | final span = await trace('span', () async { 23 | return spanFromContext(Context.current); 24 | }, tracer: tracer) as sdk.Span; 25 | 26 | expect(span.startTime, isNotNull); 27 | expect(span.endTime, isNotNull); 28 | }); 29 | 30 | test('traceSync starts and ends span', () { 31 | final span = traceSync('span', () { 32 | return spanFromContext(Context.current); 33 | }, tracer: tracer) as sdk.Span; 34 | 35 | expect(span.startTime, isNotNull); 36 | expect(span.endTime, isNotNull); 37 | }); 38 | 39 | test('trace propagates context', () { 40 | final parent = tracer.startSpan('parent')..end(); 41 | 42 | trace('child', () async { 43 | final child = spanFromContext(Context.current); 44 | 45 | expect(child.parentSpanId.toString(), 46 | equals(parent.spanContext.spanId.toString())); 47 | }, tracer: tracer, context: contextWithSpan(Context.current, parent)); 48 | }); 49 | 50 | test('traceSync propagates context', () { 51 | final parent = tracer.startSpan('parent')..end(); 52 | 53 | traceSync('span', () { 54 | final child = spanFromContext(Context.current); 55 | 56 | expect(child.parentSpanId.toString(), 57 | equals(parent.spanContext.spanId.toString())); 58 | }, tracer: tracer, context: contextWithSpan(Context.current, parent)); 59 | }); 60 | 61 | test('trace creates a root span', () async { 62 | final parent = tracer.startSpan('parent')..end(); 63 | final context = contextWithSpan(Context.current, parent); 64 | final token = Context.attach(context); 65 | 66 | await trace('child', () async { 67 | final child = spanFromContext(Context.current); 68 | expect(child.parentSpanId.isValid, isFalse); 69 | }, tracer: tracer, context: context, newRoot: true); 70 | 71 | Context.detach(token); 72 | }); 73 | 74 | test('traceSync creates a root span', () { 75 | final parent = tracer.startSpan('parent')..end(); 76 | final context = contextWithSpan(Context.current, parent); 77 | final token = Context.attach(context); 78 | 79 | traceSync('child', () { 80 | final child = spanFromContext(Context.current); 81 | expect(child.parentSpanId.isValid, isFalse); 82 | }, tracer: tracer, context: context, newRoot: true); 83 | 84 | Context.detach(token); 85 | }); 86 | 87 | test('trace catches, records, and rethrows exception', () async { 88 | late sdk.Span span; 89 | var caught = false; 90 | try { 91 | await trace('span', () async { 92 | span = spanFromContext(Context.current) as sdk.Span; 93 | throw Exception('Bang!'); 94 | }, tracer: tracer); 95 | } catch (e) { 96 | caught = true; 97 | } finally { 98 | expect(caught, isTrue); 99 | expect(span.endTime, isNotNull); 100 | expect(span.status.code, equals(StatusCode.error)); 101 | expect(span.status.description, equals('Exception: Bang!')); 102 | expect(span.events, [ 103 | hasExceptionEvent({ 104 | SemanticAttributes.exceptionType: '_Exception', 105 | SemanticAttributes.exceptionMessage: 'Exception: Bang!', 106 | SemanticAttributes.exceptionStacktrace: anything, 107 | SemanticAttributes.exceptionEscaped: true, 108 | }) 109 | ]); 110 | } 111 | }); 112 | 113 | test('traceSync catches, records, and rethrows exception', () async { 114 | late sdk.Span span; 115 | var caught = false; 116 | try { 117 | traceSync('span', () { 118 | span = spanFromContext(Context.current) as sdk.Span; 119 | throw Exception('Bang!'); 120 | }, tracer: tracer); 121 | } catch (e) { 122 | caught = true; 123 | } finally { 124 | expect(caught, isTrue); 125 | expect(span.endTime, isNotNull); 126 | expect(span.status.code, equals(StatusCode.error)); 127 | expect(span.status.description, equals('Exception: Bang!')); 128 | expect(span.events, [ 129 | hasExceptionEvent({ 130 | SemanticAttributes.exceptionType: '_Exception', 131 | SemanticAttributes.exceptionMessage: 'Exception: Bang!', 132 | SemanticAttributes.exceptionStacktrace: anything, 133 | SemanticAttributes.exceptionEscaped: true, 134 | }) 135 | ]); 136 | } 137 | }); 138 | } 139 | 140 | Matcher hasExceptionEvent(Map attributes) => 141 | isA().having( 142 | (e) => e.attributes, 143 | 'attributes', 144 | isA>().having( 145 | (a) => a.map((e) => [e.key, e.value]), 146 | 'attributes', 147 | containsAll(attributes.entries.map((e) => [e.key, e.value])))); 148 | -------------------------------------------------------------------------------- /test/integration/sdk/tracer_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/api.dart' as api; 6 | import 'package:opentelemetry/sdk.dart' as sdk; 7 | import 'package:opentelemetry/src/sdk/trace/span.dart'; 8 | import 'package:opentelemetry/src/sdk/trace/tracer.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | void main() { 12 | test('startSpan new trace', () { 13 | final tracer = Tracer( 14 | [], 15 | sdk.Resource([]), 16 | sdk.AlwaysOnSampler(), 17 | sdk.DateTimeTimeProvider(), 18 | sdk.IdGenerator(), 19 | sdk.InstrumentationScope( 20 | 'library_name', 'library_version', 'url://schema', []), 21 | sdk.SpanLimits()); 22 | 23 | final span = tracer.startSpan('foo') as Span; 24 | 25 | expect(span.startTime, isNotNull); 26 | expect(span.endTime, isNull); 27 | expect(span.spanContext.traceId, isNotNull); 28 | expect(span.spanContext.spanId, isNotNull); 29 | }); 30 | 31 | test('startSpan child span', () { 32 | final tracer = Tracer( 33 | [], 34 | sdk.Resource([]), 35 | sdk.AlwaysOnSampler(), 36 | sdk.DateTimeTimeProvider(), 37 | sdk.IdGenerator(), 38 | sdk.InstrumentationScope( 39 | 'library_name', 'library_version', 'url://schema', []), 40 | sdk.SpanLimits()); 41 | 42 | final parentSpan = tracer.startSpan('foo'); 43 | final context = api.contextWithSpan(api.Context.current, parentSpan); 44 | 45 | final childSpan = tracer.startSpan('bar', context: context) as Span; 46 | 47 | expect(childSpan.startTime, isNotNull); 48 | expect(childSpan.endTime, isNull); 49 | expect( 50 | childSpan.spanContext.traceId, equals(parentSpan.spanContext.traceId)); 51 | expect(childSpan.spanContext.traceState, 52 | equals(parentSpan.spanContext.traceState)); 53 | expect(childSpan.spanContext.spanId, 54 | allOf([isNotNull, isNot(equals(parentSpan.spanContext.spanId))])); 55 | }); 56 | } 57 | -------------------------------------------------------------------------------- /test/sdk/trace/span_processors/batch_processor_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/api.dart' 6 | show SpanContext, SpanId, SpanKind, TraceFlags, TraceId, TraceState; 7 | import 'package:opentelemetry/sdk.dart'; 8 | import 'package:opentelemetry/src/sdk/trace/span.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | class TestSpanExporter extends SpanExporter { 12 | final spans = []; 13 | 14 | bool isShutdown = false; 15 | 16 | @override 17 | void export(List spans) { 18 | this.spans.addAll(spans); 19 | } 20 | 21 | @override 22 | void forceFlush() {} 23 | 24 | @override 25 | void shutdown() { 26 | isShutdown = true; 27 | } 28 | } 29 | 30 | void main() { 31 | final sampledSpanContext = SpanContext(TraceId([1, 2, 3]), SpanId([7, 8, 9]), 32 | TraceFlags.sampled, TraceState.empty()); 33 | final sampledSpan = Span( 34 | 'foo', 35 | sampledSpanContext, 36 | SpanId([4, 5, 6]), 37 | [], 38 | DateTimeTimeProvider(), 39 | Resource([]), 40 | InstrumentationScope( 41 | 'library_name', 'library_version', 'url://schema', []), 42 | SpanKind.client, 43 | [], 44 | SpanLimits(), 45 | DateTimeTimeProvider().now); 46 | 47 | final unsampledSpanContext = SpanContext(TraceId([1, 2, 3]), 48 | SpanId([7, 8, 9]), TraceFlags.none, TraceState.empty()); 49 | final unsampledSpan = Span( 50 | 'foo', 51 | unsampledSpanContext, 52 | SpanId([4, 5, 6]), 53 | [], 54 | DateTimeTimeProvider(), 55 | Resource([]), 56 | InstrumentationScope( 57 | 'library_name', 'library_version', 'url://schema', []), 58 | SpanKind.client, 59 | [], 60 | SpanLimits(), 61 | DateTimeTimeProvider().now); 62 | 63 | late TestSpanExporter exporter; 64 | late BatchSpanProcessor processor; 65 | 66 | setUp(() { 67 | exporter = TestSpanExporter(); 68 | processor = BatchSpanProcessor(exporter, 69 | maxExportBatchSize: 2, scheduledDelayMillis: 60 * 60 * 1000); 70 | }); 71 | 72 | group('onEnd', () { 73 | test('adds sampled span to buffer', () { 74 | processor.onEnd(sampledSpan); 75 | expect(exporter.spans, isEmpty); 76 | processor.forceFlush(); 77 | expect(exporter.spans, [sampledSpan]); 78 | }); 79 | 80 | test('does not add unsampled span to buffer', () { 81 | processor.onEnd(unsampledSpan); 82 | expect(exporter.spans, isEmpty); 83 | processor.forceFlush(); 84 | expect(exporter.spans, isEmpty); 85 | }); 86 | 87 | test('does not add span to buffer after shutdown', () { 88 | processor 89 | ..shutdown() 90 | ..onEnd(sampledSpan) 91 | ..forceFlush(); 92 | expect(exporter.spans, isEmpty); 93 | }); 94 | }); 95 | 96 | group('forceFlush', () { 97 | test('flushes buffer', () { 98 | processor 99 | ..onEnd(sampledSpan) 100 | ..forceFlush(); 101 | expect(exporter.spans, [sampledSpan]); 102 | }); 103 | }); 104 | 105 | group('shutdown', () { 106 | test('calls exporter.shutdown()', () { 107 | processor.shutdown(); 108 | expect(exporter.isShutdown, isTrue); 109 | }); 110 | }); 111 | } 112 | -------------------------------------------------------------------------------- /test/sdk/trace/span_processors/simple_processor_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/api.dart' 6 | show SpanContext, SpanId, SpanKind, TraceFlags, TraceId, TraceState; 7 | import 'package:opentelemetry/sdk.dart'; 8 | import 'package:opentelemetry/src/sdk/trace/span.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | class TestSpanExporter extends SpanExporter { 12 | final spans = []; 13 | 14 | bool isShutdown = false; 15 | 16 | @override 17 | void export(List spans) { 18 | this.spans.addAll(spans); 19 | } 20 | 21 | @override 22 | void forceFlush() {} 23 | 24 | @override 25 | void shutdown() { 26 | isShutdown = true; 27 | } 28 | } 29 | 30 | void main() { 31 | final sampledSpanContext = SpanContext(TraceId([1, 2, 3]), SpanId([7, 8, 9]), 32 | TraceFlags.sampled, TraceState.empty()); 33 | final sampledSpan = Span( 34 | 'foo', 35 | sampledSpanContext, 36 | SpanId([4, 5, 6]), 37 | [], 38 | DateTimeTimeProvider(), 39 | Resource([]), 40 | InstrumentationScope( 41 | 'library_name', 'library_version', 'url://schema', []), 42 | SpanKind.client, 43 | [], 44 | SpanLimits(), 45 | DateTimeTimeProvider().now); 46 | 47 | final unsampledSpanContext = SpanContext(TraceId([1, 2, 3]), 48 | SpanId([7, 8, 9]), TraceFlags.none, TraceState.empty()); 49 | final unsampledSpan = Span( 50 | 'foo', 51 | unsampledSpanContext, 52 | SpanId([4, 5, 6]), 53 | [], 54 | DateTimeTimeProvider(), 55 | Resource([]), 56 | InstrumentationScope( 57 | 'library_name', 'library_version', 'url://schema', []), 58 | SpanKind.client, 59 | [], 60 | SpanLimits(), 61 | DateTimeTimeProvider().now); 62 | 63 | late TestSpanExporter exporter; 64 | late SimpleSpanProcessor processor; 65 | 66 | setUp(() { 67 | exporter = TestSpanExporter(); 68 | processor = SimpleSpanProcessor(exporter); 69 | }); 70 | 71 | group('onEnd', () { 72 | test('exports sampled span', () { 73 | processor.onEnd(sampledSpan); 74 | expect(exporter.spans, [sampledSpan]); 75 | }); 76 | 77 | test('does not export unsampled span', () { 78 | processor.onEnd(unsampledSpan); 79 | expect(exporter.spans, isEmpty); 80 | }); 81 | 82 | test('does not export after shutdown', () { 83 | processor 84 | ..shutdown() 85 | ..onEnd(sampledSpan); 86 | expect(exporter.spans, isEmpty); 87 | }); 88 | }); 89 | 90 | group('shutdown', () { 91 | test('calls exporter.shutdown()', () { 92 | processor.shutdown(); 93 | expect(exporter.isShutdown, isTrue); 94 | }); 95 | }); 96 | } 97 | -------------------------------------------------------------------------------- /test/unit/api/context/map_context_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:opentelemetry/api.dart' as api; 5 | import 'package:opentelemetry/sdk.dart' as sdk; 6 | import 'package:opentelemetry/src/experimental_api.dart'; 7 | import 'package:opentelemetry/src/sdk/trace/span.dart'; 8 | import 'package:test/test.dart'; 9 | import 'package:opentelemetry/src/api/context/map_context.dart'; 10 | 11 | void main() { 12 | final testSpanContext = api.SpanContext(api.TraceId([1, 2, 3]), 13 | api.SpanId([7, 8, 9]), api.TraceFlags.none, api.TraceState.empty()); 14 | final testSpan = Span( 15 | 'foo', 16 | testSpanContext, 17 | api.SpanId([4, 5, 6]), 18 | [], 19 | sdk.DateTimeTimeProvider(), 20 | sdk.Resource([]), 21 | sdk.InstrumentationScope( 22 | 'library_name', 'library_version', 'url://schema', []), 23 | api.SpanKind.client, 24 | [], 25 | sdk.SpanLimits(), 26 | sdk.DateTimeTimeProvider().now); 27 | group('MapContext', () { 28 | test('getValue returns null if key is not set', () { 29 | final context = createMapContext(); 30 | final key = api.ContextKey(); 31 | expect(context.getValue(key), isNull); 32 | }); 33 | 34 | test('setValue returns a new context with the value set', () { 35 | final context = createMapContext(); 36 | final key = api.ContextKey(); 37 | const value = 'testValue'; 38 | final newContext = context.setValue(key, value); 39 | expect(newContext, isNot(same(context))); 40 | expect(context.getValue(key), isNull); 41 | expect(newContext.getValue(key), equals(value)); 42 | }); 43 | 44 | test('withSpan returns a new context with the span set', () { 45 | final context = createMapContext(); 46 | final newContext = context.withSpan(testSpan); 47 | expect(newContext, isNot(same(context))); 48 | expect(api.spanFromContext(newContext), equals(testSpan)); 49 | }); 50 | 51 | test('execute runs the given function', () { 52 | final context = createMapContext(); 53 | var ran = false; 54 | context.execute(() { 55 | ran = true; 56 | }); 57 | expect(ran, isTrue); 58 | }); 59 | 60 | test('span returns the span if set, or an invalid span if not', () { 61 | final context = createMapContext(); 62 | expect(context.span, isA()); 63 | final newContext = context.withSpan(testSpan); 64 | expect(api.spanFromContext(newContext), equals(testSpan)); 65 | }); 66 | }); 67 | } 68 | -------------------------------------------------------------------------------- /test/unit/api/context/zone_context_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'dart:async'; 6 | 7 | import 'package:opentelemetry/api.dart'; 8 | import 'package:opentelemetry/src/api/context/zone_context.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | void main() { 12 | test('setValue and getValue', () { 13 | final testKey = ContextKey(); 14 | 15 | final parentContext = createZoneContext(Zone.current); 16 | final childContext = parentContext.setValue(testKey, 'bar'); 17 | expect(parentContext.getValue(testKey), isNull); 18 | expect(childContext.getValue(testKey), equals('bar')); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /test/unit/api/logs/noop/noop_logger_provider_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/src/experimental_api.dart' as api; 6 | import 'package:test/test.dart'; 7 | 8 | void main() { 9 | test('returns noop logger', () { 10 | final noopLoggerProvider = api.NoopLoggerProvider(); 11 | expect(noopLoggerProvider.get('test'), const api.NoopLogger()); 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /test/unit/api/metrics/noop_meter_provider_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/api.dart' as api; 6 | import 'package:test/test.dart'; 7 | import 'package:opentelemetry/src/api/metrics/noop/noop_meter_provider.dart'; 8 | import 'package:opentelemetry/src/experimental_api.dart' as api; 9 | 10 | void main() { 11 | group('MeterProvider:', () { 12 | setUp(() {}); 13 | 14 | test('MeterProvider.get with name returns inert instance of Meter', () { 15 | final provider = NoopMeterProvider(); 16 | expect(provider, isA()); 17 | final meter = provider.get('testname'); 18 | meter.createCounter('test').add(1); 19 | }); 20 | test('MeterProvider.get with name+version returns inert instance of Meter', 21 | () { 22 | final provider = NoopMeterProvider(); 23 | expect(provider, isA()); 24 | final meter = provider.get('testname', version: 'version'); 25 | meter.createCounter('test').add(1); 26 | }); 27 | 28 | test( 29 | 'MeterProvider.get with name+version+url returns inert instance of Meter', 30 | () { 31 | final provider = NoopMeterProvider(); 32 | expect(provider, isA()); 33 | final meter = 34 | provider.get('testname', version: 'version', schemaUrl: 'url'); 35 | meter.createCounter('test').add(1); 36 | }); 37 | 38 | test( 39 | 'MeterProvider.get with name+version+url+attributes returns inert ' 40 | 'instance of Meter', () { 41 | final provider = NoopMeterProvider(); 42 | expect(provider, isA()); 43 | final meter = provider 44 | .get('testname', version: 'version', schemaUrl: 'url', attributes: [ 45 | api.Attribute.fromString('http.method', 'post'), 46 | api.Attribute.fromString('http.scheme', 'http') 47 | ]); 48 | meter.createCounter('test').add(1); 49 | meter.createCounter('test2').add(0.034); 50 | }); 51 | }); 52 | } 53 | -------------------------------------------------------------------------------- /test/unit/api/span_context_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/api.dart' as api; 6 | import 'package:test/test.dart'; 7 | 8 | void main() { 9 | test('spanContext getters', () { 10 | final spanId = api.SpanId([4, 5, 6]); 11 | final traceId = api.TraceId([1, 2, 3]); 12 | const traceFlags = api.TraceFlags.none; 13 | final traceState = api.TraceState.empty(); 14 | 15 | final spanContext = 16 | api.SpanContext(traceId, spanId, traceFlags, traceState); 17 | 18 | expect(spanContext.traceId, same(traceId)); 19 | expect(spanContext.spanId, same(spanId)); 20 | expect(spanContext.traceFlags, same(traceFlags)); 21 | expect(spanContext.traceState, same(traceState)); 22 | }); 23 | 24 | test('valid context evaluates as valid', () { 25 | final spanId = api.SpanId([1, 2, 3]); 26 | final traceId = api.TraceId([4, 5, 6]); 27 | const traceFlags = api.TraceFlags.sampled; 28 | final traceState = api.TraceState.empty(); 29 | 30 | final testSpanContext = 31 | api.SpanContext(traceId, spanId, traceFlags, traceState); 32 | 33 | expect(testSpanContext.isValid, isTrue); 34 | expect(testSpanContext.traceId, same(traceId)); 35 | expect(testSpanContext.spanId, same(spanId)); 36 | expect(testSpanContext.traceFlags, same(traceFlags)); 37 | expect(testSpanContext.traceState, same(traceState)); 38 | }); 39 | 40 | test('invalid parsed parent span ID from header creates an invalid context', 41 | () { 42 | final spanId = api.SpanId.fromString('0000000000000000'); 43 | final traceId = api.TraceId([4, 5, 6]); 44 | const traceFlags = api.TraceFlags.sampled; 45 | final traceState = api.TraceState.empty(); 46 | 47 | final testSpanContext = 48 | api.SpanContext(traceId, spanId, traceFlags, traceState); 49 | 50 | expect(testSpanContext.isValid, isFalse); 51 | expect(testSpanContext.traceId, same(traceId)); 52 | expect(testSpanContext.spanId, same(spanId)); 53 | expect(testSpanContext.traceFlags, same(traceFlags)); 54 | expect(testSpanContext.traceState, same(traceState)); 55 | }); 56 | 57 | test('invalid parsed trace ID from header creates an invalid context', () { 58 | final spanId = api.SpanId([1, 2, 3]); 59 | final traceId = api.TraceId.fromString('00000000000000000000000000000000'); 60 | const traceFlags = api.TraceFlags.sampled; 61 | final traceState = api.TraceState.empty(); 62 | 63 | final testSpanContext = 64 | api.SpanContext(traceId, spanId, traceFlags, traceState); 65 | 66 | expect(testSpanContext.isValid, isFalse); 67 | expect(testSpanContext.traceId, same(traceId)); 68 | expect(testSpanContext.spanId, same(spanId)); 69 | expect(testSpanContext.traceFlags, same(traceFlags)); 70 | expect(testSpanContext.traceState, same(traceState)); 71 | }); 72 | 73 | test('invalid context evaluates as invalid', () { 74 | final testSpanContext = api.SpanContext.invalid(); 75 | 76 | expect(testSpanContext.isValid, isFalse); 77 | expect(testSpanContext.traceId.isValid, isFalse); 78 | expect(testSpanContext.isValid, isFalse); 79 | expect(testSpanContext.traceFlags, equals(api.TraceFlags.none)); 80 | expect(testSpanContext.traceState.isEmpty, isTrue); 81 | }); 82 | } 83 | -------------------------------------------------------------------------------- /test/unit/api/trace_state_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/src/api/trace/trace_state.dart'; 6 | import 'package:test/test.dart'; 7 | 8 | void main() { 9 | test('create empty', () { 10 | final testTraceState = TraceState.empty(); 11 | 12 | expect(testTraceState.toString(), equals('')); 13 | expect(testTraceState.isEmpty, isTrue); 14 | expect(testTraceState.size, equals(0)); 15 | }); 16 | 17 | test('create from string', () { 18 | final testTraceState = TraceState.fromString('key1=value2,key@2=value1'); 19 | 20 | expect(testTraceState.get('key1'), equals('value2')); // Regular key. 21 | expect(testTraceState.get('key@2'), equals('value1')); // Vendor key. 22 | expect(testTraceState.toString(), equals('key1=value2,key@2=value1')); 23 | expect(testTraceState.isEmpty, isFalse); 24 | expect(testTraceState.size, equals(2)); 25 | }); 26 | 27 | test('get default', () { 28 | final testTraceState = TraceState.getDefault(); 29 | 30 | expect(testTraceState.toString(), equals('')); 31 | expect(testTraceState.isEmpty, isTrue); 32 | expect(testTraceState.size, equals(0)); 33 | }); 34 | 35 | test('put valid values', () { 36 | final testTraceState = TraceState.empty() 37 | ..put('key_0-1', 'value@2') 38 | ..put('key_0-2', 'value@1') 39 | ..put('key_@vendor', 'value@3'); 40 | 41 | expect(testTraceState.get('key_0-1'), equals('value@2')); 42 | expect(testTraceState.get('key_0-2'), equals('value@1')); 43 | expect(testTraceState.get('key_@vendor'), equals('value@3')); 44 | expect(testTraceState.toString(), 45 | equals('key_0-1=value@2,key_0-2=value@1,key_@vendor=value@3')); 46 | expect(testTraceState.isEmpty, isFalse); 47 | expect(testTraceState.size, equals(3)); 48 | }); 49 | 50 | test('create from string with invalid values', () { 51 | final testTraceState = TraceState.fromString( 52 | 'key_0-1=0,value2,key&0-2=value@1,key_@thisisalotlongerthan13characters=value@3'); 53 | 54 | expect(testTraceState.get('key_0-1'), isEmpty); // Invalid value, comma. 55 | expect(testTraceState.get('key&0-2'), isEmpty); // Invalid key. 56 | expect(testTraceState.get('key_@thisisalotlongerthan13characters'), 57 | isEmpty); // Invalid vendor key. 58 | expect(testTraceState.toString(), equals('')); 59 | expect(testTraceState.isEmpty, isTrue); 60 | expect(testTraceState.size, equals(0)); 61 | }); 62 | 63 | test('put invalid values', () { 64 | final testTraceState = TraceState.empty() 65 | ..put('key_0-1', '0,value=2') // Invalid value. 66 | ..put('key&0-2', 'value@1') // Invalid key. 67 | ..put('key_@thisisalotlongerthan13characters', 68 | 'value@3'); // Invalid vendor key. 69 | 70 | expect(testTraceState.get('key_0-1'), isEmpty); 71 | expect(testTraceState.get('key_0-2'), isEmpty); 72 | expect( 73 | testTraceState.get('key_@thisisalotlongerthan13characters'), isEmpty); 74 | expect(testTraceState.toString(), equals('')); 75 | expect(testTraceState.isEmpty, isTrue); 76 | expect(testTraceState.size, equals(0)); 77 | }); 78 | 79 | test('remove valid value', () { 80 | final testTraceState = TraceState.empty() 81 | ..put('key_0-1', 'value@2') 82 | ..put('key_0-2', 'value@1') 83 | ..put('key_@vendor', 'value@3') 84 | ..remove('key_@vendor'); 85 | 86 | expect(testTraceState.get('key_0-1'), equals('value@2')); 87 | expect(testTraceState.get('key_0-2'), equals('value@1')); 88 | expect(testTraceState.get('key_@vendor'), isEmpty); 89 | expect( 90 | testTraceState.toString(), equals('key_0-1=value@2,key_0-2=value@1')); 91 | expect(testTraceState.isEmpty, isFalse); 92 | expect(testTraceState.size, equals(2)); 93 | }); 94 | 95 | test('key regex, valid key', () { 96 | final matchResult = TraceState.validKeyRegex.matchAsPrefix('key_0-1'); 97 | 98 | expect(matchResult, isNotNull); 99 | expect(matchResult!.group(0), equals('key_0-1')); 100 | }); 101 | 102 | test('key regex, valid vendor key', () { 103 | final matchResult = TraceState.validKeyRegex.matchAsPrefix('key_@vendor'); 104 | 105 | expect(matchResult, isNotNull); 106 | expect(matchResult!.group(0), equals('key_@vendor')); 107 | }); 108 | 109 | test('value regex, valid value', () { 110 | final matchResult = TraceState.validValueRegex.matchAsPrefix('value@2'); 111 | 112 | expect(matchResult, isNotNull); 113 | expect(matchResult!.group(0), equals('value@2')); 114 | }); 115 | 116 | test('key regex, invalid key', () { 117 | final matchResult = TraceState.validKeyRegex.matchAsPrefix('key&0-2'); 118 | 119 | expect(matchResult, isNull); 120 | }); 121 | 122 | test('key regex, invalid vendor key', () { 123 | final matchResult = TraceState.validKeyRegex 124 | .matchAsPrefix('key_@thisisalotlongerthan13characters'); 125 | 126 | expect(matchResult, isNull); 127 | }); 128 | 129 | test('value regex, invalid value', () { 130 | final matchResult = TraceState.validValueRegex.matchAsPrefix('0,value=2'); 131 | 132 | expect(matchResult, isNull); 133 | }); 134 | } 135 | -------------------------------------------------------------------------------- /test/unit/mocks.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | import 'package:http/http.dart' as http; 5 | import 'package:mocktail/mocktail.dart'; 6 | import 'package:opentelemetry/src/api/context/context.dart'; 7 | import 'package:opentelemetry/src/api/trace/span.dart'; 8 | import 'package:opentelemetry/src/sdk/trace/read_only_span.dart'; 9 | import 'package:opentelemetry/src/sdk/trace/span_processors/span_processor.dart'; 10 | 11 | class MockContext extends Mock implements Context {} 12 | 13 | class MockHttpClient extends Mock implements http.Client {} 14 | 15 | class MockSpan extends Mock implements Span {} 16 | 17 | class MockReadOnlySpan extends Mock implements ReadOnlySpan {} 18 | 19 | class MockSpanProcessor extends Mock implements SpanProcessor {} 20 | -------------------------------------------------------------------------------- /test/unit/sdk/exporters/console_exporter_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'dart:async'; 6 | 7 | import 'package:opentelemetry/api.dart' as api; 8 | import 'package:opentelemetry/sdk.dart' as sdk; 9 | import 'package:opentelemetry/src/sdk/trace/span.dart'; 10 | import 'package:test/test.dart'; 11 | 12 | List printLogs = []; 13 | 14 | dynamic overridePrint(Function() testFn) => () { 15 | final spec = ZoneSpecification(print: (_, __, ___, msg) { 16 | // Add to log instead of printing to stdout 17 | printLogs.add(msg); 18 | }); 19 | return Zone.current.fork(specification: spec).run(testFn); 20 | }; 21 | 22 | void main() { 23 | tearDown(() { 24 | printLogs = []; 25 | }); 26 | 27 | test('prints', overridePrint(() { 28 | final span = Span( 29 | 'foo', 30 | api.SpanContext(api.TraceId([1, 2, 3]), api.SpanId([7, 8, 9]), 31 | api.TraceFlags.none, api.TraceState.empty()), 32 | api.SpanId([4, 5, 6]), 33 | [], 34 | sdk.DateTimeTimeProvider(), 35 | sdk.Resource([]), 36 | sdk.InstrumentationScope( 37 | 'library_name', 'library_version', 'url://schema', []), 38 | api.SpanKind.internal, 39 | [], 40 | sdk.SpanLimits(), 41 | sdk.DateTimeTimeProvider().now) 42 | ..end(); 43 | 44 | sdk.ConsoleExporter().export([span]); 45 | 46 | final expected = RegExp( 47 | r'{traceId: 010203, parentId: 040506, name: foo, id: 070809, timestamp: \d+, duration: \d+, flags: 00, state: , status: StatusCode.unset}'); 48 | expect(printLogs.length, 1); 49 | expect(printLogs[0], matches(expected)); 50 | })); 51 | 52 | test('does not print after shutdown', overridePrint(() { 53 | final span = Span( 54 | 'foo', 55 | api.SpanContext(api.TraceId([1, 2, 3]), api.SpanId([7, 8, 9]), 56 | api.TraceFlags.none, api.TraceState.empty()), 57 | api.SpanId([4, 5, 6]), 58 | [], 59 | sdk.DateTimeTimeProvider(), 60 | sdk.Resource([]), 61 | sdk.InstrumentationScope( 62 | 'library_name', 'library_version', 'url://schema', []), 63 | api.SpanKind.internal, 64 | [], 65 | sdk.SpanLimits(), 66 | sdk.DateTimeTimeProvider().now); 67 | 68 | sdk.ConsoleExporter() 69 | ..shutdown() 70 | ..export([span]); 71 | 72 | expect(printLogs.length, 0); 73 | })); 74 | } 75 | -------------------------------------------------------------------------------- /test/unit/sdk/id_generator_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/src/sdk/trace/id_generator.dart'; 6 | import 'package:test/test.dart'; 7 | 8 | void main() { 9 | final generator = IdGenerator(); 10 | 11 | test('generateSpanId is the correct length', () { 12 | expect(generator.generateSpanId().length, equals(8)); 13 | }); 14 | 15 | test('generateTraceId is the correct length', () { 16 | expect(generator.generateTraceId().length, equals(16)); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /test/unit/sdk/platforms/web/web_time_provider_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('chrome') 5 | 6 | import 'package:fixnum/fixnum.dart'; 7 | import 'package:opentelemetry/src/sdk/platforms/web/time_providers/web_time_provider.dart'; 8 | import 'package:test/test.dart'; 9 | 10 | void main() { 11 | group('msToNs', () { 12 | test('msToNs rounds large fractions', () { 13 | final cases = [ 14 | [809.2223347138977, Int64(809222335)], 15 | [821.5999999046326, Int64(821600000)], 16 | [1427.1999998092651, Int64(1427200000)], 17 | ]; 18 | for (final c in cases) { 19 | final expected = c[1]; 20 | expect(msToNs(c[0] as double), expected); 21 | } 22 | }); 23 | test('msToNs rounds large wholes', () { 24 | final cases = [ 25 | [1722291888610.5, Int64(17222918886105000) * 100], 26 | [1722292170313.4, Int64(17222921703134000) * 100], 27 | [1722292193622.1, Int64(17222921936221000) * 100], 28 | ]; 29 | for (final c in cases) { 30 | final expected = c[1]; 31 | expect(msToNs(c[0] as double, fractionDigits: 1), expected); 32 | } 33 | }); 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /test/unit/sdk/platforms/web/web_trace_provider_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('chrome') 5 | import 'package:mocktail/mocktail.dart'; 6 | import 'package:opentelemetry/src/sdk/trace/span.dart'; 7 | import 'package:opentelemetry/src/sdk/trace/span_processors/span_processor.dart'; 8 | import 'package:opentelemetry/src/sdk/platforms/web/trace/web_tracer_provider.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | import '../../../mocks.dart'; 12 | 13 | void main() { 14 | test('getTracer stores tracers by name', () { 15 | final provider = WebTracerProvider(); 16 | final fooTracer = provider.getTracer('foo'); 17 | final barTracer = provider.getTracer('bar'); 18 | final fooWithVersionTracer = provider.getTracer('foo', version: '1.0'); 19 | 20 | expect( 21 | fooTracer, 22 | allOf([ 23 | isNot(barTracer), 24 | isNot(fooWithVersionTracer), 25 | same(provider.getTracer('foo')) 26 | ])); 27 | 28 | expect(provider.spanProcessors, isA>()); 29 | }); 30 | 31 | test('browserTracerProvider custom span processors', () { 32 | final mockProcessor1 = MockSpanProcessor(); 33 | final mockProcessor2 = MockSpanProcessor(); 34 | final provider = 35 | WebTracerProvider(processors: [mockProcessor1, mockProcessor2]); 36 | 37 | expect(provider.spanProcessors, [mockProcessor1, mockProcessor2]); 38 | }); 39 | 40 | test('browserTracerProvider force flushes all processors', () { 41 | final mockProcessor1 = MockSpanProcessor(); 42 | final mockProcessor2 = MockSpanProcessor(); 43 | WebTracerProvider(processors: [mockProcessor1, mockProcessor2]) 44 | .forceFlush(); 45 | 46 | verify(mockProcessor1.forceFlush).called(1); 47 | verify(mockProcessor2.forceFlush).called(1); 48 | }); 49 | 50 | test('browserTracerProvider shuts down all processors', () { 51 | final mockProcessor1 = MockSpanProcessor(); 52 | final mockProcessor2 = MockSpanProcessor(); 53 | WebTracerProvider(processors: [mockProcessor1, mockProcessor2]).shutdown(); 54 | 55 | verify(mockProcessor1.shutdown).called(1); 56 | verify(mockProcessor2.shutdown).called(1); 57 | }); 58 | 59 | test('browserTracerProvider creates a tracer which can create valid spans', 60 | () async { 61 | final span = WebTracerProvider(processors: [MockSpanProcessor()]) 62 | .getTracer('testTracer') 63 | .startSpan('testSpan') as Span 64 | ..end(); 65 | 66 | expect(span.endTime, isNotNull); 67 | expect(span.startTime, lessThanOrEqualTo(span.endTime!)); 68 | }); 69 | } 70 | -------------------------------------------------------------------------------- /test/unit/sdk/sampling/always_off_sampler_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/api.dart' as api; 6 | import 'package:opentelemetry/sdk.dart' as sdk; 7 | import 'package:opentelemetry/src/sdk/trace/span.dart'; 8 | import 'package:test/test.dart'; 9 | 10 | void main() { 11 | test('Context contains a Span', () { 12 | final traceId = api.TraceId([1, 2, 3]); 13 | final traceState = api.TraceState.fromString('test=one,two'); 14 | final testSpan = Span( 15 | 'foo', 16 | api.SpanContext( 17 | traceId, api.SpanId([7, 8, 9]), api.TraceFlags.none, traceState), 18 | api.SpanId([4, 5, 6]), 19 | [], 20 | sdk.DateTimeTimeProvider(), 21 | sdk.Resource([]), 22 | sdk.InstrumentationScope( 23 | 'library_name', 'library_version', 'url://schema', []), 24 | api.SpanKind.internal, 25 | [], 26 | sdk.SpanLimits(), 27 | sdk.DateTimeTimeProvider().now); 28 | final testContext = api.contextWithSpan(api.Context.current, testSpan); 29 | 30 | final result = sdk.AlwaysOffSampler().shouldSample( 31 | testContext, traceId, testSpan.name, api.SpanKind.internal, [], []); 32 | 33 | expect(result.decision, equals(sdk.Decision.drop)); 34 | expect(result.spanAttributes, equals([])); 35 | expect(result.traceState, same(traceState)); 36 | }); 37 | test('Context does not contain a Span', () { 38 | final traceId = api.TraceId([1, 2, 3]); 39 | final attributesList = [ 40 | api.Attribute.fromBoolean('boolTest', true), 41 | api.Attribute.fromDouble('double', 0.3) 42 | ]; 43 | final testSpan = Span( 44 | 'foo', 45 | api.SpanContext(traceId, api.SpanId([7, 8, 9]), api.TraceFlags.none, 46 | api.TraceState.empty()), 47 | api.SpanId([4, 5, 6]), 48 | [], 49 | sdk.DateTimeTimeProvider(), 50 | sdk.Resource([]), 51 | sdk.InstrumentationScope( 52 | 'library_name', 'library_version', 'url://schema', []), 53 | api.SpanKind.internal, 54 | [], 55 | sdk.SpanLimits(), 56 | sdk.DateTimeTimeProvider().now) 57 | ..setAttributes(attributesList); 58 | 59 | final result = sdk.AlwaysOffSampler().shouldSample(api.Context.current, 60 | traceId, testSpan.name, api.SpanKind.internal, attributesList, []); 61 | 62 | expect(result.decision, equals(sdk.Decision.drop)); 63 | expect(result.spanAttributes, attributesList); 64 | expect(result.traceState.isEmpty, isTrue); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /test/unit/sdk/sampling/always_on_sampler_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/api.dart' as api; 6 | import 'package:opentelemetry/sdk.dart' as sdk; 7 | import 'package:opentelemetry/src/sdk/trace/span.dart'; 8 | import 'package:test/test.dart'; 9 | 10 | void main() { 11 | test('Context contains a Span', () { 12 | final traceId = api.TraceId([1, 2, 3]); 13 | final traceState = api.TraceState.fromString('test=one,two'); 14 | final testSpan = Span( 15 | 'foo', 16 | api.SpanContext( 17 | traceId, api.SpanId([7, 8, 9]), api.TraceFlags.none, traceState), 18 | api.SpanId([4, 5, 6]), 19 | [], 20 | sdk.DateTimeTimeProvider(), 21 | sdk.Resource([]), 22 | sdk.InstrumentationScope( 23 | 'library_name', 'library_version', 'url://schema', []), 24 | api.SpanKind.internal, 25 | [], 26 | sdk.SpanLimits(), 27 | sdk.DateTimeTimeProvider().now); 28 | final testContext = api.contextWithSpan(api.Context.current, testSpan); 29 | 30 | final result = sdk.AlwaysOnSampler().shouldSample( 31 | testContext, traceId, testSpan.name, api.SpanKind.internal, [], []); 32 | 33 | expect(result.decision, equals(sdk.Decision.recordAndSample)); 34 | expect(result.spanAttributes, equals([])); 35 | expect(result.traceState, same(traceState)); 36 | }); 37 | test('Context does not contain a Span', () { 38 | final traceId = api.TraceId([1, 2, 3]); 39 | final testSpan = Span( 40 | 'foo', 41 | api.SpanContext(traceId, api.SpanId([7, 8, 9]), api.TraceFlags.none, 42 | api.TraceState.empty()), 43 | api.SpanId([4, 5, 6]), 44 | [], 45 | sdk.DateTimeTimeProvider(), 46 | sdk.Resource([]), 47 | sdk.InstrumentationScope( 48 | 'library_name', 'library_version', 'url://schema', []), 49 | api.SpanKind.internal, 50 | [], 51 | sdk.SpanLimits(), 52 | sdk.DateTimeTimeProvider().now); 53 | 54 | final result = sdk.AlwaysOnSampler().shouldSample(api.Context.current, 55 | traceId, testSpan.name, api.SpanKind.internal, [], []); 56 | 57 | expect(result.decision, equals(sdk.Decision.recordAndSample)); 58 | expect(result.spanAttributes, equals([])); 59 | expect(result.traceState.isEmpty, isTrue); 60 | }); 61 | } 62 | -------------------------------------------------------------------------------- /test/unit/sdk/span_id_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/api.dart' as api; 6 | import 'package:test/test.dart'; 7 | 8 | class MockIdGenerator implements api.IdGenerator { 9 | @override 10 | List generateSpanId() { 11 | return [1, 2, 3, 4, 5, 6, 7, 8]; 12 | } 13 | 14 | @override 15 | List generateTraceId() { 16 | throw UnimplementedError(); 17 | } 18 | } 19 | 20 | void main() { 21 | test('create with int list', () { 22 | final testSpanId = api.SpanId([1, 2, 3]); 23 | 24 | expect(testSpanId.get(), equals([1, 2, 3])); 25 | expect(testSpanId.isValid, isTrue); 26 | expect(testSpanId.toString(), equals('010203')); 27 | }); 28 | 29 | test('create from id generator', () { 30 | final testSpanId = api.SpanId.fromIdGenerator(MockIdGenerator()); 31 | 32 | expect(testSpanId.get(), equals([1, 2, 3, 4, 5, 6, 7, 8])); 33 | expect(testSpanId.isValid, isTrue); 34 | expect(testSpanId.toString(), equals('0102030405060708')); 35 | }); 36 | 37 | test('create from string', () { 38 | final testSpanId = api.SpanId.fromString('010203'); 39 | 40 | expect(testSpanId.get(), equals([0, 0, 0, 0, 0, 1, 2, 3])); 41 | expect(testSpanId.isValid, isTrue); 42 | expect(testSpanId.toString(), equals('0000000000010203')); 43 | }); 44 | 45 | test('create invalid id', () { 46 | final testSpanId = api.SpanId.invalid(); 47 | 48 | expect(testSpanId.get(), equals([0, 0, 0, 0, 0, 0, 0, 0])); 49 | expect(testSpanId.isValid, isFalse); 50 | expect(testSpanId.toString(), equals('0000000000000000')); 51 | }); 52 | 53 | test('create root id', () { 54 | final testSpanId = api.SpanId.root(); 55 | 56 | expect(testSpanId.get(), equals([])); 57 | expect(testSpanId.isValid, true); 58 | expect(testSpanId.toString(), equals('')); 59 | }); 60 | } 61 | -------------------------------------------------------------------------------- /test/unit/sdk/span_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/api.dart' as api; 6 | import 'package:opentelemetry/sdk.dart' as sdk; 7 | import 'package:opentelemetry/src/sdk/trace/span.dart'; 8 | import 'package:test/test.dart'; 9 | 10 | void main() { 11 | test('span change name', () { 12 | final span = Span( 13 | 'foo', 14 | api.SpanContext(api.TraceId([1, 2, 3]), api.SpanId([7, 8, 9]), 15 | api.TraceFlags.none, api.TraceState.empty()), 16 | api.SpanId([4, 5, 6]), 17 | [], 18 | sdk.DateTimeTimeProvider(), 19 | sdk.Resource([api.Attribute.fromString('service-name', 'foo')]), 20 | sdk.InstrumentationScope( 21 | 'library_name', 'library_version', 'url://schema', []), 22 | api.SpanKind.internal, 23 | [], 24 | sdk.SpanLimits(), 25 | sdk.DateTimeTimeProvider().now); 26 | expect(span.name, equals('foo')); 27 | 28 | span.setName('bar'); 29 | expect(span.name, equals('bar')); 30 | expect(span.resource.attributes.get('service-name'), equals('foo')); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /test/unit/sdk/trace/tracer_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | 6 | import 'package:opentelemetry/api.dart' as api; 7 | import 'package:opentelemetry/src/sdk/trace/tracer.dart'; 8 | import 'package:opentelemetry/src/sdk/trace/tracer_provider.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | void main() { 12 | group('startSpan', () { 13 | final tracer = TracerProviderBase().getTracer('test'); 14 | 15 | test('with newRoot true', () { 16 | final parent = tracer.startSpan('parent'); 17 | final context = api.contextWithSpan(api.Context.current, parent); 18 | final span = 19 | (tracer as Tracer).startSpan('', newRoot: true, context: context); 20 | expect(span.parentSpanId.isValid, isFalse); 21 | expect(span.spanContext.traceId.isValid, isTrue); 22 | expect( 23 | span.spanContext.traceId, isNot(equals(parent.spanContext.traceId))); 24 | }); 25 | 26 | test('with newRoot false', () { 27 | final parent = tracer.startSpan('parent'); 28 | final context = api.contextWithSpan(api.Context.current, parent); 29 | final span = 30 | (tracer as Tracer).startSpan('', newRoot: false, context: context); 31 | expect(span.parentSpanId.isValid, isTrue); 32 | expect(span.parentSpanId, equals(parent.spanContext.spanId)); 33 | expect(span.spanContext.traceId.isValid, isTrue); 34 | expect(span.spanContext.traceId, equals(parent.spanContext.traceId)); 35 | }); 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /test/unit/sdk/trace_id_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:opentelemetry/api.dart' as api; 6 | import 'package:test/test.dart'; 7 | 8 | class MockIdGenerator implements api.IdGenerator { 9 | @override 10 | List generateTraceId() { 11 | return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; 12 | } 13 | 14 | @override 15 | List generateSpanId() { 16 | throw UnimplementedError(); 17 | } 18 | } 19 | 20 | void main() { 21 | test('create with int list', () { 22 | final testTraceId = api.TraceId([1, 2, 3]); 23 | 24 | expect(testTraceId.get(), equals([1, 2, 3])); 25 | expect(testTraceId.isValid, isTrue); 26 | expect(testTraceId.toString(), equals('010203')); 27 | }); 28 | 29 | test('create from id generator', () { 30 | final testTraceId = api.TraceId.fromIdGenerator(MockIdGenerator()); 31 | 32 | expect(testTraceId.get(), 33 | equals([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])); 34 | expect(testTraceId.isValid, isTrue); 35 | expect(testTraceId.toString(), equals('0102030405060708090a0b0c0d0e0f')); 36 | }); 37 | 38 | test('create from string', () { 39 | final testTraceId = api.TraceId.fromString('010203'); 40 | 41 | expect(testTraceId.get(), 42 | equals([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3])); 43 | expect(testTraceId.isValid, isTrue); 44 | expect(testTraceId.toString(), equals('00000000000000000000000000010203')); 45 | }); 46 | 47 | test('create invalid id', () { 48 | final testTraceId = api.TraceId.invalid(); 49 | 50 | expect(testTraceId.get(), 51 | equals([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])); 52 | expect(testTraceId.isValid, isFalse); 53 | expect(testTraceId.toString(), equals('00000000000000000000000000000000')); 54 | }); 55 | } 56 | -------------------------------------------------------------------------------- /test/unit/sdk/trace_provider_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2021-2022 Workiva. 2 | // Licensed under the Apache License, Version 2.0. Please see https://github.com/Workiva/opentelemetry-dart/blob/master/LICENSE for more information 3 | 4 | @TestOn('vm') 5 | import 'package:fixnum/src/int64.dart'; 6 | import 'package:mocktail/mocktail.dart'; 7 | import 'package:opentelemetry/src/sdk/time_providers/time_provider.dart'; 8 | import 'package:opentelemetry/src/sdk/trace/read_only_span.dart'; 9 | import 'package:opentelemetry/src/sdk/trace/span_processors/span_processor.dart'; 10 | import 'package:opentelemetry/src/sdk/trace/tracer_provider.dart'; 11 | import 'package:test/test.dart'; 12 | 13 | import '../mocks.dart'; 14 | 15 | void main() { 16 | test('getTracer stores tracers by name', () { 17 | final provider = TracerProviderBase(); 18 | final fooTracer = provider.getTracer('foo'); 19 | final barTracer = provider.getTracer('bar'); 20 | final fooWithVersionTracer = provider.getTracer('foo', version: '1.0'); 21 | 22 | expect( 23 | fooTracer, 24 | allOf([ 25 | isNot(barTracer), 26 | isNot(fooWithVersionTracer), 27 | same(provider.getTracer('foo')) 28 | ])); 29 | 30 | expect(provider.spanProcessors, isA>()); 31 | }); 32 | 33 | test('tracerProvider custom span processors', () { 34 | final mockProcessor1 = MockSpanProcessor(); 35 | final mockProcessor2 = MockSpanProcessor(); 36 | final provider = 37 | TracerProviderBase(processors: [mockProcessor1, mockProcessor2]); 38 | 39 | expect(provider.spanProcessors, [mockProcessor1, mockProcessor2]); 40 | }); 41 | 42 | test('traceProvider custom timeProvider', () { 43 | final mockTimeProvider = FakeTimeProvider(now: Int64(123)); 44 | final provider = TracerProviderBase(timeProvider: mockTimeProvider); 45 | final span = provider.getTracer('foo').startSpan('bar') as ReadOnlySpan; 46 | expect(span.startTime, Int64(123)); 47 | }); 48 | 49 | test('tracerProvider force flushes all processors', () { 50 | final mockProcessor1 = MockSpanProcessor(); 51 | final mockProcessor2 = MockSpanProcessor(); 52 | TracerProviderBase(processors: [mockProcessor1, mockProcessor2]) 53 | .forceFlush(); 54 | 55 | verify(mockProcessor1.forceFlush).called(1); 56 | verify(mockProcessor2.forceFlush).called(1); 57 | }); 58 | 59 | test('tracerProvider shuts down all processors', () { 60 | final mockProcessor1 = MockSpanProcessor(); 61 | final mockProcessor2 = MockSpanProcessor(); 62 | TracerProviderBase(processors: [mockProcessor1, mockProcessor2]).shutdown(); 63 | 64 | verify(mockProcessor1.shutdown).called(1); 65 | verify(mockProcessor2.shutdown).called(1); 66 | }); 67 | } 68 | 69 | class FakeTimeProvider extends Mock implements TimeProvider { 70 | FakeTimeProvider({required Int64 now}) : _now = now; 71 | final Int64 _now; 72 | 73 | @override 74 | Int64 get now => _now; 75 | } 76 | --------------------------------------------------------------------------------