From 8dba488dd37837dd754268b2f186197a7e2000e4 Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Sun, 4 Oct 2026 20:35:55 -0400 Subject: [PATCH 01/14] feat: keep Rust telemetry aligned with registry conventions Signed-off-by: Yordis Prieto --- .config/mise/tasks/weaver/test/_default | 4 +- .config/mise/tasks/weaver/test/rust | 4 + .github/workflows/checks.yml | 1 + AGENTS.md | 4 + CONTRIBUTING.md | 5 + README.md | 6 +- buildscripts/check_rust_output.sh | 109 +++ mise.toml | 1 + templates/code/rust/README.md | 173 +++++ templates/code/rust/entities.rs.j2 | 61 ++ templates/code/rust/events.rs.j2 | 45 ++ templates/code/rust/logger.rs.j2 | 42 ++ templates/code/rust/meter.rs.j2 | 24 + templates/code/rust/metrics.rs.j2 | 81 +++ templates/code/rust/mod.rs.j2 | 68 ++ templates/code/rust/signal_helpers.j2 | 25 + templates/code/rust/spans.rs.j2 | 103 +++ .../inherited_deprecation.expected-error.txt | 1 + .../compile-fail/inherited_deprecation.rs | 4 + .../unknown_enum.expected-error.txt | 1 + .../attributes/compile-fail/unknown_enum.rs | 3 + .../wrong_scalar.expected-error.txt | 1 + .../attributes/compile-fail/wrong_scalar.rs | 3 + .../rust/tests/attributes/expected/mod.rs | 622 ++++++++++++++++++ .../tests/attributes/registry/manifest.yaml | 2 + .../rust/tests/attributes/registry/model.yaml | 163 +++++ templates/code/rust/tests/attributes/test.rs | 57 ++ .../excluded_attribute.expected-error.txt | 1 + .../compile-fail/excluded_attribute.rs | 3 + .../excluded_member.expected-error.txt | 1 + .../compile-fail/excluded_member.rs | 3 + .../tests/codegen_exclusion/expected/mod.rs | 72 ++ .../codegen_exclusion/registry/manifest.yaml | 2 + .../codegen_exclusion/registry/model.yaml | 35 + .../code/rust/tests/codegen_exclusion/test.rs | 13 + .../missing_identity.expected-error.txt | 1 + .../entities/compile-fail/missing_identity.rs | 5 + .../wrong_identity.expected-error.txt | 1 + .../entities/compile-fail/wrong_identity.rs | 5 + .../code/rust/tests/entities/expected/mod.rs | 201 ++++++ .../tests/entities/expected/myappentity.rs | 166 +++++ .../tests/entities/registry/manifest.yaml | 2 + .../rust/tests/entities/registry/model.yaml | 74 +++ templates/code/rust/tests/entities/test.rs | 34 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/myapp.yaml | 15 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/myapp.yaml | 13 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/myapp.yaml | 15 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 10 + .../tests/error_empty_name/expected-error.txt | 1 + .../error_empty_name/registry/manifest.yaml | 2 + .../error_empty_name/registry/model.yaml | 6 + .../error_enum_collision/expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../error_enum_collision/registry/model.yaml | 13 + .../error_enum_keyword/expected-error.txt | 1 + .../error_enum_keyword/registry/manifest.yaml | 2 + .../error_enum_keyword/registry/model.yaml | 10 + .../expected-error.txt | 1 + .../error_enum_without_members/params.yaml | 2 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 11 + .../error_event_collision/expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../error_event_collision/registry/myapp.yaml | 10 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/myapp.yaml | 22 + .../expected-error.txt | 1 + .../params.yaml | 3 + .../registry/manifest.yaml | 2 + .../registry/myapp.yaml | 10 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 11 + .../error_invalid_name/expected-error.txt | 1 + .../error_invalid_name/registry/manifest.yaml | 2 + .../error_invalid_name/registry/model.yaml | 6 + .../error_metric_collision/expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 18 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 3 + .../registry/model.yaml | 11 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 3 + .../registry/model.yaml | 8 + .../error_missing_schema/expected-error.txt | 1 + .../registry/manifest.yaml | 1 + .../error_missing_schema/registry/model.yaml | 2 + .../tests/error_mixed_enum/expected-error.txt | 1 + .../error_mixed_enum/registry/manifest.yaml | 2 + .../error_mixed_enum/registry/model.yaml | 15 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 6 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 18 + .../error_option_collision/expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/myapp.yaml | 27 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 18 + .../error_span_collision/expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../error_span_collision/registry/myapp.yaml | 16 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/myapp.yaml | 25 + .../expected-error.txt | 1 + .../params.yaml | 2 + .../registry/manifest.yaml | 2 + .../registry/myapp.yaml | 15 + .../expected-error.txt | 1 + .../params.yaml | 2 + .../registry/manifest.yaml | 2 + .../registry/myapp.yaml | 20 + .../expected-error.txt | 1 + .../params.yaml | 2 + .../registry/manifest.yaml | 2 + .../registry/myapp.yaml | 18 + .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 2 + .../code/rust/tests/events/expected/logger.rs | 40 ++ .../code/rust/tests/events/expected/mod.rs | 235 +++++++ .../rust/tests/events/expected/myappevent.rs | 106 +++ .../rust/tests/events/expected/workerevent.rs | 99 +++ .../rust/tests/events/registry/manifest.yaml | 2 + .../rust/tests/events/registry/model.yaml | 88 +++ templates/code/rust/tests/events/test.rs | 134 ++++ .../code/rust/tests/filtering/expected/mod.rs | 381 +++++++++++ .../code/rust/tests/filtering/params.yaml | 4 + .../tests/filtering/registry/manifest.yaml | 2 + .../rust/tests/filtering/registry/model.yaml | 154 +++++ templates/code/rust/tests/filtering/test.rs | 14 + .../expected/meter.rs | 22 + .../expected/mod.rs | 44 ++ .../expected/myappmetric.rs | 119 ++++ .../registry/manifest.yaml | 2 + .../registry/myapp.yaml | 53 ++ .../expected/meter.rs | 22 + .../expected/mod.rs | 44 ++ .../expected/myappmetric.rs | 59 ++ .../params.yaml | 3 + .../registry/manifest.yaml | 2 + .../registry/myapp.yaml | 30 + .../tests/imported/dependency/manifest.yaml | 2 + .../rust/tests/imported/dependency/model.yaml | 30 + .../rust/tests/imported/expected/edgeevent.rs | 42 ++ .../tests/imported/expected/edgemetric.rs | 50 ++ .../rust/tests/imported/expected/edgespan.rs | 101 +++ .../rust/tests/imported/expected/logger.rs | 40 ++ .../rust/tests/imported/expected/meter.rs | 22 + .../code/rust/tests/imported/expected/mod.rs | 50 ++ .../tests/imported/expected/myappmetric.rs | 75 +++ .../rust/tests/imported/expected/tracer.rs | 29 + .../tests/imported/registry/manifest.yaml | 6 + .../rust/tests/imported/registry/model.yaml | 65 ++ .../imported_typed/dependency-params.yaml | 1 + .../imported_typed/dependency/manifest.yaml | 2 + .../imported_typed/dependency/model.yaml | 20 + .../tests/imported_typed/expected/logger.rs | 40 ++ .../tests/imported_typed/expected/meter.rs | 22 + .../rust/tests/imported_typed/expected/mod.rs | 48 ++ .../imported_typed/expected/myappevent.rs | 42 ++ .../imported_typed/expected/myappmetric.rs | 75 +++ .../imported_typed/expected/myappspan.rs | 102 +++ .../tests/imported_typed/expected/tracer.rs | 29 + .../rust/tests/imported_typed/params.yaml | 3 + .../imported_typed/registry/manifest.yaml | 6 + .../tests/imported_typed/registry/model.yaml | 48 ++ .../tests/integer_boundaries/expected/mod.rs | 48 ++ .../integer_boundaries/registry/manifest.yaml | 2 + .../integer_boundaries/registry/model.yaml | 15 + .../rust/tests/integer_boundaries/test.rs | 13 + .../literal_escaping/expected/demometric.rs | 54 ++ .../tests/literal_escaping/expected/meter.rs | 22 + .../tests/literal_escaping/expected/mod.rs | 55 ++ .../literal_escaping/registry/manifest.yaml | 2 + .../literal_escaping/registry/model.yaml | 28 + .../code/rust/tests/literal_escaping/test.rs | 30 + .../missing_required.expected-error.txt | 1 + .../metrics/compile-fail/missing_required.rs | 5 + .../signed_counter.expected-error.txt | 1 + .../metrics/compile-fail/signed_counter.rs | 5 + .../unrelated_optional.expected-error.txt | 1 + .../compile-fail/unrelated_optional.rs | 5 + .../wrong_required_type.expected-error.txt | 1 + .../compile-fail/wrong_required_type.rs | 5 + .../rust/tests/metrics/expected/authmetric.rs | 54 ++ .../code/rust/tests/metrics/expected/meter.rs | 22 + .../code/rust/tests/metrics/expected/mod.rs | 161 +++++ .../tests/metrics/expected/myappmetric.rs | 479 ++++++++++++++ .../tests/metrics/expected/workermetric.rs | 57 ++ .../rust/tests/metrics/registry/manifest.yaml | 2 + .../rust/tests/metrics/registry/model.yaml | 170 +++++ templates/code/rust/tests/metrics/test.rs | 326 +++++++++ .../rust/tests/naming/expected/capsmetric.rs | 54 ++ .../code/rust/tests/naming/expected/meter.rs | 22 + .../code/rust/tests/naming/expected/mod.rs | 79 +++ .../rust/tests/naming/registry/manifest.yaml | 2 + .../rust/tests/naming/registry/model.yaml | 30 + templates/code/rust/tests/naming/test.rs | 15 + .../no_namespace/expected/exceptionevent.rs | 42 ++ .../no_namespace/expected/heartbeatspan.rs | 87 +++ .../tests/no_namespace/expected/hostentity.rs | 51 ++ .../tests/no_namespace/expected/logger.rs | 40 ++ .../rust/tests/no_namespace/expected/mod.rs | 201 ++++++ .../tests/no_namespace/expected/tracer.rs | 29 + .../tests/no_namespace/registry/manifest.yaml | 2 + .../tests/no_namespace/registry/model.yaml | 65 ++ .../tests/params/expected/billingmetric.rs | 53 ++ .../code/rust/tests/params/expected/meter.rs | 22 + .../code/rust/tests/params/expected/mod.rs | 109 +++ templates/code/rust/tests/params/params.yaml | 6 + .../rust/tests/params/registry/manifest.yaml | 2 + .../rust/tests/params/registry/model.yaml | 42 ++ .../missing_required.expected-error.txt | 1 + .../spans/compile-fail/missing_required.rs | 8 + ...sampling_attribute_late.expected-error.txt | 1 + .../compile-fail/sampling_attribute_late.rs | 7 + .../code/rust/tests/spans/expected/mod.rs | 206 ++++++ .../rust/tests/spans/expected/myappspan.rs | 455 +++++++++++++ .../code/rust/tests/spans/expected/tracer.rs | 29 + .../rust/tests/spans/expected/workerspan.rs | 109 +++ .../rust/tests/spans/registry/manifest.yaml | 2 + .../code/rust/tests/spans/registry/model.yaml | 130 ++++ templates/code/rust/tests/spans/test.rs | 121 ++++ templates/code/rust/tracer.rs.j2 | 31 + templates/code/rust/weaver.yaml | 611 +++++++++++++++++ 240 files changed, 9533 insertions(+), 3 deletions(-) create mode 100755 .config/mise/tasks/weaver/test/rust create mode 100755 buildscripts/check_rust_output.sh create mode 100644 templates/code/rust/README.md create mode 100644 templates/code/rust/entities.rs.j2 create mode 100644 templates/code/rust/events.rs.j2 create mode 100644 templates/code/rust/logger.rs.j2 create mode 100644 templates/code/rust/meter.rs.j2 create mode 100644 templates/code/rust/metrics.rs.j2 create mode 100644 templates/code/rust/mod.rs.j2 create mode 100644 templates/code/rust/signal_helpers.j2 create mode 100644 templates/code/rust/spans.rs.j2 create mode 100644 templates/code/rust/tests/attributes/compile-fail/inherited_deprecation.expected-error.txt create mode 100644 templates/code/rust/tests/attributes/compile-fail/inherited_deprecation.rs create mode 100644 templates/code/rust/tests/attributes/compile-fail/unknown_enum.expected-error.txt create mode 100644 templates/code/rust/tests/attributes/compile-fail/unknown_enum.rs create mode 100644 templates/code/rust/tests/attributes/compile-fail/wrong_scalar.expected-error.txt create mode 100644 templates/code/rust/tests/attributes/compile-fail/wrong_scalar.rs create mode 100644 templates/code/rust/tests/attributes/expected/mod.rs create mode 100644 templates/code/rust/tests/attributes/registry/manifest.yaml create mode 100644 templates/code/rust/tests/attributes/registry/model.yaml create mode 100644 templates/code/rust/tests/attributes/test.rs create mode 100644 templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_attribute.expected-error.txt create mode 100644 templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_attribute.rs create mode 100644 templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_member.expected-error.txt create mode 100644 templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_member.rs create mode 100644 templates/code/rust/tests/codegen_exclusion/expected/mod.rs create mode 100644 templates/code/rust/tests/codegen_exclusion/registry/manifest.yaml create mode 100644 templates/code/rust/tests/codegen_exclusion/registry/model.yaml create mode 100644 templates/code/rust/tests/codegen_exclusion/test.rs create mode 100644 templates/code/rust/tests/entities/compile-fail/missing_identity.expected-error.txt create mode 100644 templates/code/rust/tests/entities/compile-fail/missing_identity.rs create mode 100644 templates/code/rust/tests/entities/compile-fail/wrong_identity.expected-error.txt create mode 100644 templates/code/rust/tests/entities/compile-fail/wrong_identity.rs create mode 100644 templates/code/rust/tests/entities/expected/mod.rs create mode 100644 templates/code/rust/tests/entities/expected/myappentity.rs create mode 100644 templates/code/rust/tests/entities/registry/manifest.yaml create mode 100644 templates/code/rust/tests/entities/registry/model.yaml create mode 100644 templates/code/rust/tests/entities/test.rs create mode 100644 templates/code/rust/tests/error_aggregation_counter/expected-error.txt create mode 100644 templates/code/rust/tests/error_aggregation_counter/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_aggregation_counter/registry/myapp.yaml create mode 100644 templates/code/rust/tests/error_aggregation_method/expected-error.txt create mode 100644 templates/code/rust/tests/error_aggregation_method/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_aggregation_method/registry/myapp.yaml create mode 100644 templates/code/rust/tests/error_aggregation_unsorted/expected-error.txt create mode 100644 templates/code/rust/tests/error_aggregation_unsorted/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_aggregation_unsorted/registry/myapp.yaml create mode 100644 templates/code/rust/tests/error_attribute_collision/expected-error.txt create mode 100644 templates/code/rust/tests/error_attribute_collision/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_attribute_collision/registry/model.yaml create mode 100644 templates/code/rust/tests/error_empty_name/expected-error.txt create mode 100644 templates/code/rust/tests/error_empty_name/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_empty_name/registry/model.yaml create mode 100644 templates/code/rust/tests/error_enum_collision/expected-error.txt create mode 100644 templates/code/rust/tests/error_enum_collision/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_enum_collision/registry/model.yaml create mode 100644 templates/code/rust/tests/error_enum_keyword/expected-error.txt create mode 100644 templates/code/rust/tests/error_enum_keyword/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_enum_keyword/registry/model.yaml create mode 100644 templates/code/rust/tests/error_enum_without_members/expected-error.txt create mode 100644 templates/code/rust/tests/error_enum_without_members/params.yaml create mode 100644 templates/code/rust/tests/error_enum_without_members/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_enum_without_members/registry/model.yaml create mode 100644 templates/code/rust/tests/error_event_collision/expected-error.txt create mode 100644 templates/code/rust/tests/error_event_collision/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_event_collision/registry/myapp.yaml create mode 100644 templates/code/rust/tests/error_event_required_collision/expected-error.txt create mode 100644 templates/code/rust/tests/error_event_required_collision/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_event_required_collision/registry/myapp.yaml create mode 100644 templates/code/rust/tests/error_histogram_boundaries_by_unit/expected-error.txt create mode 100644 templates/code/rust/tests/error_histogram_boundaries_by_unit/params.yaml create mode 100644 templates/code/rust/tests/error_histogram_boundaries_by_unit/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_histogram_boundaries_by_unit/registry/myapp.yaml create mode 100644 templates/code/rust/tests/error_integer_enum_overflow/expected-error.txt create mode 100644 templates/code/rust/tests/error_integer_enum_overflow/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_integer_enum_overflow/registry/model.yaml create mode 100644 templates/code/rust/tests/error_invalid_name/expected-error.txt create mode 100644 templates/code/rust/tests/error_invalid_name/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_invalid_name/registry/model.yaml create mode 100644 templates/code/rust/tests/error_metric_collision/expected-error.txt create mode 100644 templates/code/rust/tests/error_metric_collision/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_metric_collision/registry/model.yaml create mode 100644 templates/code/rust/tests/error_metric_value_type/expected-error.txt create mode 100644 templates/code/rust/tests/error_metric_value_type/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_metric_value_type/registry/model.yaml create mode 100644 templates/code/rust/tests/error_missing_metric_value_type/expected-error.txt create mode 100644 templates/code/rust/tests/error_missing_metric_value_type/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_missing_metric_value_type/registry/model.yaml create mode 100644 templates/code/rust/tests/error_missing_schema/expected-error.txt create mode 100644 templates/code/rust/tests/error_missing_schema/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_missing_schema/registry/model.yaml create mode 100644 templates/code/rust/tests/error_mixed_enum/expected-error.txt create mode 100644 templates/code/rust/tests/error_mixed_enum/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_mixed_enum/registry/model.yaml create mode 100644 templates/code/rust/tests/error_namespace_uppercase/expected-error.txt create mode 100644 templates/code/rust/tests/error_namespace_uppercase/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_namespace_uppercase/registry/model.yaml create mode 100644 templates/code/rust/tests/error_observable_collision/expected-error.txt create mode 100644 templates/code/rust/tests/error_observable_collision/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_observable_collision/registry/model.yaml create mode 100644 templates/code/rust/tests/error_option_collision/expected-error.txt create mode 100644 templates/code/rust/tests/error_option_collision/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_option_collision/registry/myapp.yaml create mode 100644 templates/code/rust/tests/error_refinement_value_type/expected-error.txt create mode 100644 templates/code/rust/tests/error_refinement_value_type/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_refinement_value_type/registry/model.yaml create mode 100644 templates/code/rust/tests/error_span_collision/expected-error.txt create mode 100644 templates/code/rust/tests/error_span_collision/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_span_collision/registry/myapp.yaml create mode 100644 templates/code/rust/tests/error_span_required_collision/expected-error.txt create mode 100644 templates/code/rust/tests/error_span_required_collision/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_span_required_collision/registry/myapp.yaml create mode 100644 templates/code/rust/tests/error_stable_only_event_required_attribute/expected-error.txt create mode 100644 templates/code/rust/tests/error_stable_only_event_required_attribute/params.yaml create mode 100644 templates/code/rust/tests/error_stable_only_event_required_attribute/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_stable_only_event_required_attribute/registry/myapp.yaml create mode 100644 templates/code/rust/tests/error_stable_only_required_attribute/expected-error.txt create mode 100644 templates/code/rust/tests/error_stable_only_required_attribute/params.yaml create mode 100644 templates/code/rust/tests/error_stable_only_required_attribute/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_stable_only_required_attribute/registry/myapp.yaml create mode 100644 templates/code/rust/tests/error_stable_only_span_required_attribute/expected-error.txt create mode 100644 templates/code/rust/tests/error_stable_only_span_required_attribute/params.yaml create mode 100644 templates/code/rust/tests/error_stable_only_span_required_attribute/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_stable_only_span_required_attribute/registry/myapp.yaml create mode 100644 templates/code/rust/tests/error_unversioned_schema/expected-error.txt create mode 100644 templates/code/rust/tests/error_unversioned_schema/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_unversioned_schema/registry/model.yaml create mode 100644 templates/code/rust/tests/events/expected/logger.rs create mode 100644 templates/code/rust/tests/events/expected/mod.rs create mode 100644 templates/code/rust/tests/events/expected/myappevent.rs create mode 100644 templates/code/rust/tests/events/expected/workerevent.rs create mode 100644 templates/code/rust/tests/events/registry/manifest.yaml create mode 100644 templates/code/rust/tests/events/registry/model.yaml create mode 100644 templates/code/rust/tests/events/test.rs create mode 100644 templates/code/rust/tests/filtering/expected/mod.rs create mode 100644 templates/code/rust/tests/filtering/params.yaml create mode 100644 templates/code/rust/tests/filtering/registry/manifest.yaml create mode 100644 templates/code/rust/tests/filtering/registry/model.yaml create mode 100644 templates/code/rust/tests/filtering/test.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit/registry/manifest.yaml create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit/registry/myapp.yaml create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit_params/params.yaml create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit_params/registry/manifest.yaml create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit_params/registry/myapp.yaml create mode 100644 templates/code/rust/tests/imported/dependency/manifest.yaml create mode 100644 templates/code/rust/tests/imported/dependency/model.yaml create mode 100644 templates/code/rust/tests/imported/expected/edgeevent.rs create mode 100644 templates/code/rust/tests/imported/expected/edgemetric.rs create mode 100644 templates/code/rust/tests/imported/expected/edgespan.rs create mode 100644 templates/code/rust/tests/imported/expected/logger.rs create mode 100644 templates/code/rust/tests/imported/expected/meter.rs create mode 100644 templates/code/rust/tests/imported/expected/mod.rs create mode 100644 templates/code/rust/tests/imported/expected/myappmetric.rs create mode 100644 templates/code/rust/tests/imported/expected/tracer.rs create mode 100644 templates/code/rust/tests/imported/registry/manifest.yaml create mode 100644 templates/code/rust/tests/imported/registry/model.yaml create mode 100644 templates/code/rust/tests/imported_typed/dependency-params.yaml create mode 100644 templates/code/rust/tests/imported_typed/dependency/manifest.yaml create mode 100644 templates/code/rust/tests/imported_typed/dependency/model.yaml create mode 100644 templates/code/rust/tests/imported_typed/expected/logger.rs create mode 100644 templates/code/rust/tests/imported_typed/expected/meter.rs create mode 100644 templates/code/rust/tests/imported_typed/expected/mod.rs create mode 100644 templates/code/rust/tests/imported_typed/expected/myappevent.rs create mode 100644 templates/code/rust/tests/imported_typed/expected/myappmetric.rs create mode 100644 templates/code/rust/tests/imported_typed/expected/myappspan.rs create mode 100644 templates/code/rust/tests/imported_typed/expected/tracer.rs create mode 100644 templates/code/rust/tests/imported_typed/params.yaml create mode 100644 templates/code/rust/tests/imported_typed/registry/manifest.yaml create mode 100644 templates/code/rust/tests/imported_typed/registry/model.yaml create mode 100644 templates/code/rust/tests/integer_boundaries/expected/mod.rs create mode 100644 templates/code/rust/tests/integer_boundaries/registry/manifest.yaml create mode 100644 templates/code/rust/tests/integer_boundaries/registry/model.yaml create mode 100644 templates/code/rust/tests/integer_boundaries/test.rs create mode 100644 templates/code/rust/tests/literal_escaping/expected/demometric.rs create mode 100644 templates/code/rust/tests/literal_escaping/expected/meter.rs create mode 100644 templates/code/rust/tests/literal_escaping/expected/mod.rs create mode 100644 templates/code/rust/tests/literal_escaping/registry/manifest.yaml create mode 100644 templates/code/rust/tests/literal_escaping/registry/model.yaml create mode 100644 templates/code/rust/tests/literal_escaping/test.rs create mode 100644 templates/code/rust/tests/metrics/compile-fail/missing_required.expected-error.txt create mode 100644 templates/code/rust/tests/metrics/compile-fail/missing_required.rs create mode 100644 templates/code/rust/tests/metrics/compile-fail/signed_counter.expected-error.txt create mode 100644 templates/code/rust/tests/metrics/compile-fail/signed_counter.rs create mode 100644 templates/code/rust/tests/metrics/compile-fail/unrelated_optional.expected-error.txt create mode 100644 templates/code/rust/tests/metrics/compile-fail/unrelated_optional.rs create mode 100644 templates/code/rust/tests/metrics/compile-fail/wrong_required_type.expected-error.txt create mode 100644 templates/code/rust/tests/metrics/compile-fail/wrong_required_type.rs create mode 100644 templates/code/rust/tests/metrics/expected/authmetric.rs create mode 100644 templates/code/rust/tests/metrics/expected/meter.rs create mode 100644 templates/code/rust/tests/metrics/expected/mod.rs create mode 100644 templates/code/rust/tests/metrics/expected/myappmetric.rs create mode 100644 templates/code/rust/tests/metrics/expected/workermetric.rs create mode 100644 templates/code/rust/tests/metrics/registry/manifest.yaml create mode 100644 templates/code/rust/tests/metrics/registry/model.yaml create mode 100644 templates/code/rust/tests/metrics/test.rs create mode 100644 templates/code/rust/tests/naming/expected/capsmetric.rs create mode 100644 templates/code/rust/tests/naming/expected/meter.rs create mode 100644 templates/code/rust/tests/naming/expected/mod.rs create mode 100644 templates/code/rust/tests/naming/registry/manifest.yaml create mode 100644 templates/code/rust/tests/naming/registry/model.yaml create mode 100644 templates/code/rust/tests/naming/test.rs create mode 100644 templates/code/rust/tests/no_namespace/expected/exceptionevent.rs create mode 100644 templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs create mode 100644 templates/code/rust/tests/no_namespace/expected/hostentity.rs create mode 100644 templates/code/rust/tests/no_namespace/expected/logger.rs create mode 100644 templates/code/rust/tests/no_namespace/expected/mod.rs create mode 100644 templates/code/rust/tests/no_namespace/expected/tracer.rs create mode 100644 templates/code/rust/tests/no_namespace/registry/manifest.yaml create mode 100644 templates/code/rust/tests/no_namespace/registry/model.yaml create mode 100644 templates/code/rust/tests/params/expected/billingmetric.rs create mode 100644 templates/code/rust/tests/params/expected/meter.rs create mode 100644 templates/code/rust/tests/params/expected/mod.rs create mode 100644 templates/code/rust/tests/params/params.yaml create mode 100644 templates/code/rust/tests/params/registry/manifest.yaml create mode 100644 templates/code/rust/tests/params/registry/model.yaml create mode 100644 templates/code/rust/tests/spans/compile-fail/missing_required.expected-error.txt create mode 100644 templates/code/rust/tests/spans/compile-fail/missing_required.rs create mode 100644 templates/code/rust/tests/spans/compile-fail/sampling_attribute_late.expected-error.txt create mode 100644 templates/code/rust/tests/spans/compile-fail/sampling_attribute_late.rs create mode 100644 templates/code/rust/tests/spans/expected/mod.rs create mode 100644 templates/code/rust/tests/spans/expected/myappspan.rs create mode 100644 templates/code/rust/tests/spans/expected/tracer.rs create mode 100644 templates/code/rust/tests/spans/expected/workerspan.rs create mode 100644 templates/code/rust/tests/spans/registry/manifest.yaml create mode 100644 templates/code/rust/tests/spans/registry/model.yaml create mode 100644 templates/code/rust/tests/spans/test.rs create mode 100644 templates/code/rust/tracer.rs.j2 create mode 100644 templates/code/rust/weaver.yaml diff --git a/.config/mise/tasks/weaver/test/_default b/.config/mise/tasks/weaver/test/_default index 82e31c6..fad21d6 100755 --- a/.config/mise/tasks/weaver/test/_default +++ b/.config/mise/tasks/weaver/test/_default @@ -1,3 +1,3 @@ #!/usr/bin/env bash -#MISE description="Run every policy and template package test, and compile the generated Go" -#MISE depends=["weaver:test:policies", "weaver:test:templates", "weaver:test:go"] +#MISE description="Run every policy and template package test, and validate generated Go and Rust" +#MISE depends=["weaver:test:policies", "weaver:test:templates", "weaver:test:go", "weaver:test:rust"] diff --git a/.config/mise/tasks/weaver/test/rust b/.config/mise/tasks/weaver/test/rust new file mode 100755 index 0000000..8a6b1db --- /dev/null +++ b/.config/mise/tasks/weaver/test/rust @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +#MISE description="Check that generated Rust is formatted, tested, and passes Clippy" +set -euo pipefail +exec ./buildscripts/check_rust_output.sh diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 785e8ad..e331b4a 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -38,6 +38,7 @@ jobs: - uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4.3.0 - run: mise run weaver:test:templates - run: mise run weaver:test:go + - run: mise run weaver:test:rust markdown: name: Markdown diff --git a/AGENTS.md b/AGENTS.md index 906333e..7661133 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -38,6 +38,10 @@ Each template package includes: Generated Go must pass `gofmt`, `go build`, and `go vet`, which `mise run weaver:test:go` checks. +Generated Rust must pass formatting, consumer tests, and Clippy, which +`mise run weaver:test:rust` checks against the pinned OpenTelemetry Rust API +and SDK. + ## Contribution guidelines - Keep changes to the package being modified. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7aa7630..26bb9d4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,6 +55,11 @@ Run `mise tasks` to list every task and what it does. Every test must pass before a pull request is merged. The `Checks` workflow runs the same tasks. +For Rust packages, `mise run weaver:test:rust` compiles the expected output in +temporary crates and runs formatting, consumer tests, and Clippy. Put consumer +tests in a case's `test.rs`, importing the generated crate as +`generated_semconv`. + Keep test registries synthetic. Use neutral namespaces such as `myapp` and `auth` rather than conventions from a real system. diff --git a/README.md b/README.md index 12bf611..6f5bd25 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ is versioned and released from this repository, ready to be referenced by tag. **The packages turn a semantic convention registry into code and keep that registry fit for generation.** Templates generate typed telemetry helpers, such -as Go attribute values and metric instruments on the OpenTelemetry Go API. +as typed attribute values and signal helpers on the OpenTelemetry Go and +Rust APIs. Policies run during `weaver registry check` and reject conventions a template cannot render, before any code is written. @@ -29,6 +30,9 @@ Templates live under [`templates`](templates) and policies under [`policies`](policies). Each package directory has a README describing what it does and the params it accepts. +- [Go code generation](templates/code/go/README.md) +- [Rust code generation](templates/code/rust/README.md) + ## Using a package Weaver accepts a Git repository as a template or policy location, in the form diff --git a/buildscripts/check_rust_output.sh b/buildscripts/check_rust_output.sh new file mode 100755 index 0000000..b0d5415 --- /dev/null +++ b/buildscripts/check_rust_output.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash + +set -euo pipefail + +OTEL_RUST_VERSION="${OTEL_RUST_VERSION:-0.33.0}" +WEAVER="${WEAVER:-weaver}" +ROOT="$(pwd)" +PACKAGE_DIR="${ROOT}/templates/code/rust" +TEMPLATES_ROOT="$(realpath "${PACKAGE_DIR}/../..")" + +WORK_DIR="$(mktemp -d "${TMPDIR:-/tmp}/weaver-rust.XXXXXX")" +trap 'rm -rf "${WORK_DIR}"' EXIT +export CARGO_TARGET_DIR="${WORK_DIR}/target" + +for test_dir in "${PACKAGE_DIR}"/tests/*/; do + test_name="$(basename "${test_dir}")" + [[ -f "${test_dir}expected-error.txt" ]] && continue + expected="${test_dir}expected" + if [[ ! -f "${expected}/mod.rs" ]]; then + echo " FAIL: ${test_name} is missing expected/mod.rs." + exit 1 + fi + echo "-> Checking Rust [${test_name}] ..." + + crate_dir="${WORK_DIR}/${test_name}" + mkdir -p "${crate_dir}/src" + cp -R "${expected}/." "${crate_dir}/src/" + mv "${crate_dir}/src/mod.rs" "${crate_dir}/src/lib.rs" + if [[ -f "${test_dir}test.rs" ]]; then + mkdir -p "${crate_dir}/tests" + cp "${test_dir}test.rs" "${crate_dir}/tests/attributes.rs" + fi + if [[ -d "${test_dir}tests" ]]; then + mkdir -p "${crate_dir}/tests" + cp -R "${test_dir}tests/." "${crate_dir}/tests/" + fi + + cat >"${crate_dir}/Cargo.toml" <"${dependency_dir}/Cargo.toml" <>"${crate_dir}/Cargo.toml" + ( + cd "${dependency_dir}" + cargo fmt --all || exit 1 + cargo fmt --all --check || exit 1 + cargo clippy --all-targets -- -D warnings || exit 1 + ) || { echo " FAIL: ${test_name} dependency fails Rust validation."; exit 1; } + fi + + ( + cd "${crate_dir}" + cargo fmt --all || exit 1 + cargo fmt --all --check || exit 1 + cargo test || exit 1 + cargo clippy --all-targets -- -D warnings || exit 1 + for invalid_consumer in "${test_dir}"compile-fail/*.rs; do + [[ -f "${invalid_consumer}" ]] || continue + expected_error="${invalid_consumer%.rs}.expected-error.txt" + if [[ ! -s "${expected_error}" ]]; then + echo " FAIL: ${invalid_consumer} is missing its expected diagnostic." + exit 1 + fi + mkdir -p examples + cp "${invalid_consumer}" examples/invalid_consumer.rs + if cargo check --example invalid_consumer >diagnostics.txt 2>&1; then + echo " FAIL: ${invalid_consumer} compiled successfully." + exit 1 + fi + if ! grep -Fq -f "${expected_error}" diagnostics.txt; then + cat diagnostics.txt + echo " FAIL: ${invalid_consumer} did not fail with its expected diagnostic." + exit 1 + fi + rm examples/invalid_consumer.rs + echo " PASS: $(basename "${invalid_consumer}") rejects its invalid consumer." + done + ) || { echo " FAIL: ${test_name} does not pass Rust validation."; exit 1; } + echo " PASS: ${test_name} formats, tests, and passes Clippy." +done diff --git a/mise.toml b/mise.toml index 1013992..61eff18 100644 --- a/mise.toml +++ b/mise.toml @@ -3,4 +3,5 @@ go = "1.27.1" jq = "1.8.1" node = "24.21.0" +rust = { version = "1.99.0", profile = "minimal", components = ["rustfmt", "clippy"] } "npm:prettier" = "3.9.9" diff --git a/templates/code/rust/README.md b/templates/code/rust/README.md new file mode 100644 index 0000000..8e41fbb --- /dev/null +++ b/templates/code/rust/README.md @@ -0,0 +1,173 @@ +# Rust Template Package + +Generates typed attributes, metric instruments, span starters, event emitters, +and entity values from a semantic convention registry using OpenTelemetry Rust. + +Stability: Development. Generated code targets `opentelemetry` and +`opentelemetry_sdk` 0.33.0. + +## Generate and use a module + +From a checkout of this repository: + +```sh +weaver registry generate \ + --v2 \ + -r {your registry} \ + -t templates \ + code/rust \ + {your crate}/src/semconv +``` + +For a released package, replace `-t templates` with +`-t 'https://github.com/TrogonStack/trogonstack-weaver-packages.git@v{version}[templates]'`. +Declare `mod semconv;` in the consuming crate and add its dependencies: + +```toml +[dependencies] +opentelemetry = "0.33.0" +opentelemetry_sdk = "0.33.0" +``` + +Run `cargo fmt` after generation. Weaver writes only the files it produces, so +empty the generated directory before regenerating after removing conventions. +Keep the consuming crate's files outside that directory. + +## Generated API + +The root `mod.rs` carries `SCHEMA_URL` and inline attribute modules. Signals +live in sibling files declared by the root module. Names use the first dotted +segment as their namespace; `vendor_prefixes` removes a leading vendor segment +before choosing that namespace. + +| Module | API | +| ------------------- | -------------------------------------------------------------------------------------------- | +| `attr` | Attribute newtypes and enum variants, `KEY`, `key_value`, and conversion into `KeyValue`. | +| `meter` | Schema-aware `Meter`, with `new`, `new_with_scope`, `inner`, and a no-op `Default`. | +| `tracer` | Schema-aware `Tracer`, with `new`, `new_with_scope`, `inner`, and a no-op `Default`. | +| `logger` | Schema-aware generic `Logger`, with `new`, `new_with_scope`, `inner`, and a no-op `Default`. | +| `metric` | Synchronous instruments and observable counters, up-down counters, and gauges. | +| `span` | Span starters, typed names, start attributes, and attributes allowed after starting. | +| `event` | Typed log event emitters and options for attributes, severity, and timestamp. | +| `entity` | Entity values, attribute copies, and resources carrying the registry schema URL. | + +Handle modules are emitted when the registry includes their corresponding +signals. They set the registry schema URL on their instrumentation scope. +Use `new_with_scope` to preserve a supplied scope's name, version, and +attributes; its schema URL is replaced by the registry's schema URL. +Attribute keys, metric names, and event names retain their full registry names. + +### Typed attributes + +An attribute such as `myapp.task.id` becomes +`myappattr::TaskIdAttr::new("task-1")`. Its `key_value()` method consumes the +value and returns an OpenTelemetry `KeyValue`. Enums expose named variants, +such as `myappattr::TaskStateAttr::Running`, rather than arbitrary constructors. + +Supported backing types are `String`, `i64`, `f64`, `bool`, and their `Vec` +forms. Enums can have string, integer, fractional, or boolean values. +Deprecation metadata becomes Rust deprecation annotations. + +### Metrics + +Each metric becomes a typed instrument with a `new(&meter)` constructor and +an `add` or `record` method. Required attributes are typed arguments. Other +attributes are variants of the instrument's `Attr` enum, passed as an iterator. +Observable constructors register a callback whose typed observer has the same +required arguments and optional attribute contract. + +Set `annotations.code_generation.metric_value_type` to `int` or `double`. +Rust's integer counters and histograms use `u64`; integer up-down counters and +gauges use `i64`. Double instruments use `f64`. Constructors follow the Rust +API and return instruments directly. Observable callbacks return `()`. + +Histograms accept `annotations.aggregation` with `method: explicithistogram` +and `parameters.boundaries`. Boundaries must be a nonempty, strictly increasing +list of numbers. Without explicit aggregation, `histogram_boundaries_by_unit` +provides unit-specific boundaries; units absent from that map use SDK defaults. + +### Spans + +A span starter takes a parent `Context`, a generated tracer, required typed +attributes, and optional start attributes. A registry name template whose +placeholders refer to required attributes is expanded from those values. +Otherwise the starter takes a typed `Name`; an empty name falls back to the +span's registry type. + +All starter attributes are present before sampling. Sampling-relevant +attributes appear only in the start attribute enum. The separate late attribute +enum is accepted by `set_attributes`. The wrapper exposes `end`, +`end_with_timestamp`, `record_error`, `set_status`, and the underlying span. +`into_context` transfers the span into a parent context for nested spans and +normal OpenTelemetry context attachment. + +### Events + +Emitters produce log records with the event name and no body. Required +attributes are typed parameters. Options accept declared attributes, severity, +and timestamp. Severity defaults to Info. The emitter checks whether the logger +accepts the event, sets the observed timestamp, and copies a valid trace context +from the supplied `Context`. + +### Entities + +Entity constructors take required identity attributes before required +description attributes, followed by optional attributes. `attributes()` returns +a copy. `resource()` creates a resource with the registry schema URL and no +implicit SDK detector attributes. `Default` carries no attributes. + +### Refinements and dependencies + +Metric, span, and entity refinements receive separate APIs and are emitted only +when their base convention is emitted. Metric refinements retain their base +instrument's name, description, unit, value type, and boundaries. Event +refinements follow Weaver's resolved event name, which is the refinement id. + +Imported attributes use their plain Rust backing type by default. Set +`imported_crate_paths` to use types from a separately generated dependency: + +```yaml +params: + imported_crate_paths: + error: upstream +``` + +That mapping refers to `upstream::errorattr` in the consuming crate. Both +registries must use compatible namespace and vendor-prefix settings. + +## Parameters + +| Parameter | Default | Purpose | +| ------------------------------ | --------------------------- | ------------------------------------------------------------------------- | +| `vendor_prefixes` | `[]` | Leading vendor segments removed when deriving namespaces and identifiers. | +| `exclude_deprecated` | `false` | Exclude deprecated conventions and enum members. | +| `stable_only` | `false` | Include only stable conventions and enum members. | +| `imported_crate_paths` | `{}` | Namespace to Rust path for a separately generated dependency. | +| `histogram_boundaries_by_unit` | Duration boundaries for `s` | Default histogram boundaries by unit; `{}` disables them. | +| `header_source` | `""` | Source description in the generated header. | +| `module_description` | `""` | Additional root module documentation. | +| `regenerate_command` | `""` | Regeneration instruction in the generated header. | + +## Generation errors and limits + +The manifest must provide a schema URL ending in a schema version. Naming +collisions, unusable enums, invalid aggregation, conflicting refinements, and +filtering away required signal attributes fail generation. Attribute names use +ASCII letter-led dotted segments containing letters, digits, and underscores. +Namespace segments must be lowercase and may contain digits and underscores. + +Conditional requirements remain options because Rust cannot prove registry +conditions. Event bodies, span events, and links have no registry form; use +the underlying OpenTelemetry handles when needed. Template and `any` attribute +types are not generated. + +## Validate a change + +```sh +mise run weaver:test:templates +mise run weaver:test:rust +``` + +The Rust check formats generated fixture code in temporary crates, runs consumer +and documentation tests, verifies compile-fail examples, and runs Clippy with +warnings denied. Snapshot checks compare the original Weaver output. diff --git a/templates/code/rust/entities.rs.j2 b/templates/code/rust/entities.rs.j2 new file mode 100644 index 0000000..1dea446 --- /dev/null +++ b/templates/code/rust/entities.rs.j2 @@ -0,0 +1,61 @@ +{%- filter trim %} +{% import "signal_helpers.j2" as s -%} +{% filter regex_replace("(?m)(^[ \\t]*///[^\\n]*\\n)([ \\t]*\\n)+", "${1}") %} +// Code generated by weaver. DO NOT EDIT. +#![allow(deprecated)] +{% for def in ctx.entities %} +{%- set name = s.exported(def.short_name) ~ "Entity" %} +{% if def.optional %} +#[derive(Clone, Debug)] +pub enum {{ name }}Attr { +{% for opt in def.optional %} +{{ opt.requirement_doc | comment if opt.requirement_doc else '' }} + {{ s.exported(opt.attr_short_name) }}({{ s.attr_type(opt) }}), +{% endfor %} +} + +impl {{ name }}Attr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { +{% for opt in def.optional %} + Self::{{ s.exported(opt.attr_short_name) }}(value) => {{ s.attr_kv(opt, "value") }}, +{% endfor %} + } + } +} +{% endif %} +{{ s.docs(def) }} +{{ def.identity_doc | comment if def.identity_doc else '' }} +{{ def.description_doc | comment if def.description_doc else '' }} +{% if def.refines %}{{ ("Refines `" ~ def.refines ~ "`.") | comment }}{% endif %} +{{ s.deprecated(def) }} +#[derive(Clone, Debug, Default)] +pub struct {{ name }} { + attributes: Vec<::opentelemetry::KeyValue>, +} + +impl {{ name }} { + pub fn new({% for req in def.required %}{{ s.ident(req.attr_param) }}: {{ s.attr_type(req) }}, {% endfor %}{% if def.optional %}options: impl IntoIterator{% endif %}) -> Self { + {% if def.required or def.optional %}let {% if def.optional %}mut {% endif %}attributes = vec![ +{% for req in def.required %} + {{ s.attr_kv(req, s.ident(req.attr_param)) }}, +{% endfor %} + ]; +{% if def.optional %} attributes.extend(options.into_iter().map({{ name }}Attr::key_value)); +{% endif %} Self { attributes } +{% else %} Self::default() +{% endif %} } + + pub fn attributes(&self) -> Vec<::opentelemetry::KeyValue> { + self.attributes.clone() + } + + pub fn resource(&self) -> ::opentelemetry_sdk::Resource { + ::opentelemetry_sdk::Resource::builder_empty() + .with_schema_url(self.attributes(), super::SCHEMA_URL) + .build() + } +} +{% endfor %} +{% endfilter %} +{% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/events.rs.j2 b/templates/code/rust/events.rs.j2 new file mode 100644 index 0000000..20a0172 --- /dev/null +++ b/templates/code/rust/events.rs.j2 @@ -0,0 +1,45 @@ +{%- filter trim %} +#![allow(deprecated)] +{% import "signal_helpers.j2" as h %} +{% for def in ctx.events %} +{% set name = h.exported(def.short_name) %} +#[derive(Clone, Debug)] +pub enum {{ name }}Option { + Severity(::opentelemetry::logs::Severity), + Timestamp(::std::time::SystemTime), +{% for opt in def.optional %} +{{ opt.requirement_doc | comment if opt.requirement_doc else '' }} + {{ h.exported(opt.attr_short_name) }}({{ h.attr_type(opt) }}), +{% endfor %} +} +{{ (h.docs(def) ~ "\n" ~ h.deprecated(def)) | trim }} +pub fn {{ h.ident('emit.' ~ def.short_name) }}(context: &::opentelemetry::Context, logger: &super::logger::Logger{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}, options: impl IntoIterator) { + use ::opentelemetry::logs::LogRecord; + use ::opentelemetry::trace::TraceContextExt; + let _context_guard = context.clone().attach(); + let mut severity = ::opentelemetry::logs::Severity::Info; + let mut timestamp = None; + let {% if def.optional %}mut {% endif %}attributes: Vec<::opentelemetry::KeyValue> = vec![{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; + for option in options { + match option { + {{ name }}Option::Severity(value) => severity = value, + {{ name }}Option::Timestamp(value) => timestamp = Some(value), +{% for opt in def.optional %} + {{ name }}Option::{{ h.exported(opt.attr_short_name) }}(value) => attributes.push({{ h.attr_kv(opt, 'value') }}), +{% endfor %} + } + } + if !logger.inner().event_enabled(severity, "", Some({{ h.literal(def.name) }})) { return; } + let mut record = logger.inner().create_log_record(); + record.set_event_name({{ h.literal(def.name) }}); + record.set_severity_number(severity); + record.set_observed_timestamp(::std::time::SystemTime::now()); + if let Some(timestamp) = timestamp { record.set_timestamp(timestamp); } + let span = context.span(); + let span_context = span.span_context(); + if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } + for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + logger.inner().emit(record); +} +{% endfor %} +{% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/logger.rs.j2 b/templates/code/rust/logger.rs.j2 new file mode 100644 index 0000000..7688d56 --- /dev/null +++ b/templates/code/rust/logger.rs.j2 @@ -0,0 +1,42 @@ +{%- filter trim %} +#[derive(Clone, Debug)] +pub struct Logger::Logger>(L); +impl Logger { + pub fn new>(provider: &P, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.logger_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &L { &self.0 } +} +impl Default for Logger { + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } +} +pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { + use opentelemetry::{Value, Array}; + use opentelemetry::logs::AnyValue; + match value { + Value::Bool(value) => value.into(), + Value::I64(value) => value.into(), + Value::F64(value) => value.into(), + Value::String(value) => value.into(), + Value::Array(array) => match array { + Array::Bool(values) => values.into_iter().collect::(), + Array::I64(values) => values.into_iter().collect::(), + Array::F64(values) => values.into_iter().collect::(), + Array::String(values) => values.into_iter().collect::(), + _ => AnyValue::String(array.to_string().into()), + }, + _ => AnyValue::String(value.to_string().into()), + } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} +{% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/meter.rs.j2 b/templates/code/rust/meter.rs.j2 new file mode 100644 index 0000000..41f6596 --- /dev/null +++ b/templates/code/rust/meter.rs.j2 @@ -0,0 +1,24 @@ +{%- filter trim %} +#[derive(Clone, Debug)] +pub struct Meter(opentelemetry::metrics::Meter); +impl Meter { + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.meter_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } +} +impl Default for Meter { + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} +{% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/metrics.rs.j2 b/templates/code/rust/metrics.rs.j2 new file mode 100644 index 0000000..806b348 --- /dev/null +++ b/templates/code/rust/metrics.rs.j2 @@ -0,0 +1,81 @@ +{%- filter trim %} +#![allow(deprecated)] +{% import "signal_helpers.j2" as h %} +{% for def in ctx.metrics %} +{% set suffix = def.instrument | map_text("metric_instrument") %} +{% set name = h.exported(def.short_name) ~ suffix %} +{% set method = 'add' if def.instrument in ['counter','updowncounter'] else 'record' %} +{% set value_type = 'f64' if def.annotations.code_generation.metric_value_type == 'double' else ('i64' if def.instrument in ['updowncounter','gauge'] else 'u64') %} +{% set builder = value_type ~ '_' ~ ('up_down_counter' if def.instrument == 'updowncounter' else def.instrument) %} +{% if def.optional %} +#[derive(Clone, Debug)] +pub enum {{ name }}Attr { +{% for opt in def.optional %} +{{ opt.requirement_doc | comment if opt.requirement_doc else '' }} + {{ h.exported(opt.attr_short_name) }}({{ h.attr_type(opt) }}), +{% endfor %} +} +impl {{ name }}Attr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { +{% for opt in def.optional %} + Self::{{ h.exported(opt.attr_short_name) }}(value) => {{ h.attr_kv(opt, 'value') }}, +{% endfor %} + } + } +} +{% endif %} +{{ (h.docs(def) ~ "\n" ~ h.deprecated(def)) | trim }} +#[derive(Clone)] +pub struct {{ name }} { instrument: ::opentelemetry::metrics::{{ suffix }}<{{ value_type }}> } +impl {{ name }} { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().{{ builder }}({{ h.literal(def.instrument_name) }}) + .with_description({{ h.literal(def.description | trim) }}) + .with_unit({{ h.literal(def.unit) }}) +{% if def.bucket_boundaries %} + .with_boundaries(vec![{% for bound in def.bucket_boundaries %}{{ bound }}_f64{% if not loop.last %}, {% endif %}{% endfor %}]) +{% endif %} + .build() } + } + pub fn {{ method }}(&self, value: {{ value_type }}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) { + let {% if def.optional %}mut {% endif %}attributes = vec![{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; +{% if def.optional %} + attributes.extend(options.into_iter().map({{ name }}Attr::key_value)); +{% endif %} + self.instrument.{{ method }}(value, &attributes); + } +} +impl Default for {{ name }} { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} +{% if def.instrument != 'histogram' %} +{% set observable = h.exported(def.short_name) ~ 'Observable' ~ suffix %} +pub struct {{ name }}Observer<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument<{{ value_type }}> } +impl {{ name }}Observer<'_> { + pub fn observe(&self, value: {{ value_type }}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) { + let {% if def.optional %}mut {% endif %}attributes = vec![{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; +{% if def.optional %} + attributes.extend(options.into_iter().map({{ name }}Attr::key_value)); +{% endif %} + self.observer.observe(value, &attributes); + } +} +{{ h.deprecated(def) }} +#[derive(Clone)] +pub struct {{ observable }} { _instrument: ::opentelemetry::metrics::Observable{{ suffix }}<{{ value_type }}> } +impl {{ observable }} { + pub fn new(meter: &super::meter::Meter, callback: impl Fn({{ name }}Observer<'_>) + Send + Sync + 'static) -> Self { + Self { _instrument: meter.inner().{{ value_type }}_observable_{{ 'up_down_counter' if def.instrument == 'updowncounter' else def.instrument }}({{ h.literal(def.instrument_name) }}) + .with_description({{ h.literal(def.description | trim) }}) + .with_unit({{ h.literal(def.unit) }}) + .with_callback(move |observer| callback({{ name }}Observer { observer })) + .build() } + } +} +impl Default for {{ observable }} { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} +{% endif %} +{% endfor %} +{% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/mod.rs.j2 b/templates/code/rust/mod.rs.j2 new file mode 100644 index 0000000..417c469 --- /dev/null +++ b/templates/code/rust/mod.rs.j2 @@ -0,0 +1,68 @@ +{%- filter trim %} +{% if params.module_description %}{{ params.module_description | comment | regex_replace("///", "//!") }} +{% endif %}// Generated by OpenTelemetry Weaver. +{% if params.header_source -%} +// Source: {{ params.header_source | replace("\n", " ") | replace("\r", " ") }} +{% endif %} +{% if params.regenerate_command -%} +// Regenerate: {{ params.regenerate_command | replace("\n", " ") | replace("\r", " ") }} +{% endif %} +pub const SCHEMA_URL: &str = {{ ctx.schema_literal }}; +{% for namespace in ctx.namespaces %} +pub mod {{ namespace.name }} { +{% for attr in namespace.attributes %} + {{ [attr.brief, attr.note] | select | join("\n\n") | comment | indent(4) }} + {{ ("#[deprecated(note = " ~ attr.deprecated_literal ~ ")]\n ") if attr.deprecated_literal else "" }}#[derive(Debug, Clone, PartialEq{% if attr.type is mapping %}, Copy{% endif %})] +{% if attr.type is mapping %} + pub enum {{ attr.name }} { +{% for member in attr.type.members %} + {{ [member.brief, member.note] | select | join("\n\n") | comment | indent(8) }} + {{ ("#[deprecated(note = " ~ member.deprecated_literal ~ ")]\n ") if member.deprecated_literal else "" }}{{ member.name }}, +{% endfor %} + } +{% else %} + pub struct {{ attr.name }}({{ attr.value_type | map_text("rust_type") }}); +{% endif %} + + #[allow(deprecated)] + impl {{ attr.name }} { + pub const KEY: &'static str = {{ attr.key_literal }}; +{% if attr.type is not mapping %} + pub fn new(value: {% if attr.value_type == "string" %}impl Into{% else %}{{ attr.value_type | map_text("rust_type") }}{% endif %}) -> Self { + Self(value{% if attr.value_type == "string" %}.into(){% endif %}) + } +{% endif %} + + pub fn key_value(self) -> ::opentelemetry::KeyValue { +{% if attr.type is mapping %} + let value: {{ attr.value_type | map_text("rust_type") }} = match self { +{% for member in attr.type.members %} + Self::{{ member.name }} => {{ member.literal }}{% if attr.value_type == "string" %}.into(){% elif attr.value_type == "double" %}_f64{% endif %}, +{% endfor %} + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) +{% elif "[]" in attr.value_type %} + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::{{ attr.value_type | map_text("rust_array") }}(self.0{% if attr.value_type == "string[]" %}.into_iter().map(Into::into).collect(){% endif %}))) +{% else %} + ::opentelemetry::KeyValue::new(Self::KEY, self.0) +{% endif %} + } + } + + #[allow(deprecated)] + impl From<{{ attr.name }}> for ::opentelemetry::KeyValue { + fn from(value: {{ attr.name }}) -> Self { + value.key_value() + } + } +{% endfor %} +} +{% endfor %} + +{% if ctx.has_metrics %}pub mod meter;{% endif %} +{% if ctx.has_spans %}pub mod tracer;{% endif %} +{% if ctx.has_events %}pub mod logger;{% endif %} +{% for module in ctx.signal_modules %} +pub mod {{ module }}; +{% endfor %} +{% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/signal_helpers.j2 b/templates/code/rust/signal_helpers.j2 new file mode 100644 index 0000000..c7a7199 --- /dev/null +++ b/templates/code/rust/signal_helpers.j2 @@ -0,0 +1,25 @@ +{% macro literal(value) -%} +"{%- for char in value -%}{{ (char | tojson | replace("\\b", "\\u{0008}") | replace("\\f", "\\u{000c}") | regex_replace("\\\\u([0-9A-Fa-f]{4})", "\\u{${1}}"))[1:-1] }}{%- endfor -%}" +{%- endmacro %} +{% macro exported(value) -%}{% for dotted in value.split(".") %}{% for segment in dotted.split("_") %}{{ segment[:1] | upper }}{{ segment[1:] }}{% endfor %}{% endfor %}{%- endmacro %} +{% macro ident(value) -%}r#{{ value | snake_case }}{%- endmacro %} +{% macro attr_type(a) -%} +{%- if a.imported -%}{{ a.attr_type | map_text("rust_type") }} +{%- else -%}{{ a.attr_import_path if a.attr_import_path else 'super::' ~ a.attr_namespace ~ 'attr' }}::{{ exported(a.attr_short_name) }}Attr +{%- endif -%} +{%- endmacro %} +{% macro attr_kv(a, value) -%} +{%- if a.imported -%}::opentelemetry::KeyValue::new({{ literal(a.key) }}, {% if "[]" in a.attr_type %}::opentelemetry::Value::Array(::opentelemetry::Array::{{ a.attr_type | map_text("rust_array") }}({{ value }}{% if a.attr_type == "string[]" %}.into_iter().map(Into::into).collect(){% endif %})){% else %}{{ value }}{% endif %}) +{%- else -%}{{ value }}.key_value() +{%- endif -%} +{%- endmacro %} +{% macro deprecated(def) -%} +{%- if def.deprecated -%}#[deprecated(note = {{ literal((def.deprecated.note if def.deprecated.note else 'Deprecated by the semantic convention registry')) }})] +{%- endif -%} +{%- endmacro %} +{% macro docs(def) -%} +{{ ([def.brief, def.note] | select | join('\n\n')) | comment | trim }} +{%- if def.requirement_level == 'opt_in' %} +/// Opt-in: record only when the user requests it. +{%- endif -%} +{%- endmacro %} diff --git a/templates/code/rust/spans.rs.j2 b/templates/code/rust/spans.rs.j2 new file mode 100644 index 0000000..60167d3 --- /dev/null +++ b/templates/code/rust/spans.rs.j2 @@ -0,0 +1,103 @@ +{%- filter trim %} +#![allow(deprecated)] +{% import "signal_helpers.j2" as h %} +{% for def in ctx.spans %} +{% set name = h.exported(def.short_name) %} +{% set span = name ~ 'Span' %} +{% if def.optional %} +#[derive(Clone, Debug)] +pub enum {{ name }}StartAttr { +{% for opt in def.optional %} +{{ opt.requirement_doc | comment if opt.requirement_doc else '' }} + {{ h.exported(opt.attr_short_name) }}({{ h.attr_type(opt) }}), +{% endfor %} +} +impl {{ name }}StartAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { +{% for opt in def.optional %} + Self::{{ h.exported(opt.attr_short_name) }}(value) => {{ h.attr_kv(opt, 'value') }}, +{% endfor %} + } + } +} +{% endif %} +{% if def.has_late_attrs %} +#[derive(Clone, Debug)] +pub enum {{ name }}Attr { +{% for opt in def.optional if not opt.sampling_relevant %} + {{ h.exported(opt.attr_short_name) }}({{ h.attr_type(opt) }}), +{% endfor %} +} +impl From<{{ name }}Attr> for {{ name }}StartAttr { + fn from(value: {{ name }}Attr) -> Self { + match value { +{% for opt in def.optional if not opt.sampling_relevant %} + {{ name }}Attr::{{ h.exported(opt.attr_short_name) }}(value) => Self::{{ h.exported(opt.attr_short_name) }}(value), +{% endfor %} + } + } +} +{% endif %} +{% if not def.name_parts %} +#[derive(Clone, Debug, Default)] +pub struct {{ name }}Name(String); +impl {{ name }}Name { + pub fn new(value: impl Into) -> Self { Self(value.into()) } +} +{% endif %} +{{ (h.docs(def) ~ "\n" ~ h.deprecated(def)) | trim }} +pub struct {{ span }} { span: ::opentelemetry::global::BoxedSpan } +impl {{ span }} { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { + use ::opentelemetry::trace::TraceContextExt; + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } +{% if def.has_late_attrs %} + pub fn set_attributes(&mut self, attributes: impl IntoIterator) { + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, {{ name }}StartAttr::from(attribute).key_value()); } + } +{% endif %} +} +impl Default for {{ span }} { + fn default() -> Self { + use ::opentelemetry::trace::Tracer; + Self { span: super::tracer::Tracer::default().inner().start({{ h.literal(def.type) }}) } + } +} +{{ h.deprecated(def) }} +pub fn {{ h.ident('start.' ~ def.short_name) }}(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer{% if not def.name_parts %}, name: {{ name }}Name{% endif %}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) -> {{ span }} { + use ::opentelemetry::trace::Tracer; +{% if def.name_parts %} + let mut name = String::new(); +{% for part in def.name_parts %} +{% if part.attr %} + name.push_str(&{{ h.attr_kv(part.attr, h.ident(part.attr.attr_param) ~ ('' if (part.attr.type is mapping and not part.attr.imported) or (part.attr.imported and part.attr.attr_type in ['int', 'double', 'boolean']) else '.clone()')) }}.value.to_string()); +{% else %} +{% if part.text | length == 1 %} + name.push('{{ h.literal(part.text)[1:-1] | replace("'", "\\'") }}'); +{% else %} + name.push_str({{ h.literal(part.text) }}); +{% endif %} +{% endif %} +{% endfor %} +{% else %} + let name = if name.0.is_empty() { {{ h.literal(def.type) }}.to_owned() } else { name.0 }; +{% endif %} + let {% if def.optional %}mut {% endif %}attributes = vec![{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; +{% if def.optional %} + attributes.extend(options.into_iter().map({{ name }}StartAttr::key_value)); +{% endif %} + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::{{ def.kind | pascal_case }}) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + {{ span }} { span } +} +{% endfor %} +{% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/tests/attributes/compile-fail/inherited_deprecation.expected-error.txt b/templates/code/rust/tests/attributes/compile-fail/inherited_deprecation.expected-error.txt new file mode 100644 index 0000000..56c12c8 --- /dev/null +++ b/templates/code/rust/tests/attributes/compile-fail/inherited_deprecation.expected-error.txt @@ -0,0 +1 @@ +use of deprecated unit variant diff --git a/templates/code/rust/tests/attributes/compile-fail/inherited_deprecation.rs b/templates/code/rust/tests/attributes/compile-fail/inherited_deprecation.rs new file mode 100644 index 0000000..2fdc518 --- /dev/null +++ b/templates/code/rust/tests/attributes/compile-fail/inherited_deprecation.rs @@ -0,0 +1,4 @@ +#![deny(deprecated)] +fn main() { + let _ = generated_semconv::myappattr::TaskLaneAttr::Fast; +} diff --git a/templates/code/rust/tests/attributes/compile-fail/unknown_enum.expected-error.txt b/templates/code/rust/tests/attributes/compile-fail/unknown_enum.expected-error.txt new file mode 100644 index 0000000..3f1caed --- /dev/null +++ b/templates/code/rust/tests/attributes/compile-fail/unknown_enum.expected-error.txt @@ -0,0 +1 @@ +no variant, associated function, or constant named `Unknown` diff --git a/templates/code/rust/tests/attributes/compile-fail/unknown_enum.rs b/templates/code/rust/tests/attributes/compile-fail/unknown_enum.rs new file mode 100644 index 0000000..fe8a0cc --- /dev/null +++ b/templates/code/rust/tests/attributes/compile-fail/unknown_enum.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = generated_semconv::myappattr::TaskStateAttr::Unknown; +} diff --git a/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.expected-error.txt b/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.expected-error.txt new file mode 100644 index 0000000..26b75eb --- /dev/null +++ b/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.expected-error.txt @@ -0,0 +1 @@ +mismatched types diff --git a/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.rs b/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.rs new file mode 100644 index 0000000..c1e5aee --- /dev/null +++ b/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = generated_semconv::myappattr::TaskRetriesAttr::new("three"); +} diff --git a/templates/code/rust/tests/attributes/expected/mod.rs b/templates/code/rust/tests/attributes/expected/mod.rs new file mode 100644 index 0000000..2700729 --- /dev/null +++ b/templates/code/rust/tests/attributes/expected/mod.rs @@ -0,0 +1,622 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/attributes/1.0.0"; + +pub mod authattr { + + /// Assurance level of the authentication. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum LevelAttr { + + /// Single factor. + Low, + + /// Multiple factors. + High, + + } + + + #[allow(deprecated)] + impl LevelAttr { + pub const KEY: &'static str = "auth.level"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: i64 = match self { + + Self::Low => 1, + + Self::High => 2, + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: LevelAttr) -> Self { + value.key_value() + } + } + + /// How the user was authenticated. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum MethodAttr { + + /// A password was checked. + Password, + + /// A bearer token was checked. + Token, + + } + + + #[allow(deprecated)] + impl MethodAttr { + pub const KEY: &'static str = "auth.method"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Password => "password".into(), + + Self::Token => "token".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: MethodAttr) -> Self { + value.key_value() + } + } + + /// Identifier of the authenticated user. + #[derive(Debug, Clone, PartialEq)] + + pub struct UserIdAttr(String); + + + #[allow(deprecated)] + impl UserIdAttr { + pub const KEY: &'static str = "auth.user.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: UserIdAttr) -> Self { + value.key_value() + } + } + +} + +pub mod myappattr { + + /// Who assigned the task. + /// + /// The scheduler sets it on every task it passes along to `myapp.task.state`. Workers never set it themselves. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskAssignedByAttr(String); + + + #[allow(deprecated)] + impl TaskAssignedByAttr { + pub const KEY: &'static str = "myapp.task.assigned_by"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskAssignedByAttr) -> Self { + value.key_value() + } + } + + /// Whether the task was cancelled. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskCancelledAttr(bool); + + + #[allow(deprecated)] + impl TaskCancelledAttr { + pub const KEY: &'static str = "myapp.task.cancelled"; + + pub fn new(value: bool) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskCancelledAttr) -> Self { + value.key_value() + } + } + + /// Tests Rust string literals. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum TaskEscapedAttr { + + /// Escaped text. + Quoted, + + } + + + #[allow(deprecated)] + impl TaskEscapedAttr { + pub const KEY: &'static str = "myapp.task.escaped"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Quoted => "quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskEscapedAttr) -> Self { + value.key_value() + } + } + + /// Feature flags evaluated for the task. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskFlagsAttr(Vec); + + + #[allow(deprecated)] + impl TaskFlagsAttr { + pub const KEY: &'static str = "myapp.task.flags"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(self.0))) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskFlagsAttr) -> Self { + value.key_value() + } + } + + /// Unique identifier of the task. + /// + /// The identifier is assigned by the scheduler and stays stable across retries. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskIdAttr(String); + + + #[allow(deprecated)] + impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } + } + + /// Lane the task was scheduled in. + #[deprecated(note = "Lanes were replaced by priorities.")] + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum TaskLaneAttr { + + /// The fast lane. + #[deprecated(note = "Lanes were replaced by priorities.")] + Fast, + + /// The slow lane. + #[deprecated(note = "Every task runs in the fast lane.")] + Slow, + + } + + + #[allow(deprecated)] + impl TaskLaneAttr { + pub const KEY: &'static str = "myapp.task.lane"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Fast => "fast".into(), + + Self::Slow => "slow".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskLaneAttr) -> Self { + value.key_value() + } + } + + /// Owner of the task. + #[deprecated(note = "Replaced by `auth.user.id`.")] + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskOwnerAttr(String); + + + #[allow(deprecated)] + impl TaskOwnerAttr { + pub const KEY: &'static str = "myapp.task.owner"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskOwnerAttr) -> Self { + value.key_value() + } + } + + /// Whether the scheduler may preempt the task. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum TaskPreemptibleAttr { + + /// The scheduler may preempt the task. + Allowed, + + /// The task runs to completion. + Forbidden, + + } + + + #[allow(deprecated)] + impl TaskPreemptibleAttr { + pub const KEY: &'static str = "myapp.task.preemptible"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: bool = match self { + + Self::Allowed => true, + + Self::Forbidden => false, + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskPreemptibleAttr) -> Self { + value.key_value() + } + } + + /// Fraction of the task that has completed, between 0 and 1. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskProgressAttr(f64); + + + #[allow(deprecated)] + impl TaskProgressAttr { + pub const KEY: &'static str = "myapp.task.progress"; + + pub fn new(value: f64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskProgressAttr) -> Self { + value.key_value() + } + } + + /// Number of times the task was retried. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskRetriesAttr(i64); + + + #[allow(deprecated)] + impl TaskRetriesAttr { + pub const KEY: &'static str = "myapp.task.retries"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskRetriesAttr) -> Self { + value.key_value() + } + } + + /// Fraction of tasks whose telemetry is sampled. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum TaskSampleRateAttr { + + /// One task in ten is sampled. + Tenth, + + /// Every task is sampled. + All, + + } + + + #[allow(deprecated)] + impl TaskSampleRateAttr { + pub const KEY: &'static str = "myapp.task.sample_rate"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: f64 = match self { + + Self::Tenth => 0.1_f64, + + Self::All => 1_f64, + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskSampleRateAttr) -> Self { + value.key_value() + } + } + + /// Shards the task touched. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskShardIdsAttr(Vec); + + + #[allow(deprecated)] + impl TaskShardIdsAttr { + pub const KEY: &'static str = "myapp.task.shard_ids"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskShardIdsAttr) -> Self { + value.key_value() + } + } + + /// Current state of the task. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum TaskStateAttr { + + /// The task is waiting to run. + Queued, + + /// The task is running. + /// + /// A task stays running until it finishes or is cancelled. + Running, + + /// The task was paused. + #[deprecated(note = "Paused tasks are reported as queued.")] + Paused, + + } + + + #[allow(deprecated)] + impl TaskStateAttr { + pub const KEY: &'static str = "myapp.task.state"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Queued => "queued".into(), + + Self::Running => "running".into(), + + Self::Paused => "paused".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskStateAttr) -> Self { + value.key_value() + } + } + + /// Tags attached to the task. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskTagsAttr(Vec); + + + #[allow(deprecated)] + impl TaskTagsAttr { + pub const KEY: &'static str = "myapp.task.tags"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskTagsAttr) -> Self { + value.key_value() + } + } + + /// Scheduling weights applied to the task. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskWeightsAttr(Vec); + + + #[allow(deprecated)] + impl TaskWeightsAttr { + pub const KEY: &'static str = "myapp.task.weights"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(self.0))) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskWeightsAttr) -> Self { + value.key_value() + } + } + +} diff --git a/templates/code/rust/tests/attributes/registry/manifest.yaml b/templates/code/rust/tests/attributes/registry/manifest.yaml new file mode 100644 index 0000000..f168c1f --- /dev/null +++ b/templates/code/rust/tests/attributes/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: attributes +schema_url: https://example.com/schemas/attributes/1.0.0 diff --git a/templates/code/rust/tests/attributes/registry/model.yaml b/templates/code/rust/tests/attributes/registry/model.yaml new file mode 100644 index 0000000..74be0ec --- /dev/null +++ b/templates/code/rust/tests/attributes/registry/model.yaml @@ -0,0 +1,163 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: stable + brief: Unique identifier of the task. + note: The identifier is assigned by the scheduler and stays stable across retries. + examples: ["task_0001"] + - key: myapp.task.retries + type: int + stability: stable + brief: Number of times the task was retried. + examples: 3 + - key: myapp.task.progress + type: double + stability: development + brief: Fraction of the task that has completed, between 0 and 1. + examples: 0.5 + - key: myapp.task.cancelled + type: boolean + stability: stable + brief: Whether the task was cancelled. + examples: false + - key: myapp.task.tags + type: string[] + stability: stable + brief: Tags attached to the task. + examples: [["nightly", "batch"]] + - key: myapp.task.shard_ids + type: int[] + stability: stable + brief: Shards the task touched. + examples: [[1, 2]] + - key: myapp.task.weights + type: double[] + stability: development + brief: Scheduling weights applied to the task. + examples: [[0.25, 0.75]] + - key: myapp.task.flags + type: boolean[] + stability: development + brief: Feature flags evaluated for the task. + examples: [[true, false]] + - key: myapp.task.state + type: + members: + - id: queued + value: queued + stability: stable + brief: The task is waiting to run. + - id: running + value: running + stability: stable + brief: The task is running. + note: A task stays running until it finishes or is cancelled. + - id: paused + value: paused + stability: development + brief: The task was paused. + deprecated: + reason: obsoleted + note: Paused tasks are reported as queued. + stability: stable + brief: Current state of the task. + - key: myapp.task.owner + type: string + stability: development + brief: Owner of the task. + examples: ["solo"] + deprecated: + reason: renamed + renamed_to: auth.user.id + - key: auth.user.id + type: string + stability: stable + brief: Identifier of the authenticated user. + examples: ["u_123"] + - key: auth.method + type: + members: + - id: password + value: password + stability: stable + brief: A password was checked. + - id: token + value: token + stability: stable + brief: A bearer token was checked. + stability: stable + brief: How the user was authenticated. + - key: auth.level + type: + members: + - id: low + value: 1 + stability: stable + brief: Single factor. + - id: high + value: 2 + stability: stable + brief: Multiple factors. + stability: development + brief: Assurance level of the authentication. + - key: myapp.task.preemptible + type: + members: + - id: allowed + value: true + stability: stable + brief: The scheduler may preempt the task. + - id: forbidden + value: false + stability: stable + brief: The task runs to completion. + stability: stable + brief: Whether the scheduler may preempt the task. + - key: myapp.task.sample_rate + type: + members: + - id: tenth + value: 0.1 + stability: stable + brief: One task in ten is sampled. + - id: all + value: 1 + stability: stable + brief: Every task is sampled. + stability: stable + brief: Fraction of tasks whose telemetry is sampled. + - key: myapp.task.assigned_by + type: string + stability: stable + brief: Who assigned the task. + note: The scheduler sets it on every task it passes along to `myapp.task.state`. Workers never set it themselves. + examples: ["scheduler"] + - key: myapp.task.lane + type: + members: + - id: fast + value: fast + stability: stable + brief: The fast lane. + - id: slow + value: slow + stability: stable + brief: The slow lane. + deprecated: + reason: obsoleted + note: Every task runs in the fast lane. + stability: development + brief: Lane the task was scheduled in. + deprecated: + reason: obsoleted + note: Lanes were replaced by priorities. + - key: myapp.task.escaped + type: + members: + - id: quoted + value: "quote\" slash\\ newline\n tab\t backspace\b formfeed\f null\u0000 snowman☃" + stability: stable + brief: Escaped text. + stability: stable + brief: Tests Rust string literals. diff --git a/templates/code/rust/tests/attributes/test.rs b/templates/code/rust/tests/attributes/test.rs new file mode 100644 index 0000000..8181741 --- /dev/null +++ b/templates/code/rust/tests/attributes/test.rs @@ -0,0 +1,57 @@ +use generated_semconv::{authattr, myappattr, SCHEMA_URL}; +use opentelemetry::{Array, KeyValue, Value}; + +#[test] +fn typed_attributes_preserve_keys_values_and_schema() { + assert_eq!(SCHEMA_URL, "https://example.com/schemas/attributes/1.0.0"); + let value: KeyValue = myappattr::TaskIdAttr::new("task").into(); + assert_eq!(value, KeyValue::new("myapp.task.id", "task")); + assert_eq!( + myappattr::TaskRetriesAttr::new(4).key_value(), + KeyValue::new("myapp.task.retries", 4_i64) + ); + assert_eq!( + myappattr::TaskCancelledAttr::new(true).key_value().value, + Value::Bool(true) + ); + assert_eq!( + myappattr::TaskProgressAttr::new(0.5).key_value().value, + Value::F64(0.5) + ); + assert_eq!( + myappattr::TaskTagsAttr::new(vec!["tag".into()]) + .key_value() + .value, + Value::Array(Array::String(vec!["tag".into()])) + ); + assert_eq!( + myappattr::TaskShardIdsAttr::new(vec![1, 2]) + .key_value() + .value, + Value::Array(Array::I64(vec![1, 2])) + ); + assert_eq!( + myappattr::TaskWeightsAttr::new(vec![0.25]) + .key_value() + .value, + Value::Array(Array::F64(vec![0.25])) + ); + assert_eq!( + myappattr::TaskFlagsAttr::new(vec![false]).key_value().value, + Value::Array(Array::Bool(vec![false])) + ); + assert_eq!( + myappattr::TaskStateAttr::Running.key_value().value, + Value::String("running".into()) + ); + assert_eq!(myappattr::TaskEscapedAttr::Quoted.key_value().value, Value::String("quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃".into())); + assert_eq!(authattr::LevelAttr::High.key_value().value, Value::I64(2)); + assert_eq!( + myappattr::TaskPreemptibleAttr::Allowed.key_value().value, + Value::Bool(true) + ); + assert_eq!( + myappattr::TaskSampleRateAttr::All.key_value().value, + Value::F64(1.0) + ); +} diff --git a/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_attribute.expected-error.txt b/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_attribute.expected-error.txt new file mode 100644 index 0000000..a78250c --- /dev/null +++ b/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_attribute.expected-error.txt @@ -0,0 +1 @@ +could not find `HiddenAttr` diff --git a/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_attribute.rs b/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_attribute.rs new file mode 100644 index 0000000..4d59195 --- /dev/null +++ b/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_attribute.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = generated_semconv::demoattr::HiddenAttr::new("value"); +} diff --git a/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_member.expected-error.txt b/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_member.expected-error.txt new file mode 100644 index 0000000..9527579 --- /dev/null +++ b/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_member.expected-error.txt @@ -0,0 +1 @@ +named `Hidden` diff --git a/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_member.rs b/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_member.rs new file mode 100644 index 0000000..0dfab52 --- /dev/null +++ b/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_member.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = generated_semconv::demoattr::ModeAttr::Hidden; +} diff --git a/templates/code/rust/tests/codegen_exclusion/expected/mod.rs b/templates/code/rust/tests/codegen_exclusion/expected/mod.rs new file mode 100644 index 0000000..d166f41 --- /dev/null +++ b/templates/code/rust/tests/codegen_exclusion/expected/mod.rs @@ -0,0 +1,72 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/exclusion/1.0.0"; + +pub mod demoattr { + + /// Synthetic kept attribute. + #[derive(Debug, Clone, PartialEq)] + + pub struct KeptAttr(String); + + + #[allow(deprecated)] + impl KeptAttr { + pub const KEY: &'static str = "demo.kept"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: KeptAttr) -> Self { + value.key_value() + } + } + + /// Synthetic mode. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum ModeAttr { + + /// Included mode. + Kept, + + } + + + #[allow(deprecated)] + impl ModeAttr { + pub const KEY: &'static str = "demo.mode"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Kept => "kept".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: ModeAttr) -> Self { + value.key_value() + } + } + +} diff --git a/templates/code/rust/tests/codegen_exclusion/registry/manifest.yaml b/templates/code/rust/tests/codegen_exclusion/registry/manifest.yaml new file mode 100644 index 0000000..a20da06 --- /dev/null +++ b/templates/code/rust/tests/codegen_exclusion/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: exclusion +schema_url: https://example.com/schemas/exclusion/1.0.0 diff --git a/templates/code/rust/tests/codegen_exclusion/registry/model.yaml b/templates/code/rust/tests/codegen_exclusion/registry/model.yaml new file mode 100644 index 0000000..81a9fdc --- /dev/null +++ b/templates/code/rust/tests/codegen_exclusion/registry/model.yaml @@ -0,0 +1,35 @@ +file_format: definition/2 +attributes: + - key: demo.kept + type: string + stability: stable + brief: Synthetic kept attribute. + annotations: + code_generation: + exclude: false + - key: demo.hidden + type: string + stability: stable + brief: Synthetic excluded attribute. + annotations: + code_generation: + exclude: true + - key: demo.mode + type: + members: + - id: kept + value: kept + stability: stable + brief: Included mode. + annotations: + code_generation: + exclude: false + - id: hidden + value: hidden + stability: stable + brief: Excluded mode. + annotations: + code_generation: + exclude: true + stability: stable + brief: Synthetic mode. diff --git a/templates/code/rust/tests/codegen_exclusion/test.rs b/templates/code/rust/tests/codegen_exclusion/test.rs new file mode 100644 index 0000000..b84f50b --- /dev/null +++ b/templates/code/rust/tests/codegen_exclusion/test.rs @@ -0,0 +1,13 @@ +use generated_semconv::demoattr::{KeptAttr, ModeAttr}; +use opentelemetry::KeyValue; +#[test] +fn explicit_false_keeps_attributes_and_enum_members() { + assert_eq!( + KeptAttr::new("value").key_value(), + KeyValue::new("demo.kept", "value") + ); + assert_eq!( + ModeAttr::Kept.key_value(), + KeyValue::new("demo.mode", "kept") + ); +} diff --git a/templates/code/rust/tests/entities/compile-fail/missing_identity.expected-error.txt b/templates/code/rust/tests/entities/compile-fail/missing_identity.expected-error.txt new file mode 100644 index 0000000..129f1cd --- /dev/null +++ b/templates/code/rust/tests/entities/compile-fail/missing_identity.expected-error.txt @@ -0,0 +1 @@ +this function takes 2 arguments but 1 argument was supplied diff --git a/templates/code/rust/tests/entities/compile-fail/missing_identity.rs b/templates/code/rust/tests/entities/compile-fail/missing_identity.rs new file mode 100644 index 0000000..86bfeb8 --- /dev/null +++ b/templates/code/rust/tests/entities/compile-fail/missing_identity.rs @@ -0,0 +1,5 @@ +use generated_semconv::myappentity::HostEntity; + +fn main() { + let _ = HostEntity::new([]); +} diff --git a/templates/code/rust/tests/entities/compile-fail/wrong_identity.expected-error.txt b/templates/code/rust/tests/entities/compile-fail/wrong_identity.expected-error.txt new file mode 100644 index 0000000..68cf9b6 --- /dev/null +++ b/templates/code/rust/tests/entities/compile-fail/wrong_identity.expected-error.txt @@ -0,0 +1 @@ +expected `HostNameAttr`, found `QueueNameAttr` diff --git a/templates/code/rust/tests/entities/compile-fail/wrong_identity.rs b/templates/code/rust/tests/entities/compile-fail/wrong_identity.rs new file mode 100644 index 0000000..ad3f36e --- /dev/null +++ b/templates/code/rust/tests/entities/compile-fail/wrong_identity.rs @@ -0,0 +1,5 @@ +use generated_semconv::{myappattr, myappentity}; + +fn main() { + let _ = myappentity::HostEntity::new(myappattr::QueueNameAttr::new("queue-1"), []); +} diff --git a/templates/code/rust/tests/entities/expected/mod.rs b/templates/code/rust/tests/entities/expected/mod.rs new file mode 100644 index 0000000..4886371 --- /dev/null +++ b/templates/code/rust/tests/entities/expected/mod.rs @@ -0,0 +1,201 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/entities/1.0.0"; + +pub mod myappattr { + + /// Number of CPUs the host has. + #[deprecated(note = "Use `myapp.host.cpu.logical_count` instead.")] + #[derive(Debug, Clone, PartialEq)] + + pub struct HostCpuCountAttr(i64); + + + #[allow(deprecated)] + impl HostCpuCountAttr { + pub const KEY: &'static str = "myapp.host.cpu.count"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: HostCpuCountAttr) -> Self { + value.key_value() + } + } + + /// Name of the host. + #[derive(Debug, Clone, PartialEq)] + + pub struct HostNameAttr(String); + + + #[allow(deprecated)] + impl HostNameAttr { + pub const KEY: &'static str = "myapp.host.name"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: HostNameAttr) -> Self { + value.key_value() + } + } + + /// Role the host plays in the cluster. + #[derive(Debug, Clone, PartialEq)] + + pub struct HostRoleAttr(String); + + + #[allow(deprecated)] + impl HostRoleAttr { + pub const KEY: &'static str = "myapp.host.role"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: HostRoleAttr) -> Self { + value.key_value() + } + } + + /// Type of the host. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum HostTypeAttr { + + /// A physical host. + Physical, + + /// A virtual host. + Virtual, + + } + + + #[allow(deprecated)] + impl HostTypeAttr { + pub const KEY: &'static str = "myapp.host.type"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Physical => "physical".into(), + + Self::Virtual => "virtual".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: HostTypeAttr) -> Self { + value.key_value() + } + } + + /// Name of the queue. + #[derive(Debug, Clone, PartialEq)] + + pub struct QueueNameAttr(String); + + + #[allow(deprecated)] + impl QueueNameAttr { + pub const KEY: &'static str = "myapp.queue.name"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: QueueNameAttr) -> Self { + value.key_value() + } + } + + /// Number of items currently in the queue. + #[derive(Debug, Clone, PartialEq)] + + pub struct QueueSizeAttr(i64); + + + #[allow(deprecated)] + impl QueueSizeAttr { + pub const KEY: &'static str = "myapp.queue.size"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: QueueSizeAttr) -> Self { + value.key_value() + } + } + +} + + + + + + +pub mod myappentity; diff --git a/templates/code/rust/tests/entities/expected/myappentity.rs b/templates/code/rust/tests/entities/expected/myappentity.rs new file mode 100644 index 0000000..c0680a2 --- /dev/null +++ b/templates/code/rust/tests/entities/expected/myappentity.rs @@ -0,0 +1,166 @@ +// Code generated by weaver. DO NOT EDIT. +#![allow(deprecated)] + + +#[derive(Clone, Debug)] +pub enum HostEntityAttr { + +/// Opt-in: the convention records it only when a user asks for it. + HostCpuCount(super::myappattr::HostCpuCountAttr), + + + HostType(super::myappattr::HostTypeAttr), + +} + +impl HostEntityAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::HostCpuCount(value) => value.key_value(), + + Self::HostType(value) => value.key_value(), + + } + } +} + +/// A host running the application. +/// +/// Identified by its name across its lifetime. +/// Identifies the entity: `myapp.host.name`. +/// Describes the entity: `myapp.host.cpu.count`, `myapp.host.type`. +#[derive(Clone, Debug, Default)] +pub struct HostEntity { + attributes: Vec<::opentelemetry::KeyValue>, +} + +impl HostEntity { + pub fn new(r#myapp_host_name: super::myappattr::HostNameAttr, options: impl IntoIterator) -> Self { + let mut attributes = vec![ + + r#myapp_host_name.key_value(), + + ]; + attributes.extend(options.into_iter().map(HostEntityAttr::key_value)); + Self { attributes } + } + + pub fn attributes(&self) -> Vec<::opentelemetry::KeyValue> { + self.attributes.clone() + } + + pub fn resource(&self) -> ::opentelemetry_sdk::Resource { + ::opentelemetry_sdk::Resource::builder_empty() + .with_schema_url(self.attributes(), super::SCHEMA_URL) + .build() + } +} + + +#[derive(Clone, Debug)] +pub enum HostWorkerEntityAttr { + +/// Opt-in: the convention records it only when a user asks for it. + HostCpuCount(super::myappattr::HostCpuCountAttr), + + + HostType(super::myappattr::HostTypeAttr), + +} + +impl HostWorkerEntityAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::HostCpuCount(value) => value.key_value(), + + Self::HostType(value) => value.key_value(), + + } + } +} + +/// A host dedicated to running worker processes. +/// +/// Identified by its name across its lifetime. +/// Identifies the entity: `myapp.host.name`. +/// Describes the entity: `myapp.host.cpu.count`, `myapp.host.role`, `myapp.host.type`. +/// Refines `myapp.host`. +#[derive(Clone, Debug, Default)] +pub struct HostWorkerEntity { + attributes: Vec<::opentelemetry::KeyValue>, +} + +impl HostWorkerEntity { + pub fn new(r#myapp_host_name: super::myappattr::HostNameAttr, r#myapp_host_role: super::myappattr::HostRoleAttr, options: impl IntoIterator) -> Self { + let mut attributes = vec![ + + r#myapp_host_name.key_value(), + + r#myapp_host_role.key_value(), + + ]; + attributes.extend(options.into_iter().map(HostWorkerEntityAttr::key_value)); + Self { attributes } + } + + pub fn attributes(&self) -> Vec<::opentelemetry::KeyValue> { + self.attributes.clone() + } + + pub fn resource(&self) -> ::opentelemetry_sdk::Resource { + ::opentelemetry_sdk::Resource::builder_empty() + .with_schema_url(self.attributes(), super::SCHEMA_URL) + .build() + } +} + + +#[derive(Clone, Debug)] +pub enum QueueEntityAttr { + + + QueueSize(super::myappattr::QueueSizeAttr), + +} + +impl QueueEntityAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::QueueSize(value) => value.key_value(), + + } + } +} + +/// A queue of tasks. +/// Identifies the entity: `myapp.queue.name`. +/// Describes the entity: `myapp.queue.size`. +#[derive(Clone, Debug, Default)] +pub struct QueueEntity { + attributes: Vec<::opentelemetry::KeyValue>, +} + +impl QueueEntity { + pub fn new(r#myapp_queue_name: super::myappattr::QueueNameAttr, options: impl IntoIterator) -> Self { + let mut attributes = vec![ + + r#myapp_queue_name.key_value(), + + ]; + attributes.extend(options.into_iter().map(QueueEntityAttr::key_value)); + Self { attributes } + } + + pub fn attributes(&self) -> Vec<::opentelemetry::KeyValue> { + self.attributes.clone() + } + + pub fn resource(&self) -> ::opentelemetry_sdk::Resource { + ::opentelemetry_sdk::Resource::builder_empty() + .with_schema_url(self.attributes(), super::SCHEMA_URL) + .build() + } +} diff --git a/templates/code/rust/tests/entities/registry/manifest.yaml b/templates/code/rust/tests/entities/registry/manifest.yaml new file mode 100644 index 0000000..60bfc60 --- /dev/null +++ b/templates/code/rust/tests/entities/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: entities +schema_url: https://example.com/schemas/entities/1.0.0 diff --git a/templates/code/rust/tests/entities/registry/model.yaml b/templates/code/rust/tests/entities/registry/model.yaml new file mode 100644 index 0000000..3fb41a1 --- /dev/null +++ b/templates/code/rust/tests/entities/registry/model.yaml @@ -0,0 +1,74 @@ +file_format: definition/2 +attributes: + - key: myapp.host.name + type: string + stability: stable + brief: Name of the host. + examples: ["host-1"] + - key: myapp.host.type + type: + members: + - id: physical + value: physical + stability: stable + brief: A physical host. + - id: virtual + value: virtual + stability: stable + brief: A virtual host. + stability: stable + brief: Type of the host. + - key: myapp.host.cpu.count + type: int + stability: development + brief: Number of CPUs the host has. + examples: 4 + deprecated: + reason: uncategorized + note: Use `myapp.host.cpu.logical_count` instead. + - key: myapp.host.role + type: string + stability: stable + brief: Role the host plays in the cluster. + examples: ["worker"] + - key: myapp.queue.name + type: string + stability: stable + brief: Name of the queue. + examples: ["reports"] + - key: myapp.queue.size + type: int + stability: stable + brief: Number of items currently in the queue. + examples: 3 +entities: + - type: myapp.host + requirement_level: recommended + stability: stable + brief: A host running the application. + note: Identified by its name across its lifetime. + identity: + - ref: myapp.host.name + requirement_level: required + description: + - ref: myapp.host.type + requirement_level: recommended + - ref: myapp.host.cpu.count + requirement_level: opt_in + - type: myapp.queue + requirement_level: recommended + stability: stable + brief: A queue of tasks. + identity: + - ref: myapp.queue.name + requirement_level: required + description: + - ref: myapp.queue.size +entity_refinements: + - id: myapp.host.worker + ref: myapp.host + stability: stable + brief: A host dedicated to running worker processes. + description: + - ref: myapp.host.role + requirement_level: required diff --git a/templates/code/rust/tests/entities/test.rs b/templates/code/rust/tests/entities/test.rs new file mode 100644 index 0000000..e38d54d --- /dev/null +++ b/templates/code/rust/tests/entities/test.rs @@ -0,0 +1,34 @@ +use generated_semconv::{myappattr, myappentity, SCHEMA_URL}; + +#[test] +fn entity_resource_keeps_identity_description_and_schema() { + let entity = myappentity::HostEntity::new( + myappattr::HostNameAttr::new("worker-1"), + [myappentity::HostEntityAttr::HostType( + myappattr::HostTypeAttr::Virtual, + )], + ); + let attributes = entity.attributes(); + assert_eq!(attributes.len(), 2); + assert_eq!(attributes[0].key.as_str(), "myapp.host.name"); + assert_eq!(attributes[0].value.as_str(), "worker-1"); + assert_eq!(attributes[1].value.as_str(), "virtual"); + let resource = entity.resource(); + assert_eq!(resource.schema_url(), Some(SCHEMA_URL)); + assert_eq!(resource.len(), 2); + let mut copy = entity.attributes(); + copy.clear(); + assert_eq!(entity.attributes().len(), 2); +} + +#[test] +fn refinement_requires_its_description_attribute() { + let entity = myappentity::HostWorkerEntity::new( + myappattr::HostNameAttr::new("worker-2"), + myappattr::HostRoleAttr::new("worker"), + [], + ); + assert_eq!(entity.attributes().len(), 2); + assert_eq!(entity.attributes()[1].key.as_str(), "myapp.host.role"); + assert_eq!(myappentity::HostEntity::default().resource().len(), 0); +} diff --git a/templates/code/rust/tests/error_aggregation_counter/expected-error.txt b/templates/code/rust/tests/error_aggregation_counter/expected-error.txt new file mode 100644 index 0000000..2190d30 --- /dev/null +++ b/templates/code/rust/tests/error_aggregation_counter/expected-error.txt @@ -0,0 +1 @@ +metric myapp.task.started sets annotations.aggregation, which the Rust template supports only on a histogram diff --git a/templates/code/rust/tests/error_aggregation_counter/registry/manifest.yaml b/templates/code/rust/tests/error_aggregation_counter/registry/manifest.yaml new file mode 100644 index 0000000..8fdff1b --- /dev/null +++ b/templates/code/rust/tests/error_aggregation_counter/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_aggregation_counter +schema_url: https://example.com/schemas/error_aggregation_counter/1.0.0 diff --git a/templates/code/rust/tests/error_aggregation_counter/registry/myapp.yaml b/templates/code/rust/tests/error_aggregation_counter/registry/myapp.yaml new file mode 100644 index 0000000..900b1ec --- /dev/null +++ b/templates/code/rust/tests/error_aggregation_counter/registry/myapp.yaml @@ -0,0 +1,15 @@ +file_format: definition/2 +metrics: + - name: myapp.task.started + requirement_level: recommended + instrument: counter + unit: "{task}" + stability: stable + brief: Number of tasks started. + annotations: + code_generation: + metric_value_type: int + aggregation: + method: explicithistogram + parameters: + boundaries: [1, 10] diff --git a/templates/code/rust/tests/error_aggregation_method/expected-error.txt b/templates/code/rust/tests/error_aggregation_method/expected-error.txt new file mode 100644 index 0000000..3f55af1 --- /dev/null +++ b/templates/code/rust/tests/error_aggregation_method/expected-error.txt @@ -0,0 +1 @@ +metric myapp.task.duration sets annotations.aggregation.method to histogram, but the Rust template supports only explicithistogram diff --git a/templates/code/rust/tests/error_aggregation_method/registry/manifest.yaml b/templates/code/rust/tests/error_aggregation_method/registry/manifest.yaml new file mode 100644 index 0000000..462f08c --- /dev/null +++ b/templates/code/rust/tests/error_aggregation_method/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_aggregation_method +schema_url: https://example.com/schemas/error_aggregation_method/1.0.0 diff --git a/templates/code/rust/tests/error_aggregation_method/registry/myapp.yaml b/templates/code/rust/tests/error_aggregation_method/registry/myapp.yaml new file mode 100644 index 0000000..15edd9e --- /dev/null +++ b/templates/code/rust/tests/error_aggregation_method/registry/myapp.yaml @@ -0,0 +1,13 @@ +file_format: definition/2 +metrics: + - name: myapp.task.duration + requirement_level: recommended + instrument: histogram + unit: s + stability: stable + brief: Time a task took from start to finish. + annotations: + code_generation: + metric_value_type: double + aggregation: + method: histogram diff --git a/templates/code/rust/tests/error_aggregation_unsorted/expected-error.txt b/templates/code/rust/tests/error_aggregation_unsorted/expected-error.txt new file mode 100644 index 0000000..31ba0b3 --- /dev/null +++ b/templates/code/rust/tests/error_aggregation_unsorted/expected-error.txt @@ -0,0 +1 @@ +metric myapp.task.duration must list annotations.aggregation.parameters.boundaries in strictly increasing order diff --git a/templates/code/rust/tests/error_aggregation_unsorted/registry/manifest.yaml b/templates/code/rust/tests/error_aggregation_unsorted/registry/manifest.yaml new file mode 100644 index 0000000..3c055b4 --- /dev/null +++ b/templates/code/rust/tests/error_aggregation_unsorted/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_aggregation_unsorted +schema_url: https://example.com/schemas/error_aggregation_unsorted/1.0.0 diff --git a/templates/code/rust/tests/error_aggregation_unsorted/registry/myapp.yaml b/templates/code/rust/tests/error_aggregation_unsorted/registry/myapp.yaml new file mode 100644 index 0000000..243ba97 --- /dev/null +++ b/templates/code/rust/tests/error_aggregation_unsorted/registry/myapp.yaml @@ -0,0 +1,15 @@ +file_format: definition/2 +metrics: + - name: myapp.task.duration + requirement_level: recommended + instrument: histogram + unit: s + stability: stable + brief: Time a task took from start to finish. + annotations: + code_generation: + metric_value_type: double + aggregation: + method: explicithistogram + parameters: + boundaries: [0.1, 1, 1, 0.5] diff --git a/templates/code/rust/tests/error_attribute_collision/expected-error.txt b/templates/code/rust/tests/error_attribute_collision/expected-error.txt new file mode 100644 index 0000000..35ed613 --- /dev/null +++ b/templates/code/rust/tests/error_attribute_collision/expected-error.txt @@ -0,0 +1 @@ +attributes that render to the same Rust identifier diff --git a/templates/code/rust/tests/error_attribute_collision/registry/manifest.yaml b/templates/code/rust/tests/error_attribute_collision/registry/manifest.yaml new file mode 100644 index 0000000..5bddc29 --- /dev/null +++ b/templates/code/rust/tests/error_attribute_collision/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: demo +schema_url: https://example.com/schemas/1.0.0 diff --git a/templates/code/rust/tests/error_attribute_collision/registry/model.yaml b/templates/code/rust/tests/error_attribute_collision/registry/model.yaml new file mode 100644 index 0000000..8a0c9dd --- /dev/null +++ b/templates/code/rust/tests/error_attribute_collision/registry/model.yaml @@ -0,0 +1,10 @@ +file_format: definition/2 +attributes: + - key: demo.foo_bar + stability: stable + brief: Synthetic attribute. + type: string + - key: demo.foo.bar + stability: stable + brief: Synthetic attribute. + type: string diff --git a/templates/code/rust/tests/error_empty_name/expected-error.txt b/templates/code/rust/tests/error_empty_name/expected-error.txt new file mode 100644 index 0000000..e043b8a --- /dev/null +++ b/templates/code/rust/tests/error_empty_name/expected-error.txt @@ -0,0 +1 @@ +has no name after its namespace diff --git a/templates/code/rust/tests/error_empty_name/registry/manifest.yaml b/templates/code/rust/tests/error_empty_name/registry/manifest.yaml new file mode 100644 index 0000000..5bddc29 --- /dev/null +++ b/templates/code/rust/tests/error_empty_name/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: demo +schema_url: https://example.com/schemas/1.0.0 diff --git a/templates/code/rust/tests/error_empty_name/registry/model.yaml b/templates/code/rust/tests/error_empty_name/registry/model.yaml new file mode 100644 index 0000000..75c93c0 --- /dev/null +++ b/templates/code/rust/tests/error_empty_name/registry/model.yaml @@ -0,0 +1,6 @@ +file_format: definition/2 +attributes: + - key: demo + stability: stable + brief: Synthetic attribute. + type: string diff --git a/templates/code/rust/tests/error_enum_collision/expected-error.txt b/templates/code/rust/tests/error_enum_collision/expected-error.txt new file mode 100644 index 0000000..1263050 --- /dev/null +++ b/templates/code/rust/tests/error_enum_collision/expected-error.txt @@ -0,0 +1 @@ +enum members that render to the same Rust identifier diff --git a/templates/code/rust/tests/error_enum_collision/registry/manifest.yaml b/templates/code/rust/tests/error_enum_collision/registry/manifest.yaml new file mode 100644 index 0000000..5bddc29 --- /dev/null +++ b/templates/code/rust/tests/error_enum_collision/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: demo +schema_url: https://example.com/schemas/1.0.0 diff --git a/templates/code/rust/tests/error_enum_collision/registry/model.yaml b/templates/code/rust/tests/error_enum_collision/registry/model.yaml new file mode 100644 index 0000000..a133af8 --- /dev/null +++ b/templates/code/rust/tests/error_enum_collision/registry/model.yaml @@ -0,0 +1,13 @@ +file_format: definition/2 +attributes: + - key: demo.state + stability: stable + brief: Synthetic attribute. + type: + members: + - id: foo_bar + value: a + brief: First. + - id: foo.bar + value: b + brief: Next. diff --git a/templates/code/rust/tests/error_enum_keyword/expected-error.txt b/templates/code/rust/tests/error_enum_keyword/expected-error.txt new file mode 100644 index 0000000..57952d5 --- /dev/null +++ b/templates/code/rust/tests/error_enum_keyword/expected-error.txt @@ -0,0 +1 @@ +becomes a Rust keyword diff --git a/templates/code/rust/tests/error_enum_keyword/registry/manifest.yaml b/templates/code/rust/tests/error_enum_keyword/registry/manifest.yaml new file mode 100644 index 0000000..5bddc29 --- /dev/null +++ b/templates/code/rust/tests/error_enum_keyword/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: demo +schema_url: https://example.com/schemas/1.0.0 diff --git a/templates/code/rust/tests/error_enum_keyword/registry/model.yaml b/templates/code/rust/tests/error_enum_keyword/registry/model.yaml new file mode 100644 index 0000000..10d14e2 --- /dev/null +++ b/templates/code/rust/tests/error_enum_keyword/registry/model.yaml @@ -0,0 +1,10 @@ +file_format: definition/2 +attributes: + - key: demo.state + stability: stable + brief: Synthetic attribute. + type: + members: + - id: self + value: self + brief: Self. diff --git a/templates/code/rust/tests/error_enum_without_members/expected-error.txt b/templates/code/rust/tests/error_enum_without_members/expected-error.txt new file mode 100644 index 0000000..e7b5177 --- /dev/null +++ b/templates/code/rust/tests/error_enum_without_members/expected-error.txt @@ -0,0 +1 @@ +has no enum members left after filtering diff --git a/templates/code/rust/tests/error_enum_without_members/params.yaml b/templates/code/rust/tests/error_enum_without_members/params.yaml new file mode 100644 index 0000000..7606ce0 --- /dev/null +++ b/templates/code/rust/tests/error_enum_without_members/params.yaml @@ -0,0 +1,2 @@ +params: + stable_only: true diff --git a/templates/code/rust/tests/error_enum_without_members/registry/manifest.yaml b/templates/code/rust/tests/error_enum_without_members/registry/manifest.yaml new file mode 100644 index 0000000..5bddc29 --- /dev/null +++ b/templates/code/rust/tests/error_enum_without_members/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: demo +schema_url: https://example.com/schemas/1.0.0 diff --git a/templates/code/rust/tests/error_enum_without_members/registry/model.yaml b/templates/code/rust/tests/error_enum_without_members/registry/model.yaml new file mode 100644 index 0000000..33d5241 --- /dev/null +++ b/templates/code/rust/tests/error_enum_without_members/registry/model.yaml @@ -0,0 +1,11 @@ +file_format: definition/2 +attributes: + - key: myapp.task.state + type: + members: + - id: queued + value: queued + stability: development + brief: The task is waiting to run. + stability: stable + brief: Current state of the task. diff --git a/templates/code/rust/tests/error_event_collision/expected-error.txt b/templates/code/rust/tests/error_event_collision/expected-error.txt new file mode 100644 index 0000000..5fd8cbf --- /dev/null +++ b/templates/code/rust/tests/error_event_collision/expected-error.txt @@ -0,0 +1 @@ +package myappevent has events that render to the same Rust identifier: myapp.task.finished and myapp.task_finished diff --git a/templates/code/rust/tests/error_event_collision/registry/manifest.yaml b/templates/code/rust/tests/error_event_collision/registry/manifest.yaml new file mode 100644 index 0000000..ff89b1c --- /dev/null +++ b/templates/code/rust/tests/error_event_collision/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_event_collision +schema_url: https://example.com/schemas/error_event_collision/1.0.0 diff --git a/templates/code/rust/tests/error_event_collision/registry/myapp.yaml b/templates/code/rust/tests/error_event_collision/registry/myapp.yaml new file mode 100644 index 0000000..19927c1 --- /dev/null +++ b/templates/code/rust/tests/error_event_collision/registry/myapp.yaml @@ -0,0 +1,10 @@ +file_format: definition/2 +events: + - name: myapp.task.finished + requirement_level: recommended + stability: stable + brief: A task finished. + - name: myapp.task_finished + requirement_level: recommended + stability: stable + brief: A task finished, under another name. diff --git a/templates/code/rust/tests/error_event_required_collision/expected-error.txt b/templates/code/rust/tests/error_event_required_collision/expected-error.txt new file mode 100644 index 0000000..6fdf75b --- /dev/null +++ b/templates/code/rust/tests/error_event_required_collision/expected-error.txt @@ -0,0 +1 @@ +event myapp.task.finished has required attributes that render to the same Rust parameter: myapp.task.id and myapp.task_id diff --git a/templates/code/rust/tests/error_event_required_collision/registry/manifest.yaml b/templates/code/rust/tests/error_event_required_collision/registry/manifest.yaml new file mode 100644 index 0000000..1ff0d75 --- /dev/null +++ b/templates/code/rust/tests/error_event_required_collision/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_event_required_collision +schema_url: https://example.com/schemas/error_event_required_collision/1.0.0 diff --git a/templates/code/rust/tests/error_event_required_collision/registry/myapp.yaml b/templates/code/rust/tests/error_event_required_collision/registry/myapp.yaml new file mode 100644 index 0000000..bac7b4a --- /dev/null +++ b/templates/code/rust/tests/error_event_required_collision/registry/myapp.yaml @@ -0,0 +1,22 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: stable + brief: Unique identifier of the task. + examples: ["task_0001"] + - key: myapp.task_id + type: string + stability: stable + brief: Unique identifier of the task, under another name. + examples: ["task_0001"] +events: + - name: myapp.task.finished + requirement_level: recommended + stability: stable + brief: A task finished. + attributes: + - ref: myapp.task.id + requirement_level: required + - ref: myapp.task_id + requirement_level: required diff --git a/templates/code/rust/tests/error_histogram_boundaries_by_unit/expected-error.txt b/templates/code/rust/tests/error_histogram_boundaries_by_unit/expected-error.txt new file mode 100644 index 0000000..1f22d64 --- /dev/null +++ b/templates/code/rust/tests/error_histogram_boundaries_by_unit/expected-error.txt @@ -0,0 +1 @@ +metric myapp.task.queue_wait resolves histogram_boundaries_by_unit for unit min to boundaries that are not in strictly increasing order diff --git a/templates/code/rust/tests/error_histogram_boundaries_by_unit/params.yaml b/templates/code/rust/tests/error_histogram_boundaries_by_unit/params.yaml new file mode 100644 index 0000000..91e5edb --- /dev/null +++ b/templates/code/rust/tests/error_histogram_boundaries_by_unit/params.yaml @@ -0,0 +1,3 @@ +params: + histogram_boundaries_by_unit: + min: [10, 5, 1] diff --git a/templates/code/rust/tests/error_histogram_boundaries_by_unit/registry/manifest.yaml b/templates/code/rust/tests/error_histogram_boundaries_by_unit/registry/manifest.yaml new file mode 100644 index 0000000..50b6aed --- /dev/null +++ b/templates/code/rust/tests/error_histogram_boundaries_by_unit/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_histogram_boundaries_by_unit +schema_url: https://example.com/schemas/error_histogram_boundaries_by_unit/1.0.0 diff --git a/templates/code/rust/tests/error_histogram_boundaries_by_unit/registry/myapp.yaml b/templates/code/rust/tests/error_histogram_boundaries_by_unit/registry/myapp.yaml new file mode 100644 index 0000000..7dea0ce --- /dev/null +++ b/templates/code/rust/tests/error_histogram_boundaries_by_unit/registry/myapp.yaml @@ -0,0 +1,10 @@ +file_format: definition/2 +metrics: + - name: myapp.task.queue_wait + instrument: histogram + unit: min + stability: stable + brief: Time a task waited in the queue, in minutes. + annotations: + code_generation: + metric_value_type: double diff --git a/templates/code/rust/tests/error_integer_enum_overflow/expected-error.txt b/templates/code/rust/tests/error_integer_enum_overflow/expected-error.txt new file mode 100644 index 0000000..7dddbb9 --- /dev/null +++ b/templates/code/rust/tests/error_integer_enum_overflow/expected-error.txt @@ -0,0 +1 @@ +cannot be represented by Rust i64 diff --git a/templates/code/rust/tests/error_integer_enum_overflow/registry/manifest.yaml b/templates/code/rust/tests/error_integer_enum_overflow/registry/manifest.yaml new file mode 100644 index 0000000..5bddc29 --- /dev/null +++ b/templates/code/rust/tests/error_integer_enum_overflow/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: demo +schema_url: https://example.com/schemas/1.0.0 diff --git a/templates/code/rust/tests/error_integer_enum_overflow/registry/model.yaml b/templates/code/rust/tests/error_integer_enum_overflow/registry/model.yaml new file mode 100644 index 0000000..8dfd87c --- /dev/null +++ b/templates/code/rust/tests/error_integer_enum_overflow/registry/model.yaml @@ -0,0 +1,11 @@ +file_format: definition/2 +attributes: + - key: demo.mode + stability: stable + brief: Synthetic mode. + type: + members: + - id: enormous + value: 9223372036854775808 + stability: stable + brief: Synthetic enum value. diff --git a/templates/code/rust/tests/error_invalid_name/expected-error.txt b/templates/code/rust/tests/error_invalid_name/expected-error.txt new file mode 100644 index 0000000..c343cbd --- /dev/null +++ b/templates/code/rust/tests/error_invalid_name/expected-error.txt @@ -0,0 +1 @@ +not a supported Rust attribute name diff --git a/templates/code/rust/tests/error_invalid_name/registry/manifest.yaml b/templates/code/rust/tests/error_invalid_name/registry/manifest.yaml new file mode 100644 index 0000000..5bddc29 --- /dev/null +++ b/templates/code/rust/tests/error_invalid_name/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: demo +schema_url: https://example.com/schemas/1.0.0 diff --git a/templates/code/rust/tests/error_invalid_name/registry/model.yaml b/templates/code/rust/tests/error_invalid_name/registry/model.yaml new file mode 100644 index 0000000..2c01271 --- /dev/null +++ b/templates/code/rust/tests/error_invalid_name/registry/model.yaml @@ -0,0 +1,6 @@ +file_format: definition/2 +attributes: + - key: demo.bad-name + stability: stable + brief: Synthetic attribute. + type: string diff --git a/templates/code/rust/tests/error_metric_collision/expected-error.txt b/templates/code/rust/tests/error_metric_collision/expected-error.txt new file mode 100644 index 0000000..de37c96 --- /dev/null +++ b/templates/code/rust/tests/error_metric_collision/expected-error.txt @@ -0,0 +1 @@ +package myappmetric has metrics that render to the same Rust identifier: myapp.task.started and myapp.task_started diff --git a/templates/code/rust/tests/error_metric_collision/registry/manifest.yaml b/templates/code/rust/tests/error_metric_collision/registry/manifest.yaml new file mode 100644 index 0000000..9fb94e3 --- /dev/null +++ b/templates/code/rust/tests/error_metric_collision/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_metric_collision +schema_url: https://example.com/schemas/error_metric_collision/1.0.0 diff --git a/templates/code/rust/tests/error_metric_collision/registry/model.yaml b/templates/code/rust/tests/error_metric_collision/registry/model.yaml new file mode 100644 index 0000000..c45a39c --- /dev/null +++ b/templates/code/rust/tests/error_metric_collision/registry/model.yaml @@ -0,0 +1,18 @@ +file_format: definition/2 +metrics: + - name: myapp.task.started + instrument: counter + unit: "{task}" + stability: stable + brief: Number of tasks started. + annotations: + code_generation: + metric_value_type: int + - name: myapp.task_started + instrument: counter + unit: "{task}" + stability: stable + brief: Number of tasks started, under another name. + annotations: + code_generation: + metric_value_type: int diff --git a/templates/code/rust/tests/error_metric_value_type/expected-error.txt b/templates/code/rust/tests/error_metric_value_type/expected-error.txt new file mode 100644 index 0000000..6043237 --- /dev/null +++ b/templates/code/rust/tests/error_metric_value_type/expected-error.txt @@ -0,0 +1 @@ +must set code_generation.metric_value_type to int or double diff --git a/templates/code/rust/tests/error_metric_value_type/registry/manifest.yaml b/templates/code/rust/tests/error_metric_value_type/registry/manifest.yaml new file mode 100644 index 0000000..d10001b --- /dev/null +++ b/templates/code/rust/tests/error_metric_value_type/registry/manifest.yaml @@ -0,0 +1,3 @@ +name: synthetic +semconv_version: 1.0.0 +schema_base_url: https://example.com/schemas/ diff --git a/templates/code/rust/tests/error_metric_value_type/registry/model.yaml b/templates/code/rust/tests/error_metric_value_type/registry/model.yaml new file mode 100644 index 0000000..91b80d7 --- /dev/null +++ b/templates/code/rust/tests/error_metric_value_type/registry/model.yaml @@ -0,0 +1,11 @@ +file_format: definition/2 +metrics: + - name: myapp.task.started + brief: A task count. + stability: stable + requirement_level: recommended + instrument: counter + unit: "{task}" + annotations: + code_generation: + metric_value_type: boolean diff --git a/templates/code/rust/tests/error_missing_metric_value_type/expected-error.txt b/templates/code/rust/tests/error_missing_metric_value_type/expected-error.txt new file mode 100644 index 0000000..6043237 --- /dev/null +++ b/templates/code/rust/tests/error_missing_metric_value_type/expected-error.txt @@ -0,0 +1 @@ +must set code_generation.metric_value_type to int or double diff --git a/templates/code/rust/tests/error_missing_metric_value_type/registry/manifest.yaml b/templates/code/rust/tests/error_missing_metric_value_type/registry/manifest.yaml new file mode 100644 index 0000000..d10001b --- /dev/null +++ b/templates/code/rust/tests/error_missing_metric_value_type/registry/manifest.yaml @@ -0,0 +1,3 @@ +name: synthetic +semconv_version: 1.0.0 +schema_base_url: https://example.com/schemas/ diff --git a/templates/code/rust/tests/error_missing_metric_value_type/registry/model.yaml b/templates/code/rust/tests/error_missing_metric_value_type/registry/model.yaml new file mode 100644 index 0000000..33e25d7 --- /dev/null +++ b/templates/code/rust/tests/error_missing_metric_value_type/registry/model.yaml @@ -0,0 +1,8 @@ +file_format: definition/2 +metrics: + - name: myapp.task.started + brief: A task count. + stability: stable + requirement_level: recommended + instrument: counter + unit: "{task}" diff --git a/templates/code/rust/tests/error_missing_schema/expected-error.txt b/templates/code/rust/tests/error_missing_schema/expected-error.txt new file mode 100644 index 0000000..a365ed6 --- /dev/null +++ b/templates/code/rust/tests/error_missing_schema/expected-error.txt @@ -0,0 +1 @@ +Either 'schema_url' or both 'schema_base_url' and 'semconv_version' must be provided diff --git a/templates/code/rust/tests/error_missing_schema/registry/manifest.yaml b/templates/code/rust/tests/error_missing_schema/registry/manifest.yaml new file mode 100644 index 0000000..bc69615 --- /dev/null +++ b/templates/code/rust/tests/error_missing_schema/registry/manifest.yaml @@ -0,0 +1 @@ +name: demo diff --git a/templates/code/rust/tests/error_missing_schema/registry/model.yaml b/templates/code/rust/tests/error_missing_schema/registry/model.yaml new file mode 100644 index 0000000..b281eab --- /dev/null +++ b/templates/code/rust/tests/error_missing_schema/registry/model.yaml @@ -0,0 +1,2 @@ +file_format: definition/2 +attributes: [] diff --git a/templates/code/rust/tests/error_mixed_enum/expected-error.txt b/templates/code/rust/tests/error_mixed_enum/expected-error.txt new file mode 100644 index 0000000..2201a96 --- /dev/null +++ b/templates/code/rust/tests/error_mixed_enum/expected-error.txt @@ -0,0 +1 @@ +has enum members of more than one value type diff --git a/templates/code/rust/tests/error_mixed_enum/registry/manifest.yaml b/templates/code/rust/tests/error_mixed_enum/registry/manifest.yaml new file mode 100644 index 0000000..5bddc29 --- /dev/null +++ b/templates/code/rust/tests/error_mixed_enum/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: demo +schema_url: https://example.com/schemas/1.0.0 diff --git a/templates/code/rust/tests/error_mixed_enum/registry/model.yaml b/templates/code/rust/tests/error_mixed_enum/registry/model.yaml new file mode 100644 index 0000000..e64d5e7 --- /dev/null +++ b/templates/code/rust/tests/error_mixed_enum/registry/model.yaml @@ -0,0 +1,15 @@ +file_format: definition/2 +attributes: + - key: demo.mode + stability: stable + brief: Synthetic mode. + type: + members: + - id: text + value: text + stability: stable + brief: Synthetic enum value. + - id: number + value: 42 + stability: stable + brief: Synthetic enum value. diff --git a/templates/code/rust/tests/error_namespace_uppercase/expected-error.txt b/templates/code/rust/tests/error_namespace_uppercase/expected-error.txt new file mode 100644 index 0000000..f061fcf --- /dev/null +++ b/templates/code/rust/tests/error_namespace_uppercase/expected-error.txt @@ -0,0 +1 @@ +namespace CAPS is not a supported Rust module name diff --git a/templates/code/rust/tests/error_namespace_uppercase/registry/manifest.yaml b/templates/code/rust/tests/error_namespace_uppercase/registry/manifest.yaml new file mode 100644 index 0000000..5bddc29 --- /dev/null +++ b/templates/code/rust/tests/error_namespace_uppercase/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: demo +schema_url: https://example.com/schemas/1.0.0 diff --git a/templates/code/rust/tests/error_namespace_uppercase/registry/model.yaml b/templates/code/rust/tests/error_namespace_uppercase/registry/model.yaml new file mode 100644 index 0000000..5fed346 --- /dev/null +++ b/templates/code/rust/tests/error_namespace_uppercase/registry/model.yaml @@ -0,0 +1,6 @@ +file_format: definition/2 +attributes: + - key: CAPS.id + type: string + stability: stable + brief: Synthetic identifier. diff --git a/templates/code/rust/tests/error_observable_collision/expected-error.txt b/templates/code/rust/tests/error_observable_collision/expected-error.txt new file mode 100644 index 0000000..3470b15 --- /dev/null +++ b/templates/code/rust/tests/error_observable_collision/expected-error.txt @@ -0,0 +1 @@ +package myappmetric has metrics that render to the same Rust identifier: myapp.task.started and myapp.task.started.observable diff --git a/templates/code/rust/tests/error_observable_collision/registry/manifest.yaml b/templates/code/rust/tests/error_observable_collision/registry/manifest.yaml new file mode 100644 index 0000000..fadb55b --- /dev/null +++ b/templates/code/rust/tests/error_observable_collision/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_observable_collision +schema_url: https://example.com/schemas/error_observable_collision/1.0.0 diff --git a/templates/code/rust/tests/error_observable_collision/registry/model.yaml b/templates/code/rust/tests/error_observable_collision/registry/model.yaml new file mode 100644 index 0000000..e5fbb0c --- /dev/null +++ b/templates/code/rust/tests/error_observable_collision/registry/model.yaml @@ -0,0 +1,18 @@ +file_format: definition/2 +metrics: + - name: myapp.task.started + instrument: counter + unit: "{task}" + stability: stable + brief: Number of tasks started. + annotations: + code_generation: + metric_value_type: int + - name: myapp.task.started.observable + instrument: counter + unit: "{task}" + stability: stable + brief: Number of tasks started, observed. + annotations: + code_generation: + metric_value_type: int diff --git a/templates/code/rust/tests/error_option_collision/expected-error.txt b/templates/code/rust/tests/error_option_collision/expected-error.txt new file mode 100644 index 0000000..b69d494 --- /dev/null +++ b/templates/code/rust/tests/error_option_collision/expected-error.txt @@ -0,0 +1 @@ +metric myapp.task.started has optional attributes that render to the same Rust identifier: myapp.task.id and queue.task.id diff --git a/templates/code/rust/tests/error_option_collision/registry/manifest.yaml b/templates/code/rust/tests/error_option_collision/registry/manifest.yaml new file mode 100644 index 0000000..8d9c13c --- /dev/null +++ b/templates/code/rust/tests/error_option_collision/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_option_collision +schema_url: https://example.com/schemas/error_option_collision/1.0.0 diff --git a/templates/code/rust/tests/error_option_collision/registry/myapp.yaml b/templates/code/rust/tests/error_option_collision/registry/myapp.yaml new file mode 100644 index 0000000..4bce764 --- /dev/null +++ b/templates/code/rust/tests/error_option_collision/registry/myapp.yaml @@ -0,0 +1,27 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: stable + brief: Unique identifier of the task. + examples: ["task_0001"] + - key: queue.task.id + type: string + stability: stable + brief: Identifier the queue gave the task. + examples: ["task_0001"] +metrics: + - name: myapp.task.started + requirement_level: recommended + instrument: counter + unit: "{task}" + stability: stable + brief: Number of tasks started. + annotations: + code_generation: + metric_value_type: int + attributes: + - ref: myapp.task.id + requirement_level: recommended + - ref: queue.task.id + requirement_level: recommended diff --git a/templates/code/rust/tests/error_refinement_value_type/expected-error.txt b/templates/code/rust/tests/error_refinement_value_type/expected-error.txt new file mode 100644 index 0000000..b086b96 --- /dev/null +++ b/templates/code/rust/tests/error_refinement_value_type/expected-error.txt @@ -0,0 +1 @@ +metric refinement myapp.task.retry.duration sets a different code_generation.metric_value_type than myapp.task.duration diff --git a/templates/code/rust/tests/error_refinement_value_type/registry/manifest.yaml b/templates/code/rust/tests/error_refinement_value_type/registry/manifest.yaml new file mode 100644 index 0000000..4c4b425 --- /dev/null +++ b/templates/code/rust/tests/error_refinement_value_type/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_refinement_value_type +schema_url: https://example.com/schemas/error_refinement_value_type/1.0.0 diff --git a/templates/code/rust/tests/error_refinement_value_type/registry/model.yaml b/templates/code/rust/tests/error_refinement_value_type/registry/model.yaml new file mode 100644 index 0000000..cc22be3 --- /dev/null +++ b/templates/code/rust/tests/error_refinement_value_type/registry/model.yaml @@ -0,0 +1,18 @@ +file_format: definition/2 +metrics: + - name: myapp.task.duration + instrument: histogram + unit: s + stability: stable + brief: Time a task took from start to finish. + annotations: + code_generation: + metric_value_type: double +metric_refinements: + - id: myapp.task.retry.duration + ref: myapp.task.duration + stability: stable + brief: Time a retried task took from start to finish. + annotations: + code_generation: + metric_value_type: int diff --git a/templates/code/rust/tests/error_span_collision/expected-error.txt b/templates/code/rust/tests/error_span_collision/expected-error.txt new file mode 100644 index 0000000..15189b1 --- /dev/null +++ b/templates/code/rust/tests/error_span_collision/expected-error.txt @@ -0,0 +1 @@ +package myappspan has spans that render to the same Rust identifier: myapp.task.run and myapp.task_run diff --git a/templates/code/rust/tests/error_span_collision/registry/manifest.yaml b/templates/code/rust/tests/error_span_collision/registry/manifest.yaml new file mode 100644 index 0000000..a6edceb --- /dev/null +++ b/templates/code/rust/tests/error_span_collision/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_span_collision +schema_url: https://example.com/schemas/error_span_collision/1.0.0 diff --git a/templates/code/rust/tests/error_span_collision/registry/myapp.yaml b/templates/code/rust/tests/error_span_collision/registry/myapp.yaml new file mode 100644 index 0000000..e1d1aa4 --- /dev/null +++ b/templates/code/rust/tests/error_span_collision/registry/myapp.yaml @@ -0,0 +1,16 @@ +file_format: definition/2 +spans: + - type: myapp.task.run + kind: internal + name: + note: "" + requirement_level: recommended + stability: stable + brief: One run of a task. + - type: myapp.task_run + kind: internal + name: + note: "" + requirement_level: recommended + stability: stable + brief: One run of a task, under another name. diff --git a/templates/code/rust/tests/error_span_required_collision/expected-error.txt b/templates/code/rust/tests/error_span_required_collision/expected-error.txt new file mode 100644 index 0000000..ce98f61 --- /dev/null +++ b/templates/code/rust/tests/error_span_required_collision/expected-error.txt @@ -0,0 +1 @@ +span myapp.task.run has required attributes that render to the same Rust parameter: myapp.task.id and myapp.task_id diff --git a/templates/code/rust/tests/error_span_required_collision/registry/manifest.yaml b/templates/code/rust/tests/error_span_required_collision/registry/manifest.yaml new file mode 100644 index 0000000..6c9fa64 --- /dev/null +++ b/templates/code/rust/tests/error_span_required_collision/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_span_required_collision +schema_url: https://example.com/schemas/error_span_required_collision/1.0.0 diff --git a/templates/code/rust/tests/error_span_required_collision/registry/myapp.yaml b/templates/code/rust/tests/error_span_required_collision/registry/myapp.yaml new file mode 100644 index 0000000..292e89b --- /dev/null +++ b/templates/code/rust/tests/error_span_required_collision/registry/myapp.yaml @@ -0,0 +1,25 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: stable + brief: Unique identifier of the task. + examples: ["task_0001"] + - key: myapp.task_id + type: string + stability: stable + brief: Unique identifier of the task, under another name. + examples: ["task_0001"] +spans: + - type: myapp.task.run + kind: internal + name: + note: "" + requirement_level: recommended + stability: stable + brief: One run of a task. + attributes: + - ref: myapp.task.id + requirement_level: required + - ref: myapp.task_id + requirement_level: required diff --git a/templates/code/rust/tests/error_stable_only_event_required_attribute/expected-error.txt b/templates/code/rust/tests/error_stable_only_event_required_attribute/expected-error.txt new file mode 100644 index 0000000..f988160 --- /dev/null +++ b/templates/code/rust/tests/error_stable_only_event_required_attribute/expected-error.txt @@ -0,0 +1 @@ +event myapp.task.finished requires myapp.task.id, which exclude_deprecated or stable_only leaves out diff --git a/templates/code/rust/tests/error_stable_only_event_required_attribute/params.yaml b/templates/code/rust/tests/error_stable_only_event_required_attribute/params.yaml new file mode 100644 index 0000000..7606ce0 --- /dev/null +++ b/templates/code/rust/tests/error_stable_only_event_required_attribute/params.yaml @@ -0,0 +1,2 @@ +params: + stable_only: true diff --git a/templates/code/rust/tests/error_stable_only_event_required_attribute/registry/manifest.yaml b/templates/code/rust/tests/error_stable_only_event_required_attribute/registry/manifest.yaml new file mode 100644 index 0000000..306d160 --- /dev/null +++ b/templates/code/rust/tests/error_stable_only_event_required_attribute/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_stable_only_event_required_attribute +schema_url: https://example.com/schemas/error_stable_only_event_required_attribute/1.0.0 diff --git a/templates/code/rust/tests/error_stable_only_event_required_attribute/registry/myapp.yaml b/templates/code/rust/tests/error_stable_only_event_required_attribute/registry/myapp.yaml new file mode 100644 index 0000000..31622d2 --- /dev/null +++ b/templates/code/rust/tests/error_stable_only_event_required_attribute/registry/myapp.yaml @@ -0,0 +1,15 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: development + brief: Unique identifier of the task. + examples: ["task_0001"] +events: + - name: myapp.task.finished + requirement_level: recommended + stability: stable + brief: A task finished. + attributes: + - ref: myapp.task.id + requirement_level: required diff --git a/templates/code/rust/tests/error_stable_only_required_attribute/expected-error.txt b/templates/code/rust/tests/error_stable_only_required_attribute/expected-error.txt new file mode 100644 index 0000000..b91b482 --- /dev/null +++ b/templates/code/rust/tests/error_stable_only_required_attribute/expected-error.txt @@ -0,0 +1 @@ +metric myapp.task.started requires myapp.task.id, which exclude_deprecated or stable_only leaves out diff --git a/templates/code/rust/tests/error_stable_only_required_attribute/params.yaml b/templates/code/rust/tests/error_stable_only_required_attribute/params.yaml new file mode 100644 index 0000000..7606ce0 --- /dev/null +++ b/templates/code/rust/tests/error_stable_only_required_attribute/params.yaml @@ -0,0 +1,2 @@ +params: + stable_only: true diff --git a/templates/code/rust/tests/error_stable_only_required_attribute/registry/manifest.yaml b/templates/code/rust/tests/error_stable_only_required_attribute/registry/manifest.yaml new file mode 100644 index 0000000..7d4a2d9 --- /dev/null +++ b/templates/code/rust/tests/error_stable_only_required_attribute/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_stable_only_required_attribute +schema_url: https://example.com/schemas/error_stable_only_required_attribute/1.0.0 diff --git a/templates/code/rust/tests/error_stable_only_required_attribute/registry/myapp.yaml b/templates/code/rust/tests/error_stable_only_required_attribute/registry/myapp.yaml new file mode 100644 index 0000000..8b9004e --- /dev/null +++ b/templates/code/rust/tests/error_stable_only_required_attribute/registry/myapp.yaml @@ -0,0 +1,20 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: development + brief: Unique identifier of the task. + examples: ["task_0001"] +metrics: + - name: myapp.task.started + requirement_level: recommended + instrument: counter + unit: "{task}" + stability: stable + brief: Number of tasks started. + annotations: + code_generation: + metric_value_type: int + attributes: + - ref: myapp.task.id + requirement_level: required diff --git a/templates/code/rust/tests/error_stable_only_span_required_attribute/expected-error.txt b/templates/code/rust/tests/error_stable_only_span_required_attribute/expected-error.txt new file mode 100644 index 0000000..055b71c --- /dev/null +++ b/templates/code/rust/tests/error_stable_only_span_required_attribute/expected-error.txt @@ -0,0 +1 @@ +span myapp.task.run requires myapp.task.id, which exclude_deprecated or stable_only leaves out diff --git a/templates/code/rust/tests/error_stable_only_span_required_attribute/params.yaml b/templates/code/rust/tests/error_stable_only_span_required_attribute/params.yaml new file mode 100644 index 0000000..7606ce0 --- /dev/null +++ b/templates/code/rust/tests/error_stable_only_span_required_attribute/params.yaml @@ -0,0 +1,2 @@ +params: + stable_only: true diff --git a/templates/code/rust/tests/error_stable_only_span_required_attribute/registry/manifest.yaml b/templates/code/rust/tests/error_stable_only_span_required_attribute/registry/manifest.yaml new file mode 100644 index 0000000..cc77b79 --- /dev/null +++ b/templates/code/rust/tests/error_stable_only_span_required_attribute/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: error_stable_only_span_required_attribute +schema_url: https://example.com/schemas/error_stable_only_span_required_attribute/1.0.0 diff --git a/templates/code/rust/tests/error_stable_only_span_required_attribute/registry/myapp.yaml b/templates/code/rust/tests/error_stable_only_span_required_attribute/registry/myapp.yaml new file mode 100644 index 0000000..0b0acfc --- /dev/null +++ b/templates/code/rust/tests/error_stable_only_span_required_attribute/registry/myapp.yaml @@ -0,0 +1,18 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: development + brief: Unique identifier of the task. + examples: ["task_0001"] +spans: + - type: myapp.task.run + kind: internal + name: + note: "" + requirement_level: recommended + stability: stable + brief: One run of a task. + attributes: + - ref: myapp.task.id + requirement_level: required diff --git a/templates/code/rust/tests/error_unversioned_schema/expected-error.txt b/templates/code/rust/tests/error_unversioned_schema/expected-error.txt new file mode 100644 index 0000000..c2bdbcc --- /dev/null +++ b/templates/code/rust/tests/error_unversioned_schema/expected-error.txt @@ -0,0 +1 @@ +the registry schema_url must name a schema version diff --git a/templates/code/rust/tests/error_unversioned_schema/registry/manifest.yaml b/templates/code/rust/tests/error_unversioned_schema/registry/manifest.yaml new file mode 100644 index 0000000..078407f --- /dev/null +++ b/templates/code/rust/tests/error_unversioned_schema/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: demo +schema_url: https://example.com/schemas/demo diff --git a/templates/code/rust/tests/error_unversioned_schema/registry/model.yaml b/templates/code/rust/tests/error_unversioned_schema/registry/model.yaml new file mode 100644 index 0000000..b281eab --- /dev/null +++ b/templates/code/rust/tests/error_unversioned_schema/registry/model.yaml @@ -0,0 +1,2 @@ +file_format: definition/2 +attributes: [] diff --git a/templates/code/rust/tests/events/expected/logger.rs b/templates/code/rust/tests/events/expected/logger.rs new file mode 100644 index 0000000..c7a2373 --- /dev/null +++ b/templates/code/rust/tests/events/expected/logger.rs @@ -0,0 +1,40 @@ +#[derive(Clone, Debug)] +pub struct Logger::Logger>(L); +impl Logger { + pub fn new>(provider: &P, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.logger_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &L { &self.0 } +} +impl Default for Logger { + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } +} +pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { + use opentelemetry::{Value, Array}; + use opentelemetry::logs::AnyValue; + match value { + Value::Bool(value) => value.into(), + Value::I64(value) => value.into(), + Value::F64(value) => value.into(), + Value::String(value) => value.into(), + Value::Array(array) => match array { + Array::Bool(values) => values.into_iter().collect::(), + Array::I64(values) => values.into_iter().collect::(), + Array::F64(values) => values.into_iter().collect::(), + Array::String(values) => values.into_iter().collect::(), + _ => AnyValue::String(array.to_string().into()), + }, + _ => AnyValue::String(value.to_string().into()), + } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/events/expected/mod.rs b/templates/code/rust/tests/events/expected/mod.rs new file mode 100644 index 0000000..98b132e --- /dev/null +++ b/templates/code/rust/tests/events/expected/mod.rs @@ -0,0 +1,235 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/events/1.0.0"; + +pub mod myappattr { + + /// Synthetic bool values. + #[derive(Debug, Clone, PartialEq)] + + pub struct BoolValuesAttr(Vec); + + + #[allow(deprecated)] + impl BoolValuesAttr { + pub const KEY: &'static str = "myapp.bool.values"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(self.0))) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: BoolValuesAttr) -> Self { + value.key_value() + } + } + + /// Synthetic double values. + #[derive(Debug, Clone, PartialEq)] + + pub struct DoubleValuesAttr(Vec); + + + #[allow(deprecated)] + impl DoubleValuesAttr { + pub const KEY: &'static str = "myapp.double.values"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(self.0))) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: DoubleValuesAttr) -> Self { + value.key_value() + } + } + + /// Synthetic int values. + #[derive(Debug, Clone, PartialEq)] + + pub struct IntValuesAttr(Vec); + + + #[allow(deprecated)] + impl IntValuesAttr { + pub const KEY: &'static str = "myapp.int.values"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: IntValuesAttr) -> Self { + value.key_value() + } + } + + /// Synthetic string values. + #[derive(Debug, Clone, PartialEq)] + + pub struct StringValuesAttr(Vec); + + + #[allow(deprecated)] + impl StringValuesAttr { + pub const KEY: &'static str = "myapp.string.values"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: StringValuesAttr) -> Self { + value.key_value() + } + } + + /// Number of the attempt, starting at 1. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskAttemptAttr(i64); + + + #[allow(deprecated)] + impl TaskAttemptAttr { + pub const KEY: &'static str = "myapp.task.attempt"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskAttemptAttr) -> Self { + value.key_value() + } + } + + /// Current state of the task. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum TaskStateAttr { + + /// The task finished. + Done, + + /// The task gave up. + Failed, + + } + + + #[allow(deprecated)] + impl TaskStateAttr { + pub const KEY: &'static str = "myapp.task.state"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Done => "done".into(), + + Self::Failed => "failed".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskStateAttr) -> Self { + value.key_value() + } + } + +} + +pub mod workerattr { + + /// Name of the worker host. + #[derive(Debug, Clone, PartialEq)] + + pub struct HostNameAttr(String); + + + #[allow(deprecated)] + impl HostNameAttr { + pub const KEY: &'static str = "worker.host.name"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: HostNameAttr) -> Self { + value.key_value() + } + } + +} + + + + +pub mod logger; + +pub mod myappevent; + +pub mod workerevent; diff --git a/templates/code/rust/tests/events/expected/myappevent.rs b/templates/code/rust/tests/events/expected/myappevent.rs new file mode 100644 index 0000000..a12b810 --- /dev/null +++ b/templates/code/rust/tests/events/expected/myappevent.rs @@ -0,0 +1,106 @@ +#![allow(deprecated)] + + + +#[derive(Clone, Debug)] +pub enum TaskFinishedOption { + Severity(::opentelemetry::logs::Severity), + Timestamp(::std::time::SystemTime), + + + BoolValues(super::myappattr::BoolValuesAttr), + + + DoubleValues(super::myappattr::DoubleValuesAttr), + + + IntValues(super::myappattr::IntValuesAttr), + + + StringValues(super::myappattr::StringValuesAttr), + +/// Recommended: When the task ran more than once. + TaskAttempt(super::myappattr::TaskAttemptAttr), + +/// Opt-in: the convention records it only when a user asks for it. + HostName(super::workerattr::HostNameAttr), + +} +/// A task reached a final state. +/// +/// Emitted once per task, after its last attempt. +pub fn r#emit_task_finished(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) { + use ::opentelemetry::logs::LogRecord; + use ::opentelemetry::trace::TraceContextExt; + let _context_guard = context.clone().attach(); + let mut severity = ::opentelemetry::logs::Severity::Info; + let mut timestamp = None; + let mut attributes: Vec<::opentelemetry::KeyValue> = vec![r#myapp_task_state.key_value()]; + for option in options { + match option { + TaskFinishedOption::Severity(value) => severity = value, + TaskFinishedOption::Timestamp(value) => timestamp = Some(value), + + TaskFinishedOption::BoolValues(value) => attributes.push(value.key_value()), + + TaskFinishedOption::DoubleValues(value) => attributes.push(value.key_value()), + + TaskFinishedOption::IntValues(value) => attributes.push(value.key_value()), + + TaskFinishedOption::StringValues(value) => attributes.push(value.key_value()), + + TaskFinishedOption::TaskAttempt(value) => attributes.push(value.key_value()), + + TaskFinishedOption::HostName(value) => attributes.push(value.key_value()), + + } + } + if !logger.inner().event_enabled(severity, "", Some("myapp.task.finished")) { return; } + let mut record = logger.inner().create_log_record(); + record.set_event_name("myapp.task.finished"); + record.set_severity_number(severity); + record.set_observed_timestamp(::std::time::SystemTime::now()); + if let Some(timestamp) = timestamp { record.set_timestamp(timestamp); } + let span = context.span(); + let span_context = span.span_context(); + if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } + for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + logger.inner().emit(record); +} + + +#[derive(Clone, Debug)] +pub enum TaskRetriedOption { + Severity(::opentelemetry::logs::Severity), + Timestamp(::std::time::SystemTime), + +} +/// A task is about to run again. +/// Opt-in: record only when the user requests it. +#[deprecated(note = "Read the attempt from `myapp.task.finished` instead.")] +pub fn r#emit_task_retried(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#myapp_task_attempt: super::myappattr::TaskAttemptAttr, options: impl IntoIterator) { + use ::opentelemetry::logs::LogRecord; + use ::opentelemetry::trace::TraceContextExt; + let _context_guard = context.clone().attach(); + let mut severity = ::opentelemetry::logs::Severity::Info; + let mut timestamp = None; + let attributes: Vec<::opentelemetry::KeyValue> = vec![r#myapp_task_attempt.key_value()]; + for option in options { + match option { + TaskRetriedOption::Severity(value) => severity = value, + TaskRetriedOption::Timestamp(value) => timestamp = Some(value), + + } + } + if !logger.inner().event_enabled(severity, "", Some("myapp.task.retried")) { return; } + let mut record = logger.inner().create_log_record(); + record.set_event_name("myapp.task.retried"); + record.set_severity_number(severity); + record.set_observed_timestamp(::std::time::SystemTime::now()); + if let Some(timestamp) = timestamp { record.set_timestamp(timestamp); } + let span = context.span(); + let span_context = span.span_context(); + if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } + for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + logger.inner().emit(record); +} diff --git a/templates/code/rust/tests/events/expected/workerevent.rs b/templates/code/rust/tests/events/expected/workerevent.rs new file mode 100644 index 0000000..5f0f2dc --- /dev/null +++ b/templates/code/rust/tests/events/expected/workerevent.rs @@ -0,0 +1,99 @@ +#![allow(deprecated)] + + + +#[derive(Clone, Debug)] +pub enum HostStartedOption { + Severity(::opentelemetry::logs::Severity), + Timestamp(::std::time::SystemTime), + +} +/// A worker host started taking tasks. +pub fn r#emit_host_started(context: &::opentelemetry::Context, logger: &super::logger::Logger, options: impl IntoIterator) { + use ::opentelemetry::logs::LogRecord; + use ::opentelemetry::trace::TraceContextExt; + let _context_guard = context.clone().attach(); + let mut severity = ::opentelemetry::logs::Severity::Info; + let mut timestamp = None; + let attributes: Vec<::opentelemetry::KeyValue> = vec![]; + for option in options { + match option { + HostStartedOption::Severity(value) => severity = value, + HostStartedOption::Timestamp(value) => timestamp = Some(value), + + } + } + if !logger.inner().event_enabled(severity, "", Some("worker.host.started")) { return; } + let mut record = logger.inner().create_log_record(); + record.set_event_name("worker.host.started"); + record.set_severity_number(severity); + record.set_observed_timestamp(::std::time::SystemTime::now()); + if let Some(timestamp) = timestamp { record.set_timestamp(timestamp); } + let span = context.span(); + let span_context = span.span_context(); + if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } + for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + logger.inner().emit(record); +} + + +#[derive(Clone, Debug)] +pub enum TaskFinishedOption { + Severity(::opentelemetry::logs::Severity), + Timestamp(::std::time::SystemTime), + + + BoolValues(super::myappattr::BoolValuesAttr), + + + DoubleValues(super::myappattr::DoubleValuesAttr), + + + IntValues(super::myappattr::IntValuesAttr), + + + StringValues(super::myappattr::StringValuesAttr), + +/// Recommended: When the task ran more than once. + TaskAttempt(super::myappattr::TaskAttemptAttr), + +} +/// A task reached a final state on a worker. +/// +/// Emitted once per task, after its last attempt. +pub fn r#emit_task_finished(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#myapp_task_state: super::myappattr::TaskStateAttr, r#worker_host_name: super::workerattr::HostNameAttr, options: impl IntoIterator) { + use ::opentelemetry::logs::LogRecord; + use ::opentelemetry::trace::TraceContextExt; + let _context_guard = context.clone().attach(); + let mut severity = ::opentelemetry::logs::Severity::Info; + let mut timestamp = None; + let mut attributes: Vec<::opentelemetry::KeyValue> = vec![r#myapp_task_state.key_value(), r#worker_host_name.key_value()]; + for option in options { + match option { + TaskFinishedOption::Severity(value) => severity = value, + TaskFinishedOption::Timestamp(value) => timestamp = Some(value), + + TaskFinishedOption::BoolValues(value) => attributes.push(value.key_value()), + + TaskFinishedOption::DoubleValues(value) => attributes.push(value.key_value()), + + TaskFinishedOption::IntValues(value) => attributes.push(value.key_value()), + + TaskFinishedOption::StringValues(value) => attributes.push(value.key_value()), + + TaskFinishedOption::TaskAttempt(value) => attributes.push(value.key_value()), + + } + } + if !logger.inner().event_enabled(severity, "", Some("worker.task.finished")) { return; } + let mut record = logger.inner().create_log_record(); + record.set_event_name("worker.task.finished"); + record.set_severity_number(severity); + record.set_observed_timestamp(::std::time::SystemTime::now()); + if let Some(timestamp) = timestamp { record.set_timestamp(timestamp); } + let span = context.span(); + let span_context = span.span_context(); + if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } + for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + logger.inner().emit(record); +} diff --git a/templates/code/rust/tests/events/registry/manifest.yaml b/templates/code/rust/tests/events/registry/manifest.yaml new file mode 100644 index 0000000..18c4f14 --- /dev/null +++ b/templates/code/rust/tests/events/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: events +schema_url: https://example.com/schemas/events/1.0.0 diff --git a/templates/code/rust/tests/events/registry/model.yaml b/templates/code/rust/tests/events/registry/model.yaml new file mode 100644 index 0000000..7280fa5 --- /dev/null +++ b/templates/code/rust/tests/events/registry/model.yaml @@ -0,0 +1,88 @@ +file_format: definition/2 +attributes: + - key: myapp.task.state + type: + members: + - id: done + value: done + stability: stable + brief: The task finished. + - id: failed + value: failed + stability: stable + brief: The task gave up. + stability: stable + brief: Current state of the task. + - key: myapp.task.attempt + type: int + stability: stable + brief: Number of the attempt, starting at 1. + examples: [1] + - key: worker.host.name + type: string + stability: stable + brief: Name of the worker host. + examples: ["worker-1"] + - key: myapp.bool.values + type: boolean[] + stability: stable + brief: Synthetic bool values. + examples: [[true]] + - key: myapp.int.values + type: int[] + stability: stable + brief: Synthetic int values. + examples: [[1]] + - key: myapp.double.values + type: double[] + stability: stable + brief: Synthetic double values. + examples: [[1.5]] + - key: myapp.string.values + type: string[] + stability: stable + brief: Synthetic string values. + examples: [["fetch"]] +events: + - name: myapp.task.finished + stability: development + requirement_level: recommended + brief: A task reached a final state. + note: Emitted once per task, after its last attempt. + attributes: + - ref: myapp.task.state + requirement_level: required + - ref: myapp.task.attempt + requirement_level: + recommended: When the task ran more than once. + - ref: worker.host.name + requirement_level: opt_in + - ref: myapp.bool.values + requirement_level: recommended + - ref: myapp.int.values + requirement_level: recommended + - ref: myapp.double.values + requirement_level: recommended + - ref: myapp.string.values + requirement_level: recommended + - name: myapp.task.retried + stability: development + requirement_level: opt_in + brief: A task is about to run again. + deprecated: + reason: obsoleted + note: Read the attempt from `myapp.task.finished` instead. + attributes: + - ref: myapp.task.attempt + requirement_level: required + - name: worker.host.started + stability: stable + requirement_level: recommended + brief: A worker host started taking tasks. +event_refinements: + - id: worker.task.finished + ref: myapp.task.finished + brief: A task reached a final state on a worker. + attributes: + - ref: worker.host.name + requirement_level: required diff --git a/templates/code/rust/tests/events/test.rs b/templates/code/rust/tests/events/test.rs new file mode 100644 index 0000000..a197451 --- /dev/null +++ b/templates/code/rust/tests/events/test.rs @@ -0,0 +1,134 @@ +use generated_semconv::{logger, myappattr, myappevent, workerattr, workerevent, SCHEMA_URL}; +use opentelemetry::logs::{AnyValue, Severity}; +use opentelemetry::trace::{SpanContext, SpanId, TraceContextExt, TraceFlags, TraceId, TraceState}; +use opentelemetry_sdk::logs::{InMemoryLogExporter, SdkLoggerProvider}; + +#[test] +fn typed_events_have_schema_timestamps_severity_attributes_and_trace_context() { + let exporter = InMemoryLogExporter::default(); + let provider = SdkLoggerProvider::builder() + .with_simple_exporter(exporter.clone()) + .build(); + let logger = logger::Logger::new_with_scope( + &provider, + opentelemetry::InstrumentationScope::builder("worker") + .with_version("1.2.3") + .with_schema_url("https://example.com/ignored/1.0.0") + .with_attributes([opentelemetry::KeyValue::new("scope.kind", "test")]) + .build(), + ); + let span = SpanContext::new( + TraceId::from(7), + SpanId::from(9), + TraceFlags::SAMPLED, + false, + TraceState::default(), + ); + let context = opentelemetry::Context::new().with_remote_span_context(span.clone()); + let timestamp = std::time::UNIX_EPOCH + std::time::Duration::from_secs(100); + myappevent::emit_task_finished( + &context, + &logger, + myappattr::TaskStateAttr::Done, + [ + myappevent::TaskFinishedOption::TaskAttempt(myappattr::TaskAttemptAttr::new(2)), + myappevent::TaskFinishedOption::HostName(workerattr::HostNameAttr::new("worker-1")), + myappevent::TaskFinishedOption::Severity(Severity::Warn), + myappevent::TaskFinishedOption::Timestamp(timestamp), + myappevent::TaskFinishedOption::BoolValues(myappattr::BoolValuesAttr::new(vec![true])), + myappevent::TaskFinishedOption::IntValues(myappattr::IntValuesAttr::new(vec![1])), + myappevent::TaskFinishedOption::DoubleValues(myappattr::DoubleValuesAttr::new(vec![ + 1.5, + ])), + myappevent::TaskFinishedOption::StringValues(myappattr::StringValuesAttr::new(vec![ + "fetch".into(), + ])), + ], + ); + workerevent::emit_task_finished( + &context, + &logger, + myappattr::TaskStateAttr::Done, + workerattr::HostNameAttr::new("worker-1"), + [], + ); + provider.force_flush().unwrap(); + let logs = exporter.get_emitted_logs().unwrap(); + assert_eq!(logs.len(), 2); + let log = &logs[0]; + assert_eq!(log.record.event_name(), Some("myapp.task.finished")); + assert_eq!(log.record.severity_number(), Some(Severity::Warn)); + assert_eq!(log.record.timestamp(), Some(timestamp)); + assert!(log.record.observed_timestamp().is_some()); + assert!(log.record.body().is_none()); + assert_eq!(log.instrumentation.schema_url(), Some(SCHEMA_URL)); + assert_eq!(log.instrumentation.name(), "worker"); + assert_eq!(log.instrumentation.version(), Some("1.2.3")); + assert!(log + .instrumentation + .attributes() + .any(|kv| kv.key.as_str() == "scope.kind")); + assert_eq!( + log.record.trace_context().unwrap().trace_id, + span.trace_id() + ); + assert_eq!(log.record.trace_context().unwrap().span_id, span.span_id()); + assert!(log + .record + .attributes_iter() + .any(|(key, value)| key.as_str() == "myapp.task.attempt" && value == &AnyValue::Int(2))); + for (key, expected) in [ + ("myapp.bool.values", AnyValue::Boolean(true)), + ("myapp.int.values", AnyValue::Int(1)), + ("myapp.double.values", AnyValue::Double(1.5)), + ("myapp.string.values", AnyValue::String("fetch".into())), + ] { + assert!(log + .record + .attributes_iter() + .any(|(attr_key, value)| attr_key.as_str() == key + && value == &AnyValue::ListAny(Box::new(vec![expected.clone()])))); + } + assert_eq!(logs[1].record.event_name(), Some("worker.task.finished")); + assert_eq!(logs[1].record.severity_number(), Some(Severity::Info)); + assert!(logs[1].record.timestamp().is_none()); + myappevent::emit_task_finished( + &context, + &logger::Logger::default(), + myappattr::TaskStateAttr::Done, + [], + ); +} + +struct DisabledProvider; +struct DisabledLogger; +impl opentelemetry::logs::LoggerProvider for DisabledProvider { + type Logger = DisabledLogger; + fn logger_with_scope(&self, _: opentelemetry::InstrumentationScope) -> DisabledLogger { + DisabledLogger + } +} +impl opentelemetry::logs::Logger for DisabledLogger { + type LogRecord = opentelemetry_sdk::logs::SdkLogRecord; + fn create_log_record(&self) -> Self::LogRecord { + panic!("disabled events must not create a record") + } + fn emit(&self, _: Self::LogRecord) { + panic!("disabled events must not emit a record") + } + fn event_enabled(&self, severity: Severity, target: &str, name: Option<&str>) -> bool { + assert_eq!(severity, Severity::Error); + assert_eq!(target, ""); + assert_eq!(name, Some("myapp.task.finished")); + false + } +} +#[test] +fn disabled_events_are_checked_before_record_creation() { + myappevent::emit_task_finished( + &opentelemetry::Context::new(), + &logger::Logger::new(&DisabledProvider, "test"), + myappattr::TaskStateAttr::Done, + [myappevent::TaskFinishedOption::Severity(Severity::Error)], + ); +} diff --git a/templates/code/rust/tests/filtering/expected/mod.rs b/templates/code/rust/tests/filtering/expected/mod.rs new file mode 100644 index 0000000..f0375f2 --- /dev/null +++ b/templates/code/rust/tests/filtering/expected/mod.rs @@ -0,0 +1,381 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/filtering/1.0.0"; + +pub mod authattr { + + /// How the user was authenticated. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum MethodAttr { + + /// A password was checked. + Password, + + /// A bearer token was checked. + Token, + + } + + + #[allow(deprecated)] + impl MethodAttr { + pub const KEY: &'static str = "auth.method"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Password => "password".into(), + + Self::Token => "token".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: MethodAttr) -> Self { + value.key_value() + } + } + + /// Identifier of the authenticated user. + #[derive(Debug, Clone, PartialEq)] + + pub struct UserIdAttr(String); + + + #[allow(deprecated)] + impl UserIdAttr { + pub const KEY: &'static str = "auth.user.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: UserIdAttr) -> Self { + value.key_value() + } + } + +} + +pub mod taskattr { + + /// Who assigned the task. + /// + /// The scheduler sets it on every task it passes along to `myapp.task.state`. Workers never set it themselves. + #[derive(Debug, Clone, PartialEq)] + + pub struct AssignedByAttr(String); + + + #[allow(deprecated)] + impl AssignedByAttr { + pub const KEY: &'static str = "myapp.task.assigned_by"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: AssignedByAttr) -> Self { + value.key_value() + } + } + + /// Whether the task was cancelled. + #[derive(Debug, Clone, PartialEq)] + + pub struct CancelledAttr(bool); + + + #[allow(deprecated)] + impl CancelledAttr { + pub const KEY: &'static str = "myapp.task.cancelled"; + + pub fn new(value: bool) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: CancelledAttr) -> Self { + value.key_value() + } + } + + /// Unique identifier of the task. + /// + /// The identifier is assigned by the scheduler and stays stable across retries. + #[derive(Debug, Clone, PartialEq)] + + pub struct IdAttr(String); + + + #[allow(deprecated)] + impl IdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: IdAttr) -> Self { + value.key_value() + } + } + + /// Whether the scheduler may preempt the task. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum PreemptibleAttr { + + /// The scheduler may preempt the task. + Allowed, + + /// The task runs to completion. + Forbidden, + + } + + + #[allow(deprecated)] + impl PreemptibleAttr { + pub const KEY: &'static str = "myapp.task.preemptible"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: bool = match self { + + Self::Allowed => true, + + Self::Forbidden => false, + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: PreemptibleAttr) -> Self { + value.key_value() + } + } + + /// Number of times the task was retried. + #[derive(Debug, Clone, PartialEq)] + + pub struct RetriesAttr(i64); + + + #[allow(deprecated)] + impl RetriesAttr { + pub const KEY: &'static str = "myapp.task.retries"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: RetriesAttr) -> Self { + value.key_value() + } + } + + /// Fraction of tasks whose telemetry is sampled. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum SampleRateAttr { + + /// One task in ten is sampled. + Tenth, + + /// Every task is sampled. + All, + + } + + + #[allow(deprecated)] + impl SampleRateAttr { + pub const KEY: &'static str = "myapp.task.sample_rate"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: f64 = match self { + + Self::Tenth => 0.1_f64, + + Self::All => 1_f64, + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: SampleRateAttr) -> Self { + value.key_value() + } + } + + /// Shards the task touched. + #[derive(Debug, Clone, PartialEq)] + + pub struct ShardIdsAttr(Vec); + + + #[allow(deprecated)] + impl ShardIdsAttr { + pub const KEY: &'static str = "myapp.task.shard_ids"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: ShardIdsAttr) -> Self { + value.key_value() + } + } + + /// Current state of the task. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum StateAttr { + + /// The task is waiting to run. + Queued, + + /// The task is running. + /// + /// A task stays running until it finishes or is cancelled. + Running, + + } + + + #[allow(deprecated)] + impl StateAttr { + pub const KEY: &'static str = "myapp.task.state"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Queued => "queued".into(), + + Self::Running => "running".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: StateAttr) -> Self { + value.key_value() + } + } + + /// Tags attached to the task. + #[derive(Debug, Clone, PartialEq)] + + pub struct TagsAttr(Vec); + + + #[allow(deprecated)] + impl TagsAttr { + pub const KEY: &'static str = "myapp.task.tags"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TagsAttr) -> Self { + value.key_value() + } + } + +} diff --git a/templates/code/rust/tests/filtering/params.yaml b/templates/code/rust/tests/filtering/params.yaml new file mode 100644 index 0000000..5ccc45f --- /dev/null +++ b/templates/code/rust/tests/filtering/params.yaml @@ -0,0 +1,4 @@ +params: + stable_only: true + exclude_deprecated: true + vendor_prefixes: [myapp] diff --git a/templates/code/rust/tests/filtering/registry/manifest.yaml b/templates/code/rust/tests/filtering/registry/manifest.yaml new file mode 100644 index 0000000..b9f7519 --- /dev/null +++ b/templates/code/rust/tests/filtering/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: filtering +schema_url: https://example.com/schemas/filtering/1.0.0 diff --git a/templates/code/rust/tests/filtering/registry/model.yaml b/templates/code/rust/tests/filtering/registry/model.yaml new file mode 100644 index 0000000..e43af4d --- /dev/null +++ b/templates/code/rust/tests/filtering/registry/model.yaml @@ -0,0 +1,154 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: stable + brief: Unique identifier of the task. + note: The identifier is assigned by the scheduler and stays stable across retries. + examples: ["task_0001"] + - key: myapp.task.retries + type: int + stability: stable + brief: Number of times the task was retried. + examples: 3 + - key: myapp.task.progress + type: double + stability: development + brief: Fraction of the task that has completed, between 0 and 1. + examples: 0.5 + - key: myapp.task.cancelled + type: boolean + stability: stable + brief: Whether the task was cancelled. + examples: false + - key: myapp.task.tags + type: string[] + stability: stable + brief: Tags attached to the task. + examples: [["nightly", "batch"]] + - key: myapp.task.shard_ids + type: int[] + stability: stable + brief: Shards the task touched. + examples: [[1, 2]] + - key: myapp.task.weights + type: double[] + stability: development + brief: Scheduling weights applied to the task. + examples: [[0.25, 0.75]] + - key: myapp.task.flags + type: boolean[] + stability: development + brief: Feature flags evaluated for the task. + examples: [[true, false]] + - key: myapp.task.state + type: + members: + - id: queued + value: queued + stability: stable + brief: The task is waiting to run. + - id: running + value: running + stability: stable + brief: The task is running. + note: A task stays running until it finishes or is cancelled. + - id: paused + value: paused + stability: development + brief: The task was paused. + deprecated: + reason: obsoleted + note: Paused tasks are reported as queued. + stability: stable + brief: Current state of the task. + - key: myapp.task.owner + type: string + stability: development + brief: Owner of the task. + examples: ["solo"] + deprecated: + reason: renamed + renamed_to: auth.user.id + - key: auth.user.id + type: string + stability: stable + brief: Identifier of the authenticated user. + examples: ["u_123"] + - key: auth.method + type: + members: + - id: password + value: password + stability: stable + brief: A password was checked. + - id: token + value: token + stability: stable + brief: A bearer token was checked. + stability: stable + brief: How the user was authenticated. + - key: auth.level + type: + members: + - id: low + value: 1 + stability: stable + brief: Single factor. + - id: high + value: 2 + stability: stable + brief: Multiple factors. + stability: development + brief: Assurance level of the authentication. + - key: myapp.task.preemptible + type: + members: + - id: allowed + value: true + stability: stable + brief: The scheduler may preempt the task. + - id: forbidden + value: false + stability: stable + brief: The task runs to completion. + stability: stable + brief: Whether the scheduler may preempt the task. + - key: myapp.task.sample_rate + type: + members: + - id: tenth + value: 0.1 + stability: stable + brief: One task in ten is sampled. + - id: all + value: 1 + stability: stable + brief: Every task is sampled. + stability: stable + brief: Fraction of tasks whose telemetry is sampled. + - key: myapp.task.assigned_by + type: string + stability: stable + brief: Who assigned the task. + note: The scheduler sets it on every task it passes along to `myapp.task.state`. Workers never set it themselves. + examples: ["scheduler"] + - key: myapp.task.lane + type: + members: + - id: fast + value: fast + stability: stable + brief: The fast lane. + - id: slow + value: slow + stability: stable + brief: The slow lane. + deprecated: + reason: obsoleted + note: Every task runs in the fast lane. + stability: development + brief: Lane the task was scheduled in. + deprecated: + reason: obsoleted + note: Lanes were replaced by priorities. diff --git a/templates/code/rust/tests/filtering/test.rs b/templates/code/rust/tests/filtering/test.rs new file mode 100644 index 0000000..1336487 --- /dev/null +++ b/templates/code/rust/tests/filtering/test.rs @@ -0,0 +1,14 @@ +use generated_semconv::taskattr::{IdAttr, StateAttr}; +use opentelemetry::{KeyValue, Value}; + +#[test] +fn vendor_prefix_changes_types_but_preserves_telemetry_keys() { + assert_eq!( + IdAttr::new("task").key_value(), + KeyValue::new("myapp.task.id", "task") + ); + assert_eq!( + StateAttr::Queued.key_value().value, + Value::String("queued".into()) + ); +} diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs new file mode 100644 index 0000000..176d064 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs @@ -0,0 +1,22 @@ +#[derive(Clone, Debug)] +pub struct Meter(opentelemetry::metrics::Meter); +impl Meter { + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.meter_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } +} +impl Default for Meter { + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs new file mode 100644 index 0000000..b04aff6 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs @@ -0,0 +1,44 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/histogram_boundaries_by_unit/1.0.0"; + +pub mod myappattr { + + /// Unique identifier of the task. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskIdAttr(String); + + + #[allow(deprecated)] + impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } + } + +} + + +pub mod meter; + + + +pub mod myappmetric; diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs new file mode 100644 index 0000000..3b81a78 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs @@ -0,0 +1,119 @@ +#![allow(deprecated)] + + + + + + + + +/// Time a task took from start to finish. +#[derive(Clone)] +pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +impl TaskDurationHistogram { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_histogram("myapp.task.duration") + .with_description("Time a task took from start to finish.") + .with_unit("s") + + .with_boundaries(vec![0.005_f64, 0.01_f64, 0.025_f64, 0.05_f64, 0.075_f64, 0.1_f64, 0.25_f64, 0.5_f64, 0.75_f64, 1_f64, 2.5_f64, 5_f64, 7.5_f64, 10_f64]) + + .build() } + } + pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { + let attributes = vec![r#myapp_task_id.key_value()]; + + self.instrument.record(value, &attributes); + } +} +impl Default for TaskDurationHistogram { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + + + + + + + +/// Time between a task being queued and started. +#[derive(Clone)] +pub struct TaskLatencyHistogram { instrument: ::opentelemetry::metrics::Histogram } +impl TaskLatencyHistogram { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_histogram("myapp.task.latency") + .with_description("Time between a task being queued and started.") + .with_unit("s") + + .with_boundaries(vec![1_f64, 10_f64, 100_f64]) + + .build() } + } + pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { + let attributes = vec![r#myapp_task_id.key_value()]; + + self.instrument.record(value, &attributes); + } +} +impl Default for TaskLatencyHistogram { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + + + + + + + +/// Time a retried task took from start to finish. +#[derive(Clone)] +pub struct TaskRetryDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +impl TaskRetryDurationHistogram { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_histogram("myapp.task.duration") + .with_description("Time a task took from start to finish.") + .with_unit("s") + + .with_boundaries(vec![0.005_f64, 0.01_f64, 0.025_f64, 0.05_f64, 0.075_f64, 0.1_f64, 0.25_f64, 0.5_f64, 0.75_f64, 1_f64, 2.5_f64, 5_f64, 7.5_f64, 10_f64]) + + .build() } + } + pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { + let attributes = vec![r#myapp_task_id.key_value()]; + + self.instrument.record(value, &attributes); + } +} +impl Default for TaskRetryDurationHistogram { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + + + + + + + +/// Size of a task's payload. +#[derive(Clone)] +pub struct TaskSizeHistogram { instrument: ::opentelemetry::metrics::Histogram } +impl TaskSizeHistogram { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_histogram("myapp.task.size") + .with_description("Size of a task\u{0027}s payload.") + .with_unit("By") + + .build() } + } + pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { + let attributes = vec![r#myapp_task_id.key_value()]; + + self.instrument.record(value, &attributes); + } +} +impl Default for TaskSizeHistogram { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/registry/manifest.yaml b/templates/code/rust/tests/histogram_boundaries_by_unit/registry/manifest.yaml new file mode 100644 index 0000000..437da86 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: histogram_boundaries_by_unit +schema_url: https://example.com/schemas/histogram_boundaries_by_unit/1.0.0 diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/registry/myapp.yaml b/templates/code/rust/tests/histogram_boundaries_by_unit/registry/myapp.yaml new file mode 100644 index 0000000..6d1f779 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/registry/myapp.yaml @@ -0,0 +1,53 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: stable + brief: Unique identifier of the task. + examples: ["task_0001"] +metrics: + - name: myapp.task.duration + instrument: histogram + unit: s + stability: stable + brief: Time a task took from start to finish. + annotations: + code_generation: + metric_value_type: double + attributes: + - ref: myapp.task.id + requirement_level: required + - name: myapp.task.latency + instrument: histogram + unit: s + stability: stable + brief: Time between a task being queued and started. + annotations: + code_generation: + metric_value_type: double + aggregation: + method: explicithistogram + parameters: + boundaries: [1, 10, 100] + attributes: + - ref: myapp.task.id + requirement_level: required + - name: myapp.task.size + instrument: histogram + unit: By + stability: stable + brief: Size of a task's payload. + annotations: + code_generation: + metric_value_type: double + attributes: + - ref: myapp.task.id + requirement_level: required +metric_refinements: + - id: myapp.task.retry.duration + ref: myapp.task.duration + stability: stable + brief: Time a retried task took from start to finish. + attributes: + - ref: myapp.task.id + requirement_level: required diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs new file mode 100644 index 0000000..176d064 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs @@ -0,0 +1,22 @@ +#[derive(Clone, Debug)] +pub struct Meter(opentelemetry::metrics::Meter); +impl Meter { + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.meter_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } +} +impl Default for Meter { + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs new file mode 100644 index 0000000..bf8cc35 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs @@ -0,0 +1,44 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/histogram_boundaries_by_unit_params/1.0.0"; + +pub mod myappattr { + + /// Unique identifier of the task. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskIdAttr(String); + + + #[allow(deprecated)] + impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } + } + +} + + +pub mod meter; + + + +pub mod myappmetric; diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs new file mode 100644 index 0000000..5b37fab --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs @@ -0,0 +1,59 @@ +#![allow(deprecated)] + + + + + + + + +/// Time a task took from start to finish. +#[derive(Clone)] +pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +impl TaskDurationHistogram { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_histogram("myapp.task.duration") + .with_description("Time a task took from start to finish.") + .with_unit("s") + + .build() } + } + pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { + let attributes = vec![r#myapp_task_id.key_value()]; + + self.instrument.record(value, &attributes); + } +} +impl Default for TaskDurationHistogram { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + + + + + + + +/// Time a task waited in the queue, in minutes. +#[derive(Clone)] +pub struct TaskQueueWaitHistogram { instrument: ::opentelemetry::metrics::Histogram } +impl TaskQueueWaitHistogram { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_histogram("myapp.task.queue_wait") + .with_description("Time a task waited in the queue, in minutes.") + .with_unit("min") + + .with_boundaries(vec![1_f64, 5_f64, 10_f64, 30_f64, 60_f64]) + + .build() } + } + pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { + let attributes = vec![r#myapp_task_id.key_value()]; + + self.instrument.record(value, &attributes); + } +} +impl Default for TaskQueueWaitHistogram { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/params.yaml b/templates/code/rust/tests/histogram_boundaries_by_unit_params/params.yaml new file mode 100644 index 0000000..a4d15ed --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/params.yaml @@ -0,0 +1,3 @@ +params: + histogram_boundaries_by_unit: + min: [1, 5, 10, 30, 60] diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/registry/manifest.yaml b/templates/code/rust/tests/histogram_boundaries_by_unit_params/registry/manifest.yaml new file mode 100644 index 0000000..22ea470 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: histogram_boundaries_by_unit_params +schema_url: https://example.com/schemas/histogram_boundaries_by_unit_params/1.0.0 diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/registry/myapp.yaml b/templates/code/rust/tests/histogram_boundaries_by_unit_params/registry/myapp.yaml new file mode 100644 index 0000000..cda8262 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/registry/myapp.yaml @@ -0,0 +1,30 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: stable + brief: Unique identifier of the task. + examples: ["task_0001"] +metrics: + - name: myapp.task.duration + instrument: histogram + unit: s + stability: stable + brief: Time a task took from start to finish. + annotations: + code_generation: + metric_value_type: double + attributes: + - ref: myapp.task.id + requirement_level: required + - name: myapp.task.queue_wait + instrument: histogram + unit: min + stability: stable + brief: Time a task waited in the queue, in minutes. + annotations: + code_generation: + metric_value_type: double + attributes: + - ref: myapp.task.id + requirement_level: required diff --git a/templates/code/rust/tests/imported/dependency/manifest.yaml b/templates/code/rust/tests/imported/dependency/manifest.yaml new file mode 100644 index 0000000..6fe2cd0 --- /dev/null +++ b/templates/code/rust/tests/imported/dependency/manifest.yaml @@ -0,0 +1,2 @@ +name: upstream +schema_url: https://example.com/schemas/upstream/1.0.0 diff --git a/templates/code/rust/tests/imported/dependency/model.yaml b/templates/code/rust/tests/imported/dependency/model.yaml new file mode 100644 index 0000000..109e05e --- /dev/null +++ b/templates/code/rust/tests/imported/dependency/model.yaml @@ -0,0 +1,30 @@ +file_format: definition/2 +attributes: + - key: error.type + type: + members: + - id: timeout + value: timeout + stability: stable + brief: The operation timed out. + - id: other + value: _OTHER + stability: stable + brief: Any other error. + stability: stable + brief: Describes a class of error. + - key: server.address + type: string + stability: stable + brief: Server domain name or IP address. + examples: ["example.com"] + - key: server.port + type: int + stability: stable + brief: Server port number. + examples: [443] + - key: http.request.method_list + type: string[] + stability: stable + brief: Methods attempted, in order. + examples: [["GET", "POST"]] diff --git a/templates/code/rust/tests/imported/expected/edgeevent.rs b/templates/code/rust/tests/imported/expected/edgeevent.rs new file mode 100644 index 0000000..3225685 --- /dev/null +++ b/templates/code/rust/tests/imported/expected/edgeevent.rs @@ -0,0 +1,42 @@ +#![allow(deprecated)] + + + +#[derive(Clone, Debug)] +pub enum UpstreamFailedOption { + Severity(::opentelemetry::logs::Severity), + Timestamp(::std::time::SystemTime), + + + ServerAddress(String), + +} +/// A request to an upstream server failed. +pub fn r#emit_upstream_failed(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#error_type: String, options: impl IntoIterator) { + use ::opentelemetry::logs::LogRecord; + use ::opentelemetry::trace::TraceContextExt; + let _context_guard = context.clone().attach(); + let mut severity = ::opentelemetry::logs::Severity::Info; + let mut timestamp = None; + let mut attributes: Vec<::opentelemetry::KeyValue> = vec![::opentelemetry::KeyValue::new("error.type", r#error_type)]; + for option in options { + match option { + UpstreamFailedOption::Severity(value) => severity = value, + UpstreamFailedOption::Timestamp(value) => timestamp = Some(value), + + UpstreamFailedOption::ServerAddress(value) => attributes.push(::opentelemetry::KeyValue::new("server.address", value)), + + } + } + if !logger.inner().event_enabled(severity, "", Some("edge.upstream.failed")) { return; } + let mut record = logger.inner().create_log_record(); + record.set_event_name("edge.upstream.failed"); + record.set_severity_number(severity); + record.set_observed_timestamp(::std::time::SystemTime::now()); + if let Some(timestamp) = timestamp { record.set_timestamp(timestamp); } + let span = context.span(); + let span_context = span.span_context(); + if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } + for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + logger.inner().emit(record); +} diff --git a/templates/code/rust/tests/imported/expected/edgemetric.rs b/templates/code/rust/tests/imported/expected/edgemetric.rs new file mode 100644 index 0000000..d99b409 --- /dev/null +++ b/templates/code/rust/tests/imported/expected/edgemetric.rs @@ -0,0 +1,50 @@ +#![allow(deprecated)] + + + + + + + + +#[derive(Clone, Debug)] +pub enum UpstreamDurationHistogramAttr { + + + ServerPort(i64), + +} +impl UpstreamDurationHistogramAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), + + } + } +} + +/// Time spent waiting on an upstream server. +#[derive(Clone)] +pub struct UpstreamDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +impl UpstreamDurationHistogram { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_histogram("edge.upstream.duration") + .with_description("Time spent waiting on an upstream server.") + .with_unit("s") + + .with_boundaries(vec![0.005_f64, 0.01_f64, 0.025_f64, 0.05_f64, 0.075_f64, 0.1_f64, 0.25_f64, 0.5_f64, 0.75_f64, 1_f64, 2.5_f64, 5_f64, 7.5_f64, 10_f64]) + + .build() } + } + pub fn record(&self, value: f64, r#server_address: String, options: impl IntoIterator) { + let mut attributes = vec![::opentelemetry::KeyValue::new("server.address", r#server_address)]; + + attributes.extend(options.into_iter().map(UpstreamDurationHistogramAttr::key_value)); + + self.instrument.record(value, &attributes); + } +} +impl Default for UpstreamDurationHistogram { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} diff --git a/templates/code/rust/tests/imported/expected/edgespan.rs b/templates/code/rust/tests/imported/expected/edgespan.rs new file mode 100644 index 0000000..dfe7deb --- /dev/null +++ b/templates/code/rust/tests/imported/expected/edgespan.rs @@ -0,0 +1,101 @@ +#![allow(deprecated)] + + + + + +#[derive(Clone, Debug)] +pub enum UpstreamRequestStartAttr { + +/// Conditionally required: If the request failed. + ErrorType(String), + + + HttpRequestMethodList(Vec), + +} +impl UpstreamRequestStartAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::ErrorType(value) => ::opentelemetry::KeyValue::new("error.type", value), + + Self::HttpRequestMethodList(value) => ::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.into_iter().map(Into::into).collect()))), + + } + } +} + + +#[derive(Clone, Debug)] +pub enum UpstreamRequestAttr { + + HttpRequestMethodList(Vec), + +} +impl From for UpstreamRequestStartAttr { + fn from(value: UpstreamRequestAttr) -> Self { + match value { + + UpstreamRequestAttr::HttpRequestMethodList(value) => Self::HttpRequestMethodList(value), + + } + } +} + + +/// A request to an upstream server. +pub struct UpstreamRequestSpan { span: ::opentelemetry::global::BoxedSpan } +impl UpstreamRequestSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { + use ::opentelemetry::trace::TraceContextExt; + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } + + pub fn set_attributes(&mut self, attributes: impl IntoIterator) { + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, UpstreamRequestStartAttr::from(attribute).key_value()); } + } + +} +impl Default for UpstreamRequestSpan { + fn default() -> Self { + use ::opentelemetry::trace::Tracer; + Self { span: super::tracer::Tracer::default().inner().start("edge.upstream.request") } + } +} + +pub fn r#start_upstream_request(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#server_address: String, r#server_port: i64, options: impl IntoIterator) -> UpstreamRequestSpan { + use ::opentelemetry::trace::Tracer; + + let mut name = String::new(); + + + name.push_str(&::opentelemetry::KeyValue::new("server.address", r#server_address.clone()).value.to_string()); + + + + + name.push(':'); + + + + + name.push_str(&::opentelemetry::KeyValue::new("server.port", r#server_port).value.to_string()); + + + + let mut attributes = vec![::opentelemetry::KeyValue::new("server.address", r#server_address), ::opentelemetry::KeyValue::new("server.port", r#server_port)]; + + attributes.extend(options.into_iter().map(UpstreamRequestStartAttr::key_value)); + + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Client) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + UpstreamRequestSpan { span } +} diff --git a/templates/code/rust/tests/imported/expected/logger.rs b/templates/code/rust/tests/imported/expected/logger.rs new file mode 100644 index 0000000..c7a2373 --- /dev/null +++ b/templates/code/rust/tests/imported/expected/logger.rs @@ -0,0 +1,40 @@ +#[derive(Clone, Debug)] +pub struct Logger::Logger>(L); +impl Logger { + pub fn new>(provider: &P, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.logger_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &L { &self.0 } +} +impl Default for Logger { + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } +} +pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { + use opentelemetry::{Value, Array}; + use opentelemetry::logs::AnyValue; + match value { + Value::Bool(value) => value.into(), + Value::I64(value) => value.into(), + Value::F64(value) => value.into(), + Value::String(value) => value.into(), + Value::Array(array) => match array { + Array::Bool(values) => values.into_iter().collect::(), + Array::I64(values) => values.into_iter().collect::(), + Array::F64(values) => values.into_iter().collect::(), + Array::String(values) => values.into_iter().collect::(), + _ => AnyValue::String(array.to_string().into()), + }, + _ => AnyValue::String(value.to_string().into()), + } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/imported/expected/meter.rs b/templates/code/rust/tests/imported/expected/meter.rs new file mode 100644 index 0000000..176d064 --- /dev/null +++ b/templates/code/rust/tests/imported/expected/meter.rs @@ -0,0 +1,22 @@ +#[derive(Clone, Debug)] +pub struct Meter(opentelemetry::metrics::Meter); +impl Meter { + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.meter_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } +} +impl Default for Meter { + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/imported/expected/mod.rs b/templates/code/rust/tests/imported/expected/mod.rs new file mode 100644 index 0000000..a0567e2 --- /dev/null +++ b/templates/code/rust/tests/imported/expected/mod.rs @@ -0,0 +1,50 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/myapp/1.0.0"; + +pub mod myappattr { + + /// Unique identifier of the task. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskIdAttr(String); + + + #[allow(deprecated)] + impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } + } + +} + + +pub mod meter; +pub mod tracer; +pub mod logger; + +pub mod edgeevent; + +pub mod edgemetric; + +pub mod edgespan; + +pub mod myappmetric; diff --git a/templates/code/rust/tests/imported/expected/myappmetric.rs b/templates/code/rust/tests/imported/expected/myappmetric.rs new file mode 100644 index 0000000..a973012 --- /dev/null +++ b/templates/code/rust/tests/imported/expected/myappmetric.rs @@ -0,0 +1,75 @@ +#![allow(deprecated)] + + + + + + + + +#[derive(Clone, Debug)] +pub enum TaskFailedCounterAttr { + + + HttpRequestMethodList(Vec), + +} +impl TaskFailedCounterAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::HttpRequestMethodList(value) => ::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.into_iter().map(Into::into).collect()))), + + } + } +} + +/// Number of tasks that failed. +#[derive(Clone)] +pub struct TaskFailedCounter { instrument: ::opentelemetry::metrics::Counter } +impl TaskFailedCounter { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().u64_counter("myapp.task.failed") + .with_description("Number of tasks that failed.") + .with_unit("{task}") + + .build() } + } + pub fn add(&self, value: u64, r#error_type: String, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { + let mut attributes = vec![::opentelemetry::KeyValue::new("error.type", r#error_type), r#myapp_task_id.key_value()]; + + attributes.extend(options.into_iter().map(TaskFailedCounterAttr::key_value)); + + self.instrument.add(value, &attributes); + } +} +impl Default for TaskFailedCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + +pub struct TaskFailedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl TaskFailedCounterObserver<'_> { + pub fn observe(&self, value: u64, r#error_type: String, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { + let mut attributes = vec![::opentelemetry::KeyValue::new("error.type", r#error_type), r#myapp_task_id.key_value()]; + + attributes.extend(options.into_iter().map(TaskFailedCounterAttr::key_value)); + + self.observer.observe(value, &attributes); + } +} + +#[derive(Clone)] +pub struct TaskFailedObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +impl TaskFailedObservableCounter { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFailedCounterObserver<'_>) + Send + Sync + 'static) -> Self { + Self { _instrument: meter.inner().u64_observable_counter("myapp.task.failed") + .with_description("Number of tasks that failed.") + .with_unit("{task}") + .with_callback(move |observer| callback(TaskFailedCounterObserver { observer })) + .build() } + } +} +impl Default for TaskFailedObservableCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} diff --git a/templates/code/rust/tests/imported/expected/tracer.rs b/templates/code/rust/tests/imported/expected/tracer.rs new file mode 100644 index 0000000..6580bf3 --- /dev/null +++ b/templates/code/rust/tests/imported/expected/tracer.rs @@ -0,0 +1,29 @@ +pub struct Tracer(opentelemetry::global::BoxedTracer); +impl Tracer { + pub fn new(provider: &P, scope: impl Into>) -> Self + where + P::Tracer: Send + Sync + 'static, + ::Span: Send + Sync + 'static, + { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self + where + P::Tracer: Send + Sync + 'static, + ::Span: Send + Sync + 'static, + { + Self(opentelemetry::global::BoxedTracer::new(Box::new(provider.tracer_with_scope(registry_scope(scope))))) + } + pub fn inner(&self) -> &opentelemetry::global::BoxedTracer { &self.0 } +} +impl Default for Tracer { + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/imported/registry/manifest.yaml b/templates/code/rust/tests/imported/registry/manifest.yaml new file mode 100644 index 0000000..d1bbe08 --- /dev/null +++ b/templates/code/rust/tests/imported/registry/manifest.yaml @@ -0,0 +1,6 @@ +name: myapp +schema_url: https://example.com/schemas/myapp/1.0.0 +dependencies: + - name: upstream + registry_path: dependency + schema_url: https://example.com/schemas/upstream/1.0.0 diff --git a/templates/code/rust/tests/imported/registry/model.yaml b/templates/code/rust/tests/imported/registry/model.yaml new file mode 100644 index 0000000..dac6860 --- /dev/null +++ b/templates/code/rust/tests/imported/registry/model.yaml @@ -0,0 +1,65 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: stable + brief: Unique identifier of the task. + examples: ["task_0001"] +metrics: + - name: myapp.task.failed + instrument: counter + unit: "{task}" + stability: stable + brief: Number of tasks that failed. + annotations: + code_generation: + metric_value_type: int + attributes: + - ref: myapp.task.id + requirement_level: required + - ref: error.type + requirement_level: required + - ref: http.request.method_list + requirement_level: recommended + - name: edge.upstream.duration + instrument: histogram + unit: s + stability: stable + brief: Time spent waiting on an upstream server. + annotations: + code_generation: + metric_value_type: double + attributes: + - ref: server.address + requirement_level: required + - ref: server.port + requirement_level: recommended +spans: + - type: edge.upstream.request + kind: client + requirement_level: recommended + stability: stable + brief: A request to an upstream server. + name: + note: "`{server.address}:{server.port}`" + attributes: + - ref: server.address + requirement_level: required + - ref: server.port + requirement_level: required + - ref: error.type + requirement_level: + conditionally_required: If the request failed. + sampling_relevant: true + - ref: http.request.method_list + requirement_level: recommended +events: + - name: edge.upstream.failed + requirement_level: recommended + stability: stable + brief: A request to an upstream server failed. + attributes: + - ref: error.type + requirement_level: required + - ref: server.address + requirement_level: recommended diff --git a/templates/code/rust/tests/imported_typed/dependency-params.yaml b/templates/code/rust/tests/imported_typed/dependency-params.yaml new file mode 100644 index 0000000..7957adf --- /dev/null +++ b/templates/code/rust/tests/imported_typed/dependency-params.yaml @@ -0,0 +1 @@ +params: diff --git a/templates/code/rust/tests/imported_typed/dependency/manifest.yaml b/templates/code/rust/tests/imported_typed/dependency/manifest.yaml new file mode 100644 index 0000000..6fe2cd0 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/dependency/manifest.yaml @@ -0,0 +1,2 @@ +name: upstream +schema_url: https://example.com/schemas/upstream/1.0.0 diff --git a/templates/code/rust/tests/imported_typed/dependency/model.yaml b/templates/code/rust/tests/imported_typed/dependency/model.yaml new file mode 100644 index 0000000..c550f39 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/dependency/model.yaml @@ -0,0 +1,20 @@ +file_format: definition/2 +attributes: + - key: error.type + type: + members: + - id: timeout + value: timeout + stability: stable + brief: The operation timed out. + - id: other + value: _OTHER + stability: stable + brief: Any other error. + stability: stable + brief: Describes a class of error. + - key: server.port + type: int + stability: stable + brief: Server port number. + examples: [443] diff --git a/templates/code/rust/tests/imported_typed/expected/logger.rs b/templates/code/rust/tests/imported_typed/expected/logger.rs new file mode 100644 index 0000000..c7a2373 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/expected/logger.rs @@ -0,0 +1,40 @@ +#[derive(Clone, Debug)] +pub struct Logger::Logger>(L); +impl Logger { + pub fn new>(provider: &P, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.logger_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &L { &self.0 } +} +impl Default for Logger { + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } +} +pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { + use opentelemetry::{Value, Array}; + use opentelemetry::logs::AnyValue; + match value { + Value::Bool(value) => value.into(), + Value::I64(value) => value.into(), + Value::F64(value) => value.into(), + Value::String(value) => value.into(), + Value::Array(array) => match array { + Array::Bool(values) => values.into_iter().collect::(), + Array::I64(values) => values.into_iter().collect::(), + Array::F64(values) => values.into_iter().collect::(), + Array::String(values) => values.into_iter().collect::(), + _ => AnyValue::String(array.to_string().into()), + }, + _ => AnyValue::String(value.to_string().into()), + } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/imported_typed/expected/meter.rs b/templates/code/rust/tests/imported_typed/expected/meter.rs new file mode 100644 index 0000000..176d064 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/expected/meter.rs @@ -0,0 +1,22 @@ +#[derive(Clone, Debug)] +pub struct Meter(opentelemetry::metrics::Meter); +impl Meter { + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.meter_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } +} +impl Default for Meter { + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/imported_typed/expected/mod.rs b/templates/code/rust/tests/imported_typed/expected/mod.rs new file mode 100644 index 0000000..014b203 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/expected/mod.rs @@ -0,0 +1,48 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/myapp/1.0.0"; + +pub mod myappattr { + + /// Unique identifier of the task. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskIdAttr(String); + + + #[allow(deprecated)] + impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } + } + +} + + +pub mod meter; +pub mod tracer; +pub mod logger; + +pub mod myappevent; + +pub mod myappmetric; + +pub mod myappspan; diff --git a/templates/code/rust/tests/imported_typed/expected/myappevent.rs b/templates/code/rust/tests/imported_typed/expected/myappevent.rs new file mode 100644 index 0000000..0f5e8d5 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/expected/myappevent.rs @@ -0,0 +1,42 @@ +#![allow(deprecated)] + + + +#[derive(Clone, Debug)] +pub enum TaskErroredOption { + Severity(::opentelemetry::logs::Severity), + Timestamp(::std::time::SystemTime), + + + ServerPort(i64), + +} +/// A task failed with an error. +pub fn r#emit_task_errored(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#error_type: upstream::errorattr::TypeAttr, options: impl IntoIterator) { + use ::opentelemetry::logs::LogRecord; + use ::opentelemetry::trace::TraceContextExt; + let _context_guard = context.clone().attach(); + let mut severity = ::opentelemetry::logs::Severity::Info; + let mut timestamp = None; + let mut attributes: Vec<::opentelemetry::KeyValue> = vec![r#error_type.key_value()]; + for option in options { + match option { + TaskErroredOption::Severity(value) => severity = value, + TaskErroredOption::Timestamp(value) => timestamp = Some(value), + + TaskErroredOption::ServerPort(value) => attributes.push(::opentelemetry::KeyValue::new("server.port", value)), + + } + } + if !logger.inner().event_enabled(severity, "", Some("myapp.task.errored")) { return; } + let mut record = logger.inner().create_log_record(); + record.set_event_name("myapp.task.errored"); + record.set_severity_number(severity); + record.set_observed_timestamp(::std::time::SystemTime::now()); + if let Some(timestamp) = timestamp { record.set_timestamp(timestamp); } + let span = context.span(); + let span_context = span.span_context(); + if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } + for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + logger.inner().emit(record); +} diff --git a/templates/code/rust/tests/imported_typed/expected/myappmetric.rs b/templates/code/rust/tests/imported_typed/expected/myappmetric.rs new file mode 100644 index 0000000..1d523e5 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/expected/myappmetric.rs @@ -0,0 +1,75 @@ +#![allow(deprecated)] + + + + + + + + +#[derive(Clone, Debug)] +pub enum TaskFailedCounterAttr { + + + ServerPort(i64), + +} +impl TaskFailedCounterAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), + + } + } +} + +/// Number of tasks that failed. +#[derive(Clone)] +pub struct TaskFailedCounter { instrument: ::opentelemetry::metrics::Counter } +impl TaskFailedCounter { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().u64_counter("myapp.task.failed") + .with_description("Number of tasks that failed.") + .with_unit("{task}") + + .build() } + } + pub fn add(&self, value: u64, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { + let mut attributes = vec![r#error_type.key_value(), r#myapp_task_id.key_value()]; + + attributes.extend(options.into_iter().map(TaskFailedCounterAttr::key_value)); + + self.instrument.add(value, &attributes); + } +} +impl Default for TaskFailedCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + +pub struct TaskFailedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl TaskFailedCounterObserver<'_> { + pub fn observe(&self, value: u64, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { + let mut attributes = vec![r#error_type.key_value(), r#myapp_task_id.key_value()]; + + attributes.extend(options.into_iter().map(TaskFailedCounterAttr::key_value)); + + self.observer.observe(value, &attributes); + } +} + +#[derive(Clone)] +pub struct TaskFailedObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +impl TaskFailedObservableCounter { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFailedCounterObserver<'_>) + Send + Sync + 'static) -> Self { + Self { _instrument: meter.inner().u64_observable_counter("myapp.task.failed") + .with_description("Number of tasks that failed.") + .with_unit("{task}") + .with_callback(move |observer| callback(TaskFailedCounterObserver { observer })) + .build() } + } +} +impl Default for TaskFailedObservableCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} diff --git a/templates/code/rust/tests/imported_typed/expected/myappspan.rs b/templates/code/rust/tests/imported_typed/expected/myappspan.rs new file mode 100644 index 0000000..0fbde75 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/expected/myappspan.rs @@ -0,0 +1,102 @@ +#![allow(deprecated)] + + + + + +#[derive(Clone, Debug)] +pub enum TaskDispatchStartAttr { + + + ServerPort(i64), + +} +impl TaskDispatchStartAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), + + } + } +} + + +#[derive(Clone, Debug)] +pub enum TaskDispatchAttr { + + ServerPort(i64), + +} +impl From for TaskDispatchStartAttr { + fn from(value: TaskDispatchAttr) -> Self { + match value { + + TaskDispatchAttr::ServerPort(value) => Self::ServerPort(value), + + } + } +} + + +/// Dispatch of a task. +pub struct TaskDispatchSpan { span: ::opentelemetry::global::BoxedSpan } +impl TaskDispatchSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { + use ::opentelemetry::trace::TraceContextExt; + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } + + pub fn set_attributes(&mut self, attributes: impl IntoIterator) { + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, TaskDispatchStartAttr::from(attribute).key_value()); } + } + +} +impl Default for TaskDispatchSpan { + fn default() -> Self { + use ::opentelemetry::trace::Tracer; + Self { span: super::tracer::Tracer::default().inner().start("myapp.task.dispatch") } + } +} + +pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) -> TaskDispatchSpan { + use ::opentelemetry::trace::Tracer; + + let mut name = String::new(); + + + + name.push_str("task "); + + + + + name.push_str(&r#myapp_task_id.clone().key_value().value.to_string()); + + + + + name.push_str(" failed with "); + + + + + name.push_str(&r#error_type.key_value().value.to_string()); + + + + let mut attributes = vec![r#error_type.key_value(), r#myapp_task_id.key_value()]; + + attributes.extend(options.into_iter().map(TaskDispatchStartAttr::key_value)); + + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Internal) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + TaskDispatchSpan { span } +} diff --git a/templates/code/rust/tests/imported_typed/expected/tracer.rs b/templates/code/rust/tests/imported_typed/expected/tracer.rs new file mode 100644 index 0000000..6580bf3 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/expected/tracer.rs @@ -0,0 +1,29 @@ +pub struct Tracer(opentelemetry::global::BoxedTracer); +impl Tracer { + pub fn new(provider: &P, scope: impl Into>) -> Self + where + P::Tracer: Send + Sync + 'static, + ::Span: Send + Sync + 'static, + { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self + where + P::Tracer: Send + Sync + 'static, + ::Span: Send + Sync + 'static, + { + Self(opentelemetry::global::BoxedTracer::new(Box::new(provider.tracer_with_scope(registry_scope(scope))))) + } + pub fn inner(&self) -> &opentelemetry::global::BoxedTracer { &self.0 } +} +impl Default for Tracer { + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/imported_typed/params.yaml b/templates/code/rust/tests/imported_typed/params.yaml new file mode 100644 index 0000000..960ae05 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/params.yaml @@ -0,0 +1,3 @@ +params: + imported_crate_paths: + error: upstream diff --git a/templates/code/rust/tests/imported_typed/registry/manifest.yaml b/templates/code/rust/tests/imported_typed/registry/manifest.yaml new file mode 100644 index 0000000..d1bbe08 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/registry/manifest.yaml @@ -0,0 +1,6 @@ +name: myapp +schema_url: https://example.com/schemas/myapp/1.0.0 +dependencies: + - name: upstream + registry_path: dependency + schema_url: https://example.com/schemas/upstream/1.0.0 diff --git a/templates/code/rust/tests/imported_typed/registry/model.yaml b/templates/code/rust/tests/imported_typed/registry/model.yaml new file mode 100644 index 0000000..b3c0f63 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/registry/model.yaml @@ -0,0 +1,48 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: stable + brief: Unique identifier of the task. + examples: ["task_0001"] +metrics: + - name: myapp.task.failed + instrument: counter + unit: "{task}" + stability: stable + brief: Number of tasks that failed. + annotations: + code_generation: + metric_value_type: int + attributes: + - ref: myapp.task.id + requirement_level: required + - ref: error.type + requirement_level: required + - ref: server.port + requirement_level: recommended +spans: + - type: myapp.task.dispatch + kind: internal + requirement_level: recommended + stability: stable + brief: Dispatch of a task. + name: + note: "`task {myapp.task.id} failed with {error.type}`" + attributes: + - ref: myapp.task.id + requirement_level: required + - ref: error.type + requirement_level: required + - ref: server.port + requirement_level: recommended +events: + - name: myapp.task.errored + requirement_level: recommended + stability: stable + brief: A task failed with an error. + attributes: + - ref: error.type + requirement_level: required + - ref: server.port + requirement_level: recommended diff --git a/templates/code/rust/tests/integer_boundaries/expected/mod.rs b/templates/code/rust/tests/integer_boundaries/expected/mod.rs new file mode 100644 index 0000000..0317e89 --- /dev/null +++ b/templates/code/rust/tests/integer_boundaries/expected/mod.rs @@ -0,0 +1,48 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/1.0.0"; + +pub mod demoattr { + + /// Synthetic integer limits. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum BoundaryAttr { + + /// Lowest signed 64-bit integer. + Minimum, + + /// Highest signed 64-bit integer. + Maximum, + + } + + + #[allow(deprecated)] + impl BoundaryAttr { + pub const KEY: &'static str = "demo.boundary"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: i64 = match self { + + Self::Minimum => -9223372036854775808, + + Self::Maximum => 9223372036854775807, + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: BoundaryAttr) -> Self { + value.key_value() + } + } + +} diff --git a/templates/code/rust/tests/integer_boundaries/registry/manifest.yaml b/templates/code/rust/tests/integer_boundaries/registry/manifest.yaml new file mode 100644 index 0000000..7e0695c --- /dev/null +++ b/templates/code/rust/tests/integer_boundaries/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: boundaries +schema_url: https://example.com/schemas/1.0.0 diff --git a/templates/code/rust/tests/integer_boundaries/registry/model.yaml b/templates/code/rust/tests/integer_boundaries/registry/model.yaml new file mode 100644 index 0000000..e434316 --- /dev/null +++ b/templates/code/rust/tests/integer_boundaries/registry/model.yaml @@ -0,0 +1,15 @@ +file_format: definition/2 +attributes: + - key: demo.boundary + stability: stable + brief: Synthetic integer limits. + type: + members: + - id: minimum + value: -9223372036854775808 + stability: stable + brief: Lowest signed 64-bit integer. + - id: maximum + value: 9223372036854775807 + stability: stable + brief: Highest signed 64-bit integer. diff --git a/templates/code/rust/tests/integer_boundaries/test.rs b/templates/code/rust/tests/integer_boundaries/test.rs new file mode 100644 index 0000000..f6e52b8 --- /dev/null +++ b/templates/code/rust/tests/integer_boundaries/test.rs @@ -0,0 +1,13 @@ +use generated_semconv::demoattr::BoundaryAttr; +use opentelemetry::Value; +#[test] +fn integer_enum_preserves_signed_64_bit_limits() { + assert_eq!( + BoundaryAttr::Minimum.key_value().value, + Value::I64(i64::MIN) + ); + assert_eq!( + BoundaryAttr::Maximum.key_value().value, + Value::I64(i64::MAX) + ); +} diff --git a/templates/code/rust/tests/literal_escaping/expected/demometric.rs b/templates/code/rust/tests/literal_escaping/expected/demometric.rs new file mode 100644 index 0000000..6f5c6c6 --- /dev/null +++ b/templates/code/rust/tests/literal_escaping/expected/demometric.rs @@ -0,0 +1,54 @@ +#![allow(deprecated)] + + + + + + + + +/// literal \b \f \u1234 +#[derive(Clone)] +pub struct LiteralCountCounter { instrument: ::opentelemetry::metrics::Counter } +impl LiteralCountCounter { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().u64_counter("demo.literal.count") + .with_description("literal \\b \\f \\u1234") + .with_unit("literal\\b\\u1234") + + .build() } + } + pub fn add(&self, value: u64, r#demo_literal: super::demoattr::LiteralAttr) { + let attributes = vec![r#demo_literal.key_value()]; + + self.instrument.add(value, &attributes); + } +} +impl Default for LiteralCountCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + +pub struct LiteralCountCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl LiteralCountCounterObserver<'_> { + pub fn observe(&self, value: u64, r#demo_literal: super::demoattr::LiteralAttr) { + let attributes = vec![r#demo_literal.key_value()]; + + self.observer.observe(value, &attributes); + } +} + +#[derive(Clone)] +pub struct LiteralCountObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +impl LiteralCountObservableCounter { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(LiteralCountCounterObserver<'_>) + Send + Sync + 'static) -> Self { + Self { _instrument: meter.inner().u64_observable_counter("demo.literal.count") + .with_description("literal \\b \\f \\u1234") + .with_unit("literal\\b\\u1234") + .with_callback(move |observer| callback(LiteralCountCounterObserver { observer })) + .build() } + } +} +impl Default for LiteralCountObservableCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} diff --git a/templates/code/rust/tests/literal_escaping/expected/meter.rs b/templates/code/rust/tests/literal_escaping/expected/meter.rs new file mode 100644 index 0000000..176d064 --- /dev/null +++ b/templates/code/rust/tests/literal_escaping/expected/meter.rs @@ -0,0 +1,22 @@ +#[derive(Clone, Debug)] +pub struct Meter(opentelemetry::metrics::Meter); +impl Meter { + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.meter_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } +} +impl Default for Meter { + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/literal_escaping/expected/mod.rs b/templates/code/rust/tests/literal_escaping/expected/mod.rs new file mode 100644 index 0000000..d4e797d --- /dev/null +++ b/templates/code/rust/tests/literal_escaping/expected/mod.rs @@ -0,0 +1,55 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/escaping/1.0.0"; + +pub mod demoattr { + + /// Literal escape sequences. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum LiteralAttr { + + /// Literal escape sequences. + Literal, + + /// Actual controls and escaped text. + Controls, + + } + + + #[allow(deprecated)] + impl LiteralAttr { + pub const KEY: &'static str = "demo.literal"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Literal => "backspace\\b formfeed\\f unicode\\u1234 doubled\\\\b tripled\\\\\\u0000".into(), + + Self::Controls => "backspace\u{0008} formfeed\u{000c} unicode\u{0001} slash\\b".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: LiteralAttr) -> Self { + value.key_value() + } + } + +} + + +pub mod meter; + + + +pub mod demometric; diff --git a/templates/code/rust/tests/literal_escaping/registry/manifest.yaml b/templates/code/rust/tests/literal_escaping/registry/manifest.yaml new file mode 100644 index 0000000..b77d792 --- /dev/null +++ b/templates/code/rust/tests/literal_escaping/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: escaping +schema_url: https://example.com/schemas/escaping/1.0.0 diff --git a/templates/code/rust/tests/literal_escaping/registry/model.yaml b/templates/code/rust/tests/literal_escaping/registry/model.yaml new file mode 100644 index 0000000..b30eb30 --- /dev/null +++ b/templates/code/rust/tests/literal_escaping/registry/model.yaml @@ -0,0 +1,28 @@ +file_format: definition/2 +attributes: + - key: demo.literal + stability: stable + brief: Literal escape sequences. + type: + members: + - id: literal + value: 'backspace\b formfeed\f unicode\u1234 doubled\\b tripled\\\u0000' + stability: stable + brief: Literal escape sequences. + - id: controls + value: "backspace\b formfeed\f unicode\u0001 slash\\b" + stability: stable + brief: Actual controls and escaped text. +metrics: + - name: demo.literal.count + instrument: counter + unit: 'literal\b\u1234' + stability: stable + requirement_level: recommended + brief: 'literal \b \f \u1234' + annotations: + code_generation: + metric_value_type: int + attributes: + - ref: demo.literal + requirement_level: required diff --git a/templates/code/rust/tests/literal_escaping/test.rs b/templates/code/rust/tests/literal_escaping/test.rs new file mode 100644 index 0000000..9d57b39 --- /dev/null +++ b/templates/code/rust/tests/literal_escaping/test.rs @@ -0,0 +1,30 @@ +use generated_semconv::demoattr::LiteralAttr; +use opentelemetry::Value; +#[test] +fn literal_backslashes_and_actual_control_characters_are_distinct() { + assert_eq!( + LiteralAttr::Literal.key_value().value, + Value::String(r"backspace\b formfeed\f unicode\u1234 doubled\\b tripled\\\u0000".into()) + ); + assert_eq!( + LiteralAttr::Controls.key_value().value, + Value::String("backspace\u{0008} formfeed\u{000c} unicode\u{0001} slash\\b".into()) + ); +} + +#[test] +fn signal_metadata_preserves_literal_backslash_sequences() { + use generated_semconv::{demometric::LiteralCountCounter, meter::Meter}; + use opentelemetry_sdk::metrics::{InMemoryMetricExporter, PeriodicReader, SdkMeterProvider}; + let exporter = InMemoryMetricExporter::default(); + let provider = SdkMeterProvider::builder() + .with_reader(PeriodicReader::builder(exporter.clone()).build()) + .build(); + LiteralCountCounter::new(&Meter::new(&provider, "escaping")).add(1, LiteralAttr::Literal); + provider.force_flush().unwrap(); + let exported = exporter.get_finished_metrics().unwrap(); + let scope = exported[0].scope_metrics().next().unwrap(); + let metric = scope.metrics().next().unwrap(); + assert_eq!(metric.description(), r"literal \b \f \u1234"); + assert_eq!(metric.unit(), r"literal\b\u1234"); +} diff --git a/templates/code/rust/tests/metrics/compile-fail/missing_required.expected-error.txt b/templates/code/rust/tests/metrics/compile-fail/missing_required.expected-error.txt new file mode 100644 index 0000000..2fb3720 --- /dev/null +++ b/templates/code/rust/tests/metrics/compile-fail/missing_required.expected-error.txt @@ -0,0 +1 @@ +this method takes 3 arguments but 2 arguments were supplied diff --git a/templates/code/rust/tests/metrics/compile-fail/missing_required.rs b/templates/code/rust/tests/metrics/compile-fail/missing_required.rs new file mode 100644 index 0000000..a9918a9 --- /dev/null +++ b/templates/code/rust/tests/metrics/compile-fail/missing_required.rs @@ -0,0 +1,5 @@ +use generated_semconv::{authattr, authmetric}; + +fn main() { + authmetric::AttemptsCounter::default().add(1, authattr::MethodAttr::Password); +} diff --git a/templates/code/rust/tests/metrics/compile-fail/signed_counter.expected-error.txt b/templates/code/rust/tests/metrics/compile-fail/signed_counter.expected-error.txt new file mode 100644 index 0000000..e79632e --- /dev/null +++ b/templates/code/rust/tests/metrics/compile-fail/signed_counter.expected-error.txt @@ -0,0 +1 @@ +expected `u64`, found `i64` diff --git a/templates/code/rust/tests/metrics/compile-fail/signed_counter.rs b/templates/code/rust/tests/metrics/compile-fail/signed_counter.rs new file mode 100644 index 0000000..6826e64 --- /dev/null +++ b/templates/code/rust/tests/metrics/compile-fail/signed_counter.rs @@ -0,0 +1,5 @@ +use generated_semconv::myappmetric; + +fn main() { + myappmetric::TaskStartedCounter::default().add(-1_i64, []); +} diff --git a/templates/code/rust/tests/metrics/compile-fail/unrelated_optional.expected-error.txt b/templates/code/rust/tests/metrics/compile-fail/unrelated_optional.expected-error.txt new file mode 100644 index 0000000..77b0d3f --- /dev/null +++ b/templates/code/rust/tests/metrics/compile-fail/unrelated_optional.expected-error.txt @@ -0,0 +1 @@ +named `Success` diff --git a/templates/code/rust/tests/metrics/compile-fail/unrelated_optional.rs b/templates/code/rust/tests/metrics/compile-fail/unrelated_optional.rs new file mode 100644 index 0000000..0ba50d3 --- /dev/null +++ b/templates/code/rust/tests/metrics/compile-fail/unrelated_optional.rs @@ -0,0 +1,5 @@ +use generated_semconv::{authattr, myappmetric}; + +fn main() { + let _ = myappmetric::TaskDurationHistogramAttr::Success(authattr::SuccessAttr::new(true)); +} diff --git a/templates/code/rust/tests/metrics/compile-fail/wrong_required_type.expected-error.txt b/templates/code/rust/tests/metrics/compile-fail/wrong_required_type.expected-error.txt new file mode 100644 index 0000000..f8fceb8 --- /dev/null +++ b/templates/code/rust/tests/metrics/compile-fail/wrong_required_type.expected-error.txt @@ -0,0 +1 @@ +expected `TaskIdAttr`, found `TaskStateAttr` diff --git a/templates/code/rust/tests/metrics/compile-fail/wrong_required_type.rs b/templates/code/rust/tests/metrics/compile-fail/wrong_required_type.rs new file mode 100644 index 0000000..dfcf2cd --- /dev/null +++ b/templates/code/rust/tests/metrics/compile-fail/wrong_required_type.rs @@ -0,0 +1,5 @@ +use generated_semconv::{myappattr, myappmetric}; + +fn main() { + myappmetric::TaskDurationHistogram::default().record(0.1, myappattr::TaskStateAttr::Done, []); +} diff --git a/templates/code/rust/tests/metrics/expected/authmetric.rs b/templates/code/rust/tests/metrics/expected/authmetric.rs new file mode 100644 index 0000000..21a3fc0 --- /dev/null +++ b/templates/code/rust/tests/metrics/expected/authmetric.rs @@ -0,0 +1,54 @@ +#![allow(deprecated)] + + + + + + + + +/// Number of authentication attempts. +#[derive(Clone)] +pub struct AttemptsCounter { instrument: ::opentelemetry::metrics::Counter } +impl AttemptsCounter { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().u64_counter("auth.attempts") + .with_description("Number of authentication attempts.") + .with_unit("{attempt}") + + .build() } + } + pub fn add(&self, value: u64, r#auth_method: super::authattr::MethodAttr, r#auth_success: super::authattr::SuccessAttr) { + let attributes = vec![r#auth_method.key_value(), r#auth_success.key_value()]; + + self.instrument.add(value, &attributes); + } +} +impl Default for AttemptsCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + +pub struct AttemptsCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl AttemptsCounterObserver<'_> { + pub fn observe(&self, value: u64, r#auth_method: super::authattr::MethodAttr, r#auth_success: super::authattr::SuccessAttr) { + let attributes = vec![r#auth_method.key_value(), r#auth_success.key_value()]; + + self.observer.observe(value, &attributes); + } +} + +#[derive(Clone)] +pub struct AttemptsObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +impl AttemptsObservableCounter { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(AttemptsCounterObserver<'_>) + Send + Sync + 'static) -> Self { + Self { _instrument: meter.inner().u64_observable_counter("auth.attempts") + .with_description("Number of authentication attempts.") + .with_unit("{attempt}") + .with_callback(move |observer| callback(AttemptsCounterObserver { observer })) + .build() } + } +} +impl Default for AttemptsObservableCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} diff --git a/templates/code/rust/tests/metrics/expected/meter.rs b/templates/code/rust/tests/metrics/expected/meter.rs new file mode 100644 index 0000000..176d064 --- /dev/null +++ b/templates/code/rust/tests/metrics/expected/meter.rs @@ -0,0 +1,22 @@ +#[derive(Clone, Debug)] +pub struct Meter(opentelemetry::metrics::Meter); +impl Meter { + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.meter_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } +} +impl Default for Meter { + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/metrics/expected/mod.rs b/templates/code/rust/tests/metrics/expected/mod.rs new file mode 100644 index 0000000..f013806 --- /dev/null +++ b/templates/code/rust/tests/metrics/expected/mod.rs @@ -0,0 +1,161 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/metrics/1.0.0"; + +pub mod authattr { + + /// How the user was authenticated. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum MethodAttr { + + /// A password was checked. + Password, + + /// A bearer token was checked. + Token, + + } + + + #[allow(deprecated)] + impl MethodAttr { + pub const KEY: &'static str = "auth.method"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Password => "password".into(), + + Self::Token => "token".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: MethodAttr) -> Self { + value.key_value() + } + } + + /// Whether the attempt succeeded. + #[derive(Debug, Clone, PartialEq)] + + pub struct SuccessAttr(bool); + + + #[allow(deprecated)] + impl SuccessAttr { + pub const KEY: &'static str = "auth.success"; + + pub fn new(value: bool) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: SuccessAttr) -> Self { + value.key_value() + } + } + +} + +pub mod myappattr { + + /// Unique identifier of the task. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskIdAttr(String); + + + #[allow(deprecated)] + impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } + } + + /// Current state of the task. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum TaskStateAttr { + + /// The task is waiting to run. + Queued, + + /// The task finished. + Done, + + } + + + #[allow(deprecated)] + impl TaskStateAttr { + pub const KEY: &'static str = "myapp.task.state"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Queued => "queued".into(), + + Self::Done => "done".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskStateAttr) -> Self { + value.key_value() + } + } + +} + + +pub mod meter; + + + +pub mod authmetric; + +pub mod myappmetric; + +pub mod workermetric; diff --git a/templates/code/rust/tests/metrics/expected/myappmetric.rs b/templates/code/rust/tests/metrics/expected/myappmetric.rs new file mode 100644 index 0000000..6eeaaca --- /dev/null +++ b/templates/code/rust/tests/metrics/expected/myappmetric.rs @@ -0,0 +1,479 @@ +#![allow(deprecated)] + + + + + + + + +/// Number of tasks waiting in the queue. +#[deprecated(note = "Replaced by `myapp.task.active`.")] +#[derive(Clone)] +pub struct QueueDepthGauge { instrument: ::opentelemetry::metrics::Gauge } +impl QueueDepthGauge { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().i64_gauge("myapp.queue.depth") + .with_description("Number of tasks waiting in the queue.") + .with_unit("{task}") + + .build() } + } + pub fn record(&self, value: i64) { + let attributes = vec![]; + + self.instrument.record(value, &attributes); + } +} +impl Default for QueueDepthGauge { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + +pub struct QueueDepthGaugeObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl QueueDepthGaugeObserver<'_> { + pub fn observe(&self, value: i64) { + let attributes = vec![]; + + self.observer.observe(value, &attributes); + } +} +#[deprecated(note = "Replaced by `myapp.task.active`.")] +#[derive(Clone)] +pub struct QueueDepthObservableGauge { _instrument: ::opentelemetry::metrics::ObservableGauge } +impl QueueDepthObservableGauge { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(QueueDepthGaugeObserver<'_>) + Send + Sync + 'static) -> Self { + Self { _instrument: meter.inner().i64_observable_gauge("myapp.queue.depth") + .with_description("Number of tasks waiting in the queue.") + .with_unit("{task}") + .with_callback(move |observer| callback(QueueDepthGaugeObserver { observer })) + .build() } + } +} +impl Default for QueueDepthObservableGauge { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} + + + + + + + + +/// Number of tasks currently running. +#[derive(Clone)] +pub struct TaskActiveUpDownCounter { instrument: ::opentelemetry::metrics::UpDownCounter } +impl TaskActiveUpDownCounter { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().i64_up_down_counter("myapp.task.active") + .with_description("Number of tasks currently running.") + .with_unit("{task}") + + .build() } + } + pub fn add(&self, value: i64, r#myapp_task_state: super::myappattr::TaskStateAttr) { + let attributes = vec![r#myapp_task_state.key_value()]; + + self.instrument.add(value, &attributes); + } +} +impl Default for TaskActiveUpDownCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + +pub struct TaskActiveUpDownCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl TaskActiveUpDownCounterObserver<'_> { + pub fn observe(&self, value: i64, r#myapp_task_state: super::myappattr::TaskStateAttr) { + let attributes = vec![r#myapp_task_state.key_value()]; + + self.observer.observe(value, &attributes); + } +} + +#[derive(Clone)] +pub struct TaskActiveObservableUpDownCounter { _instrument: ::opentelemetry::metrics::ObservableUpDownCounter } +impl TaskActiveObservableUpDownCounter { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskActiveUpDownCounterObserver<'_>) + Send + Sync + 'static) -> Self { + Self { _instrument: meter.inner().i64_observable_up_down_counter("myapp.task.active") + .with_description("Number of tasks currently running.") + .with_unit("{task}") + .with_callback(move |observer| callback(TaskActiveUpDownCounterObserver { observer })) + .build() } + } +} +impl Default for TaskActiveObservableUpDownCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} + + + + + + + + +#[derive(Clone, Debug)] +pub enum TaskDurationHistogramAttr { + +/// Opt-in: the convention records it only when a user asks for it. + Method(super::authattr::MethodAttr), + +/// Conditionally required: If the task reached a final state. + TaskState(super::myappattr::TaskStateAttr), + +} +impl TaskDurationHistogramAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::Method(value) => value.key_value(), + + Self::TaskState(value) => value.key_value(), + + } + } +} + +/// Time a task took from start to finish. +/// +/// Measured by the worker that ran the task. +#[derive(Clone)] +pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +impl TaskDurationHistogram { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_histogram("myapp.task.duration") + .with_description("Time a task took from start to finish.") + .with_unit("s") + + .with_boundaries(vec![0_f64, 0.005_f64, 0.01_f64, 0.1_f64, 1_f64, 10_f64]) + + .build() } + } + pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { + let mut attributes = vec![r#myapp_task_id.key_value()]; + + attributes.extend(options.into_iter().map(TaskDurationHistogramAttr::key_value)); + + self.instrument.record(value, &attributes); + } +} +impl Default for TaskDurationHistogram { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + + + + + + + +/// Fractional active task adjustment. +#[derive(Clone)] +pub struct TaskFloatActiveUpDownCounter { instrument: ::opentelemetry::metrics::UpDownCounter } +impl TaskFloatActiveUpDownCounter { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_up_down_counter("myapp.task.float.active") + .with_description("Fractional active task adjustment.") + .with_unit("{task}") + + .build() } + } + pub fn add(&self, value: f64) { + let attributes = vec![]; + + self.instrument.add(value, &attributes); + } +} +impl Default for TaskFloatActiveUpDownCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + +pub struct TaskFloatActiveUpDownCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl TaskFloatActiveUpDownCounterObserver<'_> { + pub fn observe(&self, value: f64) { + let attributes = vec![]; + + self.observer.observe(value, &attributes); + } +} + +#[derive(Clone)] +pub struct TaskFloatActiveObservableUpDownCounter { _instrument: ::opentelemetry::metrics::ObservableUpDownCounter } +impl TaskFloatActiveObservableUpDownCounter { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFloatActiveUpDownCounterObserver<'_>) + Send + Sync + 'static) -> Self { + Self { _instrument: meter.inner().f64_observable_up_down_counter("myapp.task.float.active") + .with_description("Fractional active task adjustment.") + .with_unit("{task}") + .with_callback(move |observer| callback(TaskFloatActiveUpDownCounterObserver { observer })) + .build() } + } +} +impl Default for TaskFloatActiveObservableUpDownCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} + + + + + + + + +/// Fractional queue depth. +#[derive(Clone)] +pub struct TaskFloatDepthGauge { instrument: ::opentelemetry::metrics::Gauge } +impl TaskFloatDepthGauge { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_gauge("myapp.task.float.depth") + .with_description("Fractional queue depth.") + .with_unit("{task}") + + .build() } + } + pub fn record(&self, value: f64) { + let attributes = vec![]; + + self.instrument.record(value, &attributes); + } +} +impl Default for TaskFloatDepthGauge { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + +pub struct TaskFloatDepthGaugeObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl TaskFloatDepthGaugeObserver<'_> { + pub fn observe(&self, value: f64) { + let attributes = vec![]; + + self.observer.observe(value, &attributes); + } +} + +#[derive(Clone)] +pub struct TaskFloatDepthObservableGauge { _instrument: ::opentelemetry::metrics::ObservableGauge } +impl TaskFloatDepthObservableGauge { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFloatDepthGaugeObserver<'_>) + Send + Sync + 'static) -> Self { + Self { _instrument: meter.inner().f64_observable_gauge("myapp.task.float.depth") + .with_description("Fractional queue depth.") + .with_unit("{task}") + .with_callback(move |observer| callback(TaskFloatDepthGaugeObserver { observer })) + .build() } + } +} +impl Default for TaskFloatDepthObservableGauge { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} + + + + + + + + +/// Fractional tasks started. +#[derive(Clone)] +pub struct TaskFloatStartedCounter { instrument: ::opentelemetry::metrics::Counter } +impl TaskFloatStartedCounter { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_counter("myapp.task.float.started") + .with_description("Fractional tasks started.") + .with_unit("{task}") + + .build() } + } + pub fn add(&self, value: f64) { + let attributes = vec![]; + + self.instrument.add(value, &attributes); + } +} +impl Default for TaskFloatStartedCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + +pub struct TaskFloatStartedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl TaskFloatStartedCounterObserver<'_> { + pub fn observe(&self, value: f64) { + let attributes = vec![]; + + self.observer.observe(value, &attributes); + } +} + +#[derive(Clone)] +pub struct TaskFloatStartedObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +impl TaskFloatStartedObservableCounter { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFloatStartedCounterObserver<'_>) + Send + Sync + 'static) -> Self { + Self { _instrument: meter.inner().f64_observable_counter("myapp.task.float.started") + .with_description("Fractional tasks started.") + .with_unit("{task}") + .with_callback(move |observer| callback(TaskFloatStartedCounterObserver { observer })) + .build() } + } +} +impl Default for TaskFloatStartedObservableCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} + + + + + + + + +/// Task payload size. +#[derive(Clone)] +pub struct TaskPayloadHistogram { instrument: ::opentelemetry::metrics::Histogram } +impl TaskPayloadHistogram { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().u64_histogram("myapp.task.payload") + .with_description("Task payload size.") + .with_unit("By") + + .with_boundaries(vec![128_f64, 256_f64, 1024_f64]) + + .build() } + } + pub fn record(&self, value: u64) { + let attributes = vec![]; + + self.instrument.record(value, &attributes); + } +} +impl Default for TaskPayloadHistogram { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + + + + + + + +#[derive(Clone, Debug)] +pub enum TaskRetryDurationHistogramAttr { + +/// Opt-in: the convention records it only when a user asks for it. + Method(super::authattr::MethodAttr), + +} +impl TaskRetryDurationHistogramAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::Method(value) => value.key_value(), + + } + } +} + +/// Time a retried task took from start to finish. +/// +/// Recorded only for tasks that ran more than once. +#[derive(Clone)] +pub struct TaskRetryDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +impl TaskRetryDurationHistogram { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_histogram("myapp.task.duration") + .with_description("Time a task took from start to finish.") + .with_unit("s") + + .with_boundaries(vec![0_f64, 0.005_f64, 0.01_f64, 0.1_f64, 1_f64, 10_f64]) + + .build() } + } + pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) { + let mut attributes = vec![r#myapp_task_id.key_value(), r#myapp_task_state.key_value()]; + + attributes.extend(options.into_iter().map(TaskRetryDurationHistogramAttr::key_value)); + + self.instrument.record(value, &attributes); + } +} +impl Default for TaskRetryDurationHistogram { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + + + + + + + +#[derive(Clone, Debug)] +pub enum TaskStartedCounterAttr { + +/// Recommended: When the scheduler assigned an id before the task started. + TaskId(super::myappattr::TaskIdAttr), + +} +impl TaskStartedCounterAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::TaskId(value) => value.key_value(), + + } + } +} + +/// Number of tasks started. +/// Opt-in: record only when the user requests it. +#[derive(Clone)] +pub struct TaskStartedCounter { instrument: ::opentelemetry::metrics::Counter } +impl TaskStartedCounter { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().u64_counter("myapp.task.started") + .with_description("Number of tasks started.") + .with_unit("{task}") + + .build() } + } + pub fn add(&self, value: u64, options: impl IntoIterator) { + let mut attributes = vec![]; + + attributes.extend(options.into_iter().map(TaskStartedCounterAttr::key_value)); + + self.instrument.add(value, &attributes); + } +} +impl Default for TaskStartedCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + +pub struct TaskStartedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl TaskStartedCounterObserver<'_> { + pub fn observe(&self, value: u64, options: impl IntoIterator) { + let mut attributes = vec![]; + + attributes.extend(options.into_iter().map(TaskStartedCounterAttr::key_value)); + + self.observer.observe(value, &attributes); + } +} + +#[derive(Clone)] +pub struct TaskStartedObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +impl TaskStartedObservableCounter { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskStartedCounterObserver<'_>) + Send + Sync + 'static) -> Self { + Self { _instrument: meter.inner().u64_observable_counter("myapp.task.started") + .with_description("Number of tasks started.") + .with_unit("{task}") + .with_callback(move |observer| callback(TaskStartedCounterObserver { observer })) + .build() } + } +} +impl Default for TaskStartedObservableCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} diff --git a/templates/code/rust/tests/metrics/expected/workermetric.rs b/templates/code/rust/tests/metrics/expected/workermetric.rs new file mode 100644 index 0000000..1f8a287 --- /dev/null +++ b/templates/code/rust/tests/metrics/expected/workermetric.rs @@ -0,0 +1,57 @@ +#![allow(deprecated)] + + + + + + + + +#[derive(Clone, Debug)] +pub enum TaskDurationHistogramAttr { + +/// Opt-in: the convention records it only when a user asks for it. + Method(super::authattr::MethodAttr), + +/// Conditionally required: If the task reached a final state. + TaskState(super::myappattr::TaskStateAttr), + +} +impl TaskDurationHistogramAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::Method(value) => value.key_value(), + + Self::TaskState(value) => value.key_value(), + + } + } +} + +/// Time a task took on the worker that ran it. +/// +/// Measured by the worker that ran the task. +#[derive(Clone)] +pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +impl TaskDurationHistogram { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_histogram("myapp.task.duration") + .with_description("Time a task took from start to finish.") + .with_unit("s") + + .with_boundaries(vec![0_f64, 0.005_f64, 0.01_f64, 0.1_f64, 1_f64, 10_f64]) + + .build() } + } + pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { + let mut attributes = vec![r#myapp_task_id.key_value()]; + + attributes.extend(options.into_iter().map(TaskDurationHistogramAttr::key_value)); + + self.instrument.record(value, &attributes); + } +} +impl Default for TaskDurationHistogram { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} diff --git a/templates/code/rust/tests/metrics/registry/manifest.yaml b/templates/code/rust/tests/metrics/registry/manifest.yaml new file mode 100644 index 0000000..6a5676e --- /dev/null +++ b/templates/code/rust/tests/metrics/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: metrics +schema_url: https://example.com/schemas/metrics/1.0.0 diff --git a/templates/code/rust/tests/metrics/registry/model.yaml b/templates/code/rust/tests/metrics/registry/model.yaml new file mode 100644 index 0000000..12a099b --- /dev/null +++ b/templates/code/rust/tests/metrics/registry/model.yaml @@ -0,0 +1,170 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: stable + brief: Unique identifier of the task. + examples: ["task_0001"] + - key: myapp.task.state + type: + members: + - id: queued + value: queued + stability: stable + brief: The task is waiting to run. + - id: done + value: done + stability: stable + brief: The task finished. + stability: stable + brief: Current state of the task. + - key: auth.method + type: + members: + - id: password + value: password + stability: stable + brief: A password was checked. + - id: token + value: token + stability: stable + brief: A bearer token was checked. + stability: stable + brief: How the user was authenticated. + - key: auth.success + type: boolean + stability: stable + brief: Whether the attempt succeeded. + examples: true +metrics: + - name: myapp.task.duration + requirement_level: recommended + instrument: histogram + unit: s + stability: stable + brief: Time a task took from start to finish. + note: Measured by the worker that ran the task. + annotations: + code_generation: + metric_value_type: double + aggregation: + method: explicithistogram + parameters: + boundaries: [0, 0.005, 0.01, 0.1, 1, 10] + attributes: + - ref: myapp.task.id + requirement_level: required + - ref: myapp.task.state + requirement_level: + conditionally_required: If the task reached a final state. + - ref: auth.method + requirement_level: opt_in + - name: myapp.task.started + requirement_level: opt_in + instrument: counter + unit: "{task}" + stability: stable + brief: Number of tasks started. + annotations: + code_generation: + metric_value_type: int + attributes: + - ref: myapp.task.id + requirement_level: + recommended: When the scheduler assigned an id before the task started. + - name: myapp.task.active + requirement_level: recommended + instrument: updowncounter + unit: "{task}" + stability: development + brief: Number of tasks currently running. + annotations: + code_generation: + metric_value_type: int + attributes: + - ref: myapp.task.state + requirement_level: required + - name: myapp.queue.depth + requirement_level: recommended + instrument: gauge + unit: "{task}" + stability: development + brief: Number of tasks waiting in the queue. + annotations: + code_generation: + metric_value_type: int + deprecated: + reason: renamed + renamed_to: myapp.task.active + - name: auth.attempts + requirement_level: recommended + instrument: counter + unit: "{attempt}" + stability: stable + brief: Number of authentication attempts. + annotations: + code_generation: + metric_value_type: int + attributes: + - ref: auth.method + requirement_level: required + - ref: auth.success + requirement_level: required + - name: myapp.task.float.started + requirement_level: recommended + instrument: counter + unit: "{task}" + stability: stable + brief: Fractional tasks started. + annotations: + code_generation: + metric_value_type: double + - name: myapp.task.float.active + requirement_level: recommended + instrument: updowncounter + unit: "{task}" + stability: stable + brief: Fractional active task adjustment. + annotations: + code_generation: + metric_value_type: double + - name: myapp.task.float.depth + requirement_level: recommended + instrument: gauge + unit: "{task}" + stability: stable + brief: Fractional queue depth. + annotations: + code_generation: + metric_value_type: double + - name: myapp.task.payload + requirement_level: recommended + instrument: histogram + unit: By + stability: stable + brief: Task payload size. + annotations: + code_generation: + metric_value_type: int + aggregation: + method: explicithistogram + parameters: + boundaries: [128, 256, 1024] +metric_refinements: + - id: myapp.task.retry.duration + ref: myapp.task.duration + stability: stable + brief: Time a retried task took from start to finish. + note: Recorded only for tasks that ran more than once. + attributes: + - ref: myapp.task.id + requirement_level: required + - ref: myapp.task.state + requirement_level: required + - id: worker.task.duration + ref: myapp.task.duration + stability: stable + brief: Time a task took on the worker that ran it. + attributes: + - ref: myapp.task.id + requirement_level: required diff --git a/templates/code/rust/tests/metrics/test.rs b/templates/code/rust/tests/metrics/test.rs new file mode 100644 index 0000000..3341631 --- /dev/null +++ b/templates/code/rust/tests/metrics/test.rs @@ -0,0 +1,326 @@ +use generated_semconv::{authattr, authmetric, meter, myappattr, myappmetric, workermetric}; +use opentelemetry::KeyValue; +use opentelemetry_sdk::metrics::data::{AggregatedMetrics, MetricData}; +use opentelemetry_sdk::metrics::{InMemoryMetricExporter, PeriodicReader, SdkMeterProvider}; +use std::time::Duration; + +fn provider() -> (SdkMeterProvider, InMemoryMetricExporter) { + let exporter = InMemoryMetricExporter::default(); + let provider = SdkMeterProvider::builder() + .with_reader( + PeriodicReader::builder(exporter.clone()) + .with_interval(Duration::from_secs(3600)) + .build(), + ) + .build(); + (provider, exporter) +} + +#[test] +#[allow(deprecated)] +fn synchronous_metrics_export_types_values_attributes_and_refinements() { + let (provider, exporter) = provider(); + let meter = meter::Meter::new_with_scope( + &provider, + opentelemetry::InstrumentationScope::builder("synthetic-worker") + .with_version("1.2.3") + .with_schema_url("https://example.com/other/1.0.0") + .with_attributes([opentelemetry::KeyValue::new("scope.kind", "worker")]) + .build(), + ); + myappmetric::TaskDurationHistogram::new(&meter).record( + 0.1, + myappattr::TaskIdAttr::new("base"), + [ + myappmetric::TaskDurationHistogramAttr::TaskState(myappattr::TaskStateAttr::Queued), + myappmetric::TaskDurationHistogramAttr::Method(authattr::MethodAttr::Password), + ], + ); + myappmetric::TaskRetryDurationHistogram::new(&meter).record( + 0.2, + myappattr::TaskIdAttr::new("retry"), + myappattr::TaskStateAttr::Done, + [myappmetric::TaskRetryDurationHistogramAttr::Method( + authattr::MethodAttr::Token, + )], + ); + workermetric::TaskDurationHistogram::new(&meter).record( + 0.3, + myappattr::TaskIdAttr::new("worker"), + [], + ); + myappmetric::TaskStartedCounter::new(&meter).add( + 7, + [myappmetric::TaskStartedCounterAttr::TaskId( + myappattr::TaskIdAttr::new("started"), + )], + ); + myappmetric::TaskActiveUpDownCounter::new(&meter).add(-2, myappattr::TaskStateAttr::Queued); + myappmetric::QueueDepthGauge::new(&meter).record(5); + authmetric::AttemptsCounter::new(&meter).add( + 3, + authattr::MethodAttr::Password, + authattr::SuccessAttr::new(true), + ); + + provider.force_flush().unwrap(); + let exported = exporter.get_finished_metrics().unwrap(); + let scope = exported[0].scope_metrics().next().unwrap(); + assert_eq!(scope.scope().version(), Some("1.2.3")); + assert!(scope + .scope() + .attributes() + .any(|attribute| attribute.key.as_str() == "scope.kind" + && attribute.value.as_str() == "worker")); + assert_eq!(scope.scope().name(), "synthetic-worker"); + assert_eq!( + scope.scope().schema_url(), + Some(generated_semconv::SCHEMA_URL) + ); + let find = |name: &str| { + scope + .metrics() + .find(|metric| metric.name() == name) + .unwrap() + }; + + let duration = find("myapp.task.duration"); + assert_eq!( + duration.description(), + "Time a task took from start to finish." + ); + assert_eq!(duration.unit(), "s"); + let AggregatedMetrics::F64(MetricData::Histogram(histogram)) = duration.data() else { + panic!("duration must be an f64 histogram"); + }; + assert_eq!(histogram.data_points().count(), 3); + for (id, value, expected_attrs) in [ + ( + "base", + 0.1, + vec![ + KeyValue::new("myapp.task.id", "base"), + KeyValue::new("myapp.task.state", "queued"), + KeyValue::new("auth.method", "password"), + ], + ), + ( + "retry", + 0.2, + vec![ + KeyValue::new("myapp.task.id", "retry"), + KeyValue::new("myapp.task.state", "done"), + KeyValue::new("auth.method", "token"), + ], + ), + ( + "worker", + 0.3, + vec![KeyValue::new("myapp.task.id", "worker")], + ), + ] { + let point = histogram + .data_points() + .find(|point| { + point + .attributes() + .any(|attr| *attr == KeyValue::new("myapp.task.id", id)) + }) + .unwrap(); + assert_eq!(point.count(), 1); + assert_eq!(point.sum(), value); + assert_eq!( + point.bounds().collect::>(), + [0.0, 0.005, 0.01, 0.1, 1.0, 10.0] + ); + assert_eq!(point.attributes().count(), expected_attrs.len()); + for expected in expected_attrs { + assert!(point.attributes().any(|actual| *actual == expected)); + } + } + + let started = find("myapp.task.started"); + assert_eq!(started.unit(), "{task}"); + let AggregatedMetrics::U64(MetricData::Sum(sum)) = started.data() else { + panic!("counter must be an unsigned sum"); + }; + let point = sum.data_points().next().unwrap(); + assert_eq!(point.value(), 7); + assert_eq!( + point.attributes().collect::>(), + [&KeyValue::new("myapp.task.id", "started")] + ); + + let AggregatedMetrics::I64(MetricData::Sum(sum)) = find("myapp.task.active").data() else { + panic!("up-down counter must preserve signed values"); + }; + let point = sum.data_points().next().unwrap(); + assert_eq!(point.value(), -2); + assert_eq!( + point.attributes().collect::>(), + [&KeyValue::new("myapp.task.state", "queued")] + ); + + let AggregatedMetrics::I64(MetricData::Gauge(gauge)) = find("myapp.queue.depth").data() else { + panic!("queue depth must be a signed gauge"); + }; + let point = gauge.data_points().next().unwrap(); + assert_eq!(point.value(), 5); + assert_eq!(point.attributes().count(), 0); + + let attempts = find("auth.attempts"); + assert_eq!(attempts.unit(), "{attempt}"); + let AggregatedMetrics::U64(MetricData::Sum(sum)) = attempts.data() else { + panic!("attempts must be an unsigned sum"); + }; + let point = sum.data_points().next().unwrap(); + assert_eq!(point.value(), 3); + assert!(point + .attributes() + .any(|attr| *attr == KeyValue::new("auth.method", "password"))); + assert!(point + .attributes() + .any(|attr| *attr == KeyValue::new("auth.success", true))); + provider.shutdown().unwrap(); +} + +#[test] +#[allow(deprecated)] +fn observable_callbacks_export_values_and_typed_attributes() { + let (provider, exporter) = provider(); + let meter = meter::Meter::new(&provider, "synthetic-observer"); + let _started = myappmetric::TaskStartedObservableCounter::new(&meter, |observer| { + observer.observe( + 11, + [myappmetric::TaskStartedCounterAttr::TaskId( + myappattr::TaskIdAttr::new("observed"), + )], + ); + }); + let _active = myappmetric::TaskActiveObservableUpDownCounter::new(&meter, |observer| { + observer.observe(-4, myappattr::TaskStateAttr::Queued); + }); + let _depth = myappmetric::QueueDepthObservableGauge::new(&meter, |observer| { + observer.observe(9); + }); + let _attempts = authmetric::AttemptsObservableCounter::new(&meter, |observer| { + observer.observe( + 13, + authattr::MethodAttr::Token, + authattr::SuccessAttr::new(false), + ); + }); + provider.force_flush().unwrap(); + let exported = exporter.get_finished_metrics().unwrap(); + let scope = exported[0].scope_metrics().next().unwrap(); + assert_eq!( + scope.scope().schema_url(), + Some(generated_semconv::SCHEMA_URL) + ); + let find = |name: &str| { + scope + .metrics() + .find(|metric| metric.name() == name) + .unwrap() + }; + let AggregatedMetrics::U64(MetricData::Sum(started)) = find("myapp.task.started").data() else { + panic!("observable counter must export an unsigned sum"); + }; + let point = started.data_points().next().unwrap(); + assert_eq!(point.value(), 11); + assert!(point + .attributes() + .any(|attr| *attr == KeyValue::new("myapp.task.id", "observed"))); + let AggregatedMetrics::I64(MetricData::Sum(active)) = find("myapp.task.active").data() else { + panic!("observable up-down counter must preserve signed values"); + }; + assert_eq!(active.data_points().next().unwrap().value(), -4); + let AggregatedMetrics::I64(MetricData::Gauge(depth)) = find("myapp.queue.depth").data() else { + panic!("observable gauge must export a gauge"); + }; + assert_eq!(depth.data_points().next().unwrap().value(), 9); + let AggregatedMetrics::U64(MetricData::Sum(attempts)) = find("auth.attempts").data() else { + panic!("observable counter must export an unsigned sum"); + }; + let point = attempts.data_points().next().unwrap(); + assert_eq!(point.value(), 13); + assert!(point + .attributes() + .any(|attr| *attr == KeyValue::new("auth.method", "token"))); + assert!(point + .attributes() + .any(|attr| *attr == KeyValue::new("auth.success", false))); + provider.shutdown().unwrap(); +} + +#[test] +fn alternate_numeric_types_export_sync_and_observable_measurements() { + let (provider, exporter) = provider(); + let sync_meter = meter::Meter::new(&provider, "synthetic-float-sync"); + myappmetric::TaskFloatStartedCounter::new(&sync_meter).add(0.5); + myappmetric::TaskFloatActiveUpDownCounter::new(&sync_meter).add(-1.25); + myappmetric::TaskFloatDepthGauge::new(&sync_meter).record(2.5); + myappmetric::TaskPayloadHistogram::new(&sync_meter).record(512); + let async_meter = meter::Meter::new(&provider, "synthetic-float-async"); + let _started = myappmetric::TaskFloatStartedObservableCounter::new(&async_meter, |observer| { + observer.observe(0.75); + }); + let _active = + myappmetric::TaskFloatActiveObservableUpDownCounter::new(&async_meter, |observer| { + observer.observe(-2.5); + }); + let _depth = myappmetric::TaskFloatDepthObservableGauge::new(&async_meter, |observer| { + observer.observe(3.75); + }); + provider.force_flush().unwrap(); + let exported = exporter.get_finished_metrics().unwrap(); + for (name, started_value, active_value, depth_value) in [ + ("synthetic-float-sync", 0.5, -1.25, 2.5), + ("synthetic-float-async", 0.75, -2.5, 3.75), + ] { + let scope = exported[0] + .scope_metrics() + .find(|scope| scope.scope().name() == name) + .unwrap(); + assert_eq!( + scope.scope().schema_url(), + Some(generated_semconv::SCHEMA_URL) + ); + let find = |metric_name: &str| { + scope + .metrics() + .find(|metric| metric.name() == metric_name) + .unwrap() + }; + let AggregatedMetrics::F64(MetricData::Sum(started)) = + find("myapp.task.float.started").data() + else { + panic!("double counter must export a floating sum"); + }; + assert_eq!(started.data_points().next().unwrap().value(), started_value); + let AggregatedMetrics::F64(MetricData::Sum(active)) = + find("myapp.task.float.active").data() + else { + panic!("double up-down counter must export a floating sum"); + }; + assert_eq!(active.data_points().next().unwrap().value(), active_value); + let AggregatedMetrics::F64(MetricData::Gauge(depth)) = + find("myapp.task.float.depth").data() + else { + panic!("double gauge must export a floating gauge"); + }; + assert_eq!(depth.data_points().next().unwrap().value(), depth_value); + if name == "synthetic-float-sync" { + let payload = find("myapp.task.payload"); + assert_eq!(payload.unit(), "By"); + let AggregatedMetrics::U64(MetricData::Histogram(histogram)) = payload.data() else { + panic!("integer histogram must preserve unsigned measurements"); + }; + let point = histogram.data_points().next().unwrap(); + assert_eq!(point.count(), 1); + assert_eq!(point.sum(), 512); + assert_eq!(point.bounds().collect::>(), [128.0, 256.0, 1024.0]); + } + } + provider.shutdown().unwrap(); +} diff --git a/templates/code/rust/tests/naming/expected/capsmetric.rs b/templates/code/rust/tests/naming/expected/capsmetric.rs new file mode 100644 index 0000000..35b461e --- /dev/null +++ b/templates/code/rust/tests/naming/expected/capsmetric.rs @@ -0,0 +1,54 @@ +#![allow(deprecated)] + + + + + + + + +/// Synthetic count. +#[derive(Clone)] +pub struct Http2STATUSCountCounter { instrument: ::opentelemetry::metrics::Counter } +impl Http2STATUSCountCounter { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().u64_counter("caps.http2_STATUS.count") + .with_description("Synthetic count.") + .with_unit("{item}") + + .build() } + } + pub fn add(&self, value: u64, r#caps_http2_status_api_id: super::capsattr::Http2STATUSApiIDAttr, r#caps_mode2_state: super::capsattr::Mode2STATEAttr) { + let attributes = vec![r#caps_http2_status_api_id.key_value(), r#caps_mode2_state.key_value()]; + + self.instrument.add(value, &attributes); + } +} +impl Default for Http2STATUSCountCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} + + +pub struct Http2STATUSCountCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl Http2STATUSCountCounterObserver<'_> { + pub fn observe(&self, value: u64, r#caps_http2_status_api_id: super::capsattr::Http2STATUSApiIDAttr, r#caps_mode2_state: super::capsattr::Mode2STATEAttr) { + let attributes = vec![r#caps_http2_status_api_id.key_value(), r#caps_mode2_state.key_value()]; + + self.observer.observe(value, &attributes); + } +} + +#[derive(Clone)] +pub struct Http2STATUSCountObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +impl Http2STATUSCountObservableCounter { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(Http2STATUSCountCounterObserver<'_>) + Send + Sync + 'static) -> Self { + Self { _instrument: meter.inner().u64_observable_counter("caps.http2_STATUS.count") + .with_description("Synthetic count.") + .with_unit("{item}") + .with_callback(move |observer| callback(Http2STATUSCountCounterObserver { observer })) + .build() } + } +} +impl Default for Http2STATUSCountObservableCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} diff --git a/templates/code/rust/tests/naming/expected/meter.rs b/templates/code/rust/tests/naming/expected/meter.rs new file mode 100644 index 0000000..176d064 --- /dev/null +++ b/templates/code/rust/tests/naming/expected/meter.rs @@ -0,0 +1,22 @@ +#[derive(Clone, Debug)] +pub struct Meter(opentelemetry::metrics::Meter); +impl Meter { + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.meter_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } +} +impl Default for Meter { + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/naming/expected/mod.rs b/templates/code/rust/tests/naming/expected/mod.rs new file mode 100644 index 0000000..168f015 --- /dev/null +++ b/templates/code/rust/tests/naming/expected/mod.rs @@ -0,0 +1,79 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/naming/1.0.0"; + +pub mod capsattr { + + /// Synthetic identifier. + #[derive(Debug, Clone, PartialEq)] + + pub struct Http2STATUSApiIDAttr(String); + + + #[allow(deprecated)] + impl Http2STATUSApiIDAttr { + pub const KEY: &'static str = "caps.http2_STATUS.api_ID"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: Http2STATUSApiIDAttr) -> Self { + value.key_value() + } + } + + /// Synthetic mode. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum Mode2STATEAttr { + + /// Synthetic state. + HTTP2ReadySTATE, + + } + + + #[allow(deprecated)] + impl Mode2STATEAttr { + pub const KEY: &'static str = "caps.mode2_STATE"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::HTTP2ReadySTATE => "ready".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: Mode2STATEAttr) -> Self { + value.key_value() + } + } + +} + + +pub mod meter; + + + +pub mod capsmetric; diff --git a/templates/code/rust/tests/naming/registry/manifest.yaml b/templates/code/rust/tests/naming/registry/manifest.yaml new file mode 100644 index 0000000..b9a8901 --- /dev/null +++ b/templates/code/rust/tests/naming/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: naming +schema_url: https://example.com/schemas/naming/1.0.0 diff --git a/templates/code/rust/tests/naming/registry/model.yaml b/templates/code/rust/tests/naming/registry/model.yaml new file mode 100644 index 0000000..6824a23 --- /dev/null +++ b/templates/code/rust/tests/naming/registry/model.yaml @@ -0,0 +1,30 @@ +file_format: definition/2 +attributes: + - key: caps.http2_STATUS.api_ID + type: string + stability: stable + brief: Synthetic identifier. + - key: caps.mode2_STATE + type: + members: + - id: HTTP2_ready_STATE + value: ready + stability: stable + brief: Synthetic state. + stability: stable + brief: Synthetic mode. +metrics: + - name: caps.http2_STATUS.count + instrument: counter + unit: "{item}" + requirement_level: recommended + stability: stable + brief: Synthetic count. + annotations: + code_generation: + metric_value_type: int + attributes: + - ref: caps.http2_STATUS.api_ID + requirement_level: required + - ref: caps.mode2_STATE + requirement_level: required diff --git a/templates/code/rust/tests/naming/test.rs b/templates/code/rust/tests/naming/test.rs new file mode 100644 index 0000000..002ca7e --- /dev/null +++ b/templates/code/rust/tests/naming/test.rs @@ -0,0 +1,15 @@ +#![allow(non_camel_case_types, non_snake_case)] +use generated_semconv::{capsattr, capsmetric, meter}; +use opentelemetry::KeyValue; + +#[test] +fn names_preserve_capitalization_and_digits_in_attributes_and_signals() { + let identifier = capsattr::Http2STATUSApiIDAttr::new("value"); + assert_eq!( + identifier.clone().key_value(), + KeyValue::new("caps.http2_STATUS.api_ID", "value") + ); + let mode = capsattr::Mode2STATEAttr::HTTP2ReadySTATE; + let metric = capsmetric::Http2STATUSCountCounter::new(&meter::Meter::default()); + metric.add(1, identifier, mode); +} diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs new file mode 100644 index 0000000..3437543 --- /dev/null +++ b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs @@ -0,0 +1,42 @@ +#![allow(deprecated)] + + + +#[derive(Clone, Debug)] +pub enum Option { + Severity(::opentelemetry::logs::Severity), + Timestamp(::std::time::SystemTime), + + + Message(super::exceptionattr::MessageAttr), + +} +/// A noteworthy exception occurred. +pub fn r#emit_(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#exception_type: super::exceptionattr::TypeAttr, options: impl IntoIterator) { + use ::opentelemetry::logs::LogRecord; + use ::opentelemetry::trace::TraceContextExt; + let _context_guard = context.clone().attach(); + let mut severity = ::opentelemetry::logs::Severity::Info; + let mut timestamp = None; + let mut attributes: Vec<::opentelemetry::KeyValue> = vec![r#exception_type.key_value()]; + for option in options { + match option { + Option::Severity(value) => severity = value, + Option::Timestamp(value) => timestamp = Some(value), + + Option::Message(value) => attributes.push(value.key_value()), + + } + } + if !logger.inner().event_enabled(severity, "", Some("exception")) { return; } + let mut record = logger.inner().create_log_record(); + record.set_event_name("exception"); + record.set_severity_number(severity); + record.set_observed_timestamp(::std::time::SystemTime::now()); + if let Some(timestamp) = timestamp { record.set_timestamp(timestamp); } + let span = context.span(); + let span_context = span.span_context(); + if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } + for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + logger.inner().emit(record); +} diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs new file mode 100644 index 0000000..dbe6b1e --- /dev/null +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs @@ -0,0 +1,87 @@ +#![allow(deprecated)] + + + + + +#[derive(Clone, Debug)] +pub enum StartAttr { + + + Source(super::heartbeatattr::SourceAttr), + +} +impl StartAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::Source(value) => value.key_value(), + + } + } +} + + +#[derive(Clone, Debug)] +pub enum Attr { + + Source(super::heartbeatattr::SourceAttr), + +} +impl From for StartAttr { + fn from(value: Attr) -> Self { + match value { + + Attr::Source(value) => Self::Source(value), + + } + } +} + + +#[derive(Clone, Debug, Default)] +pub struct Name(String); +impl Name { + pub fn new(value: impl Into) -> Self { Self(value.into()) } +} + +/// A periodic liveness signal. +pub struct Span { span: ::opentelemetry::global::BoxedSpan } +impl Span { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { + use ::opentelemetry::trace::TraceContextExt; + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } + + pub fn set_attributes(&mut self, attributes: impl IntoIterator) { + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, StartAttr::from(attribute).key_value()); } + } + +} +impl Default for Span { + fn default() -> Self { + use ::opentelemetry::trace::Tracer; + Self { span: super::tracer::Tracer::default().inner().start("heartbeat") } + } +} + +pub fn r#start_(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: Name, r#heartbeat_sequence: super::heartbeatattr::SequenceAttr, options: impl IntoIterator) -> Span { + use ::opentelemetry::trace::Tracer; + + let name = if name.0.is_empty() { "heartbeat".to_owned() } else { name.0 }; + + let mut attributes = vec![r#heartbeat_sequence.key_value()]; + + attributes.extend(options.into_iter().map(StartAttr::key_value)); + + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Internal) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + Span { span } +} diff --git a/templates/code/rust/tests/no_namespace/expected/hostentity.rs b/templates/code/rust/tests/no_namespace/expected/hostentity.rs new file mode 100644 index 0000000..668852f --- /dev/null +++ b/templates/code/rust/tests/no_namespace/expected/hostentity.rs @@ -0,0 +1,51 @@ +// Code generated by weaver. DO NOT EDIT. +#![allow(deprecated)] + + +#[derive(Clone, Debug)] +pub enum EntityAttr { + + + Name(super::hostattr::NameAttr), + +} + +impl EntityAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::Name(value) => value.key_value(), + + } + } +} + +/// A physical or virtual machine. +/// Identifies the entity: `host.id`. +/// Describes the entity: `host.name`. +#[derive(Clone, Debug, Default)] +pub struct Entity { + attributes: Vec<::opentelemetry::KeyValue>, +} + +impl Entity { + pub fn new(r#host_id: super::hostattr::IdAttr, options: impl IntoIterator) -> Self { + let mut attributes = vec![ + + r#host_id.key_value(), + + ]; + attributes.extend(options.into_iter().map(EntityAttr::key_value)); + Self { attributes } + } + + pub fn attributes(&self) -> Vec<::opentelemetry::KeyValue> { + self.attributes.clone() + } + + pub fn resource(&self) -> ::opentelemetry_sdk::Resource { + ::opentelemetry_sdk::Resource::builder_empty() + .with_schema_url(self.attributes(), super::SCHEMA_URL) + .build() + } +} diff --git a/templates/code/rust/tests/no_namespace/expected/logger.rs b/templates/code/rust/tests/no_namespace/expected/logger.rs new file mode 100644 index 0000000..c7a2373 --- /dev/null +++ b/templates/code/rust/tests/no_namespace/expected/logger.rs @@ -0,0 +1,40 @@ +#[derive(Clone, Debug)] +pub struct Logger::Logger>(L); +impl Logger { + pub fn new>(provider: &P, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.logger_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &L { &self.0 } +} +impl Default for Logger { + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } +} +pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { + use opentelemetry::{Value, Array}; + use opentelemetry::logs::AnyValue; + match value { + Value::Bool(value) => value.into(), + Value::I64(value) => value.into(), + Value::F64(value) => value.into(), + Value::String(value) => value.into(), + Value::Array(array) => match array { + Array::Bool(values) => values.into_iter().collect::(), + Array::I64(values) => values.into_iter().collect::(), + Array::F64(values) => values.into_iter().collect::(), + Array::String(values) => values.into_iter().collect::(), + _ => AnyValue::String(array.to_string().into()), + }, + _ => AnyValue::String(value.to_string().into()), + } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/no_namespace/expected/mod.rs b/templates/code/rust/tests/no_namespace/expected/mod.rs new file mode 100644 index 0000000..368c549 --- /dev/null +++ b/templates/code/rust/tests/no_namespace/expected/mod.rs @@ -0,0 +1,201 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/no_namespace/1.0.0"; + +pub mod exceptionattr { + + /// The exception message. + #[derive(Debug, Clone, PartialEq)] + + pub struct MessageAttr(String); + + + #[allow(deprecated)] + impl MessageAttr { + pub const KEY: &'static str = "exception.message"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: MessageAttr) -> Self { + value.key_value() + } + } + + /// The type of the exception. + #[derive(Debug, Clone, PartialEq)] + + pub struct TypeAttr(String); + + + #[allow(deprecated)] + impl TypeAttr { + pub const KEY: &'static str = "exception.type"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TypeAttr) -> Self { + value.key_value() + } + } + +} + +pub mod heartbeatattr { + + /// Sequence number of the heartbeat. + #[derive(Debug, Clone, PartialEq)] + + pub struct SequenceAttr(i64); + + + #[allow(deprecated)] + impl SequenceAttr { + pub const KEY: &'static str = "heartbeat.sequence"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: SequenceAttr) -> Self { + value.key_value() + } + } + + /// Name of the component that sent the heartbeat. + #[derive(Debug, Clone, PartialEq)] + + pub struct SourceAttr(String); + + + #[allow(deprecated)] + impl SourceAttr { + pub const KEY: &'static str = "heartbeat.source"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: SourceAttr) -> Self { + value.key_value() + } + } + +} + +pub mod hostattr { + + /// Unique identifier of the host. + #[derive(Debug, Clone, PartialEq)] + + pub struct IdAttr(String); + + + #[allow(deprecated)] + impl IdAttr { + pub const KEY: &'static str = "host.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: IdAttr) -> Self { + value.key_value() + } + } + + /// Name of the host. + #[derive(Debug, Clone, PartialEq)] + + pub struct NameAttr(String); + + + #[allow(deprecated)] + impl NameAttr { + pub const KEY: &'static str = "host.name"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: NameAttr) -> Self { + value.key_value() + } + } + +} + + + +pub mod tracer; +pub mod logger; + +pub mod exceptionevent; + +pub mod heartbeatspan; + +pub mod hostentity; diff --git a/templates/code/rust/tests/no_namespace/expected/tracer.rs b/templates/code/rust/tests/no_namespace/expected/tracer.rs new file mode 100644 index 0000000..6580bf3 --- /dev/null +++ b/templates/code/rust/tests/no_namespace/expected/tracer.rs @@ -0,0 +1,29 @@ +pub struct Tracer(opentelemetry::global::BoxedTracer); +impl Tracer { + pub fn new(provider: &P, scope: impl Into>) -> Self + where + P::Tracer: Send + Sync + 'static, + ::Span: Send + Sync + 'static, + { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self + where + P::Tracer: Send + Sync + 'static, + ::Span: Send + Sync + 'static, + { + Self(opentelemetry::global::BoxedTracer::new(Box::new(provider.tracer_with_scope(registry_scope(scope))))) + } + pub fn inner(&self) -> &opentelemetry::global::BoxedTracer { &self.0 } +} +impl Default for Tracer { + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/no_namespace/registry/manifest.yaml b/templates/code/rust/tests/no_namespace/registry/manifest.yaml new file mode 100644 index 0000000..af4761c --- /dev/null +++ b/templates/code/rust/tests/no_namespace/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: no_namespace +schema_url: https://example.com/schemas/no_namespace/1.0.0 diff --git a/templates/code/rust/tests/no_namespace/registry/model.yaml b/templates/code/rust/tests/no_namespace/registry/model.yaml new file mode 100644 index 0000000..d9cc883 --- /dev/null +++ b/templates/code/rust/tests/no_namespace/registry/model.yaml @@ -0,0 +1,65 @@ +file_format: definition/2 +attributes: + - key: exception.type + type: string + stability: stable + brief: The type of the exception. + examples: ["ValueError"] + - key: exception.message + type: string + stability: stable + brief: The exception message. + examples: ["division by zero"] + - key: heartbeat.sequence + type: int + stability: stable + brief: Sequence number of the heartbeat. + examples: 1 + - key: heartbeat.source + type: string + stability: stable + brief: Name of the component that sent the heartbeat. + examples: ["worker-1"] + - key: host.id + type: string + stability: stable + brief: Unique identifier of the host. + examples: ["h-1"] + - key: host.name + type: string + stability: stable + brief: Name of the host. + examples: ["worker-1"] +entities: + - type: host + requirement_level: recommended + stability: stable + brief: A physical or virtual machine. + identity: + - ref: host.id + requirement_level: required + description: + - ref: host.name +events: + - name: exception + requirement_level: recommended + stability: stable + brief: A noteworthy exception occurred. + attributes: + - ref: exception.type + requirement_level: required + - ref: exception.message + requirement_level: recommended +spans: + - type: heartbeat + kind: internal + requirement_level: recommended + stability: stable + brief: A periodic liveness signal. + name: + note: "`heartbeat`" + attributes: + - ref: heartbeat.sequence + requirement_level: required + - ref: heartbeat.source + requirement_level: recommended diff --git a/templates/code/rust/tests/params/expected/billingmetric.rs b/templates/code/rust/tests/params/expected/billingmetric.rs new file mode 100644 index 0000000..2b0f812 --- /dev/null +++ b/templates/code/rust/tests/params/expected/billingmetric.rs @@ -0,0 +1,53 @@ +#![allow(deprecated)] + + + + + + + + +#[derive(Clone, Debug)] +pub enum InvoiceAmountHistogramAttr { + + + Currency(super::billingattr::CurrencyAttr), + + + RequestUrl(super::myappattr::RequestUrlAttr), + +} +impl InvoiceAmountHistogramAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::Currency(value) => value.key_value(), + + Self::RequestUrl(value) => value.key_value(), + + } + } +} + +/// Amount of each issued invoice. +#[derive(Clone)] +pub struct InvoiceAmountHistogram { instrument: ::opentelemetry::metrics::Histogram } +impl InvoiceAmountHistogram { + pub fn new(meter: &super::meter::Meter) -> Self { + Self { instrument: meter.inner().f64_histogram("acme.billing.invoice.amount") + .with_description("Amount of each issued invoice.") + .with_unit("{currency_unit}") + + .build() } + } + pub fn record(&self, value: f64, r#billing_invoice_id: super::billingattr::InvoiceIdAttr, options: impl IntoIterator) { + let mut attributes = vec![r#billing_invoice_id.key_value()]; + + attributes.extend(options.into_iter().map(InvoiceAmountHistogramAttr::key_value)); + + self.instrument.record(value, &attributes); + } +} +impl Default for InvoiceAmountHistogram { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} diff --git a/templates/code/rust/tests/params/expected/meter.rs b/templates/code/rust/tests/params/expected/meter.rs new file mode 100644 index 0000000..176d064 --- /dev/null +++ b/templates/code/rust/tests/params/expected/meter.rs @@ -0,0 +1,22 @@ +#[derive(Clone, Debug)] +pub struct Meter(opentelemetry::metrics::Meter); +impl Meter { + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.meter_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } +} +impl Default for Meter { + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/params/expected/mod.rs b/templates/code/rust/tests/params/expected/mod.rs new file mode 100644 index 0000000..e8d18c6 --- /dev/null +++ b/templates/code/rust/tests/params/expected/mod.rs @@ -0,0 +1,109 @@ +//! Typed telemetry for a synthetic registry. +// Generated by OpenTelemetry Weaver. +// Source: model/ + +// Regenerate: mise run generate + +pub const SCHEMA_URL: &str = "https://example.com/schemas/params/1.0.0"; + +pub mod billingattr { + + /// Identifier of the invoice. + #[derive(Debug, Clone, PartialEq)] + + pub struct InvoiceIdAttr(String); + + + #[allow(deprecated)] + impl InvoiceIdAttr { + pub const KEY: &'static str = "acme.billing.invoice.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: InvoiceIdAttr) -> Self { + value.key_value() + } + } + + /// ISO 4217 currency code of the amount. + #[derive(Debug, Clone, PartialEq)] + + pub struct CurrencyAttr(String); + + + #[allow(deprecated)] + impl CurrencyAttr { + pub const KEY: &'static str = "billing.currency"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: CurrencyAttr) -> Self { + value.key_value() + } + } + +} + +pub mod myappattr { + + /// URL the request was sent to. + #[derive(Debug, Clone, PartialEq)] + + pub struct RequestUrlAttr(String); + + + #[allow(deprecated)] + impl RequestUrlAttr { + pub const KEY: &'static str = "myapp.request.url"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: RequestUrlAttr) -> Self { + value.key_value() + } + } + +} + + +pub mod meter; + + + +pub mod billingmetric; diff --git a/templates/code/rust/tests/params/params.yaml b/templates/code/rust/tests/params/params.yaml new file mode 100644 index 0000000..dbafdc2 --- /dev/null +++ b/templates/code/rust/tests/params/params.yaml @@ -0,0 +1,6 @@ +params: + module_description: Typed telemetry for a synthetic registry. + header_source: model/ + regenerate_command: mise run generate + vendor_prefixes: [acme] + exclude_deprecated: true diff --git a/templates/code/rust/tests/params/registry/manifest.yaml b/templates/code/rust/tests/params/registry/manifest.yaml new file mode 100644 index 0000000..afaa82c --- /dev/null +++ b/templates/code/rust/tests/params/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: params +schema_url: https://example.com/schemas/params/1.0.0 diff --git a/templates/code/rust/tests/params/registry/model.yaml b/templates/code/rust/tests/params/registry/model.yaml new file mode 100644 index 0000000..d4b4995 --- /dev/null +++ b/templates/code/rust/tests/params/registry/model.yaml @@ -0,0 +1,42 @@ +file_format: definition/2 +attributes: + - key: acme.billing.invoice.id + type: string + stability: stable + brief: Identifier of the invoice. + examples: ["inv_1"] + - key: billing.currency + type: string + stability: stable + brief: ISO 4217 currency code of the amount. + examples: ["EUR"] + - key: acme.billing.legacy_code + type: string + stability: development + brief: Code used before invoices had identifiers. + examples: ["X1"] + deprecated: + reason: renamed + renamed_to: acme.billing.invoice.id + - key: myapp.request.url + type: string + stability: stable + brief: URL the request was sent to. + examples: ["https://example.com/"] +metrics: + - name: acme.billing.invoice.amount + requirement_level: recommended + instrument: histogram + unit: "{currency_unit}" + stability: stable + brief: Amount of each issued invoice. + annotations: + code_generation: + metric_value_type: double + attributes: + - ref: acme.billing.invoice.id + requirement_level: required + - ref: billing.currency + requirement_level: recommended + - ref: myapp.request.url + requirement_level: recommended diff --git a/templates/code/rust/tests/spans/compile-fail/missing_required.expected-error.txt b/templates/code/rust/tests/spans/compile-fail/missing_required.expected-error.txt new file mode 100644 index 0000000..3d7bf5d --- /dev/null +++ b/templates/code/rust/tests/spans/compile-fail/missing_required.expected-error.txt @@ -0,0 +1 @@ +this function takes 5 arguments but 3 arguments were supplied diff --git a/templates/code/rust/tests/spans/compile-fail/missing_required.rs b/templates/code/rust/tests/spans/compile-fail/missing_required.rs new file mode 100644 index 0000000..8cb0571 --- /dev/null +++ b/templates/code/rust/tests/spans/compile-fail/missing_required.rs @@ -0,0 +1,8 @@ +use generated_semconv::{myappspan, tracer}; +fn main() { + myappspan::start_task_dispatch( + &opentelemetry::Context::new(), + &tracer::Tracer::default(), + [], + ); +} diff --git a/templates/code/rust/tests/spans/compile-fail/sampling_attribute_late.expected-error.txt b/templates/code/rust/tests/spans/compile-fail/sampling_attribute_late.expected-error.txt new file mode 100644 index 0000000..ab8b948 --- /dev/null +++ b/templates/code/rust/tests/spans/compile-fail/sampling_attribute_late.expected-error.txt @@ -0,0 +1 @@ +expected `TaskDispatchAttr`, found `TaskDispatchStartAttr` diff --git a/templates/code/rust/tests/spans/compile-fail/sampling_attribute_late.rs b/templates/code/rust/tests/spans/compile-fail/sampling_attribute_late.rs new file mode 100644 index 0000000..a99f5b0 --- /dev/null +++ b/templates/code/rust/tests/spans/compile-fail/sampling_attribute_late.rs @@ -0,0 +1,7 @@ +use generated_semconv::{myappattr, myappspan}; +fn main() { + let mut span = myappspan::TaskDispatchSpan::default(); + span.set_attributes([myappspan::TaskDispatchStartAttr::TaskId( + myappattr::TaskIdAttr::new("task-1"), + )]); +} diff --git a/templates/code/rust/tests/spans/expected/mod.rs b/templates/code/rust/tests/spans/expected/mod.rs new file mode 100644 index 0000000..46ef580 --- /dev/null +++ b/templates/code/rust/tests/spans/expected/mod.rs @@ -0,0 +1,206 @@ +// Generated by OpenTelemetry Weaver. + + +pub const SCHEMA_URL: &str = "https://example.com/schemas/spans/1.0.0"; + +pub mod myappattr { + + /// Name of the queue the task came from. + #[derive(Debug, Clone, PartialEq)] + + pub struct QueueNameAttr(String); + + + #[allow(deprecated)] + impl QueueNameAttr { + pub const KEY: &'static str = "myapp.queue.name"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: QueueNameAttr) -> Self { + value.key_value() + } + } + + /// Number of the attempt, starting at one. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskAttemptAttr(i64); + + + #[allow(deprecated)] + impl TaskAttemptAttr { + pub const KEY: &'static str = "myapp.task.attempt"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskAttemptAttr) -> Self { + value.key_value() + } + } + + /// Unique identifier of the task. + #[derive(Debug, Clone, PartialEq)] + + pub struct TaskIdAttr(String); + + + #[allow(deprecated)] + impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } + } + + /// Current state of the task. + #[derive(Debug, Clone, PartialEq, Copy)] + + pub enum TaskStateAttr { + + /// The task is waiting to run. + Queued, + + /// The task finished. + Done, + + } + + + #[allow(deprecated)] + impl TaskStateAttr { + pub const KEY: &'static str = "myapp.task.state"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Queued => "queued".into(), + + Self::Done => "done".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: TaskStateAttr) -> Self { + value.key_value() + } + } + +} + +pub mod workerattr { + + /// Host name of the worker. + #[derive(Debug, Clone, PartialEq)] + + pub struct HostNameAttr(String); + + + #[allow(deprecated)] + impl HostNameAttr { + pub const KEY: &'static str = "worker.host.name"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: HostNameAttr) -> Self { + value.key_value() + } + } + + /// Port the worker listens on. + #[derive(Debug, Clone, PartialEq)] + + pub struct HostPortAttr(i64); + + + #[allow(deprecated)] + impl HostPortAttr { + pub const KEY: &'static str = "worker.host.port"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } + } + + #[allow(deprecated)] + impl From for ::opentelemetry::KeyValue { + fn from(value: HostPortAttr) -> Self { + value.key_value() + } + } + +} + + + +pub mod tracer; + + +pub mod myappspan; + +pub mod workerspan; diff --git a/templates/code/rust/tests/spans/expected/myappspan.rs b/templates/code/rust/tests/spans/expected/myappspan.rs new file mode 100644 index 0000000..258bfd7 --- /dev/null +++ b/templates/code/rust/tests/spans/expected/myappspan.rs @@ -0,0 +1,455 @@ +#![allow(deprecated)] + + + + + + + +/// Synthetic escaped name. +pub struct NameApostropheSpan { span: ::opentelemetry::global::BoxedSpan } +impl NameApostropheSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { + use ::opentelemetry::trace::TraceContextExt; + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } + +} +impl Default for NameApostropheSpan { + fn default() -> Self { + use ::opentelemetry::trace::Tracer; + Self { span: super::tracer::Tracer::default().inner().start("myapp.name.apostrophe") } + } +} + +pub fn r#start_name_apostrophe(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameApostropheSpan { + use ::opentelemetry::trace::Tracer; + + let mut name = String::new(); + + + + name.push('\u{0027}'); + + + + + name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); + + + + let attributes = vec![r#worker_host_port.key_value()]; + + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Internal) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + NameApostropheSpan { span } +} + + + + + + +/// Synthetic escaped name. +pub struct NameBackslashSpan { span: ::opentelemetry::global::BoxedSpan } +impl NameBackslashSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { + use ::opentelemetry::trace::TraceContextExt; + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } + +} +impl Default for NameBackslashSpan { + fn default() -> Self { + use ::opentelemetry::trace::Tracer; + Self { span: super::tracer::Tracer::default().inner().start("myapp.name.backslash") } + } +} + +pub fn r#start_name_backslash(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameBackslashSpan { + use ::opentelemetry::trace::Tracer; + + let mut name = String::new(); + + + + name.push('\\'); + + + + + name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); + + + + let attributes = vec![r#worker_host_port.key_value()]; + + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Internal) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + NameBackslashSpan { span } +} + + + + + + +/// Synthetic escaped name. +pub struct NameControlSpan { span: ::opentelemetry::global::BoxedSpan } +impl NameControlSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { + use ::opentelemetry::trace::TraceContextExt; + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } + +} +impl Default for NameControlSpan { + fn default() -> Self { + use ::opentelemetry::trace::Tracer; + Self { span: super::tracer::Tracer::default().inner().start("myapp.name.control") } + } +} + +pub fn r#start_name_control(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameControlSpan { + use ::opentelemetry::trace::Tracer; + + let mut name = String::new(); + + + + name.push('\u{0008}'); + + + + + name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); + + + + let attributes = vec![r#worker_host_port.key_value()]; + + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Internal) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + NameControlSpan { span } +} + + + + + + +/// Synthetic escaped name. +pub struct NameUnicodeSpan { span: ::opentelemetry::global::BoxedSpan } +impl NameUnicodeSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { + use ::opentelemetry::trace::TraceContextExt; + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } + +} +impl Default for NameUnicodeSpan { + fn default() -> Self { + use ::opentelemetry::trace::Tracer; + Self { span: super::tracer::Tracer::default().inner().start("myapp.name.unicode") } + } +} + +pub fn r#start_name_unicode(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameUnicodeSpan { + use ::opentelemetry::trace::Tracer; + + let mut name = String::new(); + + + + name.push('é'); + + + + + name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); + + + + let attributes = vec![r#worker_host_port.key_value()]; + + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Internal) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + NameUnicodeSpan { span } +} + + + + + + +#[derive(Clone, Debug, Default)] +pub struct QueueDrainName(String); +impl QueueDrainName { + pub fn new(value: impl Into) -> Self { Self(value.into()) } +} + +/// Removing every task from a queue. +/// Opt-in: record only when the user requests it. +#[deprecated(note = "Drain queues by dispatching their tasks instead.")] +pub struct QueueDrainSpan { span: ::opentelemetry::global::BoxedSpan } +impl QueueDrainSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { + use ::opentelemetry::trace::TraceContextExt; + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } + +} +impl Default for QueueDrainSpan { + fn default() -> Self { + use ::opentelemetry::trace::Tracer; + Self { span: super::tracer::Tracer::default().inner().start("myapp.queue.drain") } + } +} +#[deprecated(note = "Drain queues by dispatching their tasks instead.")] +pub fn r#start_queue_drain(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: QueueDrainName) -> QueueDrainSpan { + use ::opentelemetry::trace::Tracer; + + let name = if name.0.is_empty() { "myapp.queue.drain".to_owned() } else { name.0 }; + + let attributes = vec![]; + + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Consumer) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + QueueDrainSpan { span } +} + + + + +#[derive(Clone, Debug)] +pub enum TaskDispatchStartAttr { + +/// Recommended: When the task came from a named queue. + QueueName(super::myappattr::QueueNameAttr), + +/// Opt-in: the convention records it only when a user asks for it. + TaskAttempt(super::myappattr::TaskAttemptAttr), + + + TaskId(super::myappattr::TaskIdAttr), + +} +impl TaskDispatchStartAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::QueueName(value) => value.key_value(), + + Self::TaskAttempt(value) => value.key_value(), + + Self::TaskId(value) => value.key_value(), + + } + } +} + + +#[derive(Clone, Debug)] +pub enum TaskDispatchAttr { + + QueueName(super::myappattr::QueueNameAttr), + + TaskAttempt(super::myappattr::TaskAttemptAttr), + +} +impl From for TaskDispatchStartAttr { + fn from(value: TaskDispatchAttr) -> Self { + match value { + + TaskDispatchAttr::QueueName(value) => Self::QueueName(value), + + TaskDispatchAttr::TaskAttempt(value) => Self::TaskAttempt(value), + + } + } +} + + +/// The scheduler handing a task to a worker. +/// +/// Ends when the worker accepts the task. +pub struct TaskDispatchSpan { span: ::opentelemetry::global::BoxedSpan } +impl TaskDispatchSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { + use ::opentelemetry::trace::TraceContextExt; + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } + + pub fn set_attributes(&mut self, attributes: impl IntoIterator) { + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, TaskDispatchStartAttr::from(attribute).key_value()); } + } + +} +impl Default for TaskDispatchSpan { + fn default() -> Self { + use ::opentelemetry::trace::Tracer; + Self { span: super::tracer::Tracer::default().inner().start("myapp.task.dispatch") } + } +} + +pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_name: super::workerattr::HostNameAttr, r#worker_host_port: super::workerattr::HostPortAttr, options: impl IntoIterator) -> TaskDispatchSpan { + use ::opentelemetry::trace::Tracer; + + let mut name = String::new(); + + + + name.push_str("dispatch "); + + + + + name.push_str(&r#worker_host_name.clone().key_value().value.to_string()); + + + + + name.push(':'); + + + + + name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); + + + + let mut attributes = vec![r#worker_host_name.key_value(), r#worker_host_port.key_value()]; + + attributes.extend(options.into_iter().map(TaskDispatchStartAttr::key_value)); + + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Client) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + TaskDispatchSpan { span } +} + + + + +#[derive(Clone, Debug)] +pub enum TaskRunStartAttr { + + + TaskId(super::myappattr::TaskIdAttr), + +} +impl TaskRunStartAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::TaskId(value) => value.key_value(), + + } + } +} + + +#[derive(Clone, Debug)] +pub enum TaskRunAttr { + + TaskId(super::myappattr::TaskIdAttr), + +} +impl From for TaskRunStartAttr { + fn from(value: TaskRunAttr) -> Self { + match value { + + TaskRunAttr::TaskId(value) => Self::TaskId(value), + + } + } +} + + +#[derive(Clone, Debug, Default)] +pub struct TaskRunName(String); +impl TaskRunName { + pub fn new(value: impl Into) -> Self { Self(value.into()) } +} + +/// One run of a task. +pub struct TaskRunSpan { span: ::opentelemetry::global::BoxedSpan } +impl TaskRunSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { + use ::opentelemetry::trace::TraceContextExt; + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } + + pub fn set_attributes(&mut self, attributes: impl IntoIterator) { + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, TaskRunStartAttr::from(attribute).key_value()); } + } + +} +impl Default for TaskRunSpan { + fn default() -> Self { + use ::opentelemetry::trace::Tracer; + Self { span: super::tracer::Tracer::default().inner().start("myapp.task.run") } + } +} + +pub fn r#start_task_run(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: TaskRunName, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) -> TaskRunSpan { + use ::opentelemetry::trace::Tracer; + + let name = if name.0.is_empty() { "myapp.task.run".to_owned() } else { name.0 }; + + let mut attributes = vec![r#myapp_task_state.key_value()]; + + attributes.extend(options.into_iter().map(TaskRunStartAttr::key_value)); + + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Internal) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + TaskRunSpan { span } +} diff --git a/templates/code/rust/tests/spans/expected/tracer.rs b/templates/code/rust/tests/spans/expected/tracer.rs new file mode 100644 index 0000000..6580bf3 --- /dev/null +++ b/templates/code/rust/tests/spans/expected/tracer.rs @@ -0,0 +1,29 @@ +pub struct Tracer(opentelemetry::global::BoxedTracer); +impl Tracer { + pub fn new(provider: &P, scope: impl Into>) -> Self + where + P::Tracer: Send + Sync + 'static, + ::Span: Send + Sync + 'static, + { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self + where + P::Tracer: Send + Sync + 'static, + ::Span: Send + Sync + 'static, + { + Self(opentelemetry::global::BoxedTracer::new(Box::new(provider.tracer_with_scope(registry_scope(scope))))) + } + pub fn inner(&self) -> &opentelemetry::global::BoxedTracer { &self.0 } +} +impl Default for Tracer { + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/spans/expected/workerspan.rs b/templates/code/rust/tests/spans/expected/workerspan.rs new file mode 100644 index 0000000..b27676f --- /dev/null +++ b/templates/code/rust/tests/spans/expected/workerspan.rs @@ -0,0 +1,109 @@ +#![allow(deprecated)] + + + + + +#[derive(Clone, Debug)] +pub enum TaskDispatchStartAttr { + +/// Recommended: When the task came from a named queue. + QueueName(super::myappattr::QueueNameAttr), + + + TaskId(super::myappattr::TaskIdAttr), + +} +impl TaskDispatchStartAttr { + fn key_value(self) -> ::opentelemetry::KeyValue { + match self { + + Self::QueueName(value) => value.key_value(), + + Self::TaskId(value) => value.key_value(), + + } + } +} + + +#[derive(Clone, Debug)] +pub enum TaskDispatchAttr { + + QueueName(super::myappattr::QueueNameAttr), + +} +impl From for TaskDispatchStartAttr { + fn from(value: TaskDispatchAttr) -> Self { + match value { + + TaskDispatchAttr::QueueName(value) => Self::QueueName(value), + + } + } +} + + +/// The scheduler handing a task to a worker. +/// +/// Ends when the worker accepts the task. +pub struct TaskDispatchSpan { span: ::opentelemetry::global::BoxedSpan } +impl TaskDispatchSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { + use ::opentelemetry::trace::TraceContextExt; + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } + + pub fn set_attributes(&mut self, attributes: impl IntoIterator) { + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, TaskDispatchStartAttr::from(attribute).key_value()); } + } + +} +impl Default for TaskDispatchSpan { + fn default() -> Self { + use ::opentelemetry::trace::Tracer; + Self { span: super::tracer::Tracer::default().inner().start("myapp.task.dispatch") } + } +} + +pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#myapp_task_attempt: super::myappattr::TaskAttemptAttr, r#worker_host_name: super::workerattr::HostNameAttr, r#worker_host_port: super::workerattr::HostPortAttr, options: impl IntoIterator) -> TaskDispatchSpan { + use ::opentelemetry::trace::Tracer; + + let mut name = String::new(); + + + + name.push_str("dispatch "); + + + + + name.push_str(&r#worker_host_name.clone().key_value().value.to_string()); + + + + + name.push(':'); + + + + + name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); + + + + let mut attributes = vec![r#myapp_task_attempt.key_value(), r#worker_host_name.key_value(), r#worker_host_port.key_value()]; + + attributes.extend(options.into_iter().map(TaskDispatchStartAttr::key_value)); + + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Client) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + TaskDispatchSpan { span } +} diff --git a/templates/code/rust/tests/spans/registry/manifest.yaml b/templates/code/rust/tests/spans/registry/manifest.yaml new file mode 100644 index 0000000..1520442 --- /dev/null +++ b/templates/code/rust/tests/spans/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: spans +schema_url: https://example.com/schemas/spans/1.0.0 diff --git a/templates/code/rust/tests/spans/registry/model.yaml b/templates/code/rust/tests/spans/registry/model.yaml new file mode 100644 index 0000000..71cba23 --- /dev/null +++ b/templates/code/rust/tests/spans/registry/model.yaml @@ -0,0 +1,130 @@ +file_format: definition/2 +attributes: + - key: myapp.task.id + type: string + stability: stable + brief: Unique identifier of the task. + examples: ["task_0001"] + - key: myapp.task.state + type: + members: + - id: queued + value: queued + stability: stable + brief: The task is waiting to run. + - id: done + value: done + stability: stable + brief: The task finished. + stability: stable + brief: Current state of the task. + - key: myapp.task.attempt + type: int + stability: stable + brief: Number of the attempt, starting at one. + examples: 1 + - key: myapp.queue.name + type: string + stability: stable + brief: Name of the queue the task came from. + examples: ["reports"] + - key: worker.host.name + type: string + stability: stable + brief: Host name of the worker. + examples: ["worker-1"] + - key: worker.host.port + type: int + stability: stable + brief: Port the worker listens on. + examples: 8080 +spans: + - type: myapp.task.dispatch + kind: client + requirement_level: recommended + stability: stable + brief: The scheduler handing a task to a worker. + note: Ends when the worker accepts the task. + name: + note: "`dispatch {worker.host.name}:{worker.host.port}`" + attributes: + - ref: worker.host.name + requirement_level: required + - ref: worker.host.port + requirement_level: required + - ref: myapp.task.id + requirement_level: recommended + sampling_relevant: true + - ref: myapp.queue.name + requirement_level: + recommended: When the task came from a named queue. + - ref: myapp.task.attempt + requirement_level: opt_in + - type: myapp.task.run + kind: internal + requirement_level: recommended + stability: stable + brief: One run of a task. + name: + note: "`run {myapp.task.id}`" + attributes: + - ref: myapp.task.state + requirement_level: required + - ref: myapp.task.id + requirement_level: recommended + - type: myapp.queue.drain + kind: consumer + requirement_level: opt_in + stability: development + brief: Removing every task from a queue. + name: + note: "`drain` followed by the queue's name, such as `drain reports`." + deprecated: + reason: obsoleted + note: Drain queues by dispatching their tasks instead. + - type: myapp.name.apostrophe + kind: internal + requirement_level: recommended + stability: stable + brief: Synthetic escaped name. + name: + note: "`'{worker.host.port}`" + attributes: + - ref: worker.host.port + requirement_level: required + - type: myapp.name.backslash + kind: internal + requirement_level: recommended + stability: stable + brief: Synthetic escaped name. + name: + note: "`\\{worker.host.port}`" + attributes: + - ref: worker.host.port + requirement_level: required + - type: myapp.name.unicode + kind: internal + requirement_level: recommended + stability: stable + brief: Synthetic escaped name. + name: + note: "`é{worker.host.port}`" + attributes: + - ref: worker.host.port + requirement_level: required + - type: myapp.name.control + kind: internal + requirement_level: recommended + stability: stable + brief: Synthetic escaped name. + name: + note: "`\b{worker.host.port}`" + attributes: + - ref: worker.host.port + requirement_level: required +span_refinements: + - id: worker.task.dispatch + ref: myapp.task.dispatch + attributes: + - ref: myapp.task.attempt + requirement_level: required diff --git a/templates/code/rust/tests/spans/test.rs b/templates/code/rust/tests/spans/test.rs new file mode 100644 index 0000000..df382be --- /dev/null +++ b/templates/code/rust/tests/spans/test.rs @@ -0,0 +1,121 @@ +use generated_semconv::{myappattr, myappspan, tracer, workerattr, workerspan, SCHEMA_URL}; +use opentelemetry::trace::{Span, TraceContextExt}; +use opentelemetry_sdk::trace::{InMemorySpanExporter, SdkTracerProvider}; + +#[test] +fn derived_names_refinements_parent_context_and_late_attributes() { + let exporter = InMemorySpanExporter::default(); + let provider = SdkTracerProvider::builder() + .with_simple_exporter(exporter.clone()) + .build(); + let tracer = tracer::Tracer::new_with_scope( + &provider, + opentelemetry::InstrumentationScope::builder("worker") + .with_version("1.2.3") + .with_schema_url("https://example.com/ignored/1.0.0") + .with_attributes([opentelemetry::KeyValue::new("scope.kind", "test")]) + .build(), + ); + let parent = myappspan::start_task_dispatch( + &opentelemetry::Context::new(), + &tracer, + workerattr::HostNameAttr::new("worker-1"), + workerattr::HostPortAttr::new(8080), + [myappspan::TaskDispatchStartAttr::TaskId( + myappattr::TaskIdAttr::new("task-1"), + )], + ); + let context = parent.into_context(&opentelemetry::Context::new()); + let mut child = myappspan::start_task_run( + &context, + &tracer, + myappspan::TaskRunName::new("run task-1"), + myappattr::TaskStateAttr::Done, + [], + ); + child.set_attributes([myappspan::TaskRunAttr::TaskId(myappattr::TaskIdAttr::new( + "task-1", + ))]); + child.set_status(opentelemetry::trace::Status::Ok); + child.end(); + context.span().end(); + let mut refined = workerspan::start_task_dispatch( + &opentelemetry::Context::new(), + &tracer, + myappattr::TaskAttemptAttr::new(3), + workerattr::HostNameAttr::new("worker-2"), + workerattr::HostPortAttr::new(9090), + [], + ); + refined.end(); + let mut fallback = myappspan::start_task_run( + &opentelemetry::Context::new(), + &tracer, + myappspan::TaskRunName::default(), + myappattr::TaskStateAttr::Done, + [], + ); + fallback.end(); + myappspan::start_name_apostrophe( + &opentelemetry::Context::new(), + &tracer, + workerattr::HostPortAttr::new(1), + ) + .end(); + myappspan::start_name_backslash( + &opentelemetry::Context::new(), + &tracer, + workerattr::HostPortAttr::new(1), + ) + .end(); + myappspan::start_name_unicode( + &opentelemetry::Context::new(), + &tracer, + workerattr::HostPortAttr::new(1), + ) + .end(); + myappspan::start_name_control( + &opentelemetry::Context::new(), + &tracer, + workerattr::HostPortAttr::new(1), + ) + .end(); + provider.force_flush().unwrap(); + let spans = exporter.get_finished_spans().unwrap(); + assert_eq!(spans.len(), 8); + let child = spans.iter().find(|span| span.name == "run task-1").unwrap(); + let parent = spans + .iter() + .find(|span| span.name == "dispatch worker-1:8080") + .unwrap(); + assert_eq!(child.parent_span_id, parent.span_context.span_id()); + assert_eq!(parent.span_kind, opentelemetry::trace::SpanKind::Client); + assert_eq!(child.status, opentelemetry::trace::Status::Ok); + assert!(child + .attributes + .iter() + .any(|kv| kv.key.as_str() == "myapp.task.id" && kv.value.as_str() == "task-1")); + assert_eq!(parent.instrumentation_scope.schema_url(), Some(SCHEMA_URL)); + assert_eq!(parent.instrumentation_scope.name(), "worker"); + assert_eq!(parent.instrumentation_scope.version(), Some("1.2.3")); + assert!(parent + .instrumentation_scope + .attributes() + .any(|kv| kv.key.as_str() == "scope.kind")); + let refined = spans + .iter() + .find(|span| span.name == "dispatch worker-2:9090") + .unwrap(); + assert!(refined + .attributes + .iter() + .any(|kv| kv.key.as_str() == "myapp.task.attempt" + && kv.value == opentelemetry::Value::I64(3))); + assert!(spans.iter().any(|span| span.name == "myapp.task.run")); + for name in ["'1", "\\1", "é1", "\u{0008}1"] { + assert!(spans.iter().any(|span| span.name == name)); + } + let mut noop = myappspan::TaskRunSpan::default(); + assert!(!noop.span().is_recording()); + noop.end(); +} diff --git a/templates/code/rust/tracer.rs.j2 b/templates/code/rust/tracer.rs.j2 new file mode 100644 index 0000000..5d1b247 --- /dev/null +++ b/templates/code/rust/tracer.rs.j2 @@ -0,0 +1,31 @@ +{%- filter trim %} +pub struct Tracer(opentelemetry::global::BoxedTracer); +impl Tracer { + pub fn new(provider: &P, scope: impl Into>) -> Self + where + P::Tracer: Send + Sync + 'static, + ::Span: Send + Sync + 'static, + { + Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + } + pub fn new_with_scope(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self + where + P::Tracer: Send + Sync + 'static, + ::Span: Send + Sync + 'static, + { + Self(opentelemetry::global::BoxedTracer::new(Box::new(provider.tracer_with_scope(registry_scope(scope))))) + } + pub fn inner(&self) -> &opentelemetry::global::BoxedTracer { &self.0 } +} +impl Default for Tracer { + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} +{% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/weaver.yaml b/templates/code/rust/weaver.yaml new file mode 100644 index 0000000..ab0928a --- /dev/null +++ b/templates/code/rust/weaver.yaml @@ -0,0 +1,611 @@ +params: + module_description: "" + histogram_boundaries_by_unit: + s: [0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10] + vendor_prefixes: [] + exclude_deprecated: false + stable_only: false + imported_crate_paths: {} + header_source: "" + regenerate_command: "" + +templates: + - template: mod.rs.j2 + application_mode: single + file_name: mod.rs + filter: |- + def title: split(".") | map(split("_")) | flatten | map(.[0:1] as $first | ($first | ascii_upcase) + .[1:]) | join(""); + def keyword: . as $name | ["as", "break", "const", "continue", "crate", "else", "enum", "extern", "false", "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref", "return", "self", "Self", "static", "struct", "super", "trait", "true", "type", "unsafe", "use", "where", "while", "async", "await", "dyn", "abstract", "become", "box", "do", "final", "gen", "macro", "override", "priv", "try", "typeof", "unsized", "virtual", "yield"] | any(. == $name); + def valid_name: test("^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)*$"); + def ns: split(".") as $s + | if ($s | length) > 1 and ($vendor_prefixes | any(. == $s[0])) + then {namespace: $s[1], short_name: ($s[2:] | join("."))} + else {namespace: $s[0], short_name: ($s[1:] | join("."))} end | if (.namespace | test("^[a-z][a-z0-9_]*$") | not) + then error("namespace \(.namespace) is not a supported Rust module name") else . end; + def value_type($key): + if type != "object" then . + elif (.members | length) == 0 then error("attribute \($key) has no enum members left after filtering") + elif (.members | all(.value | type == "string")) then "string" + elif (.members | all(.value | type == "boolean")) then "boolean" + elif (.members | all(.value | type == "number" and . == floor)) then "int" + elif (.members | all(.value | type == "number")) then "double" + else error("attribute \($key) has enum members of more than one value type") end; + def rust_literal: + if type == "string" then explode | map([.] | implode | tojson | gsub("\\\\b"; "\\u{0008}") | gsub("\\\\f"; "\\u{000c}") | gsub("\\\\u(?[0-9a-fA-F]{4})"; "\\u{\(.code)}") | .[1:-1]) | join("") | "\"" + . + "\"" + else tostring end; + .schema_url as $schema + | if $schema == null or $schema == "https://unknown/unknown" or ($schema | test("^https?://[^/]+(/[^/]+)*/[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z.-]+)?$") | not) + then error("the registry schema_url must name a schema version") else . end + | {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $opts + | (semconv_grouped_metrics($opts) | map(.metrics) | add // [] | map(.name)) as $metrics + | (.registry.spans // [] | stability_filter($opts) | code_generation_exclude_filter($opts) | deprecated_filter($opts) | map(.type)) as $spans + | (.registry.entities // [] | stability_filter($opts) | code_generation_exclude_filter($opts) | deprecated_filter($opts) | map(.type)) as $entities + | ([($metrics + (.refinements.metrics // [] | stability_filter($opts) | code_generation_exclude_filter($opts) | deprecated_filter($opts) | map(select(.id != .name and (.name as $base | $metrics | any(. == $base))) | .id)))[] | ns | .namespace + "metric"] + + [($spans + (.refinements.spans // [] | stability_filter($opts) | code_generation_exclude_filter($opts) | deprecated_filter($opts) | map(select(.id != .type and (.type as $base | $spans | any(. == $base))) | .id)))[] | ns | .namespace + "span"] + + [((.registry.events // [] | stability_filter($opts) | code_generation_exclude_filter($opts) | deprecated_filter($opts) | map(.name)) + (.refinements.events // [] | stability_filter($opts) | code_generation_exclude_filter($opts) | deprecated_filter($opts) | map(.id)))[] | ns | .namespace + "event"] + + [($entities + (.refinements.entities // [] | stability_filter($opts) | code_generation_exclude_filter($opts) | deprecated_filter($opts) | map(select(.id != .type and (.type as $base | $entities | any(. == $base))) | .id)))[] | ns | .namespace + "entity"] | unique) as $signal_modules + | semconv_grouped_attributes($opts) + | map(.attributes) | add // [] + | map(if (.key | valid_name | not) then error("attribute \(.key) is not a supported Rust attribute name") else . end) + | map(. + (.key | ns)) + | map(if .short_name == "" then error("attribute \(.key) has no name after its namespace") else . end) + | map(. + {name: ((.short_name | title) + "Attr"), value_type: (.key as $key | .type | value_type($key)), key_literal: (.key | rust_literal), deprecated_literal: (if .deprecated then (.deprecated.note // .deprecated.renamed_to // .deprecated.reason | rust_literal) else null end)}) + | map(if (.value_type as $t | ["string", "int", "double", "boolean", "string[]", "int[]", "double[]", "boolean[]"] | any(. == $t) | not) + then error("attribute \(.key) has an unsupported Rust value type") else . end) + | map(if .value_type == "int" and (.type | type) == "object" + and (.type.members | any(.value >= 9223372036854775808 or .value < -9223372036854775808 or (.value | tostring | test("^-?[0-9]+$") | not))) + then error("attribute \(.key) has an enum value that cannot be represented by Rust i64") else . end) + | map(if (.type | type) == "object" then + .key as $key | .deprecated_literal as $attribute_deprecated | .type.members |= map( + if (.id | valid_name | not) then error("enum member \(.id) of \($key) is not a supported Rust identifier") else . end + | . + {name: (.id | title), literal: (.value | rust_literal), deprecated_literal: (if .deprecated then (.deprecated.note // .deprecated.renamed_to // .deprecated.reason | rust_literal) else $attribute_deprecated end)} + | if (.name | keyword) then error("enum member \(.id) of \($key) becomes a Rust keyword") else . end) + | (.type.members | group_by(.name) | map(select(length > 1))) as $collisions + | if ($collisions | length) > 0 then error("attribute \($key) has enum members that render to the same Rust identifier") else . end + else . end) + | group_by(.namespace) + | map(if (group_by(.name) | any(length > 1)) then error("namespace \(.[0].namespace) has attributes that render to the same Rust identifier") else . end) + | {signal_modules: $signal_modules, has_metrics: ($signal_modules | any(endswith("metric"))), has_spans: ($signal_modules | any(endswith("span"))), has_events: ($signal_modules | any(endswith("event"))), schema_literal: ($schema | rust_literal), namespaces: map({name: (.[0].namespace + "attr"), attributes: sort_by(.key)})} + + - template: metrics.rs.j2 + filter: |- + def ns: if (test("^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)*$") | not) + then error("name \(.) is not a supported Rust signal identifier") else . end + | split(".") as $s + | if ($s | length) > 1 and ($vendor_prefixes | any(. == $s[0])) + then {namespace: $s[1], prefix: ($s[0:2] | join(".")), short_name: ($s[2:] | join(".")), param: ($s[1:] | join("."))} + else {namespace: $s[0], prefix: $s[0], short_name: ($s[1:] | join(".")), param: ($s | join("."))} + end | if (.namespace | test("^[a-z][a-z0-9_]*$") | not) + then error("namespace \(.namespace) is not a supported Rust module name") else . end; + def enum_value_type($key): + .members as $members + | if ($members | length) == 0 + then error("attribute \($key) has no enum members left after exclude_deprecated or stable_only, so no value of it could be built") + elif ($members | all(.value | type == "string")) then "string" + elif ($members | all(.value | type == "boolean")) then "boolean" + elif ($members | all(.value | type == "number" and . == floor)) then "int" + elif ($members | all(.value | type == "number")) then "double" + else error("attribute \($key) has enum members of more than one value type, which no single Rust type can hold") + end; + def kept($o): + stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) + | map(.attributes = (if .attributes == null then .attributes else .attributes | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) end)); + def instruments($o): + (semconv_grouped_metrics($o) | map(.metrics) | add // []) as $metrics + | ($metrics | map(.name)) as $kept_bases + | (.registry.metrics // [] | map({key: .name, value: .}) | from_entries) as $bases + | $metrics + (.refinements.metrics // [] | map(select(.id != .name)) | kept($o) + | map(select(.name as $base | $kept_bases | any(. == $base))) + | map(. as $r | $bases[$r.name] as $b + | if ($r.annotations.code_generation.metric_value_type // null) != ($b.annotations.code_generation.metric_value_type // null) + then error("metric refinement \($r.id) sets a different code_generation.metric_value_type than \($r.name), but both record into one instrument") + elif ($r.annotations.aggregation // null) != ($b.annotations.aggregation // null) + then error("metric refinement \($r.id) sets a different annotations.aggregation than \($r.name), but both record into one instrument") + else . + {name: $r.id, refines: $r.name, instrument_name: $r.name, description: $b.brief, unit: $b.unit} end)); + {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $opts + | (semconv_grouped_attributes($opts) | map(.attributes) | add // [] | map(.key)) as $rendered + | (instruments({v2: true}) + | map({key: .name, value: [(.attributes // [])[] | select(.requirement_level == "required") | .key]}) + | from_entries) as $declared_required + | instruments($opts) + | map({instrument_name: .name, description: .brief} + .) + | map(if (.annotations.code_generation.metric_value_type // "") as $t | ["int", "double"] | any(. == $t) | not + then error("metric \(.name) must set code_generation.metric_value_type to int or double") + elif (.instrument as $kind | ["counter", "updowncounter", "histogram", "gauge"] | any(. == $kind) | not) + then error("metric \(.name) has an unsupported Rust instrument") else . end) + | map(.name as $metric + | (($declared_required[$metric] // []) - [(.attributes // [])[] | .key]) as $dropped + | if ($dropped | length) > 0 + then error("metric \($metric) requires \($dropped | join(", ")), which exclude_deprecated or stable_only leaves out, so its generated method could not set them") + else . end) + | map(.name as $metric + | .unit as $unit + | (.annotations.aggregation // null) as $aggregation + | ($aggregation | if type == "object" and (.parameters | type) == "object" then .parameters.boundaries else null end) as $bounds + | if $aggregation != null then + if .instrument != "histogram" + then error("metric \($metric) sets annotations.aggregation, which the Rust template supports only on a histogram") + elif ($aggregation | type) != "object" or ($aggregation.parameters // {} | type) != "object" + then error("metric \($metric) must set annotations.aggregation to an object with a method and parameters") + elif $aggregation.method != "explicithistogram" + then error("metric \($metric) sets annotations.aggregation.method to \($aggregation.method | tostring), but the Rust template supports only explicithistogram") + elif (($aggregation | keys) - ["method", "parameters"] | length) > 0 or (($aggregation.parameters // {} | keys) - ["boundaries"] | length) > 0 + then error("metric \($metric) sets annotations.aggregation fields other than method and parameters.boundaries, which the Rust API cannot express") + elif ($bounds | type) != "array" or ($bounds | length) == 0 or ($bounds | any(type != "number")) + then error("metric \($metric) must set annotations.aggregation.parameters.boundaries to a non-empty list of numbers") + elif ([range(1; $bounds | length) | select($bounds[.] <= $bounds[. - 1])] | length) > 0 + then error("metric \($metric) must list annotations.aggregation.parameters.boundaries in strictly increasing order") + else . + {bucket_boundaries: $bounds} end + elif .instrument == "histogram" and ($unit | type) == "string" and ($histogram_boundaries_by_unit | has($unit)) then + ($histogram_boundaries_by_unit[$unit]) as $default_bounds + | if ($default_bounds | type) != "array" or ($default_bounds | length) == 0 or ($default_bounds | any(type != "number")) + then error("metric \($metric) resolves histogram_boundaries_by_unit for unit \($unit) to boundaries that are not a non-empty list of numbers") + elif ([range(1; $default_bounds | length) | select($default_bounds[.] <= $default_bounds[. - 1])] | length) > 0 + then error("metric \($metric) resolves histogram_boundaries_by_unit for unit \($unit) to boundaries that are not in strictly increasing order") + else . + {bucket_boundaries: $default_bounds} end + else . end) + | map(. + (.name | ns | {namespace, prefix, short_name})) + | map(if .short_name == "" + then error("metric \(.name) has no name left after its namespace, so it cannot become a Rust identifier") + else . end) + | map(.name as $metric + | .attributes |= ((. // []) | sort_by(.key) | map( + (.key | ns) as $attr_ns + | if (.key as $k | $rendered | any(. == $k)) + then . + {attr_namespace: $attr_ns.namespace, attr_short_name: $attr_ns.short_name, attr_param: $attr_ns.param} + elif ($imported_crate_paths | has($attr_ns.namespace)) + then (if (.type | type) == "object" and (((.type.members // []) | length) == 0) + then error("metric \($metric) references imported attribute \(.key) whose enum has no members, so no value of it could be built") + elif (.type | type) != "object" and ([.type] | inside(["string", "string[]", "int", "int[]", "double", "double[]", "boolean", "boolean[]"]) | not) + then error("metric \($metric) references imported attribute \(.key) of type \(.type | tostring), which the Rust template does not render") + else . end + | . + {attr_namespace: $attr_ns.namespace, attr_short_name: $attr_ns.short_name, attr_param: $attr_ns.param, + attr_import_path: ($imported_crate_paths[$attr_ns.namespace] + "::" + $attr_ns.namespace + "attr")}) + else . + {imported: true, attr_short_name: .key, attr_param: .key, + attr_type: (if (.type | type) == "object" + then (.key as $key | .type | enum_value_type($key)) + elif ([.type] | inside(["string", "string[]", "int", "int[]", "double", "double[]", "boolean", "boolean[]"])) + then .type + else error("metric \($metric) references imported attribute \(.key) of type \(.type | tostring), which the Rust template does not render") end)} + end))) + | map(.attributes |= map(. + {requirement_doc: (.requirement_level + | if type == "object" and has("conditionally_required") then "Conditionally required: \(.conditionally_required)" + elif type == "object" and has("recommended") then "Recommended: \(.recommended)" + elif . == "opt_in" then "Opt-in: the convention records it only when a user asks for it." + else null end)})) + | map(.required = (.attributes | map(select(.requirement_level == "required")))) + | map(if (.required | any(.attr_param == "self" or .attr_param == "Self" or .attr_param == "crate" or .attr_param == "super")) + then error("signal \(.id // .name) has a required attribute that becomes a reserved Rust parameter") else . end) + | map(.optional = (.attributes | map(select(.requirement_level != "required")))) + | map(if (.optional | any(.attr_short_name == "self" or .attr_short_name == "Self")) + then error("signal \(.id // .name) has an optional attribute that becomes the reserved Rust Self identifier") else . end) + | map( + (.required + | group_by(.attr_param | gsub("[._]"; "") | ascii_downcase) + | map(select(length > 1) | map(.key) | join(" and "))) as $required_collisions + | (.optional + | group_by(.attr_short_name | gsub("[._]"; "") | ascii_downcase) + | map(select(length > 1) | map(.key) | join(" and "))) as $optional_collisions + | if ($required_collisions | length) > 0 + then error("metric \(.name) has required attributes that render to the same Rust parameter: \($required_collisions | join("; "))") + elif ($optional_collisions | length) > 0 + then error("metric \(.name) has optional attributes that render to the same Rust identifier: \($optional_collisions | join("; "))") + else . end + ) + | map(if (.required | any(.attr_param == "value" or .attr_param == "options" or .attr_param == "attributes")) + then error("metric \(.name) has a required attribute whose parameter shadows its generated method") else . end) + | group_by(.namespace) + | map( + ([.[] | .name as $metric | (.short_name | gsub("[._]"; "") | ascii_downcase) as $short | .instrument as $kind + | ([$short + $kind, $short + $kind + "attr", $short + $kind + "observer", $short + $kind + "callback"] + + (if $kind == "histogram" then [] else [$short + "observable" + $kind] end))[] + | {identifier: ., name: $metric}] + | group_by(.identifier) + | map(select(length > 1) | map(.name) | unique | join(" and ")) + | unique) as $collisions + | if ($collisions | length) > 0 + then error("package \(.[0].namespace)metric has metrics that render to the same Rust identifier: \($collisions | join("; "))") + else . end + ) + | map({namespace: .[0].namespace, prefix: .[0].prefix, metrics: sort_by(.name), + uses_attributes: ([.[] | .attributes[]] | length > 0)}) + application_mode: each + file_name: "{{ ctx.namespace }}metric.rs" + + - template: spans.rs.j2 + filter: |- + def ns: if (test("^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)*$") | not) + then error("name \(.) is not a supported Rust signal identifier") else . end + | split(".") as $s + | if ($s | length) > 1 and ($vendor_prefixes | any(. == $s[0])) + then {namespace: $s[1], prefix: ($s[0:2] | join(".")), short_name: ($s[2:] | join(".")), param: ($s[1:] | join("."))} + else {namespace: $s[0], prefix: $s[0], short_name: ($s[1:] | join(".")), param: ($s | join("."))} + end | if (.namespace | test("^[a-z][a-z0-9_]*$") | not) + then error("namespace \(.namespace) is not a supported Rust module name") else . end; + def enum_value_type($key): + .members as $members + | if ($members | length) == 0 + then error("attribute \($key) has no enum members left after exclude_deprecated or stable_only, so no value of it could be built") + elif ($members | all(.value | type == "string")) then "string" + elif ($members | all(.value | type == "boolean")) then "boolean" + elif ($members | all(.value | type == "number" and . == floor)) then "int" + elif ($members | all(.value | type == "number")) then "double" + else error("attribute \($key) has enum members of more than one value type, which no single Rust type can hold") + end; + def norm: gsub("[._]"; "") | ascii_downcase; + def kept($o): + stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) + | map(.attributes = (if .attributes == null then .attributes else .attributes | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) end)); + def spans($o): + (.registry.spans // [] | kept($o) | map(. + {id: .type})) as $spans + | ($spans | map(.type)) as $kept_bases + | $spans + (.refinements.spans // [] | map(select(.id != .type)) | kept($o) + | map(select(.type as $base | $kept_bases | any(. == $base)) | . + {refines: .type})); + def name_parts: + .required as $required + | [(.name.note // "") | scan("`[^`]*`"; "g")] as $codes + | if ($codes | length) != 1 then null + else ($codes[0] | .[1:-1]) as $code + | [$code | scan("\\{[^{}]*\\}"; "g") | .[1:-1]] as $keys + | [$code | splits("\\{[^{}]*\\}")] as $texts + | if ($keys | length) == 0 + or ($texts | any(test("[{}]"))) + or ($keys | any(. as $k | $required | any(.key == $k) | not)) + then null + else [range(0; $keys | length) as $i | {text: $texts[$i]}, ($keys[$i] as $k | {attr: ($required | map(select(.key == $k)) | .[0])})] + + [{text: $texts[-1]}] + | map(select(.text != "")) + end + end; + {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $opts + | (semconv_grouped_attributes($opts) | map(.attributes) | add // [] | map(.key)) as $rendered + | (spans({v2: true}) + | map({key: .id, value: [(.attributes // [])[] | select(.requirement_level == "required") | .key]}) + | from_entries) as $declared_required + | spans($opts) + | map(.id as $span + | (($declared_required[$span] // []) - [(.attributes // [])[] | .key]) as $dropped + | if ($dropped | length) > 0 + then error("span \($span) requires \($dropped | join(", ")), which exclude_deprecated or stable_only leaves out, so its generated starter could not set them") + else . end) + | map(. + (.id | ns | {namespace, prefix, short_name})) + | map(.id as $span + | .attributes |= ((. // []) | sort_by(.key) | map( + (.key | ns) as $attr_ns + | if (.key as $k | $rendered | any(. == $k)) + then . + {attr_namespace: $attr_ns.namespace, attr_short_name: $attr_ns.short_name, attr_param: $attr_ns.param} + elif ($imported_crate_paths | has($attr_ns.namespace)) + then (if (.type | type) == "object" and (((.type.members // []) | length) == 0) + then error("span \($span) references imported attribute \(.key) whose enum has no members, so no value of it could be built") + elif (.type | type) != "object" and ([.type] | inside(["string", "string[]", "int", "int[]", "double", "double[]", "boolean", "boolean[]"]) | not) + then error("span \($span) references imported attribute \(.key) of type \(.type | tostring), which the Rust template does not render") + else . end + | . + {attr_namespace: $attr_ns.namespace, attr_short_name: $attr_ns.short_name, attr_param: $attr_ns.param, + attr_import_path: ($imported_crate_paths[$attr_ns.namespace] + "::" + $attr_ns.namespace + "attr")}) + else . + {imported: true, attr_short_name: .key, attr_param: .key, + attr_type: (if (.type | type) == "object" + then (.key as $key | .type | enum_value_type($key)) + elif ([.type] | inside(["string", "string[]", "int", "int[]", "double", "double[]", "boolean", "boolean[]"])) + then .type + else error("span \($span) references imported attribute \(.key) of type \(.type | tostring), which the Rust template does not render") end)} + end))) + | map(.attributes |= map(. + {requirement_doc: (.requirement_level + | if type == "object" and has("conditionally_required") then "Conditionally required: \(.conditionally_required)" + elif type == "object" and has("recommended") then "Recommended: \(.recommended)" + elif . == "opt_in" then "Opt-in: the convention records it only when a user asks for it." + else null end)})) + | map(.required = (.attributes | map(select(.requirement_level == "required")))) + | map(if (.required | any(.attr_param == "self" or .attr_param == "Self" or .attr_param == "crate" or .attr_param == "super")) + then error("signal \(.id // .name) has a required attribute that becomes a reserved Rust parameter") else . end) + | map(.optional = (.attributes | map(select(.requirement_level != "required")))) + | map(if (.optional | any(.attr_short_name == "self" or .attr_short_name == "Self")) + then error("signal \(.id // .name) has an optional attribute that becomes the reserved Rust Self identifier") else . end) + | map(.has_late_attrs = (.optional | any(.sampling_relevant != true))) + | map(.name_parts = name_parts) + | map(.name_template = (if .name_parts then [.name.note | scan("`[^`]*`"; "g")][0][1:-1] else null end)) + | map( + (.required + | group_by(.attr_param | norm) + | map(select(length > 1) | map(.key) | join(" and "))) as $required_collisions + | (.optional + | group_by(.attr_short_name | norm) + | map(select(length > 1) | map(.key) | join(" and "))) as $optional_collisions + | (.required | map(select(.attr_param | norm | . as $p | ["context", "tracer", "name", "options", "option", "attributes", "span"] | any(. == $p))) | map(.key)) as $shadowing + | if ($required_collisions | length) > 0 + then error("span \(.id) has required attributes that render to the same Rust parameter: \($required_collisions | join("; "))") + elif ($optional_collisions | length) > 0 + then error("span \(.id) has optional attributes that render to the same Rust identifier: \($optional_collisions | join("; "))") + elif ($shadowing | length) > 0 + then error("span \(.id) has required attributes whose Rust parameter would shadow a name its starter declares: \($shadowing | join(", "))") + else . end + ) + | group_by(.namespace) + | map( + ([.[] | . as $def | .id as $span | (.short_name | norm) as $short + | (["P:start" + $short, "P:" + $short + "span"] + + (if $def.name_parts then [] else ["P:" + $short + "name", "P:new" + $short + "name"] end) + + (if ($def.optional | length) > 0 then ["P:" + $short + "startattr"] else [] end) + + (if $def.has_late_attrs then ["P:" + $short + "attr"] else [] end) + + ($def.optional | map(.attr_short_name | norm) | map("P:with" + $short + ., "p:" + $short + "span" + .)))[] + | {identifier: ., name: $span}] + | group_by(.identifier) + | map(select(length > 1) | map(.name) | unique | join(" and ")) + | unique) as $collisions + | if ($collisions | length) > 0 + then error("package \(.[0].namespace)span has spans that render to the same Rust identifier: \($collisions | join("; "))") + else . end + ) + | map({namespace: .[0].namespace, prefix: .[0].prefix, spans: sort_by(.id), + uses_attributes: ([.[] | .attributes[]] | length > 0)}) + application_mode: each + file_name: "{{ ctx.namespace }}span.rs" + + - template: events.rs.j2 + filter: |- + def ns: if (test("^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)*$") | not) + then error("name \(.) is not a supported Rust signal identifier") else . end + | split(".") as $s + | if ($s | length) > 1 and ($vendor_prefixes | any(. == $s[0])) + then {namespace: $s[1], prefix: ($s[0:2] | join(".")), short_name: ($s[2:] | join(".")), param: ($s[1:] | join("."))} + else {namespace: $s[0], prefix: $s[0], short_name: ($s[1:] | join(".")), param: ($s | join("."))} + end | if (.namespace | test("^[a-z][a-z0-9_]*$") | not) + then error("namespace \(.namespace) is not a supported Rust module name") else . end; + def enum_value_type($key): + .members as $members + | if ($members | length) == 0 + then error("attribute \($key) has no enum members left after exclude_deprecated or stable_only, so no value of it could be built") + elif ($members | all(.value | type == "string")) then "string" + elif ($members | all(.value | type == "boolean")) then "boolean" + elif ($members | all(.value | type == "number" and . == floor)) then "int" + elif ($members | all(.value | type == "number")) then "double" + else error("attribute \($key) has enum members of more than one value type, which no single Rust type can hold") + end; + def norm: gsub("[._]"; "") | ascii_downcase; + def kept($o): + stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) + | map(.attributes = (if .attributes == null then .attributes else .attributes | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) end)); + def events($o): + [.registry.events // [] | .[].name] as $bases + | (.registry.events // [] | kept($o) | map(. + {id: .name})) + + (.refinements.events // [] | map(select(.id as $id | $bases | any(. == $id) | not)) | kept($o)); + {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $opts + | (semconv_grouped_attributes($opts) | map(.attributes) | add // [] | map(.key)) as $rendered + | (events({v2: true}) + | map({key: .id, value: [(.attributes // [])[] | select(.requirement_level == "required") | .key]}) + | from_entries) as $declared_required + | events($opts) + | map(.id as $event + | (($declared_required[$event] // []) - [(.attributes // [])[] | .key]) as $dropped + | if ($dropped | length) > 0 + then error("event \($event) requires \($dropped | join(", ")), which exclude_deprecated or stable_only leaves out, so its generated Emit function could not set them") + else . end) + | map(. + (.id | ns | {namespace, prefix, short_name})) + | map(.id as $event + | .attributes |= ((. // []) | sort_by(.key) | map( + (.key | ns) as $attr_ns + | if (.key as $k | $rendered | any(. == $k)) + then . + {attr_namespace: $attr_ns.namespace, attr_short_name: $attr_ns.short_name, attr_param: $attr_ns.param} + elif ($imported_crate_paths | has($attr_ns.namespace)) + then (if (.type | type) == "object" and (((.type.members // []) | length) == 0) + then error("event \($event) references imported attribute \(.key) whose enum has no members, so no value of it could be built") + elif (.type | type) != "object" and ([.type] | inside(["string", "string[]", "int", "int[]", "double", "double[]", "boolean", "boolean[]"]) | not) + then error("event \($event) references imported attribute \(.key) of type \(.type | tostring), which the Rust template does not render") + else . end + | . + {attr_namespace: $attr_ns.namespace, attr_short_name: $attr_ns.short_name, attr_param: $attr_ns.param, + attr_import_path: ($imported_crate_paths[$attr_ns.namespace] + "::" + $attr_ns.namespace + "attr")}) + else . + {imported: true, attr_short_name: .key, attr_param: .key, + attr_type: (if (.type | type) == "object" + then (.key as $key | .type | enum_value_type($key)) + elif ([.type] | inside(["string", "string[]", "int", "int[]", "double", "double[]", "boolean", "boolean[]"])) + then .type + else error("event \($event) references imported attribute \(.key) of type \(.type | tostring), which the Rust template does not render") end)} + end))) + | map(.attributes |= map(. + {requirement_doc: (.requirement_level + | if type == "object" and has("conditionally_required") then "Conditionally required: \(.conditionally_required)" + elif type == "object" and has("recommended") then "Recommended: \(.recommended)" + elif . == "opt_in" then "Opt-in: the convention records it only when a user asks for it." + else null end)})) + | map(.required = (.attributes | map(select(.requirement_level == "required")))) + | map(if (.required | any(.attr_param == "self" or .attr_param == "Self" or .attr_param == "crate" or .attr_param == "super")) + then error("signal \(.id // .name) has a required attribute that becomes a reserved Rust parameter") else . end) + | map(.optional = (.attributes | map(select(.requirement_level != "required")))) + | map(if (.optional | any(.attr_short_name == "self" or .attr_short_name == "Self")) + then error("signal \(.id // .name) has an optional attribute that becomes the reserved Rust Self identifier") else . end) + | map( + (.required + | group_by(.attr_param | norm) + | map(select(length > 1) | map(.key) | join(" and "))) as $required_collisions + | (.optional + | group_by(.attr_short_name | norm) + | map(select(length > 1) | map(.key) | join(" and "))) as $optional_collisions + | (.optional | map(select(.attr_short_name | norm | . as $p | ["severity", "timestamp"] | any(. == $p))) | map(.key)) as $reserved + | (.required | map(select(.attr_param | norm | . as $p | ["context", "logger", "options", "option", "record", "attributes", "severity", "timestamp"] | any(. == $p))) | map(.key)) as $shadowing + | if ($required_collisions | length) > 0 + then error("event \(.id) has required attributes that render to the same Rust parameter: \($required_collisions | join("; "))") + elif ($optional_collisions | length) > 0 + then error("event \(.id) has optional attributes that render to the same Rust identifier: \($optional_collisions | join("; "))") + elif ($reserved | length) > 0 + then error("event \(.id) has optional attributes whose option would share a name with its severity or timestamp option: \($reserved | join(", "))") + elif ($shadowing | length) > 0 + then error("event \(.id) has required attributes whose Rust parameter would shadow a name its Emit function declares: \($shadowing | join(", "))") + else . end + ) + | group_by(.namespace) + | map( + ([.[] | . as $def | .id as $event | (.short_name | norm) as $short + | (["P:emit" + $short, "P:" + $short + "option", + "P:with" + $short + "severity", "P:with" + $short + "timestamp", + "p:" + $short + "option", "p:" + $short + "eventseverity", "p:" + $short + "eventtimestamp"] + + ($def.optional | map(.attr_short_name | norm) | map("P:with" + $short + ., "p:" + $short + "event" + .)))[] + | {identifier: ., name: $event}] + | group_by(.identifier) + | map(select(length > 1) | map(.name) | unique | join(" and ")) + | unique) as $collisions + | if ($collisions | length) > 0 + then error("package \(.[0].namespace)event has events that render to the same Rust identifier: \($collisions | join("; "))") + else . end + ) + | map({namespace: .[0].namespace, prefix: .[0].prefix, events: sort_by(.id), + uses_attributes: ([.[] | .attributes[] | select(.imported)] | length > 0)}) + application_mode: each + file_name: "{{ ctx.namespace }}event.rs" + + - template: entities.rs.j2 + filter: |- + def ns: if (test("^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)*$") | not) + then error("name \(.) is not a supported Rust signal identifier") else . end + | split(".") as $s + | if ($s | length) > 1 and ($vendor_prefixes | any(. == $s[0])) + then {namespace: $s[1], prefix: ($s[0:2] | join(".")), short_name: ($s[2:] | join(".")), param: ($s[1:] | join("."))} + else {namespace: $s[0], prefix: $s[0], short_name: ($s[1:] | join(".")), param: ($s | join("."))} + end | if (.namespace | test("^[a-z][a-z0-9_]*$") | not) + then error("namespace \(.namespace) is not a supported Rust module name") else . end; + def enum_value_type($key): + .members as $members + | if ($members | length) == 0 + then error("attribute \($key) has no enum members left after exclude_deprecated or stable_only, so no value of it could be built") + elif ($members | all(.value | type == "string")) then "string" + elif ($members | all(.value | type == "boolean")) then "boolean" + elif ($members | all(.value | type == "number" and . == floor)) then "int" + elif ($members | all(.value | type == "number")) then "double" + else error("attribute \($key) has enum members of more than one value type, which no single Rust type can hold") + end; + def norm: gsub("[._]"; "") | ascii_downcase; + def kept($o): + stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) + | map(.identity = (if .identity == null then .identity else .identity | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) end)) + | map(.description = (if .description == null then .description else .description | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) end)); + def entities($o): + (.registry.entities // [] | kept($o) | map(. + {id: .type})) as $entities + | ($entities | map(.type)) as $kept_bases + | $entities + (.refinements.entities // [] | map(select(.id != .type)) | kept($o) + | map(select(.type as $base | $kept_bases | any(. == $base)) | . + {refines: .type})); + def resolved($entity; $rendered): + (.key | ns) as $attr_ns + | if (.key as $k | $rendered | any(. == $k)) + then . + {attr_namespace: $attr_ns.namespace, attr_short_name: $attr_ns.short_name, attr_param: $attr_ns.param} + elif ($imported_crate_paths | has($attr_ns.namespace)) + then (if (.type | type) == "object" and (((.type.members // []) | length) == 0) + then error("entity \($entity) references imported attribute \(.key) whose enum has no members, so no value of it could be built") + elif (.type | type) != "object" and ([.type] | inside(["string", "string[]", "int", "int[]", "double", "double[]", "boolean", "boolean[]"]) | not) + then error("entity \($entity) references imported attribute \(.key) of type \(.type | tostring), which the Rust template does not render") + else . end + | . + {attr_namespace: $attr_ns.namespace, attr_short_name: $attr_ns.short_name, attr_param: $attr_ns.param, + attr_import_path: ($imported_crate_paths[$attr_ns.namespace] + "::" + $attr_ns.namespace + "attr")}) + else . + {imported: true, attr_short_name: .key, attr_param: .key, + attr_type: (if (.type | type) == "object" + then (.key as $key | .type | enum_value_type($key)) + elif ([.type] | inside(["string", "string[]", "int", "int[]", "double", "double[]", "boolean", "boolean[]"])) + then .type + else error("entity \($entity) references imported attribute \(.key) of type \(.type | tostring), which the Rust template does not render") end)} + end; + {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $opts + | (semconv_grouped_attributes($opts) | map(.attributes) | add // [] | map(.key)) as $rendered + | (entities({v2: true}) + | map({key: .id, value: [((.identity // []) + (.description // []))[] | select(.requirement_level == "required") | .key]}) + | from_entries) as $declared_required + | entities($opts) + | map(.id as $entity + | (($declared_required[$entity] // []) - [((.identity // []) + (.description // []))[] | .key]) as $dropped + | if ($dropped | length) > 0 + then error("entity \($entity) requires \($dropped | join(", ")), which exclude_deprecated or stable_only leaves out, so its generated constructor could not set them") + else . end) + | map(. + (.id | ns | {namespace, prefix, short_name})) + | map(.id as $entity + | .identity = ((.identity // []) | sort_by(.key) | map(resolved($entity; $rendered))) + | .description = ((.description // []) | sort_by(.key) | map(resolved($entity; $rendered))) + | .attributes = (.identity + .description)) + | map(. + {identity_doc: (if (.identity | length) > 0 then "Identifies the entity: " + (.identity | map("`" + .key + "`") | join(", ")) + "." else null end), + description_doc: (if (.description | length) > 0 then "Describes the entity: " + (.description | map("`" + .key + "`") | join(", ")) + "." else null end)}) + | map(.attributes |= map(. + {requirement_doc: (.requirement_level + | if type == "object" and has("conditionally_required") then "Conditionally required: \(.conditionally_required)" + elif type == "object" and has("recommended") then "Recommended: \(.recommended)" + elif . == "opt_in" then "Opt-in: the convention records it only when a user asks for it." + else null end)})) + | map(.required = (.attributes | map(select(.requirement_level == "required")))) + | map(if (.required | any(.attr_param == "self" or .attr_param == "Self" or .attr_param == "crate" or .attr_param == "super")) + then error("signal \(.id // .name) has a required attribute that becomes a reserved Rust parameter") else . end) + | map(.optional = (.attributes | map(select(.requirement_level != "required")))) + | map(if (.optional | any(.attr_short_name == "self" or .attr_short_name == "Self")) + then error("signal \(.id // .name) has an optional attribute that becomes the reserved Rust Self identifier") else . end) + | map( + (.required + | group_by(.attr_param | norm) + | map(select(length > 1) | map(.key) | join(" and "))) as $required_collisions + | (.optional + | group_by(.attr_short_name | norm) + | map(select(length > 1) | map(.key) | join(" and "))) as $optional_collisions + | (.required | map(select(.attr_param | norm | . as $p | ["attributes", "options", "option"] | any(. == $p))) | map(.key)) as $shadowing + | if ($required_collisions | length) > 0 + then error("entity \(.id) has required attributes that render to the same Rust parameter: \($required_collisions | join("; "))") + elif ($optional_collisions | length) > 0 + then error("entity \(.id) has optional attributes that render to the same Rust identifier: \($optional_collisions | join("; "))") + elif ($shadowing | length) > 0 + then error("entity \(.id) has required attributes whose Rust parameter would shadow a name its constructor declares: \($shadowing | join(", "))") + else . end + ) + | group_by(.namespace) + | map( + ([.[] | . as $def | .id as $entity | (.short_name | norm) as $short + | (["P:new" + $short + "entity", "P:" + $short + "entity"] + + (if ($def.optional | length) > 0 then ["P:" + $short + "entityattr"] else [] end) + + ($def.optional | map(.attr_short_name | norm) | map("P:with" + $short + "entity" + ., "p:" + $short + "entity" + .)))[] + | {identifier: ., name: $entity}] + | group_by(.identifier) + | map(select(length > 1) | map(.name) | unique | join(" and ")) + | unique) as $collisions + | if ($collisions | length) > 0 + then error("package \(.[0].namespace)entity has entities that render to the same Rust identifier: \($collisions | join("; "))") + else . end + ) + | map({namespace: .[0].namespace, prefix: .[0].prefix, entities: sort_by(.id), + uses_attributes: ([.[] | .attributes[]] | length > 0)}) + application_mode: each + file_name: "{{ ctx.namespace }}entity.rs" + + - template: meter.rs.j2 + filter: |- + {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $o + | if (semconv_grouped_metrics($o) | map(.metrics) | add // [] | length) > 0 then [{}] else [] end + application_mode: each + file_name: meter.rs + - template: tracer.rs.j2 + filter: |- + {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $o + | if (.registry.spans // [] | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) | length) > 0 then [{}] else [] end + application_mode: each + file_name: tracer.rs + - template: logger.rs.j2 + filter: |- + {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $o + | if ((.registry.events // []) + (.refinements.events // []) | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) | length) > 0 then [{}] else [] end + application_mode: each + file_name: logger.rs + +text_maps: + metric_instrument: + counter: Counter + updowncounter: UpDownCounter + histogram: Histogram + gauge: Gauge + rust_type: + string: String + int: i64 + double: f64 + boolean: bool + string[]: Vec + int[]: Vec + double[]: Vec + boolean[]: Vec + rust_array: + string[]: String + int[]: I64 + double[]: F64 + boolean[]: Bool + +comment_formats: + rust: + format: markdown + prefix: "/// " + trim: true +default_comment_format: rust From 2142542ba3737987cac44104c739f9538c8e8be6 Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Sun, 4 Oct 2026 20:50:37 -0400 Subject: [PATCH 02/14] refactor: keep Rust attribute namespaces easy to navigate Signed-off-by: Yordis Prieto --- templates/code/rust/README.md | 5 +- templates/code/rust/attributes.rs.j2 | 49 ++ templates/code/rust/mod.rs.j2 | 49 +- .../tests/attributes/expected/authattr.rs | 110 ++++ .../rust/tests/attributes/expected/mod.rs | 618 +----------------- .../tests/attributes/expected/myappattr.rs | 502 ++++++++++++++ .../codegen_exclusion/expected/demoattr.rs | 65 ++ .../tests/codegen_exclusion/expected/mod.rs | 68 +- .../code/rust/tests/entities/expected/mod.rs | 190 +----- .../rust/tests/entities/expected/myappattr.rs | 187 ++++++ .../code/rust/tests/events/expected/mod.rs | 222 +------ .../rust/tests/events/expected/myappattr.rs | 186 ++++++ .../rust/tests/events/expected/workerattr.rs | 30 + .../rust/tests/filtering/expected/authattr.rs | 70 ++ .../code/rust/tests/filtering/expected/mod.rs | 377 +---------- .../rust/tests/filtering/expected/taskattr.rs | 301 +++++++++ .../expected/mod.rs | 33 +- .../expected/myappattr.rs | 30 + .../expected/mod.rs | 33 +- .../expected/myappattr.rs | 30 + .../code/rust/tests/imported/expected/mod.rs | 33 +- .../rust/tests/imported/expected/myappattr.rs | 30 + .../rust/tests/imported_typed/expected/mod.rs | 33 +- .../imported_typed/expected/myappattr.rs | 30 + .../integer_boundaries/expected/demoattr.rs | 41 ++ .../tests/integer_boundaries/expected/mod.rs | 44 +- .../literal_escaping/expected/demoattr.rs | 41 ++ .../tests/literal_escaping/expected/mod.rs | 44 +- .../rust/tests/metrics/expected/authattr.rs | 70 ++ .../code/rust/tests/metrics/expected/mod.rs | 146 +---- .../rust/tests/metrics/expected/myappattr.rs | 70 ++ .../rust/tests/naming/expected/capsattr.rs | 65 ++ .../code/rust/tests/naming/expected/mod.rs | 68 +- .../no_namespace/expected/exceptionattr.rs | 59 ++ .../no_namespace/expected/heartbeatattr.rs | 59 ++ .../tests/no_namespace/expected/hostattr.rs | 59 ++ .../rust/tests/no_namespace/expected/mod.rs | 186 +----- .../rust/tests/params/expected/billingattr.rs | 59 ++ .../code/rust/tests/params/expected/mod.rs | 95 +-- .../rust/tests/params/expected/myappattr.rs | 30 + .../code/rust/tests/spans/expected/mod.rs | 193 +----- .../rust/tests/spans/expected/myappattr.rs | 128 ++++ .../rust/tests/spans/expected/workerattr.rs | 59 ++ templates/code/rust/weaver.yaml | 42 +- 44 files changed, 2418 insertions(+), 2421 deletions(-) create mode 100644 templates/code/rust/attributes.rs.j2 create mode 100644 templates/code/rust/tests/attributes/expected/authattr.rs create mode 100644 templates/code/rust/tests/attributes/expected/myappattr.rs create mode 100644 templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs create mode 100644 templates/code/rust/tests/entities/expected/myappattr.rs create mode 100644 templates/code/rust/tests/events/expected/myappattr.rs create mode 100644 templates/code/rust/tests/events/expected/workerattr.rs create mode 100644 templates/code/rust/tests/filtering/expected/authattr.rs create mode 100644 templates/code/rust/tests/filtering/expected/taskattr.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs create mode 100644 templates/code/rust/tests/imported/expected/myappattr.rs create mode 100644 templates/code/rust/tests/imported_typed/expected/myappattr.rs create mode 100644 templates/code/rust/tests/integer_boundaries/expected/demoattr.rs create mode 100644 templates/code/rust/tests/literal_escaping/expected/demoattr.rs create mode 100644 templates/code/rust/tests/metrics/expected/authattr.rs create mode 100644 templates/code/rust/tests/metrics/expected/myappattr.rs create mode 100644 templates/code/rust/tests/naming/expected/capsattr.rs create mode 100644 templates/code/rust/tests/no_namespace/expected/exceptionattr.rs create mode 100644 templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs create mode 100644 templates/code/rust/tests/no_namespace/expected/hostattr.rs create mode 100644 templates/code/rust/tests/params/expected/billingattr.rs create mode 100644 templates/code/rust/tests/params/expected/myappattr.rs create mode 100644 templates/code/rust/tests/spans/expected/myappattr.rs create mode 100644 templates/code/rust/tests/spans/expected/workerattr.rs diff --git a/templates/code/rust/README.md b/templates/code/rust/README.md index 8e41fbb..a8eb8ae 100644 --- a/templates/code/rust/README.md +++ b/templates/code/rust/README.md @@ -35,8 +35,9 @@ Keep the consuming crate's files outside that directory. ## Generated API -The root `mod.rs` carries `SCHEMA_URL` and inline attribute modules. Signals -live in sibling files declared by the root module. Names use the first dotted +The root `mod.rs` carries `SCHEMA_URL` and declares the generated modules. +Each attribute namespace lives in a sibling `attr.rs` file, alongside +the signal modules. Names use the first dotted segment as their namespace; `vendor_prefixes` removes a leading vendor segment before choosing that namespace. diff --git a/templates/code/rust/attributes.rs.j2 b/templates/code/rust/attributes.rs.j2 new file mode 100644 index 0000000..5f07737 --- /dev/null +++ b/templates/code/rust/attributes.rs.j2 @@ -0,0 +1,49 @@ +{%- filter trim %} +// Generated by OpenTelemetry Weaver. +{% for attr in ctx.attributes %} +{{ [attr.brief, attr.note] | select | join("\n\n") | comment | indent(0) }} +{{ ("#[deprecated(note = " ~ attr.deprecated_literal ~ ")]\n") if attr.deprecated_literal else "" }}#[derive(Debug, Clone, PartialEq{% if attr.type is mapping %}, Copy{% endif %})] +{% if attr.type is mapping %} +pub enum {{ attr.name }} { +{% for member in attr.type.members %} + {{ [member.brief, member.note] | select | join("\n\n") | comment | indent(4) }} + {{ ("#[deprecated(note = " ~ member.deprecated_literal ~ ")]\n ") if member.deprecated_literal else "" }}{{ member.name }}, +{% endfor %} +} +{% else %} +pub struct {{ attr.name }}({{ attr.value_type | map_text("rust_type") }}); +{% endif %} + +#[allow(deprecated)] +impl {{ attr.name }} { + pub const KEY: &'static str = {{ attr.key_literal }}; +{% if attr.type is not mapping %} + pub fn new(value: {% if attr.value_type == "string" %}impl Into{% else %}{{ attr.value_type | map_text("rust_type") }}{% endif %}) -> Self { + Self(value{% if attr.value_type == "string" %}.into(){% endif %}) + } +{% endif %} + + pub fn key_value(self) -> ::opentelemetry::KeyValue { +{% if attr.type is mapping %} + let value: {{ attr.value_type | map_text("rust_type") }} = match self { +{% for member in attr.type.members %} + Self::{{ member.name }} => {{ member.literal }}{% if attr.value_type == "string" %}.into(){% elif attr.value_type == "double" %}_f64{% endif %}, +{% endfor %} + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) +{% elif "[]" in attr.value_type %} + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::{{ attr.value_type | map_text("rust_array") }}(self.0{% if attr.value_type == "string[]" %}.into_iter().map(Into::into).collect(){% endif %}))) +{% else %} + ::opentelemetry::KeyValue::new(Self::KEY, self.0) +{% endif %} + } +} + +#[allow(deprecated)] +impl From<{{ attr.name }}> for ::opentelemetry::KeyValue { + fn from(value: {{ attr.name }}) -> Self { + value.key_value() + } +} +{% endfor %} +{% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/mod.rs.j2 b/templates/code/rust/mod.rs.j2 index 417c469..0eba441 100644 --- a/templates/code/rust/mod.rs.j2 +++ b/templates/code/rust/mod.rs.j2 @@ -9,54 +9,7 @@ {% endif %} pub const SCHEMA_URL: &str = {{ ctx.schema_literal }}; {% for namespace in ctx.namespaces %} -pub mod {{ namespace.name }} { -{% for attr in namespace.attributes %} - {{ [attr.brief, attr.note] | select | join("\n\n") | comment | indent(4) }} - {{ ("#[deprecated(note = " ~ attr.deprecated_literal ~ ")]\n ") if attr.deprecated_literal else "" }}#[derive(Debug, Clone, PartialEq{% if attr.type is mapping %}, Copy{% endif %})] -{% if attr.type is mapping %} - pub enum {{ attr.name }} { -{% for member in attr.type.members %} - {{ [member.brief, member.note] | select | join("\n\n") | comment | indent(8) }} - {{ ("#[deprecated(note = " ~ member.deprecated_literal ~ ")]\n ") if member.deprecated_literal else "" }}{{ member.name }}, -{% endfor %} - } -{% else %} - pub struct {{ attr.name }}({{ attr.value_type | map_text("rust_type") }}); -{% endif %} - - #[allow(deprecated)] - impl {{ attr.name }} { - pub const KEY: &'static str = {{ attr.key_literal }}; -{% if attr.type is not mapping %} - pub fn new(value: {% if attr.value_type == "string" %}impl Into{% else %}{{ attr.value_type | map_text("rust_type") }}{% endif %}) -> Self { - Self(value{% if attr.value_type == "string" %}.into(){% endif %}) - } -{% endif %} - - pub fn key_value(self) -> ::opentelemetry::KeyValue { -{% if attr.type is mapping %} - let value: {{ attr.value_type | map_text("rust_type") }} = match self { -{% for member in attr.type.members %} - Self::{{ member.name }} => {{ member.literal }}{% if attr.value_type == "string" %}.into(){% elif attr.value_type == "double" %}_f64{% endif %}, -{% endfor %} - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) -{% elif "[]" in attr.value_type %} - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::{{ attr.value_type | map_text("rust_array") }}(self.0{% if attr.value_type == "string[]" %}.into_iter().map(Into::into).collect(){% endif %}))) -{% else %} - ::opentelemetry::KeyValue::new(Self::KEY, self.0) -{% endif %} - } - } - - #[allow(deprecated)] - impl From<{{ attr.name }}> for ::opentelemetry::KeyValue { - fn from(value: {{ attr.name }}) -> Self { - value.key_value() - } - } -{% endfor %} -} +pub mod {{ namespace }}; {% endfor %} {% if ctx.has_metrics %}pub mod meter;{% endif %} diff --git a/templates/code/rust/tests/attributes/expected/authattr.rs b/templates/code/rust/tests/attributes/expected/authattr.rs new file mode 100644 index 0000000..ed79374 --- /dev/null +++ b/templates/code/rust/tests/attributes/expected/authattr.rs @@ -0,0 +1,110 @@ +// Generated by OpenTelemetry Weaver. + +/// Assurance level of the authentication. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum LevelAttr { + + /// Single factor. + Low, + + /// Multiple factors. + High, + +} + + +#[allow(deprecated)] +impl LevelAttr { + pub const KEY: &'static str = "auth.level"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: i64 = match self { + + Self::Low => 1, + + Self::High => 2, + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: LevelAttr) -> Self { + value.key_value() + } +} + +/// How the user was authenticated. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum MethodAttr { + + /// A password was checked. + Password, + + /// A bearer token was checked. + Token, + +} + + +#[allow(deprecated)] +impl MethodAttr { + pub const KEY: &'static str = "auth.method"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Password => "password".into(), + + Self::Token => "token".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: MethodAttr) -> Self { + value.key_value() + } +} + +/// Identifier of the authenticated user. +#[derive(Debug, Clone, PartialEq)] + +pub struct UserIdAttr(String); + + +#[allow(deprecated)] +impl UserIdAttr { + pub const KEY: &'static str = "auth.user.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: UserIdAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/attributes/expected/mod.rs b/templates/code/rust/tests/attributes/expected/mod.rs index 2700729..3dadc9e 100644 --- a/templates/code/rust/tests/attributes/expected/mod.rs +++ b/templates/code/rust/tests/attributes/expected/mod.rs @@ -3,620 +3,6 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/attributes/1.0.0"; -pub mod authattr { +pub mod authattr; - /// Assurance level of the authentication. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum LevelAttr { - - /// Single factor. - Low, - - /// Multiple factors. - High, - - } - - - #[allow(deprecated)] - impl LevelAttr { - pub const KEY: &'static str = "auth.level"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: i64 = match self { - - Self::Low => 1, - - Self::High => 2, - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: LevelAttr) -> Self { - value.key_value() - } - } - - /// How the user was authenticated. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum MethodAttr { - - /// A password was checked. - Password, - - /// A bearer token was checked. - Token, - - } - - - #[allow(deprecated)] - impl MethodAttr { - pub const KEY: &'static str = "auth.method"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Password => "password".into(), - - Self::Token => "token".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: MethodAttr) -> Self { - value.key_value() - } - } - - /// Identifier of the authenticated user. - #[derive(Debug, Clone, PartialEq)] - - pub struct UserIdAttr(String); - - - #[allow(deprecated)] - impl UserIdAttr { - pub const KEY: &'static str = "auth.user.id"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: UserIdAttr) -> Self { - value.key_value() - } - } - -} - -pub mod myappattr { - - /// Who assigned the task. - /// - /// The scheduler sets it on every task it passes along to `myapp.task.state`. Workers never set it themselves. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskAssignedByAttr(String); - - - #[allow(deprecated)] - impl TaskAssignedByAttr { - pub const KEY: &'static str = "myapp.task.assigned_by"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskAssignedByAttr) -> Self { - value.key_value() - } - } - - /// Whether the task was cancelled. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskCancelledAttr(bool); - - - #[allow(deprecated)] - impl TaskCancelledAttr { - pub const KEY: &'static str = "myapp.task.cancelled"; - - pub fn new(value: bool) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskCancelledAttr) -> Self { - value.key_value() - } - } - - /// Tests Rust string literals. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum TaskEscapedAttr { - - /// Escaped text. - Quoted, - - } - - - #[allow(deprecated)] - impl TaskEscapedAttr { - pub const KEY: &'static str = "myapp.task.escaped"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Quoted => "quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskEscapedAttr) -> Self { - value.key_value() - } - } - - /// Feature flags evaluated for the task. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskFlagsAttr(Vec); - - - #[allow(deprecated)] - impl TaskFlagsAttr { - pub const KEY: &'static str = "myapp.task.flags"; - - pub fn new(value: Vec) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(self.0))) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskFlagsAttr) -> Self { - value.key_value() - } - } - - /// Unique identifier of the task. - /// - /// The identifier is assigned by the scheduler and stays stable across retries. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskIdAttr(String); - - - #[allow(deprecated)] - impl TaskIdAttr { - pub const KEY: &'static str = "myapp.task.id"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskIdAttr) -> Self { - value.key_value() - } - } - - /// Lane the task was scheduled in. - #[deprecated(note = "Lanes were replaced by priorities.")] - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum TaskLaneAttr { - - /// The fast lane. - #[deprecated(note = "Lanes were replaced by priorities.")] - Fast, - - /// The slow lane. - #[deprecated(note = "Every task runs in the fast lane.")] - Slow, - - } - - - #[allow(deprecated)] - impl TaskLaneAttr { - pub const KEY: &'static str = "myapp.task.lane"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Fast => "fast".into(), - - Self::Slow => "slow".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskLaneAttr) -> Self { - value.key_value() - } - } - - /// Owner of the task. - #[deprecated(note = "Replaced by `auth.user.id`.")] - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskOwnerAttr(String); - - - #[allow(deprecated)] - impl TaskOwnerAttr { - pub const KEY: &'static str = "myapp.task.owner"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskOwnerAttr) -> Self { - value.key_value() - } - } - - /// Whether the scheduler may preempt the task. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum TaskPreemptibleAttr { - - /// The scheduler may preempt the task. - Allowed, - - /// The task runs to completion. - Forbidden, - - } - - - #[allow(deprecated)] - impl TaskPreemptibleAttr { - pub const KEY: &'static str = "myapp.task.preemptible"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: bool = match self { - - Self::Allowed => true, - - Self::Forbidden => false, - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskPreemptibleAttr) -> Self { - value.key_value() - } - } - - /// Fraction of the task that has completed, between 0 and 1. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskProgressAttr(f64); - - - #[allow(deprecated)] - impl TaskProgressAttr { - pub const KEY: &'static str = "myapp.task.progress"; - - pub fn new(value: f64) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskProgressAttr) -> Self { - value.key_value() - } - } - - /// Number of times the task was retried. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskRetriesAttr(i64); - - - #[allow(deprecated)] - impl TaskRetriesAttr { - pub const KEY: &'static str = "myapp.task.retries"; - - pub fn new(value: i64) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskRetriesAttr) -> Self { - value.key_value() - } - } - - /// Fraction of tasks whose telemetry is sampled. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum TaskSampleRateAttr { - - /// One task in ten is sampled. - Tenth, - - /// Every task is sampled. - All, - - } - - - #[allow(deprecated)] - impl TaskSampleRateAttr { - pub const KEY: &'static str = "myapp.task.sample_rate"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: f64 = match self { - - Self::Tenth => 0.1_f64, - - Self::All => 1_f64, - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskSampleRateAttr) -> Self { - value.key_value() - } - } - - /// Shards the task touched. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskShardIdsAttr(Vec); - - - #[allow(deprecated)] - impl TaskShardIdsAttr { - pub const KEY: &'static str = "myapp.task.shard_ids"; - - pub fn new(value: Vec) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskShardIdsAttr) -> Self { - value.key_value() - } - } - - /// Current state of the task. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum TaskStateAttr { - - /// The task is waiting to run. - Queued, - - /// The task is running. - /// - /// A task stays running until it finishes or is cancelled. - Running, - - /// The task was paused. - #[deprecated(note = "Paused tasks are reported as queued.")] - Paused, - - } - - - #[allow(deprecated)] - impl TaskStateAttr { - pub const KEY: &'static str = "myapp.task.state"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Queued => "queued".into(), - - Self::Running => "running".into(), - - Self::Paused => "paused".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskStateAttr) -> Self { - value.key_value() - } - } - - /// Tags attached to the task. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskTagsAttr(Vec); - - - #[allow(deprecated)] - impl TaskTagsAttr { - pub const KEY: &'static str = "myapp.task.tags"; - - pub fn new(value: Vec) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskTagsAttr) -> Self { - value.key_value() - } - } - - /// Scheduling weights applied to the task. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskWeightsAttr(Vec); - - - #[allow(deprecated)] - impl TaskWeightsAttr { - pub const KEY: &'static str = "myapp.task.weights"; - - pub fn new(value: Vec) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(self.0))) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskWeightsAttr) -> Self { - value.key_value() - } - } - -} +pub mod myappattr; diff --git a/templates/code/rust/tests/attributes/expected/myappattr.rs b/templates/code/rust/tests/attributes/expected/myappattr.rs new file mode 100644 index 0000000..1a5b632 --- /dev/null +++ b/templates/code/rust/tests/attributes/expected/myappattr.rs @@ -0,0 +1,502 @@ +// Generated by OpenTelemetry Weaver. + +/// Who assigned the task. +/// +/// The scheduler sets it on every task it passes along to `myapp.task.state`. Workers never set it themselves. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskAssignedByAttr(String); + + +#[allow(deprecated)] +impl TaskAssignedByAttr { + pub const KEY: &'static str = "myapp.task.assigned_by"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskAssignedByAttr) -> Self { + value.key_value() + } +} + +/// Whether the task was cancelled. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskCancelledAttr(bool); + + +#[allow(deprecated)] +impl TaskCancelledAttr { + pub const KEY: &'static str = "myapp.task.cancelled"; + + pub fn new(value: bool) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskCancelledAttr) -> Self { + value.key_value() + } +} + +/// Tests Rust string literals. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum TaskEscapedAttr { + + /// Escaped text. + Quoted, + +} + + +#[allow(deprecated)] +impl TaskEscapedAttr { + pub const KEY: &'static str = "myapp.task.escaped"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Quoted => "quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskEscapedAttr) -> Self { + value.key_value() + } +} + +/// Feature flags evaluated for the task. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskFlagsAttr(Vec); + + +#[allow(deprecated)] +impl TaskFlagsAttr { + pub const KEY: &'static str = "myapp.task.flags"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(self.0))) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskFlagsAttr) -> Self { + value.key_value() + } +} + +/// Unique identifier of the task. +/// +/// The identifier is assigned by the scheduler and stays stable across retries. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskIdAttr(String); + + +#[allow(deprecated)] +impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } +} + +/// Lane the task was scheduled in. +#[deprecated(note = "Lanes were replaced by priorities.")] +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum TaskLaneAttr { + + /// The fast lane. + #[deprecated(note = "Lanes were replaced by priorities.")] + Fast, + + /// The slow lane. + #[deprecated(note = "Every task runs in the fast lane.")] + Slow, + +} + + +#[allow(deprecated)] +impl TaskLaneAttr { + pub const KEY: &'static str = "myapp.task.lane"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Fast => "fast".into(), + + Self::Slow => "slow".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskLaneAttr) -> Self { + value.key_value() + } +} + +/// Owner of the task. +#[deprecated(note = "Replaced by `auth.user.id`.")] +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskOwnerAttr(String); + + +#[allow(deprecated)] +impl TaskOwnerAttr { + pub const KEY: &'static str = "myapp.task.owner"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskOwnerAttr) -> Self { + value.key_value() + } +} + +/// Whether the scheduler may preempt the task. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum TaskPreemptibleAttr { + + /// The scheduler may preempt the task. + Allowed, + + /// The task runs to completion. + Forbidden, + +} + + +#[allow(deprecated)] +impl TaskPreemptibleAttr { + pub const KEY: &'static str = "myapp.task.preemptible"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: bool = match self { + + Self::Allowed => true, + + Self::Forbidden => false, + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskPreemptibleAttr) -> Self { + value.key_value() + } +} + +/// Fraction of the task that has completed, between 0 and 1. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskProgressAttr(f64); + + +#[allow(deprecated)] +impl TaskProgressAttr { + pub const KEY: &'static str = "myapp.task.progress"; + + pub fn new(value: f64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskProgressAttr) -> Self { + value.key_value() + } +} + +/// Number of times the task was retried. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskRetriesAttr(i64); + + +#[allow(deprecated)] +impl TaskRetriesAttr { + pub const KEY: &'static str = "myapp.task.retries"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskRetriesAttr) -> Self { + value.key_value() + } +} + +/// Fraction of tasks whose telemetry is sampled. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum TaskSampleRateAttr { + + /// One task in ten is sampled. + Tenth, + + /// Every task is sampled. + All, + +} + + +#[allow(deprecated)] +impl TaskSampleRateAttr { + pub const KEY: &'static str = "myapp.task.sample_rate"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: f64 = match self { + + Self::Tenth => 0.1_f64, + + Self::All => 1_f64, + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskSampleRateAttr) -> Self { + value.key_value() + } +} + +/// Shards the task touched. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskShardIdsAttr(Vec); + + +#[allow(deprecated)] +impl TaskShardIdsAttr { + pub const KEY: &'static str = "myapp.task.shard_ids"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskShardIdsAttr) -> Self { + value.key_value() + } +} + +/// Current state of the task. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum TaskStateAttr { + + /// The task is waiting to run. + Queued, + + /// The task is running. + /// + /// A task stays running until it finishes or is cancelled. + Running, + + /// The task was paused. + #[deprecated(note = "Paused tasks are reported as queued.")] + Paused, + +} + + +#[allow(deprecated)] +impl TaskStateAttr { + pub const KEY: &'static str = "myapp.task.state"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Queued => "queued".into(), + + Self::Running => "running".into(), + + Self::Paused => "paused".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskStateAttr) -> Self { + value.key_value() + } +} + +/// Tags attached to the task. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskTagsAttr(Vec); + + +#[allow(deprecated)] +impl TaskTagsAttr { + pub const KEY: &'static str = "myapp.task.tags"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskTagsAttr) -> Self { + value.key_value() + } +} + +/// Scheduling weights applied to the task. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskWeightsAttr(Vec); + + +#[allow(deprecated)] +impl TaskWeightsAttr { + pub const KEY: &'static str = "myapp.task.weights"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(self.0))) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskWeightsAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs new file mode 100644 index 0000000..432fe83 --- /dev/null +++ b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs @@ -0,0 +1,65 @@ +// Generated by OpenTelemetry Weaver. + +/// Synthetic kept attribute. +#[derive(Debug, Clone, PartialEq)] + +pub struct KeptAttr(String); + + +#[allow(deprecated)] +impl KeptAttr { + pub const KEY: &'static str = "demo.kept"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: KeptAttr) -> Self { + value.key_value() + } +} + +/// Synthetic mode. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum ModeAttr { + + /// Included mode. + Kept, + +} + + +#[allow(deprecated)] +impl ModeAttr { + pub const KEY: &'static str = "demo.mode"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Kept => "kept".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: ModeAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/codegen_exclusion/expected/mod.rs b/templates/code/rust/tests/codegen_exclusion/expected/mod.rs index d166f41..5fe343d 100644 --- a/templates/code/rust/tests/codegen_exclusion/expected/mod.rs +++ b/templates/code/rust/tests/codegen_exclusion/expected/mod.rs @@ -3,70 +3,4 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/exclusion/1.0.0"; -pub mod demoattr { - - /// Synthetic kept attribute. - #[derive(Debug, Clone, PartialEq)] - - pub struct KeptAttr(String); - - - #[allow(deprecated)] - impl KeptAttr { - pub const KEY: &'static str = "demo.kept"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: KeptAttr) -> Self { - value.key_value() - } - } - - /// Synthetic mode. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum ModeAttr { - - /// Included mode. - Kept, - - } - - - #[allow(deprecated)] - impl ModeAttr { - pub const KEY: &'static str = "demo.mode"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Kept => "kept".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: ModeAttr) -> Self { - value.key_value() - } - } - -} +pub mod demoattr; diff --git a/templates/code/rust/tests/entities/expected/mod.rs b/templates/code/rust/tests/entities/expected/mod.rs index 4886371..cf054c4 100644 --- a/templates/code/rust/tests/entities/expected/mod.rs +++ b/templates/code/rust/tests/entities/expected/mod.rs @@ -3,195 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/entities/1.0.0"; -pub mod myappattr { - - /// Number of CPUs the host has. - #[deprecated(note = "Use `myapp.host.cpu.logical_count` instead.")] - #[derive(Debug, Clone, PartialEq)] - - pub struct HostCpuCountAttr(i64); - - - #[allow(deprecated)] - impl HostCpuCountAttr { - pub const KEY: &'static str = "myapp.host.cpu.count"; - - pub fn new(value: i64) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: HostCpuCountAttr) -> Self { - value.key_value() - } - } - - /// Name of the host. - #[derive(Debug, Clone, PartialEq)] - - pub struct HostNameAttr(String); - - - #[allow(deprecated)] - impl HostNameAttr { - pub const KEY: &'static str = "myapp.host.name"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: HostNameAttr) -> Self { - value.key_value() - } - } - - /// Role the host plays in the cluster. - #[derive(Debug, Clone, PartialEq)] - - pub struct HostRoleAttr(String); - - - #[allow(deprecated)] - impl HostRoleAttr { - pub const KEY: &'static str = "myapp.host.role"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: HostRoleAttr) -> Self { - value.key_value() - } - } - - /// Type of the host. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum HostTypeAttr { - - /// A physical host. - Physical, - - /// A virtual host. - Virtual, - - } - - - #[allow(deprecated)] - impl HostTypeAttr { - pub const KEY: &'static str = "myapp.host.type"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Physical => "physical".into(), - - Self::Virtual => "virtual".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: HostTypeAttr) -> Self { - value.key_value() - } - } - - /// Name of the queue. - #[derive(Debug, Clone, PartialEq)] - - pub struct QueueNameAttr(String); - - - #[allow(deprecated)] - impl QueueNameAttr { - pub const KEY: &'static str = "myapp.queue.name"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: QueueNameAttr) -> Self { - value.key_value() - } - } - - /// Number of items currently in the queue. - #[derive(Debug, Clone, PartialEq)] - - pub struct QueueSizeAttr(i64); - - - #[allow(deprecated)] - impl QueueSizeAttr { - pub const KEY: &'static str = "myapp.queue.size"; - - pub fn new(value: i64) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: QueueSizeAttr) -> Self { - value.key_value() - } - } - -} +pub mod myappattr; diff --git a/templates/code/rust/tests/entities/expected/myappattr.rs b/templates/code/rust/tests/entities/expected/myappattr.rs new file mode 100644 index 0000000..5ef1a7d --- /dev/null +++ b/templates/code/rust/tests/entities/expected/myappattr.rs @@ -0,0 +1,187 @@ +// Generated by OpenTelemetry Weaver. + +/// Number of CPUs the host has. +#[deprecated(note = "Use `myapp.host.cpu.logical_count` instead.")] +#[derive(Debug, Clone, PartialEq)] + +pub struct HostCpuCountAttr(i64); + + +#[allow(deprecated)] +impl HostCpuCountAttr { + pub const KEY: &'static str = "myapp.host.cpu.count"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: HostCpuCountAttr) -> Self { + value.key_value() + } +} + +/// Name of the host. +#[derive(Debug, Clone, PartialEq)] + +pub struct HostNameAttr(String); + + +#[allow(deprecated)] +impl HostNameAttr { + pub const KEY: &'static str = "myapp.host.name"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: HostNameAttr) -> Self { + value.key_value() + } +} + +/// Role the host plays in the cluster. +#[derive(Debug, Clone, PartialEq)] + +pub struct HostRoleAttr(String); + + +#[allow(deprecated)] +impl HostRoleAttr { + pub const KEY: &'static str = "myapp.host.role"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: HostRoleAttr) -> Self { + value.key_value() + } +} + +/// Type of the host. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum HostTypeAttr { + + /// A physical host. + Physical, + + /// A virtual host. + Virtual, + +} + + +#[allow(deprecated)] +impl HostTypeAttr { + pub const KEY: &'static str = "myapp.host.type"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Physical => "physical".into(), + + Self::Virtual => "virtual".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: HostTypeAttr) -> Self { + value.key_value() + } +} + +/// Name of the queue. +#[derive(Debug, Clone, PartialEq)] + +pub struct QueueNameAttr(String); + + +#[allow(deprecated)] +impl QueueNameAttr { + pub const KEY: &'static str = "myapp.queue.name"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: QueueNameAttr) -> Self { + value.key_value() + } +} + +/// Number of items currently in the queue. +#[derive(Debug, Clone, PartialEq)] + +pub struct QueueSizeAttr(i64); + + +#[allow(deprecated)] +impl QueueSizeAttr { + pub const KEY: &'static str = "myapp.queue.size"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: QueueSizeAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/events/expected/mod.rs b/templates/code/rust/tests/events/expected/mod.rs index 98b132e..81e6b53 100644 --- a/templates/code/rust/tests/events/expected/mod.rs +++ b/templates/code/rust/tests/events/expected/mod.rs @@ -3,227 +3,9 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/events/1.0.0"; -pub mod myappattr { +pub mod myappattr; - /// Synthetic bool values. - #[derive(Debug, Clone, PartialEq)] - - pub struct BoolValuesAttr(Vec); - - - #[allow(deprecated)] - impl BoolValuesAttr { - pub const KEY: &'static str = "myapp.bool.values"; - - pub fn new(value: Vec) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(self.0))) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: BoolValuesAttr) -> Self { - value.key_value() - } - } - - /// Synthetic double values. - #[derive(Debug, Clone, PartialEq)] - - pub struct DoubleValuesAttr(Vec); - - - #[allow(deprecated)] - impl DoubleValuesAttr { - pub const KEY: &'static str = "myapp.double.values"; - - pub fn new(value: Vec) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(self.0))) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: DoubleValuesAttr) -> Self { - value.key_value() - } - } - - /// Synthetic int values. - #[derive(Debug, Clone, PartialEq)] - - pub struct IntValuesAttr(Vec); - - - #[allow(deprecated)] - impl IntValuesAttr { - pub const KEY: &'static str = "myapp.int.values"; - - pub fn new(value: Vec) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: IntValuesAttr) -> Self { - value.key_value() - } - } - - /// Synthetic string values. - #[derive(Debug, Clone, PartialEq)] - - pub struct StringValuesAttr(Vec); - - - #[allow(deprecated)] - impl StringValuesAttr { - pub const KEY: &'static str = "myapp.string.values"; - - pub fn new(value: Vec) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: StringValuesAttr) -> Self { - value.key_value() - } - } - - /// Number of the attempt, starting at 1. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskAttemptAttr(i64); - - - #[allow(deprecated)] - impl TaskAttemptAttr { - pub const KEY: &'static str = "myapp.task.attempt"; - - pub fn new(value: i64) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskAttemptAttr) -> Self { - value.key_value() - } - } - - /// Current state of the task. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum TaskStateAttr { - - /// The task finished. - Done, - - /// The task gave up. - Failed, - - } - - - #[allow(deprecated)] - impl TaskStateAttr { - pub const KEY: &'static str = "myapp.task.state"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Done => "done".into(), - - Self::Failed => "failed".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskStateAttr) -> Self { - value.key_value() - } - } - -} - -pub mod workerattr { - - /// Name of the worker host. - #[derive(Debug, Clone, PartialEq)] - - pub struct HostNameAttr(String); - - - #[allow(deprecated)] - impl HostNameAttr { - pub const KEY: &'static str = "worker.host.name"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: HostNameAttr) -> Self { - value.key_value() - } - } - -} +pub mod workerattr; diff --git a/templates/code/rust/tests/events/expected/myappattr.rs b/templates/code/rust/tests/events/expected/myappattr.rs new file mode 100644 index 0000000..d72e442 --- /dev/null +++ b/templates/code/rust/tests/events/expected/myappattr.rs @@ -0,0 +1,186 @@ +// Generated by OpenTelemetry Weaver. + +/// Synthetic bool values. +#[derive(Debug, Clone, PartialEq)] + +pub struct BoolValuesAttr(Vec); + + +#[allow(deprecated)] +impl BoolValuesAttr { + pub const KEY: &'static str = "myapp.bool.values"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(self.0))) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: BoolValuesAttr) -> Self { + value.key_value() + } +} + +/// Synthetic double values. +#[derive(Debug, Clone, PartialEq)] + +pub struct DoubleValuesAttr(Vec); + + +#[allow(deprecated)] +impl DoubleValuesAttr { + pub const KEY: &'static str = "myapp.double.values"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(self.0))) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: DoubleValuesAttr) -> Self { + value.key_value() + } +} + +/// Synthetic int values. +#[derive(Debug, Clone, PartialEq)] + +pub struct IntValuesAttr(Vec); + + +#[allow(deprecated)] +impl IntValuesAttr { + pub const KEY: &'static str = "myapp.int.values"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: IntValuesAttr) -> Self { + value.key_value() + } +} + +/// Synthetic string values. +#[derive(Debug, Clone, PartialEq)] + +pub struct StringValuesAttr(Vec); + + +#[allow(deprecated)] +impl StringValuesAttr { + pub const KEY: &'static str = "myapp.string.values"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: StringValuesAttr) -> Self { + value.key_value() + } +} + +/// Number of the attempt, starting at 1. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskAttemptAttr(i64); + + +#[allow(deprecated)] +impl TaskAttemptAttr { + pub const KEY: &'static str = "myapp.task.attempt"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskAttemptAttr) -> Self { + value.key_value() + } +} + +/// Current state of the task. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum TaskStateAttr { + + /// The task finished. + Done, + + /// The task gave up. + Failed, + +} + + +#[allow(deprecated)] +impl TaskStateAttr { + pub const KEY: &'static str = "myapp.task.state"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Done => "done".into(), + + Self::Failed => "failed".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskStateAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/events/expected/workerattr.rs b/templates/code/rust/tests/events/expected/workerattr.rs new file mode 100644 index 0000000..4146047 --- /dev/null +++ b/templates/code/rust/tests/events/expected/workerattr.rs @@ -0,0 +1,30 @@ +// Generated by OpenTelemetry Weaver. + +/// Name of the worker host. +#[derive(Debug, Clone, PartialEq)] + +pub struct HostNameAttr(String); + + +#[allow(deprecated)] +impl HostNameAttr { + pub const KEY: &'static str = "worker.host.name"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: HostNameAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/filtering/expected/authattr.rs b/templates/code/rust/tests/filtering/expected/authattr.rs new file mode 100644 index 0000000..c577061 --- /dev/null +++ b/templates/code/rust/tests/filtering/expected/authattr.rs @@ -0,0 +1,70 @@ +// Generated by OpenTelemetry Weaver. + +/// How the user was authenticated. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum MethodAttr { + + /// A password was checked. + Password, + + /// A bearer token was checked. + Token, + +} + + +#[allow(deprecated)] +impl MethodAttr { + pub const KEY: &'static str = "auth.method"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Password => "password".into(), + + Self::Token => "token".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: MethodAttr) -> Self { + value.key_value() + } +} + +/// Identifier of the authenticated user. +#[derive(Debug, Clone, PartialEq)] + +pub struct UserIdAttr(String); + + +#[allow(deprecated)] +impl UserIdAttr { + pub const KEY: &'static str = "auth.user.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: UserIdAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/filtering/expected/mod.rs b/templates/code/rust/tests/filtering/expected/mod.rs index f0375f2..2729cec 100644 --- a/templates/code/rust/tests/filtering/expected/mod.rs +++ b/templates/code/rust/tests/filtering/expected/mod.rs @@ -3,379 +3,6 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/filtering/1.0.0"; -pub mod authattr { +pub mod authattr; - /// How the user was authenticated. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum MethodAttr { - - /// A password was checked. - Password, - - /// A bearer token was checked. - Token, - - } - - - #[allow(deprecated)] - impl MethodAttr { - pub const KEY: &'static str = "auth.method"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Password => "password".into(), - - Self::Token => "token".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: MethodAttr) -> Self { - value.key_value() - } - } - - /// Identifier of the authenticated user. - #[derive(Debug, Clone, PartialEq)] - - pub struct UserIdAttr(String); - - - #[allow(deprecated)] - impl UserIdAttr { - pub const KEY: &'static str = "auth.user.id"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: UserIdAttr) -> Self { - value.key_value() - } - } - -} - -pub mod taskattr { - - /// Who assigned the task. - /// - /// The scheduler sets it on every task it passes along to `myapp.task.state`. Workers never set it themselves. - #[derive(Debug, Clone, PartialEq)] - - pub struct AssignedByAttr(String); - - - #[allow(deprecated)] - impl AssignedByAttr { - pub const KEY: &'static str = "myapp.task.assigned_by"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: AssignedByAttr) -> Self { - value.key_value() - } - } - - /// Whether the task was cancelled. - #[derive(Debug, Clone, PartialEq)] - - pub struct CancelledAttr(bool); - - - #[allow(deprecated)] - impl CancelledAttr { - pub const KEY: &'static str = "myapp.task.cancelled"; - - pub fn new(value: bool) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: CancelledAttr) -> Self { - value.key_value() - } - } - - /// Unique identifier of the task. - /// - /// The identifier is assigned by the scheduler and stays stable across retries. - #[derive(Debug, Clone, PartialEq)] - - pub struct IdAttr(String); - - - #[allow(deprecated)] - impl IdAttr { - pub const KEY: &'static str = "myapp.task.id"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: IdAttr) -> Self { - value.key_value() - } - } - - /// Whether the scheduler may preempt the task. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum PreemptibleAttr { - - /// The scheduler may preempt the task. - Allowed, - - /// The task runs to completion. - Forbidden, - - } - - - #[allow(deprecated)] - impl PreemptibleAttr { - pub const KEY: &'static str = "myapp.task.preemptible"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: bool = match self { - - Self::Allowed => true, - - Self::Forbidden => false, - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: PreemptibleAttr) -> Self { - value.key_value() - } - } - - /// Number of times the task was retried. - #[derive(Debug, Clone, PartialEq)] - - pub struct RetriesAttr(i64); - - - #[allow(deprecated)] - impl RetriesAttr { - pub const KEY: &'static str = "myapp.task.retries"; - - pub fn new(value: i64) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: RetriesAttr) -> Self { - value.key_value() - } - } - - /// Fraction of tasks whose telemetry is sampled. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum SampleRateAttr { - - /// One task in ten is sampled. - Tenth, - - /// Every task is sampled. - All, - - } - - - #[allow(deprecated)] - impl SampleRateAttr { - pub const KEY: &'static str = "myapp.task.sample_rate"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: f64 = match self { - - Self::Tenth => 0.1_f64, - - Self::All => 1_f64, - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: SampleRateAttr) -> Self { - value.key_value() - } - } - - /// Shards the task touched. - #[derive(Debug, Clone, PartialEq)] - - pub struct ShardIdsAttr(Vec); - - - #[allow(deprecated)] - impl ShardIdsAttr { - pub const KEY: &'static str = "myapp.task.shard_ids"; - - pub fn new(value: Vec) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: ShardIdsAttr) -> Self { - value.key_value() - } - } - - /// Current state of the task. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum StateAttr { - - /// The task is waiting to run. - Queued, - - /// The task is running. - /// - /// A task stays running until it finishes or is cancelled. - Running, - - } - - - #[allow(deprecated)] - impl StateAttr { - pub const KEY: &'static str = "myapp.task.state"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Queued => "queued".into(), - - Self::Running => "running".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: StateAttr) -> Self { - value.key_value() - } - } - - /// Tags attached to the task. - #[derive(Debug, Clone, PartialEq)] - - pub struct TagsAttr(Vec); - - - #[allow(deprecated)] - impl TagsAttr { - pub const KEY: &'static str = "myapp.task.tags"; - - pub fn new(value: Vec) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TagsAttr) -> Self { - value.key_value() - } - } - -} +pub mod taskattr; diff --git a/templates/code/rust/tests/filtering/expected/taskattr.rs b/templates/code/rust/tests/filtering/expected/taskattr.rs new file mode 100644 index 0000000..ff3d95b --- /dev/null +++ b/templates/code/rust/tests/filtering/expected/taskattr.rs @@ -0,0 +1,301 @@ +// Generated by OpenTelemetry Weaver. + +/// Who assigned the task. +/// +/// The scheduler sets it on every task it passes along to `myapp.task.state`. Workers never set it themselves. +#[derive(Debug, Clone, PartialEq)] + +pub struct AssignedByAttr(String); + + +#[allow(deprecated)] +impl AssignedByAttr { + pub const KEY: &'static str = "myapp.task.assigned_by"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: AssignedByAttr) -> Self { + value.key_value() + } +} + +/// Whether the task was cancelled. +#[derive(Debug, Clone, PartialEq)] + +pub struct CancelledAttr(bool); + + +#[allow(deprecated)] +impl CancelledAttr { + pub const KEY: &'static str = "myapp.task.cancelled"; + + pub fn new(value: bool) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: CancelledAttr) -> Self { + value.key_value() + } +} + +/// Unique identifier of the task. +/// +/// The identifier is assigned by the scheduler and stays stable across retries. +#[derive(Debug, Clone, PartialEq)] + +pub struct IdAttr(String); + + +#[allow(deprecated)] +impl IdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: IdAttr) -> Self { + value.key_value() + } +} + +/// Whether the scheduler may preempt the task. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum PreemptibleAttr { + + /// The scheduler may preempt the task. + Allowed, + + /// The task runs to completion. + Forbidden, + +} + + +#[allow(deprecated)] +impl PreemptibleAttr { + pub const KEY: &'static str = "myapp.task.preemptible"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: bool = match self { + + Self::Allowed => true, + + Self::Forbidden => false, + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: PreemptibleAttr) -> Self { + value.key_value() + } +} + +/// Number of times the task was retried. +#[derive(Debug, Clone, PartialEq)] + +pub struct RetriesAttr(i64); + + +#[allow(deprecated)] +impl RetriesAttr { + pub const KEY: &'static str = "myapp.task.retries"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: RetriesAttr) -> Self { + value.key_value() + } +} + +/// Fraction of tasks whose telemetry is sampled. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum SampleRateAttr { + + /// One task in ten is sampled. + Tenth, + + /// Every task is sampled. + All, + +} + + +#[allow(deprecated)] +impl SampleRateAttr { + pub const KEY: &'static str = "myapp.task.sample_rate"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: f64 = match self { + + Self::Tenth => 0.1_f64, + + Self::All => 1_f64, + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: SampleRateAttr) -> Self { + value.key_value() + } +} + +/// Shards the task touched. +#[derive(Debug, Clone, PartialEq)] + +pub struct ShardIdsAttr(Vec); + + +#[allow(deprecated)] +impl ShardIdsAttr { + pub const KEY: &'static str = "myapp.task.shard_ids"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: ShardIdsAttr) -> Self { + value.key_value() + } +} + +/// Current state of the task. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum StateAttr { + + /// The task is waiting to run. + Queued, + + /// The task is running. + /// + /// A task stays running until it finishes or is cancelled. + Running, + +} + + +#[allow(deprecated)] +impl StateAttr { + pub const KEY: &'static str = "myapp.task.state"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Queued => "queued".into(), + + Self::Running => "running".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: StateAttr) -> Self { + value.key_value() + } +} + +/// Tags attached to the task. +#[derive(Debug, Clone, PartialEq)] + +pub struct TagsAttr(Vec); + + +#[allow(deprecated)] +impl TagsAttr { + pub const KEY: &'static str = "myapp.task.tags"; + + pub fn new(value: Vec) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TagsAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs index b04aff6..d6e3e68 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs @@ -3,38 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/histogram_boundaries_by_unit/1.0.0"; -pub mod myappattr { - - /// Unique identifier of the task. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskIdAttr(String); - - - #[allow(deprecated)] - impl TaskIdAttr { - pub const KEY: &'static str = "myapp.task.id"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskIdAttr) -> Self { - value.key_value() - } - } - -} +pub mod myappattr; pub mod meter; diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs new file mode 100644 index 0000000..21a7729 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs @@ -0,0 +1,30 @@ +// Generated by OpenTelemetry Weaver. + +/// Unique identifier of the task. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskIdAttr(String); + + +#[allow(deprecated)] +impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs index bf8cc35..eeaf0b3 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs @@ -3,38 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/histogram_boundaries_by_unit_params/1.0.0"; -pub mod myappattr { - - /// Unique identifier of the task. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskIdAttr(String); - - - #[allow(deprecated)] - impl TaskIdAttr { - pub const KEY: &'static str = "myapp.task.id"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskIdAttr) -> Self { - value.key_value() - } - } - -} +pub mod myappattr; pub mod meter; diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs new file mode 100644 index 0000000..21a7729 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs @@ -0,0 +1,30 @@ +// Generated by OpenTelemetry Weaver. + +/// Unique identifier of the task. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskIdAttr(String); + + +#[allow(deprecated)] +impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/imported/expected/mod.rs b/templates/code/rust/tests/imported/expected/mod.rs index a0567e2..fcd3acd 100644 --- a/templates/code/rust/tests/imported/expected/mod.rs +++ b/templates/code/rust/tests/imported/expected/mod.rs @@ -3,38 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/myapp/1.0.0"; -pub mod myappattr { - - /// Unique identifier of the task. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskIdAttr(String); - - - #[allow(deprecated)] - impl TaskIdAttr { - pub const KEY: &'static str = "myapp.task.id"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskIdAttr) -> Self { - value.key_value() - } - } - -} +pub mod myappattr; pub mod meter; diff --git a/templates/code/rust/tests/imported/expected/myappattr.rs b/templates/code/rust/tests/imported/expected/myappattr.rs new file mode 100644 index 0000000..21a7729 --- /dev/null +++ b/templates/code/rust/tests/imported/expected/myappattr.rs @@ -0,0 +1,30 @@ +// Generated by OpenTelemetry Weaver. + +/// Unique identifier of the task. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskIdAttr(String); + + +#[allow(deprecated)] +impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/imported_typed/expected/mod.rs b/templates/code/rust/tests/imported_typed/expected/mod.rs index 014b203..8e89569 100644 --- a/templates/code/rust/tests/imported_typed/expected/mod.rs +++ b/templates/code/rust/tests/imported_typed/expected/mod.rs @@ -3,38 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/myapp/1.0.0"; -pub mod myappattr { - - /// Unique identifier of the task. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskIdAttr(String); - - - #[allow(deprecated)] - impl TaskIdAttr { - pub const KEY: &'static str = "myapp.task.id"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskIdAttr) -> Self { - value.key_value() - } - } - -} +pub mod myappattr; pub mod meter; diff --git a/templates/code/rust/tests/imported_typed/expected/myappattr.rs b/templates/code/rust/tests/imported_typed/expected/myappattr.rs new file mode 100644 index 0000000..21a7729 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/expected/myappattr.rs @@ -0,0 +1,30 @@ +// Generated by OpenTelemetry Weaver. + +/// Unique identifier of the task. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskIdAttr(String); + + +#[allow(deprecated)] +impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs b/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs new file mode 100644 index 0000000..ced94f4 --- /dev/null +++ b/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs @@ -0,0 +1,41 @@ +// Generated by OpenTelemetry Weaver. + +/// Synthetic integer limits. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum BoundaryAttr { + + /// Lowest signed 64-bit integer. + Minimum, + + /// Highest signed 64-bit integer. + Maximum, + +} + + +#[allow(deprecated)] +impl BoundaryAttr { + pub const KEY: &'static str = "demo.boundary"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: i64 = match self { + + Self::Minimum => -9223372036854775808, + + Self::Maximum => 9223372036854775807, + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: BoundaryAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/integer_boundaries/expected/mod.rs b/templates/code/rust/tests/integer_boundaries/expected/mod.rs index 0317e89..6688a87 100644 --- a/templates/code/rust/tests/integer_boundaries/expected/mod.rs +++ b/templates/code/rust/tests/integer_boundaries/expected/mod.rs @@ -3,46 +3,4 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/1.0.0"; -pub mod demoattr { - - /// Synthetic integer limits. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum BoundaryAttr { - - /// Lowest signed 64-bit integer. - Minimum, - - /// Highest signed 64-bit integer. - Maximum, - - } - - - #[allow(deprecated)] - impl BoundaryAttr { - pub const KEY: &'static str = "demo.boundary"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: i64 = match self { - - Self::Minimum => -9223372036854775808, - - Self::Maximum => 9223372036854775807, - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: BoundaryAttr) -> Self { - value.key_value() - } - } - -} +pub mod demoattr; diff --git a/templates/code/rust/tests/literal_escaping/expected/demoattr.rs b/templates/code/rust/tests/literal_escaping/expected/demoattr.rs new file mode 100644 index 0000000..a844e46 --- /dev/null +++ b/templates/code/rust/tests/literal_escaping/expected/demoattr.rs @@ -0,0 +1,41 @@ +// Generated by OpenTelemetry Weaver. + +/// Literal escape sequences. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum LiteralAttr { + + /// Literal escape sequences. + Literal, + + /// Actual controls and escaped text. + Controls, + +} + + +#[allow(deprecated)] +impl LiteralAttr { + pub const KEY: &'static str = "demo.literal"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Literal => "backspace\\b formfeed\\f unicode\\u1234 doubled\\\\b tripled\\\\\\u0000".into(), + + Self::Controls => "backspace\u{0008} formfeed\u{000c} unicode\u{0001} slash\\b".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: LiteralAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/literal_escaping/expected/mod.rs b/templates/code/rust/tests/literal_escaping/expected/mod.rs index d4e797d..70f8a96 100644 --- a/templates/code/rust/tests/literal_escaping/expected/mod.rs +++ b/templates/code/rust/tests/literal_escaping/expected/mod.rs @@ -3,49 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/escaping/1.0.0"; -pub mod demoattr { - - /// Literal escape sequences. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum LiteralAttr { - - /// Literal escape sequences. - Literal, - - /// Actual controls and escaped text. - Controls, - - } - - - #[allow(deprecated)] - impl LiteralAttr { - pub const KEY: &'static str = "demo.literal"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Literal => "backspace\\b formfeed\\f unicode\\u1234 doubled\\\\b tripled\\\\\\u0000".into(), - - Self::Controls => "backspace\u{0008} formfeed\u{000c} unicode\u{0001} slash\\b".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: LiteralAttr) -> Self { - value.key_value() - } - } - -} +pub mod demoattr; pub mod meter; diff --git a/templates/code/rust/tests/metrics/expected/authattr.rs b/templates/code/rust/tests/metrics/expected/authattr.rs new file mode 100644 index 0000000..29f94b7 --- /dev/null +++ b/templates/code/rust/tests/metrics/expected/authattr.rs @@ -0,0 +1,70 @@ +// Generated by OpenTelemetry Weaver. + +/// How the user was authenticated. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum MethodAttr { + + /// A password was checked. + Password, + + /// A bearer token was checked. + Token, + +} + + +#[allow(deprecated)] +impl MethodAttr { + pub const KEY: &'static str = "auth.method"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Password => "password".into(), + + Self::Token => "token".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: MethodAttr) -> Self { + value.key_value() + } +} + +/// Whether the attempt succeeded. +#[derive(Debug, Clone, PartialEq)] + +pub struct SuccessAttr(bool); + + +#[allow(deprecated)] +impl SuccessAttr { + pub const KEY: &'static str = "auth.success"; + + pub fn new(value: bool) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: SuccessAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/metrics/expected/mod.rs b/templates/code/rust/tests/metrics/expected/mod.rs index f013806..11b41ec 100644 --- a/templates/code/rust/tests/metrics/expected/mod.rs +++ b/templates/code/rust/tests/metrics/expected/mod.rs @@ -3,151 +3,9 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/metrics/1.0.0"; -pub mod authattr { +pub mod authattr; - /// How the user was authenticated. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum MethodAttr { - - /// A password was checked. - Password, - - /// A bearer token was checked. - Token, - - } - - - #[allow(deprecated)] - impl MethodAttr { - pub const KEY: &'static str = "auth.method"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Password => "password".into(), - - Self::Token => "token".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: MethodAttr) -> Self { - value.key_value() - } - } - - /// Whether the attempt succeeded. - #[derive(Debug, Clone, PartialEq)] - - pub struct SuccessAttr(bool); - - - #[allow(deprecated)] - impl SuccessAttr { - pub const KEY: &'static str = "auth.success"; - - pub fn new(value: bool) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: SuccessAttr) -> Self { - value.key_value() - } - } - -} - -pub mod myappattr { - - /// Unique identifier of the task. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskIdAttr(String); - - - #[allow(deprecated)] - impl TaskIdAttr { - pub const KEY: &'static str = "myapp.task.id"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskIdAttr) -> Self { - value.key_value() - } - } - - /// Current state of the task. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum TaskStateAttr { - - /// The task is waiting to run. - Queued, - - /// The task finished. - Done, - - } - - - #[allow(deprecated)] - impl TaskStateAttr { - pub const KEY: &'static str = "myapp.task.state"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Queued => "queued".into(), - - Self::Done => "done".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskStateAttr) -> Self { - value.key_value() - } - } - -} +pub mod myappattr; pub mod meter; diff --git a/templates/code/rust/tests/metrics/expected/myappattr.rs b/templates/code/rust/tests/metrics/expected/myappattr.rs new file mode 100644 index 0000000..4b9c416 --- /dev/null +++ b/templates/code/rust/tests/metrics/expected/myappattr.rs @@ -0,0 +1,70 @@ +// Generated by OpenTelemetry Weaver. + +/// Unique identifier of the task. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskIdAttr(String); + + +#[allow(deprecated)] +impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } +} + +/// Current state of the task. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum TaskStateAttr { + + /// The task is waiting to run. + Queued, + + /// The task finished. + Done, + +} + + +#[allow(deprecated)] +impl TaskStateAttr { + pub const KEY: &'static str = "myapp.task.state"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Queued => "queued".into(), + + Self::Done => "done".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskStateAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/naming/expected/capsattr.rs b/templates/code/rust/tests/naming/expected/capsattr.rs new file mode 100644 index 0000000..7c4dd81 --- /dev/null +++ b/templates/code/rust/tests/naming/expected/capsattr.rs @@ -0,0 +1,65 @@ +// Generated by OpenTelemetry Weaver. + +/// Synthetic identifier. +#[derive(Debug, Clone, PartialEq)] + +pub struct Http2STATUSApiIDAttr(String); + + +#[allow(deprecated)] +impl Http2STATUSApiIDAttr { + pub const KEY: &'static str = "caps.http2_STATUS.api_ID"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: Http2STATUSApiIDAttr) -> Self { + value.key_value() + } +} + +/// Synthetic mode. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum Mode2STATEAttr { + + /// Synthetic state. + HTTP2ReadySTATE, + +} + + +#[allow(deprecated)] +impl Mode2STATEAttr { + pub const KEY: &'static str = "caps.mode2_STATE"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::HTTP2ReadySTATE => "ready".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: Mode2STATEAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/naming/expected/mod.rs b/templates/code/rust/tests/naming/expected/mod.rs index 168f015..79da2c3 100644 --- a/templates/code/rust/tests/naming/expected/mod.rs +++ b/templates/code/rust/tests/naming/expected/mod.rs @@ -3,73 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/naming/1.0.0"; -pub mod capsattr { - - /// Synthetic identifier. - #[derive(Debug, Clone, PartialEq)] - - pub struct Http2STATUSApiIDAttr(String); - - - #[allow(deprecated)] - impl Http2STATUSApiIDAttr { - pub const KEY: &'static str = "caps.http2_STATUS.api_ID"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: Http2STATUSApiIDAttr) -> Self { - value.key_value() - } - } - - /// Synthetic mode. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum Mode2STATEAttr { - - /// Synthetic state. - HTTP2ReadySTATE, - - } - - - #[allow(deprecated)] - impl Mode2STATEAttr { - pub const KEY: &'static str = "caps.mode2_STATE"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::HTTP2ReadySTATE => "ready".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: Mode2STATEAttr) -> Self { - value.key_value() - } - } - -} +pub mod capsattr; pub mod meter; diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs new file mode 100644 index 0000000..d6830da --- /dev/null +++ b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs @@ -0,0 +1,59 @@ +// Generated by OpenTelemetry Weaver. + +/// The exception message. +#[derive(Debug, Clone, PartialEq)] + +pub struct MessageAttr(String); + + +#[allow(deprecated)] +impl MessageAttr { + pub const KEY: &'static str = "exception.message"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: MessageAttr) -> Self { + value.key_value() + } +} + +/// The type of the exception. +#[derive(Debug, Clone, PartialEq)] + +pub struct TypeAttr(String); + + +#[allow(deprecated)] +impl TypeAttr { + pub const KEY: &'static str = "exception.type"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TypeAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs new file mode 100644 index 0000000..03b0638 --- /dev/null +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs @@ -0,0 +1,59 @@ +// Generated by OpenTelemetry Weaver. + +/// Sequence number of the heartbeat. +#[derive(Debug, Clone, PartialEq)] + +pub struct SequenceAttr(i64); + + +#[allow(deprecated)] +impl SequenceAttr { + pub const KEY: &'static str = "heartbeat.sequence"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: SequenceAttr) -> Self { + value.key_value() + } +} + +/// Name of the component that sent the heartbeat. +#[derive(Debug, Clone, PartialEq)] + +pub struct SourceAttr(String); + + +#[allow(deprecated)] +impl SourceAttr { + pub const KEY: &'static str = "heartbeat.source"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: SourceAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/no_namespace/expected/hostattr.rs b/templates/code/rust/tests/no_namespace/expected/hostattr.rs new file mode 100644 index 0000000..4278d02 --- /dev/null +++ b/templates/code/rust/tests/no_namespace/expected/hostattr.rs @@ -0,0 +1,59 @@ +// Generated by OpenTelemetry Weaver. + +/// Unique identifier of the host. +#[derive(Debug, Clone, PartialEq)] + +pub struct IdAttr(String); + + +#[allow(deprecated)] +impl IdAttr { + pub const KEY: &'static str = "host.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: IdAttr) -> Self { + value.key_value() + } +} + +/// Name of the host. +#[derive(Debug, Clone, PartialEq)] + +pub struct NameAttr(String); + + +#[allow(deprecated)] +impl NameAttr { + pub const KEY: &'static str = "host.name"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: NameAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/no_namespace/expected/mod.rs b/templates/code/rust/tests/no_namespace/expected/mod.rs index 368c549..e481b66 100644 --- a/templates/code/rust/tests/no_namespace/expected/mod.rs +++ b/templates/code/rust/tests/no_namespace/expected/mod.rs @@ -3,191 +3,11 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/no_namespace/1.0.0"; -pub mod exceptionattr { +pub mod exceptionattr; - /// The exception message. - #[derive(Debug, Clone, PartialEq)] +pub mod heartbeatattr; - pub struct MessageAttr(String); - - - #[allow(deprecated)] - impl MessageAttr { - pub const KEY: &'static str = "exception.message"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: MessageAttr) -> Self { - value.key_value() - } - } - - /// The type of the exception. - #[derive(Debug, Clone, PartialEq)] - - pub struct TypeAttr(String); - - - #[allow(deprecated)] - impl TypeAttr { - pub const KEY: &'static str = "exception.type"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TypeAttr) -> Self { - value.key_value() - } - } - -} - -pub mod heartbeatattr { - - /// Sequence number of the heartbeat. - #[derive(Debug, Clone, PartialEq)] - - pub struct SequenceAttr(i64); - - - #[allow(deprecated)] - impl SequenceAttr { - pub const KEY: &'static str = "heartbeat.sequence"; - - pub fn new(value: i64) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: SequenceAttr) -> Self { - value.key_value() - } - } - - /// Name of the component that sent the heartbeat. - #[derive(Debug, Clone, PartialEq)] - - pub struct SourceAttr(String); - - - #[allow(deprecated)] - impl SourceAttr { - pub const KEY: &'static str = "heartbeat.source"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: SourceAttr) -> Self { - value.key_value() - } - } - -} - -pub mod hostattr { - - /// Unique identifier of the host. - #[derive(Debug, Clone, PartialEq)] - - pub struct IdAttr(String); - - - #[allow(deprecated)] - impl IdAttr { - pub const KEY: &'static str = "host.id"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: IdAttr) -> Self { - value.key_value() - } - } - - /// Name of the host. - #[derive(Debug, Clone, PartialEq)] - - pub struct NameAttr(String); - - - #[allow(deprecated)] - impl NameAttr { - pub const KEY: &'static str = "host.name"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: NameAttr) -> Self { - value.key_value() - } - } - -} +pub mod hostattr; diff --git a/templates/code/rust/tests/params/expected/billingattr.rs b/templates/code/rust/tests/params/expected/billingattr.rs new file mode 100644 index 0000000..8e1db27 --- /dev/null +++ b/templates/code/rust/tests/params/expected/billingattr.rs @@ -0,0 +1,59 @@ +// Generated by OpenTelemetry Weaver. + +/// Identifier of the invoice. +#[derive(Debug, Clone, PartialEq)] + +pub struct InvoiceIdAttr(String); + + +#[allow(deprecated)] +impl InvoiceIdAttr { + pub const KEY: &'static str = "acme.billing.invoice.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: InvoiceIdAttr) -> Self { + value.key_value() + } +} + +/// ISO 4217 currency code of the amount. +#[derive(Debug, Clone, PartialEq)] + +pub struct CurrencyAttr(String); + + +#[allow(deprecated)] +impl CurrencyAttr { + pub const KEY: &'static str = "billing.currency"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: CurrencyAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/params/expected/mod.rs b/templates/code/rust/tests/params/expected/mod.rs index e8d18c6..5f81689 100644 --- a/templates/code/rust/tests/params/expected/mod.rs +++ b/templates/code/rust/tests/params/expected/mod.rs @@ -6,100 +6,9 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/params/1.0.0"; -pub mod billingattr { +pub mod billingattr; - /// Identifier of the invoice. - #[derive(Debug, Clone, PartialEq)] - - pub struct InvoiceIdAttr(String); - - - #[allow(deprecated)] - impl InvoiceIdAttr { - pub const KEY: &'static str = "acme.billing.invoice.id"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: InvoiceIdAttr) -> Self { - value.key_value() - } - } - - /// ISO 4217 currency code of the amount. - #[derive(Debug, Clone, PartialEq)] - - pub struct CurrencyAttr(String); - - - #[allow(deprecated)] - impl CurrencyAttr { - pub const KEY: &'static str = "billing.currency"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: CurrencyAttr) -> Self { - value.key_value() - } - } - -} - -pub mod myappattr { - - /// URL the request was sent to. - #[derive(Debug, Clone, PartialEq)] - - pub struct RequestUrlAttr(String); - - - #[allow(deprecated)] - impl RequestUrlAttr { - pub const KEY: &'static str = "myapp.request.url"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: RequestUrlAttr) -> Self { - value.key_value() - } - } - -} +pub mod myappattr; pub mod meter; diff --git a/templates/code/rust/tests/params/expected/myappattr.rs b/templates/code/rust/tests/params/expected/myappattr.rs new file mode 100644 index 0000000..0560b99 --- /dev/null +++ b/templates/code/rust/tests/params/expected/myappattr.rs @@ -0,0 +1,30 @@ +// Generated by OpenTelemetry Weaver. + +/// URL the request was sent to. +#[derive(Debug, Clone, PartialEq)] + +pub struct RequestUrlAttr(String); + + +#[allow(deprecated)] +impl RequestUrlAttr { + pub const KEY: &'static str = "myapp.request.url"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: RequestUrlAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/spans/expected/mod.rs b/templates/code/rust/tests/spans/expected/mod.rs index 46ef580..212d15d 100644 --- a/templates/code/rust/tests/spans/expected/mod.rs +++ b/templates/code/rust/tests/spans/expected/mod.rs @@ -3,198 +3,9 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/spans/1.0.0"; -pub mod myappattr { +pub mod myappattr; - /// Name of the queue the task came from. - #[derive(Debug, Clone, PartialEq)] - - pub struct QueueNameAttr(String); - - - #[allow(deprecated)] - impl QueueNameAttr { - pub const KEY: &'static str = "myapp.queue.name"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: QueueNameAttr) -> Self { - value.key_value() - } - } - - /// Number of the attempt, starting at one. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskAttemptAttr(i64); - - - #[allow(deprecated)] - impl TaskAttemptAttr { - pub const KEY: &'static str = "myapp.task.attempt"; - - pub fn new(value: i64) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskAttemptAttr) -> Self { - value.key_value() - } - } - - /// Unique identifier of the task. - #[derive(Debug, Clone, PartialEq)] - - pub struct TaskIdAttr(String); - - - #[allow(deprecated)] - impl TaskIdAttr { - pub const KEY: &'static str = "myapp.task.id"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskIdAttr) -> Self { - value.key_value() - } - } - - /// Current state of the task. - #[derive(Debug, Clone, PartialEq, Copy)] - - pub enum TaskStateAttr { - - /// The task is waiting to run. - Queued, - - /// The task finished. - Done, - - } - - - #[allow(deprecated)] - impl TaskStateAttr { - pub const KEY: &'static str = "myapp.task.state"; - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - let value: String = match self { - - Self::Queued => "queued".into(), - - Self::Done => "done".into(), - - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: TaskStateAttr) -> Self { - value.key_value() - } - } - -} - -pub mod workerattr { - - /// Host name of the worker. - #[derive(Debug, Clone, PartialEq)] - - pub struct HostNameAttr(String); - - - #[allow(deprecated)] - impl HostNameAttr { - pub const KEY: &'static str = "worker.host.name"; - - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: HostNameAttr) -> Self { - value.key_value() - } - } - - /// Port the worker listens on. - #[derive(Debug, Clone, PartialEq)] - - pub struct HostPortAttr(i64); - - - #[allow(deprecated)] - impl HostPortAttr { - pub const KEY: &'static str = "worker.host.port"; - - pub fn new(value: i64) -> Self { - Self(value) - } - - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - - } - } - - #[allow(deprecated)] - impl From for ::opentelemetry::KeyValue { - fn from(value: HostPortAttr) -> Self { - value.key_value() - } - } - -} +pub mod workerattr; diff --git a/templates/code/rust/tests/spans/expected/myappattr.rs b/templates/code/rust/tests/spans/expected/myappattr.rs new file mode 100644 index 0000000..a3c8d6e --- /dev/null +++ b/templates/code/rust/tests/spans/expected/myappattr.rs @@ -0,0 +1,128 @@ +// Generated by OpenTelemetry Weaver. + +/// Name of the queue the task came from. +#[derive(Debug, Clone, PartialEq)] + +pub struct QueueNameAttr(String); + + +#[allow(deprecated)] +impl QueueNameAttr { + pub const KEY: &'static str = "myapp.queue.name"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: QueueNameAttr) -> Self { + value.key_value() + } +} + +/// Number of the attempt, starting at one. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskAttemptAttr(i64); + + +#[allow(deprecated)] +impl TaskAttemptAttr { + pub const KEY: &'static str = "myapp.task.attempt"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskAttemptAttr) -> Self { + value.key_value() + } +} + +/// Unique identifier of the task. +#[derive(Debug, Clone, PartialEq)] + +pub struct TaskIdAttr(String); + + +#[allow(deprecated)] +impl TaskIdAttr { + pub const KEY: &'static str = "myapp.task.id"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskIdAttr) -> Self { + value.key_value() + } +} + +/// Current state of the task. +#[derive(Debug, Clone, PartialEq, Copy)] + +pub enum TaskStateAttr { + + /// The task is waiting to run. + Queued, + + /// The task finished. + Done, + +} + + +#[allow(deprecated)] +impl TaskStateAttr { + pub const KEY: &'static str = "myapp.task.state"; + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + let value: String = match self { + + Self::Queued => "queued".into(), + + Self::Done => "done".into(), + + }; + ::opentelemetry::KeyValue::new(Self::KEY, value) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskStateAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/tests/spans/expected/workerattr.rs b/templates/code/rust/tests/spans/expected/workerattr.rs new file mode 100644 index 0000000..242e2b0 --- /dev/null +++ b/templates/code/rust/tests/spans/expected/workerattr.rs @@ -0,0 +1,59 @@ +// Generated by OpenTelemetry Weaver. + +/// Host name of the worker. +#[derive(Debug, Clone, PartialEq)] + +pub struct HostNameAttr(String); + + +#[allow(deprecated)] +impl HostNameAttr { + pub const KEY: &'static str = "worker.host.name"; + + pub fn new(value: impl Into) -> Self { + Self(value.into()) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: HostNameAttr) -> Self { + value.key_value() + } +} + +/// Port the worker listens on. +#[derive(Debug, Clone, PartialEq)] + +pub struct HostPortAttr(i64); + + +#[allow(deprecated)] +impl HostPortAttr { + pub const KEY: &'static str = "worker.host.port"; + + pub fn new(value: i64) -> Self { + Self(value) + } + + + pub fn key_value(self) -> ::opentelemetry::KeyValue { + + ::opentelemetry::KeyValue::new(Self::KEY, self.0) + + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + fn from(value: HostPortAttr) -> Self { + value.key_value() + } +} diff --git a/templates/code/rust/weaver.yaml b/templates/code/rust/weaver.yaml index ab0928a..d45e154 100644 --- a/templates/code/rust/weaver.yaml +++ b/templates/code/rust/weaver.yaml @@ -14,22 +14,11 @@ templates: application_mode: single file_name: mod.rs filter: |- - def title: split(".") | map(split("_")) | flatten | map(.[0:1] as $first | ($first | ascii_upcase) + .[1:]) | join(""); - def keyword: . as $name | ["as", "break", "const", "continue", "crate", "else", "enum", "extern", "false", "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref", "return", "self", "Self", "static", "struct", "super", "trait", "true", "type", "unsafe", "use", "where", "while", "async", "await", "dyn", "abstract", "become", "box", "do", "final", "gen", "macro", "override", "priv", "try", "typeof", "unsized", "virtual", "yield"] | any(. == $name); - def valid_name: test("^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)*$"); def ns: split(".") as $s | if ($s | length) > 1 and ($vendor_prefixes | any(. == $s[0])) then {namespace: $s[1], short_name: ($s[2:] | join("."))} else {namespace: $s[0], short_name: ($s[1:] | join("."))} end | if (.namespace | test("^[a-z][a-z0-9_]*$") | not) then error("namespace \(.namespace) is not a supported Rust module name") else . end; - def value_type($key): - if type != "object" then . - elif (.members | length) == 0 then error("attribute \($key) has no enum members left after filtering") - elif (.members | all(.value | type == "string")) then "string" - elif (.members | all(.value | type == "boolean")) then "boolean" - elif (.members | all(.value | type == "number" and . == floor)) then "int" - elif (.members | all(.value | type == "number")) then "double" - else error("attribute \($key) has enum members of more than one value type") end; def rust_literal: if type == "string" then explode | map([.] | implode | tojson | gsub("\\\\b"; "\\u{0008}") | gsub("\\\\f"; "\\u{000c}") | gsub("\\\\u(?[0-9a-fA-F]{4})"; "\\u{\(.code)}") | .[1:-1]) | join("") | "\"" + . + "\"" else tostring end; @@ -45,6 +34,34 @@ templates: + [((.registry.events // [] | stability_filter($opts) | code_generation_exclude_filter($opts) | deprecated_filter($opts) | map(.name)) + (.refinements.events // [] | stability_filter($opts) | code_generation_exclude_filter($opts) | deprecated_filter($opts) | map(.id)))[] | ns | .namespace + "event"] + [($entities + (.refinements.entities // [] | stability_filter($opts) | code_generation_exclude_filter($opts) | deprecated_filter($opts) | map(select(.id != .type and (.type as $base | $entities | any(. == $base))) | .id)))[] | ns | .namespace + "entity"] | unique) as $signal_modules | semconv_grouped_attributes($opts) + | map(.attributes) | add // [] | map(.key | ns | .namespace + "attr") | unique + | {signal_modules: $signal_modules, has_metrics: ($signal_modules | any(endswith("metric"))), has_spans: ($signal_modules | any(endswith("span"))), has_events: ($signal_modules | any(endswith("event"))), schema_literal: ($schema | rust_literal), namespaces: .} + + - template: attributes.rs.j2 + application_mode: each + file_name: "{{ ctx.name }}.rs" + filter: |- + def title: split(".") | map(split("_")) | flatten | map(.[0:1] as $first | ($first | ascii_upcase) + .[1:]) | join(""); + def keyword: . as $name | ["as", "break", "const", "continue", "crate", "else", "enum", "extern", "false", "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref", "return", "self", "Self", "static", "struct", "super", "trait", "true", "type", "unsafe", "use", "where", "while", "async", "await", "dyn", "abstract", "become", "box", "do", "final", "gen", "macro", "override", "priv", "try", "typeof", "unsized", "virtual", "yield"] | any(. == $name); + def valid_name: test("^[A-Za-z][A-Za-z0-9_]*(\\.[A-Za-z][A-Za-z0-9_]*)*$"); + def ns: split(".") as $s + | if ($s | length) > 1 and ($vendor_prefixes | any(. == $s[0])) + then {namespace: $s[1], short_name: ($s[2:] | join("."))} + else {namespace: $s[0], short_name: ($s[1:] | join("."))} end | if (.namespace | test("^[a-z][a-z0-9_]*$") | not) + then error("namespace \(.namespace) is not a supported Rust module name") else . end; + def value_type($key): + if type != "object" then . + elif (.members | length) == 0 then error("attribute \($key) has no enum members left after filtering") + elif (.members | all(.value | type == "string")) then "string" + elif (.members | all(.value | type == "boolean")) then "boolean" + elif (.members | all(.value | type == "number" and . == floor)) then "int" + elif (.members | all(.value | type == "number")) then "double" + else error("attribute \($key) has enum members of more than one value type") end; + def rust_literal: + if type == "string" then explode | map([.] | implode | tojson | gsub("\\\\b"; "\\u{0008}") | gsub("\\\\f"; "\\u{000c}") | gsub("\\\\u(?[0-9a-fA-F]{4})"; "\\u{\(.code)}") | .[1:-1]) | join("") | "\"" + . + "\"" + else tostring end; + {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $opts + | semconv_grouped_attributes($opts) | map(.attributes) | add // [] | map(if (.key | valid_name | not) then error("attribute \(.key) is not a supported Rust attribute name") else . end) | map(. + (.key | ns)) @@ -65,7 +82,8 @@ templates: else . end) | group_by(.namespace) | map(if (group_by(.name) | any(length > 1)) then error("namespace \(.[0].namespace) has attributes that render to the same Rust identifier") else . end) - | {signal_modules: $signal_modules, has_metrics: ($signal_modules | any(endswith("metric"))), has_spans: ($signal_modules | any(endswith("span"))), has_events: ($signal_modules | any(endswith("event"))), schema_literal: ($schema | rust_literal), namespaces: map({name: (.[0].namespace + "attr"), attributes: sort_by(.key)})} + + | map({name: (.[0].namespace + "attr"), attributes: sort_by(.key)}) - template: metrics.rs.j2 filter: |- From 70579bfe72504559de6d7c7263cdbf814ea2dd4e Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Sun, 4 Oct 2026 21:25:13 -0400 Subject: [PATCH 03/14] fix: keep generated Rust readable Signed-off-by: Yordis Prieto --- templates/code/rust/entities.rs.j2 | 3 +- templates/code/rust/mod.rs.j2 | 12 +- templates/code/rust/signal_helpers.j2 | 3 +- .../tests/attributes/expected/authattr.rs | 31 ---- .../rust/tests/attributes/expected/mod.rs | 4 - .../tests/attributes/expected/myappattr.rs | 130 --------------- .../codegen_exclusion/expected/demoattr.rs | 17 -- .../tests/codegen_exclusion/expected/mod.rs | 3 - .../code/rust/tests/entities/expected/mod.rs | 8 - .../rust/tests/entities/expected/myappattr.rs | 47 ------ .../tests/entities/expected/myappentity.rs | 32 ---- .../code/rust/tests/events/expected/mod.rs | 9 - .../rust/tests/events/expected/myappattr.rs | 47 ------ .../rust/tests/events/expected/myappevent.rs | 21 --- .../rust/tests/events/expected/workerattr.rs | 7 - .../rust/tests/events/expected/workerevent.rs | 19 --- .../rust/tests/filtering/expected/authattr.rs | 19 --- .../code/rust/tests/filtering/expected/mod.rs | 4 - .../rust/tests/filtering/expected/taskattr.rs | 78 --------- .../expected/mod.rs | 7 - .../expected/myappattr.rs | 7 - .../expected/myappmetric.rs | 43 ----- .../expected/mod.rs | 7 - .../expected/myappattr.rs | 7 - .../expected/myappmetric.rs | 21 --- .../rust/tests/imported/expected/edgeevent.rs | 7 - .../tests/imported/expected/edgemetric.rs | 17 -- .../rust/tests/imported/expected/edgespan.rs | 37 ----- .../code/rust/tests/imported/expected/mod.rs | 8 - .../rust/tests/imported/expected/myappattr.rs | 7 - .../tests/imported/expected/myappmetric.rs | 20 --- .../rust/tests/imported_typed/expected/mod.rs | 7 - .../imported_typed/expected/myappattr.rs | 7 - .../imported_typed/expected/myappevent.rs | 7 - .../imported_typed/expected/myappmetric.rs | 20 --- .../imported_typed/expected/myappspan.rs | 40 ----- .../integer_boundaries/expected/demoattr.rs | 12 -- .../tests/integer_boundaries/expected/mod.rs | 3 - .../literal_escaping/expected/demoattr.rs | 12 -- .../literal_escaping/expected/demometric.rs | 13 -- .../tests/literal_escaping/expected/mod.rs | 7 - .../rust/tests/metrics/expected/authattr.rs | 19 --- .../rust/tests/metrics/expected/authmetric.rs | 13 -- .../code/rust/tests/metrics/expected/mod.rs | 10 -- .../rust/tests/metrics/expected/myappattr.rs | 19 --- .../tests/metrics/expected/myappmetric.rs | 132 --------------- .../tests/metrics/expected/workermetric.rs | 19 --- .../rust/tests/naming/expected/capsattr.rs | 17 -- .../rust/tests/naming/expected/capsmetric.rs | 13 -- .../code/rust/tests/naming/expected/mod.rs | 7 - .../no_namespace/expected/exceptionattr.rs | 14 -- .../no_namespace/expected/exceptionevent.rs | 7 - .../no_namespace/expected/heartbeatattr.rs | 14 -- .../no_namespace/expected/heartbeatspan.rs | 24 --- .../tests/no_namespace/expected/hostattr.rs | 14 -- .../tests/no_namespace/expected/hostentity.rs | 9 - .../rust/tests/no_namespace/expected/mod.rs | 10 -- .../rust/tests/params/expected/billingattr.rs | 14 -- .../tests/params/expected/billingmetric.rs | 18 -- .../code/rust/tests/params/expected/mod.rs | 8 - .../rust/tests/params/expected/myappattr.rs | 7 - .../code/rust/tests/spans/expected/mod.rs | 9 - .../rust/tests/spans/expected/myappattr.rs | 33 ---- .../rust/tests/spans/expected/myappspan.rs | 156 ------------------ .../rust/tests/spans/expected/workerattr.rs | 14 -- .../rust/tests/spans/expected/workerspan.rs | 42 ----- templates/code/rust/weaver.yaml | 4 + 67 files changed, 16 insertions(+), 1440 deletions(-) diff --git a/templates/code/rust/entities.rs.j2 b/templates/code/rust/entities.rs.j2 index 1dea446..2cde8f8 100644 --- a/templates/code/rust/entities.rs.j2 +++ b/templates/code/rust/entities.rs.j2 @@ -36,7 +36,8 @@ pub struct {{ name }} { impl {{ name }} { pub fn new({% for req in def.required %}{{ s.ident(req.attr_param) }}: {{ s.attr_type(req) }}, {% endfor %}{% if def.optional %}options: impl IntoIterator{% endif %}) -> Self { - {% if def.required or def.optional %}let {% if def.optional %}mut {% endif %}attributes = vec![ +{% if def.required or def.optional %} + let {% if def.optional %}mut {% endif %}attributes = vec![ {% for req in def.required %} {{ s.attr_kv(req, s.ident(req.attr_param)) }}, {% endfor %} diff --git a/templates/code/rust/mod.rs.j2 b/templates/code/rust/mod.rs.j2 index 0eba441..7c6d64b 100644 --- a/templates/code/rust/mod.rs.j2 +++ b/templates/code/rust/mod.rs.j2 @@ -12,9 +12,15 @@ pub const SCHEMA_URL: &str = {{ ctx.schema_literal }}; pub mod {{ namespace }}; {% endfor %} -{% if ctx.has_metrics %}pub mod meter;{% endif %} -{% if ctx.has_spans %}pub mod tracer;{% endif %} -{% if ctx.has_events %}pub mod logger;{% endif %} +{% if ctx.has_metrics %} +pub mod meter; +{% endif %} +{% if ctx.has_spans %} +pub mod tracer; +{% endif %} +{% if ctx.has_events %} +pub mod logger; +{% endif %} {% for module in ctx.signal_modules %} pub mod {{ module }}; {% endfor %} diff --git a/templates/code/rust/signal_helpers.j2 b/templates/code/rust/signal_helpers.j2 index c7a7199..494e8b6 100644 --- a/templates/code/rust/signal_helpers.j2 +++ b/templates/code/rust/signal_helpers.j2 @@ -19,7 +19,6 @@ {%- endmacro %} {% macro docs(def) -%} {{ ([def.brief, def.note] | select | join('\n\n')) | comment | trim }} -{%- if def.requirement_level == 'opt_in' %} -/// Opt-in: record only when the user requests it. +{%- if def.requirement_level == 'opt_in' %}{{ "\n" }}/// Opt-in: record only when the user requests it. {%- endif -%} {%- endmacro %} diff --git a/templates/code/rust/tests/attributes/expected/authattr.rs b/templates/code/rust/tests/attributes/expected/authattr.rs index ed79374..9af5ebe 100644 --- a/templates/code/rust/tests/attributes/expected/authattr.rs +++ b/templates/code/rust/tests/attributes/expected/authattr.rs @@ -1,35 +1,23 @@ // Generated by OpenTelemetry Weaver. - /// Assurance level of the authentication. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum LevelAttr { - /// Single factor. Low, - /// Multiple factors. High, - } - #[allow(deprecated)] impl LevelAttr { pub const KEY: &'static str = "auth.level"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: i64 = match self { - Self::Low => 1, - Self::High => 2, - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -39,37 +27,25 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// How the user was authenticated. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum MethodAttr { - /// A password was checked. Password, - /// A bearer token was checked. Token, - } - #[allow(deprecated)] impl MethodAttr { pub const KEY: &'static str = "auth.method"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Password => "password".into(), - Self::Token => "token".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -79,26 +55,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Identifier of the authenticated user. #[derive(Debug, Clone, PartialEq)] - pub struct UserIdAttr(String); - #[allow(deprecated)] impl UserIdAttr { pub const KEY: &'static str = "auth.user.id"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/attributes/expected/mod.rs b/templates/code/rust/tests/attributes/expected/mod.rs index 3dadc9e..c487539 100644 --- a/templates/code/rust/tests/attributes/expected/mod.rs +++ b/templates/code/rust/tests/attributes/expected/mod.rs @@ -1,8 +1,4 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/attributes/1.0.0"; - pub mod authattr; - pub mod myappattr; diff --git a/templates/code/rust/tests/attributes/expected/myappattr.rs b/templates/code/rust/tests/attributes/expected/myappattr.rs index 1a5b632..a943b9f 100644 --- a/templates/code/rust/tests/attributes/expected/myappattr.rs +++ b/templates/code/rust/tests/attributes/expected/myappattr.rs @@ -1,26 +1,19 @@ // Generated by OpenTelemetry Weaver. - /// Who assigned the task. /// /// The scheduler sets it on every task it passes along to `myapp.task.state`. Workers never set it themselves. #[derive(Debug, Clone, PartialEq)] - pub struct TaskAssignedByAttr(String); - #[allow(deprecated)] impl TaskAssignedByAttr { pub const KEY: &'static str = "myapp.task.assigned_by"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -30,26 +23,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Whether the task was cancelled. #[derive(Debug, Clone, PartialEq)] - pub struct TaskCancelledAttr(bool); - #[allow(deprecated)] impl TaskCancelledAttr { pub const KEY: &'static str = "myapp.task.cancelled"; - pub fn new(value: bool) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -59,32 +45,22 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Tests Rust string literals. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum TaskEscapedAttr { - /// Escaped text. Quoted, - } - #[allow(deprecated)] impl TaskEscapedAttr { pub const KEY: &'static str = "myapp.task.escaped"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Quoted => "quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -94,26 +70,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Feature flags evaluated for the task. #[derive(Debug, Clone, PartialEq)] - pub struct TaskFlagsAttr(Vec); - #[allow(deprecated)] impl TaskFlagsAttr { pub const KEY: &'static str = "myapp.task.flags"; - pub fn new(value: Vec) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(self.0))) - } } @@ -123,28 +92,21 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Unique identifier of the task. /// /// The identifier is assigned by the scheduler and stays stable across retries. #[derive(Debug, Clone, PartialEq)] - pub struct TaskIdAttr(String); - #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -154,40 +116,28 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Lane the task was scheduled in. #[deprecated(note = "Lanes were replaced by priorities.")] #[derive(Debug, Clone, PartialEq, Copy)] - pub enum TaskLaneAttr { - /// The fast lane. #[deprecated(note = "Lanes were replaced by priorities.")] Fast, - /// The slow lane. #[deprecated(note = "Every task runs in the fast lane.")] Slow, - } - #[allow(deprecated)] impl TaskLaneAttr { pub const KEY: &'static str = "myapp.task.lane"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Fast => "fast".into(), - Self::Slow => "slow".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -197,27 +147,20 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Owner of the task. #[deprecated(note = "Replaced by `auth.user.id`.")] #[derive(Debug, Clone, PartialEq)] - pub struct TaskOwnerAttr(String); - #[allow(deprecated)] impl TaskOwnerAttr { pub const KEY: &'static str = "myapp.task.owner"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -227,37 +170,25 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Whether the scheduler may preempt the task. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum TaskPreemptibleAttr { - /// The scheduler may preempt the task. Allowed, - /// The task runs to completion. Forbidden, - } - #[allow(deprecated)] impl TaskPreemptibleAttr { pub const KEY: &'static str = "myapp.task.preemptible"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: bool = match self { - Self::Allowed => true, - Self::Forbidden => false, - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -267,26 +198,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Fraction of the task that has completed, between 0 and 1. #[derive(Debug, Clone, PartialEq)] - pub struct TaskProgressAttr(f64); - #[allow(deprecated)] impl TaskProgressAttr { pub const KEY: &'static str = "myapp.task.progress"; - pub fn new(value: f64) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -296,26 +220,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Number of times the task was retried. #[derive(Debug, Clone, PartialEq)] - pub struct TaskRetriesAttr(i64); - #[allow(deprecated)] impl TaskRetriesAttr { pub const KEY: &'static str = "myapp.task.retries"; - pub fn new(value: i64) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -325,37 +242,25 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Fraction of tasks whose telemetry is sampled. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum TaskSampleRateAttr { - /// One task in ten is sampled. Tenth, - /// Every task is sampled. All, - } - #[allow(deprecated)] impl TaskSampleRateAttr { pub const KEY: &'static str = "myapp.task.sample_rate"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: f64 = match self { - Self::Tenth => 0.1_f64, - Self::All => 1_f64, - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -365,26 +270,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Shards the task touched. #[derive(Debug, Clone, PartialEq)] - pub struct TaskShardIdsAttr(Vec); - #[allow(deprecated)] impl TaskShardIdsAttr { pub const KEY: &'static str = "myapp.task.shard_ids"; - pub fn new(value: Vec) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) - } } @@ -394,45 +292,31 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum TaskStateAttr { - /// The task is waiting to run. Queued, - /// The task is running. /// /// A task stays running until it finishes or is cancelled. Running, - /// The task was paused. #[deprecated(note = "Paused tasks are reported as queued.")] Paused, - } - #[allow(deprecated)] impl TaskStateAttr { pub const KEY: &'static str = "myapp.task.state"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Queued => "queued".into(), - Self::Running => "running".into(), - Self::Paused => "paused".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -442,26 +326,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Tags attached to the task. #[derive(Debug, Clone, PartialEq)] - pub struct TaskTagsAttr(Vec); - #[allow(deprecated)] impl TaskTagsAttr { pub const KEY: &'static str = "myapp.task.tags"; - pub fn new(value: Vec) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) - } } @@ -471,26 +348,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Scheduling weights applied to the task. #[derive(Debug, Clone, PartialEq)] - pub struct TaskWeightsAttr(Vec); - #[allow(deprecated)] impl TaskWeightsAttr { pub const KEY: &'static str = "myapp.task.weights"; - pub fn new(value: Vec) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(self.0))) - } } diff --git a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs index 432fe83..fc868b9 100644 --- a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs +++ b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Synthetic kept attribute. #[derive(Debug, Clone, PartialEq)] - pub struct KeptAttr(String); - #[allow(deprecated)] impl KeptAttr { pub const KEY: &'static str = "demo.kept"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -28,32 +21,22 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Synthetic mode. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum ModeAttr { - /// Included mode. Kept, - } - #[allow(deprecated)] impl ModeAttr { pub const KEY: &'static str = "demo.mode"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Kept => "kept".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } diff --git a/templates/code/rust/tests/codegen_exclusion/expected/mod.rs b/templates/code/rust/tests/codegen_exclusion/expected/mod.rs index 5fe343d..162e747 100644 --- a/templates/code/rust/tests/codegen_exclusion/expected/mod.rs +++ b/templates/code/rust/tests/codegen_exclusion/expected/mod.rs @@ -1,6 +1,3 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/exclusion/1.0.0"; - pub mod demoattr; diff --git a/templates/code/rust/tests/entities/expected/mod.rs b/templates/code/rust/tests/entities/expected/mod.rs index cf054c4..bab3903 100644 --- a/templates/code/rust/tests/entities/expected/mod.rs +++ b/templates/code/rust/tests/entities/expected/mod.rs @@ -1,13 +1,5 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/entities/1.0.0"; - pub mod myappattr; - - - - - pub mod myappentity; diff --git a/templates/code/rust/tests/entities/expected/myappattr.rs b/templates/code/rust/tests/entities/expected/myappattr.rs index 5ef1a7d..a3d2152 100644 --- a/templates/code/rust/tests/entities/expected/myappattr.rs +++ b/templates/code/rust/tests/entities/expected/myappattr.rs @@ -1,25 +1,18 @@ // Generated by OpenTelemetry Weaver. - /// Number of CPUs the host has. #[deprecated(note = "Use `myapp.host.cpu.logical_count` instead.")] #[derive(Debug, Clone, PartialEq)] - pub struct HostCpuCountAttr(i64); - #[allow(deprecated)] impl HostCpuCountAttr { pub const KEY: &'static str = "myapp.host.cpu.count"; - pub fn new(value: i64) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -29,26 +22,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Name of the host. #[derive(Debug, Clone, PartialEq)] - pub struct HostNameAttr(String); - #[allow(deprecated)] impl HostNameAttr { pub const KEY: &'static str = "myapp.host.name"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -58,26 +44,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Role the host plays in the cluster. #[derive(Debug, Clone, PartialEq)] - pub struct HostRoleAttr(String); - #[allow(deprecated)] impl HostRoleAttr { pub const KEY: &'static str = "myapp.host.role"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -87,37 +66,25 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Type of the host. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum HostTypeAttr { - /// A physical host. Physical, - /// A virtual host. Virtual, - } - #[allow(deprecated)] impl HostTypeAttr { pub const KEY: &'static str = "myapp.host.type"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Physical => "physical".into(), - Self::Virtual => "virtual".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -127,26 +94,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Name of the queue. #[derive(Debug, Clone, PartialEq)] - pub struct QueueNameAttr(String); - #[allow(deprecated)] impl QueueNameAttr { pub const KEY: &'static str = "myapp.queue.name"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -156,26 +116,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Number of items currently in the queue. #[derive(Debug, Clone, PartialEq)] - pub struct QueueSizeAttr(i64); - #[allow(deprecated)] impl QueueSizeAttr { pub const KEY: &'static str = "myapp.queue.size"; - pub fn new(value: i64) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/entities/expected/myappentity.rs b/templates/code/rust/tests/entities/expected/myappentity.rs index c0680a2..6ea9c0b 100644 --- a/templates/code/rust/tests/entities/expected/myappentity.rs +++ b/templates/code/rust/tests/entities/expected/myappentity.rs @@ -1,30 +1,21 @@ // Code generated by weaver. DO NOT EDIT. #![allow(deprecated)] - - #[derive(Clone, Debug)] pub enum HostEntityAttr { - /// Opt-in: the convention records it only when a user asks for it. HostCpuCount(super::myappattr::HostCpuCountAttr), - HostType(super::myappattr::HostTypeAttr), - } impl HostEntityAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::HostCpuCount(value) => value.key_value(), - Self::HostType(value) => value.key_value(), - } } } - /// A host running the application. /// /// Identified by its name across its lifetime. @@ -38,9 +29,7 @@ pub struct HostEntity { impl HostEntity { pub fn new(r#myapp_host_name: super::myappattr::HostNameAttr, options: impl IntoIterator) -> Self { let mut attributes = vec![ - r#myapp_host_name.key_value(), - ]; attributes.extend(options.into_iter().map(HostEntityAttr::key_value)); Self { attributes } @@ -56,31 +45,22 @@ impl HostEntity { .build() } } - - #[derive(Clone, Debug)] pub enum HostWorkerEntityAttr { - /// Opt-in: the convention records it only when a user asks for it. HostCpuCount(super::myappattr::HostCpuCountAttr), - HostType(super::myappattr::HostTypeAttr), - } impl HostWorkerEntityAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::HostCpuCount(value) => value.key_value(), - Self::HostType(value) => value.key_value(), - } } } - /// A host dedicated to running worker processes. /// /// Identified by its name across its lifetime. @@ -95,11 +75,8 @@ pub struct HostWorkerEntity { impl HostWorkerEntity { pub fn new(r#myapp_host_name: super::myappattr::HostNameAttr, r#myapp_host_role: super::myappattr::HostRoleAttr, options: impl IntoIterator) -> Self { let mut attributes = vec![ - r#myapp_host_name.key_value(), - r#myapp_host_role.key_value(), - ]; attributes.extend(options.into_iter().map(HostWorkerEntityAttr::key_value)); Self { attributes } @@ -115,26 +92,19 @@ impl HostWorkerEntity { .build() } } - - #[derive(Clone, Debug)] pub enum QueueEntityAttr { - QueueSize(super::myappattr::QueueSizeAttr), - } impl QueueEntityAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::QueueSize(value) => value.key_value(), - } } } - /// A queue of tasks. /// Identifies the entity: `myapp.queue.name`. /// Describes the entity: `myapp.queue.size`. @@ -146,9 +116,7 @@ pub struct QueueEntity { impl QueueEntity { pub fn new(r#myapp_queue_name: super::myappattr::QueueNameAttr, options: impl IntoIterator) -> Self { let mut attributes = vec![ - r#myapp_queue_name.key_value(), - ]; attributes.extend(options.into_iter().map(QueueEntityAttr::key_value)); Self { attributes } diff --git a/templates/code/rust/tests/events/expected/mod.rs b/templates/code/rust/tests/events/expected/mod.rs index 81e6b53..924b2ab 100644 --- a/templates/code/rust/tests/events/expected/mod.rs +++ b/templates/code/rust/tests/events/expected/mod.rs @@ -1,17 +1,8 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/events/1.0.0"; - pub mod myappattr; - pub mod workerattr; - - - pub mod logger; - pub mod myappevent; - pub mod workerevent; diff --git a/templates/code/rust/tests/events/expected/myappattr.rs b/templates/code/rust/tests/events/expected/myappattr.rs index d72e442..ba1e59b 100644 --- a/templates/code/rust/tests/events/expected/myappattr.rs +++ b/templates/code/rust/tests/events/expected/myappattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Synthetic bool values. #[derive(Debug, Clone, PartialEq)] - pub struct BoolValuesAttr(Vec); - #[allow(deprecated)] impl BoolValuesAttr { pub const KEY: &'static str = "myapp.bool.values"; - pub fn new(value: Vec) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(self.0))) - } } @@ -28,26 +21,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Synthetic double values. #[derive(Debug, Clone, PartialEq)] - pub struct DoubleValuesAttr(Vec); - #[allow(deprecated)] impl DoubleValuesAttr { pub const KEY: &'static str = "myapp.double.values"; - pub fn new(value: Vec) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(self.0))) - } } @@ -57,26 +43,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Synthetic int values. #[derive(Debug, Clone, PartialEq)] - pub struct IntValuesAttr(Vec); - #[allow(deprecated)] impl IntValuesAttr { pub const KEY: &'static str = "myapp.int.values"; - pub fn new(value: Vec) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) - } } @@ -86,26 +65,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Synthetic string values. #[derive(Debug, Clone, PartialEq)] - pub struct StringValuesAttr(Vec); - #[allow(deprecated)] impl StringValuesAttr { pub const KEY: &'static str = "myapp.string.values"; - pub fn new(value: Vec) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) - } } @@ -115,26 +87,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Number of the attempt, starting at 1. #[derive(Debug, Clone, PartialEq)] - pub struct TaskAttemptAttr(i64); - #[allow(deprecated)] impl TaskAttemptAttr { pub const KEY: &'static str = "myapp.task.attempt"; - pub fn new(value: i64) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -144,37 +109,25 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum TaskStateAttr { - /// The task finished. Done, - /// The task gave up. Failed, - } - #[allow(deprecated)] impl TaskStateAttr { pub const KEY: &'static str = "myapp.task.state"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Done => "done".into(), - Self::Failed => "failed".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } diff --git a/templates/code/rust/tests/events/expected/myappevent.rs b/templates/code/rust/tests/events/expected/myappevent.rs index a12b810..f5cc294 100644 --- a/templates/code/rust/tests/events/expected/myappevent.rs +++ b/templates/code/rust/tests/events/expected/myappevent.rs @@ -1,30 +1,20 @@ #![allow(deprecated)] - - - #[derive(Clone, Debug)] pub enum TaskFinishedOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - BoolValues(super::myappattr::BoolValuesAttr), - DoubleValues(super::myappattr::DoubleValuesAttr), - IntValues(super::myappattr::IntValuesAttr), - StringValues(super::myappattr::StringValuesAttr), - /// Recommended: When the task ran more than once. TaskAttempt(super::myappattr::TaskAttemptAttr), - /// Opt-in: the convention records it only when a user asks for it. HostName(super::workerattr::HostNameAttr), - } /// A task reached a final state. /// @@ -40,19 +30,12 @@ pub fn r#emit_task_finished(context: &::opente match option { TaskFinishedOption::Severity(value) => severity = value, TaskFinishedOption::Timestamp(value) => timestamp = Some(value), - TaskFinishedOption::BoolValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::DoubleValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::IntValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::StringValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::TaskAttempt(value) => attributes.push(value.key_value()), - TaskFinishedOption::HostName(value) => attributes.push(value.key_value()), - } } if !logger.inner().event_enabled(severity, "", Some("myapp.task.finished")) { return; } @@ -67,13 +50,10 @@ pub fn r#emit_task_finished(context: &::opente for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } logger.inner().emit(record); } - - #[derive(Clone, Debug)] pub enum TaskRetriedOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - } /// A task is about to run again. /// Opt-in: record only when the user requests it. @@ -89,7 +69,6 @@ pub fn r#emit_task_retried(context: &::opentel match option { TaskRetriedOption::Severity(value) => severity = value, TaskRetriedOption::Timestamp(value) => timestamp = Some(value), - } } if !logger.inner().event_enabled(severity, "", Some("myapp.task.retried")) { return; } diff --git a/templates/code/rust/tests/events/expected/workerattr.rs b/templates/code/rust/tests/events/expected/workerattr.rs index 4146047..c39d1b4 100644 --- a/templates/code/rust/tests/events/expected/workerattr.rs +++ b/templates/code/rust/tests/events/expected/workerattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Name of the worker host. #[derive(Debug, Clone, PartialEq)] - pub struct HostNameAttr(String); - #[allow(deprecated)] impl HostNameAttr { pub const KEY: &'static str = "worker.host.name"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/events/expected/workerevent.rs b/templates/code/rust/tests/events/expected/workerevent.rs index 5f0f2dc..2bc40db 100644 --- a/templates/code/rust/tests/events/expected/workerevent.rs +++ b/templates/code/rust/tests/events/expected/workerevent.rs @@ -1,12 +1,8 @@ #![allow(deprecated)] - - - #[derive(Clone, Debug)] pub enum HostStartedOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - } /// A worker host started taking tasks. pub fn r#emit_host_started(context: &::opentelemetry::Context, logger: &super::logger::Logger, options: impl IntoIterator) { @@ -20,7 +16,6 @@ pub fn r#emit_host_started(context: &::opentel match option { HostStartedOption::Severity(value) => severity = value, HostStartedOption::Timestamp(value) => timestamp = Some(value), - } } if !logger.inner().event_enabled(severity, "", Some("worker.host.started")) { return; } @@ -35,28 +30,20 @@ pub fn r#emit_host_started(context: &::opentel for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } logger.inner().emit(record); } - - #[derive(Clone, Debug)] pub enum TaskFinishedOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - BoolValues(super::myappattr::BoolValuesAttr), - DoubleValues(super::myappattr::DoubleValuesAttr), - IntValues(super::myappattr::IntValuesAttr), - StringValues(super::myappattr::StringValuesAttr), - /// Recommended: When the task ran more than once. TaskAttempt(super::myappattr::TaskAttemptAttr), - } /// A task reached a final state on a worker. /// @@ -72,17 +59,11 @@ pub fn r#emit_task_finished(context: &::opente match option { TaskFinishedOption::Severity(value) => severity = value, TaskFinishedOption::Timestamp(value) => timestamp = Some(value), - TaskFinishedOption::BoolValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::DoubleValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::IntValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::StringValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::TaskAttempt(value) => attributes.push(value.key_value()), - } } if !logger.inner().event_enabled(severity, "", Some("worker.task.finished")) { return; } diff --git a/templates/code/rust/tests/filtering/expected/authattr.rs b/templates/code/rust/tests/filtering/expected/authattr.rs index c577061..fe1b41f 100644 --- a/templates/code/rust/tests/filtering/expected/authattr.rs +++ b/templates/code/rust/tests/filtering/expected/authattr.rs @@ -1,35 +1,23 @@ // Generated by OpenTelemetry Weaver. - /// How the user was authenticated. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum MethodAttr { - /// A password was checked. Password, - /// A bearer token was checked. Token, - } - #[allow(deprecated)] impl MethodAttr { pub const KEY: &'static str = "auth.method"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Password => "password".into(), - Self::Token => "token".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -39,26 +27,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Identifier of the authenticated user. #[derive(Debug, Clone, PartialEq)] - pub struct UserIdAttr(String); - #[allow(deprecated)] impl UserIdAttr { pub const KEY: &'static str = "auth.user.id"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/filtering/expected/mod.rs b/templates/code/rust/tests/filtering/expected/mod.rs index 2729cec..db0137c 100644 --- a/templates/code/rust/tests/filtering/expected/mod.rs +++ b/templates/code/rust/tests/filtering/expected/mod.rs @@ -1,8 +1,4 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/filtering/1.0.0"; - pub mod authattr; - pub mod taskattr; diff --git a/templates/code/rust/tests/filtering/expected/taskattr.rs b/templates/code/rust/tests/filtering/expected/taskattr.rs index ff3d95b..900647f 100644 --- a/templates/code/rust/tests/filtering/expected/taskattr.rs +++ b/templates/code/rust/tests/filtering/expected/taskattr.rs @@ -1,26 +1,19 @@ // Generated by OpenTelemetry Weaver. - /// Who assigned the task. /// /// The scheduler sets it on every task it passes along to `myapp.task.state`. Workers never set it themselves. #[derive(Debug, Clone, PartialEq)] - pub struct AssignedByAttr(String); - #[allow(deprecated)] impl AssignedByAttr { pub const KEY: &'static str = "myapp.task.assigned_by"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -30,26 +23,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Whether the task was cancelled. #[derive(Debug, Clone, PartialEq)] - pub struct CancelledAttr(bool); - #[allow(deprecated)] impl CancelledAttr { pub const KEY: &'static str = "myapp.task.cancelled"; - pub fn new(value: bool) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -59,28 +45,21 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Unique identifier of the task. /// /// The identifier is assigned by the scheduler and stays stable across retries. #[derive(Debug, Clone, PartialEq)] - pub struct IdAttr(String); - #[allow(deprecated)] impl IdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -90,37 +69,25 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Whether the scheduler may preempt the task. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum PreemptibleAttr { - /// The scheduler may preempt the task. Allowed, - /// The task runs to completion. Forbidden, - } - #[allow(deprecated)] impl PreemptibleAttr { pub const KEY: &'static str = "myapp.task.preemptible"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: bool = match self { - Self::Allowed => true, - Self::Forbidden => false, - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -130,26 +97,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Number of times the task was retried. #[derive(Debug, Clone, PartialEq)] - pub struct RetriesAttr(i64); - #[allow(deprecated)] impl RetriesAttr { pub const KEY: &'static str = "myapp.task.retries"; - pub fn new(value: i64) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -159,37 +119,25 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Fraction of tasks whose telemetry is sampled. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum SampleRateAttr { - /// One task in ten is sampled. Tenth, - /// Every task is sampled. All, - } - #[allow(deprecated)] impl SampleRateAttr { pub const KEY: &'static str = "myapp.task.sample_rate"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: f64 = match self { - Self::Tenth => 0.1_f64, - Self::All => 1_f64, - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -199,26 +147,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Shards the task touched. #[derive(Debug, Clone, PartialEq)] - pub struct ShardIdsAttr(Vec); - #[allow(deprecated)] impl ShardIdsAttr { pub const KEY: &'static str = "myapp.task.shard_ids"; - pub fn new(value: Vec) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) - } } @@ -228,39 +169,27 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum StateAttr { - /// The task is waiting to run. Queued, - /// The task is running. /// /// A task stays running until it finishes or is cancelled. Running, - } - #[allow(deprecated)] impl StateAttr { pub const KEY: &'static str = "myapp.task.state"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Queued => "queued".into(), - Self::Running => "running".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -270,26 +199,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Tags attached to the task. #[derive(Debug, Clone, PartialEq)] - pub struct TagsAttr(Vec); - #[allow(deprecated)] impl TagsAttr { pub const KEY: &'static str = "myapp.task.tags"; - pub fn new(value: Vec) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) - } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs index d6e3e68..ae1eaf7 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs @@ -1,13 +1,6 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/histogram_boundaries_by_unit/1.0.0"; - pub mod myappattr; - pub mod meter; - - - pub mod myappmetric; diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs index 21a7729..33632e5 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] - pub struct TaskIdAttr(String); - #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs index 3b81a78..7aabf28 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs @@ -1,12 +1,4 @@ #![allow(deprecated)] - - - - - - - - /// Time a task took from start to finish. #[derive(Clone)] pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } @@ -15,28 +7,17 @@ impl TaskDurationHistogram { Self { instrument: meter.inner().f64_histogram("myapp.task.duration") .with_description("Time a task took from start to finish.") .with_unit("s") - .with_boundaries(vec![0.005_f64, 0.01_f64, 0.025_f64, 0.05_f64, 0.075_f64, 0.1_f64, 0.25_f64, 0.5_f64, 0.75_f64, 1_f64, 2.5_f64, 5_f64, 7.5_f64, 10_f64]) - .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { let attributes = vec![r#myapp_task_id.key_value()]; - self.instrument.record(value, &attributes); } } impl Default for TaskDurationHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - - - - - - - /// Time between a task being queued and started. #[derive(Clone)] pub struct TaskLatencyHistogram { instrument: ::opentelemetry::metrics::Histogram } @@ -45,28 +26,17 @@ impl TaskLatencyHistogram { Self { instrument: meter.inner().f64_histogram("myapp.task.latency") .with_description("Time between a task being queued and started.") .with_unit("s") - .with_boundaries(vec![1_f64, 10_f64, 100_f64]) - .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { let attributes = vec![r#myapp_task_id.key_value()]; - self.instrument.record(value, &attributes); } } impl Default for TaskLatencyHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - - - - - - - /// Time a retried task took from start to finish. #[derive(Clone)] pub struct TaskRetryDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } @@ -75,28 +45,17 @@ impl TaskRetryDurationHistogram { Self { instrument: meter.inner().f64_histogram("myapp.task.duration") .with_description("Time a task took from start to finish.") .with_unit("s") - .with_boundaries(vec![0.005_f64, 0.01_f64, 0.025_f64, 0.05_f64, 0.075_f64, 0.1_f64, 0.25_f64, 0.5_f64, 0.75_f64, 1_f64, 2.5_f64, 5_f64, 7.5_f64, 10_f64]) - .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { let attributes = vec![r#myapp_task_id.key_value()]; - self.instrument.record(value, &attributes); } } impl Default for TaskRetryDurationHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - - - - - - - /// Size of a task's payload. #[derive(Clone)] pub struct TaskSizeHistogram { instrument: ::opentelemetry::metrics::Histogram } @@ -105,12 +64,10 @@ impl TaskSizeHistogram { Self { instrument: meter.inner().f64_histogram("myapp.task.size") .with_description("Size of a task\u{0027}s payload.") .with_unit("By") - .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { let attributes = vec![r#myapp_task_id.key_value()]; - self.instrument.record(value, &attributes); } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs index eeaf0b3..d5166c8 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs @@ -1,13 +1,6 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/histogram_boundaries_by_unit_params/1.0.0"; - pub mod myappattr; - pub mod meter; - - - pub mod myappmetric; diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs index 21a7729..33632e5 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] - pub struct TaskIdAttr(String); - #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs index 5b37fab..fc27488 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs @@ -1,12 +1,4 @@ #![allow(deprecated)] - - - - - - - - /// Time a task took from start to finish. #[derive(Clone)] pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } @@ -15,26 +7,16 @@ impl TaskDurationHistogram { Self { instrument: meter.inner().f64_histogram("myapp.task.duration") .with_description("Time a task took from start to finish.") .with_unit("s") - .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { let attributes = vec![r#myapp_task_id.key_value()]; - self.instrument.record(value, &attributes); } } impl Default for TaskDurationHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - - - - - - - /// Time a task waited in the queue, in minutes. #[derive(Clone)] pub struct TaskQueueWaitHistogram { instrument: ::opentelemetry::metrics::Histogram } @@ -43,14 +25,11 @@ impl TaskQueueWaitHistogram { Self { instrument: meter.inner().f64_histogram("myapp.task.queue_wait") .with_description("Time a task waited in the queue, in minutes.") .with_unit("min") - .with_boundaries(vec![1_f64, 5_f64, 10_f64, 30_f64, 60_f64]) - .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { let attributes = vec![r#myapp_task_id.key_value()]; - self.instrument.record(value, &attributes); } } diff --git a/templates/code/rust/tests/imported/expected/edgeevent.rs b/templates/code/rust/tests/imported/expected/edgeevent.rs index 3225685..404d356 100644 --- a/templates/code/rust/tests/imported/expected/edgeevent.rs +++ b/templates/code/rust/tests/imported/expected/edgeevent.rs @@ -1,15 +1,10 @@ #![allow(deprecated)] - - - #[derive(Clone, Debug)] pub enum UpstreamFailedOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - ServerAddress(String), - } /// A request to an upstream server failed. pub fn r#emit_upstream_failed(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#error_type: String, options: impl IntoIterator) { @@ -23,9 +18,7 @@ pub fn r#emit_upstream_failed(context: &::open match option { UpstreamFailedOption::Severity(value) => severity = value, UpstreamFailedOption::Timestamp(value) => timestamp = Some(value), - UpstreamFailedOption::ServerAddress(value) => attributes.push(::opentelemetry::KeyValue::new("server.address", value)), - } } if !logger.inner().event_enabled(severity, "", Some("edge.upstream.failed")) { return; } diff --git a/templates/code/rust/tests/imported/expected/edgemetric.rs b/templates/code/rust/tests/imported/expected/edgemetric.rs index d99b409..e83ee6b 100644 --- a/templates/code/rust/tests/imported/expected/edgemetric.rs +++ b/templates/code/rust/tests/imported/expected/edgemetric.rs @@ -1,29 +1,16 @@ #![allow(deprecated)] - - - - - - - - #[derive(Clone, Debug)] pub enum UpstreamDurationHistogramAttr { - ServerPort(i64), - } impl UpstreamDurationHistogramAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), - } } } - /// Time spent waiting on an upstream server. #[derive(Clone)] pub struct UpstreamDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } @@ -32,16 +19,12 @@ impl UpstreamDurationHistogram { Self { instrument: meter.inner().f64_histogram("edge.upstream.duration") .with_description("Time spent waiting on an upstream server.") .with_unit("s") - .with_boundaries(vec![0.005_f64, 0.01_f64, 0.025_f64, 0.05_f64, 0.075_f64, 0.1_f64, 0.25_f64, 0.5_f64, 0.75_f64, 1_f64, 2.5_f64, 5_f64, 7.5_f64, 10_f64]) - .build() } } pub fn record(&self, value: f64, r#server_address: String, options: impl IntoIterator) { let mut attributes = vec![::opentelemetry::KeyValue::new("server.address", r#server_address)]; - attributes.extend(options.into_iter().map(UpstreamDurationHistogramAttr::key_value)); - self.instrument.record(value, &attributes); } } diff --git a/templates/code/rust/tests/imported/expected/edgespan.rs b/templates/code/rust/tests/imported/expected/edgespan.rs index dfe7deb..68d2ec7 100644 --- a/templates/code/rust/tests/imported/expected/edgespan.rs +++ b/templates/code/rust/tests/imported/expected/edgespan.rs @@ -1,49 +1,30 @@ #![allow(deprecated)] - - - - - #[derive(Clone, Debug)] pub enum UpstreamRequestStartAttr { - /// Conditionally required: If the request failed. ErrorType(String), - HttpRequestMethodList(Vec), - } impl UpstreamRequestStartAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::ErrorType(value) => ::opentelemetry::KeyValue::new("error.type", value), - Self::HttpRequestMethodList(value) => ::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.into_iter().map(Into::into).collect()))), - } } } - - #[derive(Clone, Debug)] pub enum UpstreamRequestAttr { - HttpRequestMethodList(Vec), - } impl From for UpstreamRequestStartAttr { fn from(value: UpstreamRequestAttr) -> Self { match value { - UpstreamRequestAttr::HttpRequestMethodList(value) => Self::HttpRequestMethodList(value), - } } } - - /// A request to an upstream server. pub struct UpstreamRequestSpan { span: ::opentelemetry::global::BoxedSpan } impl UpstreamRequestSpan { @@ -56,11 +37,9 @@ impl UpstreamRequestSpan { pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } - pub fn set_attributes(&mut self, attributes: impl IntoIterator) { for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, UpstreamRequestStartAttr::from(attribute).key_value()); } } - } impl Default for UpstreamRequestSpan { fn default() -> Self { @@ -71,28 +50,12 @@ impl Default for UpstreamRequestSpan { pub fn r#start_upstream_request(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#server_address: String, r#server_port: i64, options: impl IntoIterator) -> UpstreamRequestSpan { use ::opentelemetry::trace::Tracer; - let mut name = String::new(); - - name.push_str(&::opentelemetry::KeyValue::new("server.address", r#server_address.clone()).value.to_string()); - - - - name.push(':'); - - - - name.push_str(&::opentelemetry::KeyValue::new("server.port", r#server_port).value.to_string()); - - - let mut attributes = vec![::opentelemetry::KeyValue::new("server.address", r#server_address), ::opentelemetry::KeyValue::new("server.port", r#server_port)]; - attributes.extend(options.into_iter().map(UpstreamRequestStartAttr::key_value)); - let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Client) .with_attributes(attributes) diff --git a/templates/code/rust/tests/imported/expected/mod.rs b/templates/code/rust/tests/imported/expected/mod.rs index fcd3acd..2690858 100644 --- a/templates/code/rust/tests/imported/expected/mod.rs +++ b/templates/code/rust/tests/imported/expected/mod.rs @@ -1,19 +1,11 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/myapp/1.0.0"; - pub mod myappattr; - pub mod meter; pub mod tracer; pub mod logger; - pub mod edgeevent; - pub mod edgemetric; - pub mod edgespan; - pub mod myappmetric; diff --git a/templates/code/rust/tests/imported/expected/myappattr.rs b/templates/code/rust/tests/imported/expected/myappattr.rs index 21a7729..33632e5 100644 --- a/templates/code/rust/tests/imported/expected/myappattr.rs +++ b/templates/code/rust/tests/imported/expected/myappattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] - pub struct TaskIdAttr(String); - #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/imported/expected/myappmetric.rs b/templates/code/rust/tests/imported/expected/myappmetric.rs index a973012..9c71ac1 100644 --- a/templates/code/rust/tests/imported/expected/myappmetric.rs +++ b/templates/code/rust/tests/imported/expected/myappmetric.rs @@ -1,29 +1,16 @@ #![allow(deprecated)] - - - - - - - - #[derive(Clone, Debug)] pub enum TaskFailedCounterAttr { - HttpRequestMethodList(Vec), - } impl TaskFailedCounterAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::HttpRequestMethodList(value) => ::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.into_iter().map(Into::into).collect()))), - } } } - /// Number of tasks that failed. #[derive(Clone)] pub struct TaskFailedCounter { instrument: ::opentelemetry::metrics::Counter } @@ -32,29 +19,22 @@ impl TaskFailedCounter { Self { instrument: meter.inner().u64_counter("myapp.task.failed") .with_description("Number of tasks that failed.") .with_unit("{task}") - .build() } } pub fn add(&self, value: u64, r#error_type: String, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { let mut attributes = vec![::opentelemetry::KeyValue::new("error.type", r#error_type), r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskFailedCounterAttr::key_value)); - self.instrument.add(value, &attributes); } } impl Default for TaskFailedCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - pub struct TaskFailedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskFailedCounterObserver<'_> { pub fn observe(&self, value: u64, r#error_type: String, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { let mut attributes = vec![::opentelemetry::KeyValue::new("error.type", r#error_type), r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskFailedCounterAttr::key_value)); - self.observer.observe(value, &attributes); } } diff --git a/templates/code/rust/tests/imported_typed/expected/mod.rs b/templates/code/rust/tests/imported_typed/expected/mod.rs index 8e89569..da9ba6d 100644 --- a/templates/code/rust/tests/imported_typed/expected/mod.rs +++ b/templates/code/rust/tests/imported_typed/expected/mod.rs @@ -1,17 +1,10 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/myapp/1.0.0"; - pub mod myappattr; - pub mod meter; pub mod tracer; pub mod logger; - pub mod myappevent; - pub mod myappmetric; - pub mod myappspan; diff --git a/templates/code/rust/tests/imported_typed/expected/myappattr.rs b/templates/code/rust/tests/imported_typed/expected/myappattr.rs index 21a7729..33632e5 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappattr.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] - pub struct TaskIdAttr(String); - #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/imported_typed/expected/myappevent.rs b/templates/code/rust/tests/imported_typed/expected/myappevent.rs index 0f5e8d5..5dc334a 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappevent.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappevent.rs @@ -1,15 +1,10 @@ #![allow(deprecated)] - - - #[derive(Clone, Debug)] pub enum TaskErroredOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - ServerPort(i64), - } /// A task failed with an error. pub fn r#emit_task_errored(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#error_type: upstream::errorattr::TypeAttr, options: impl IntoIterator) { @@ -23,9 +18,7 @@ pub fn r#emit_task_errored(context: &::opentel match option { TaskErroredOption::Severity(value) => severity = value, TaskErroredOption::Timestamp(value) => timestamp = Some(value), - TaskErroredOption::ServerPort(value) => attributes.push(::opentelemetry::KeyValue::new("server.port", value)), - } } if !logger.inner().event_enabled(severity, "", Some("myapp.task.errored")) { return; } diff --git a/templates/code/rust/tests/imported_typed/expected/myappmetric.rs b/templates/code/rust/tests/imported_typed/expected/myappmetric.rs index 1d523e5..c797eca 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappmetric.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappmetric.rs @@ -1,29 +1,16 @@ #![allow(deprecated)] - - - - - - - - #[derive(Clone, Debug)] pub enum TaskFailedCounterAttr { - ServerPort(i64), - } impl TaskFailedCounterAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), - } } } - /// Number of tasks that failed. #[derive(Clone)] pub struct TaskFailedCounter { instrument: ::opentelemetry::metrics::Counter } @@ -32,29 +19,22 @@ impl TaskFailedCounter { Self { instrument: meter.inner().u64_counter("myapp.task.failed") .with_description("Number of tasks that failed.") .with_unit("{task}") - .build() } } pub fn add(&self, value: u64, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { let mut attributes = vec![r#error_type.key_value(), r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskFailedCounterAttr::key_value)); - self.instrument.add(value, &attributes); } } impl Default for TaskFailedCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - pub struct TaskFailedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskFailedCounterObserver<'_> { pub fn observe(&self, value: u64, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { let mut attributes = vec![r#error_type.key_value(), r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskFailedCounterAttr::key_value)); - self.observer.observe(value, &attributes); } } diff --git a/templates/code/rust/tests/imported_typed/expected/myappspan.rs b/templates/code/rust/tests/imported_typed/expected/myappspan.rs index 0fbde75..35275a8 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappspan.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappspan.rs @@ -1,44 +1,27 @@ #![allow(deprecated)] - - - - - #[derive(Clone, Debug)] pub enum TaskDispatchStartAttr { - ServerPort(i64), - } impl TaskDispatchStartAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), - } } } - - #[derive(Clone, Debug)] pub enum TaskDispatchAttr { - ServerPort(i64), - } impl From for TaskDispatchStartAttr { fn from(value: TaskDispatchAttr) -> Self { match value { - TaskDispatchAttr::ServerPort(value) => Self::ServerPort(value), - } } } - - /// Dispatch of a task. pub struct TaskDispatchSpan { span: ::opentelemetry::global::BoxedSpan } impl TaskDispatchSpan { @@ -51,11 +34,9 @@ impl TaskDispatchSpan { pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } - pub fn set_attributes(&mut self, attributes: impl IntoIterator) { for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, TaskDispatchStartAttr::from(attribute).key_value()); } } - } impl Default for TaskDispatchSpan { fn default() -> Self { @@ -66,34 +47,13 @@ impl Default for TaskDispatchSpan { pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) -> TaskDispatchSpan { use ::opentelemetry::trace::Tracer; - let mut name = String::new(); - - - name.push_str("task "); - - - - name.push_str(&r#myapp_task_id.clone().key_value().value.to_string()); - - - - name.push_str(" failed with "); - - - - name.push_str(&r#error_type.key_value().value.to_string()); - - - let mut attributes = vec![r#error_type.key_value(), r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskDispatchStartAttr::key_value)); - let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) diff --git a/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs b/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs index ced94f4..aa3ef6c 100644 --- a/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs +++ b/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs @@ -1,35 +1,23 @@ // Generated by OpenTelemetry Weaver. - /// Synthetic integer limits. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum BoundaryAttr { - /// Lowest signed 64-bit integer. Minimum, - /// Highest signed 64-bit integer. Maximum, - } - #[allow(deprecated)] impl BoundaryAttr { pub const KEY: &'static str = "demo.boundary"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: i64 = match self { - Self::Minimum => -9223372036854775808, - Self::Maximum => 9223372036854775807, - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } diff --git a/templates/code/rust/tests/integer_boundaries/expected/mod.rs b/templates/code/rust/tests/integer_boundaries/expected/mod.rs index 6688a87..19656c6 100644 --- a/templates/code/rust/tests/integer_boundaries/expected/mod.rs +++ b/templates/code/rust/tests/integer_boundaries/expected/mod.rs @@ -1,6 +1,3 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/1.0.0"; - pub mod demoattr; diff --git a/templates/code/rust/tests/literal_escaping/expected/demoattr.rs b/templates/code/rust/tests/literal_escaping/expected/demoattr.rs index a844e46..1500e97 100644 --- a/templates/code/rust/tests/literal_escaping/expected/demoattr.rs +++ b/templates/code/rust/tests/literal_escaping/expected/demoattr.rs @@ -1,35 +1,23 @@ // Generated by OpenTelemetry Weaver. - /// Literal escape sequences. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum LiteralAttr { - /// Literal escape sequences. Literal, - /// Actual controls and escaped text. Controls, - } - #[allow(deprecated)] impl LiteralAttr { pub const KEY: &'static str = "demo.literal"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Literal => "backspace\\b formfeed\\f unicode\\u1234 doubled\\\\b tripled\\\\\\u0000".into(), - Self::Controls => "backspace\u{0008} formfeed\u{000c} unicode\u{0001} slash\\b".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } diff --git a/templates/code/rust/tests/literal_escaping/expected/demometric.rs b/templates/code/rust/tests/literal_escaping/expected/demometric.rs index 6f5c6c6..9d4b3cb 100644 --- a/templates/code/rust/tests/literal_escaping/expected/demometric.rs +++ b/templates/code/rust/tests/literal_escaping/expected/demometric.rs @@ -1,12 +1,4 @@ #![allow(deprecated)] - - - - - - - - /// literal \b \f \u1234 #[derive(Clone)] pub struct LiteralCountCounter { instrument: ::opentelemetry::metrics::Counter } @@ -15,25 +7,20 @@ impl LiteralCountCounter { Self { instrument: meter.inner().u64_counter("demo.literal.count") .with_description("literal \\b \\f \\u1234") .with_unit("literal\\b\\u1234") - .build() } } pub fn add(&self, value: u64, r#demo_literal: super::demoattr::LiteralAttr) { let attributes = vec![r#demo_literal.key_value()]; - self.instrument.add(value, &attributes); } } impl Default for LiteralCountCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - pub struct LiteralCountCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl LiteralCountCounterObserver<'_> { pub fn observe(&self, value: u64, r#demo_literal: super::demoattr::LiteralAttr) { let attributes = vec![r#demo_literal.key_value()]; - self.observer.observe(value, &attributes); } } diff --git a/templates/code/rust/tests/literal_escaping/expected/mod.rs b/templates/code/rust/tests/literal_escaping/expected/mod.rs index 70f8a96..43f1e41 100644 --- a/templates/code/rust/tests/literal_escaping/expected/mod.rs +++ b/templates/code/rust/tests/literal_escaping/expected/mod.rs @@ -1,13 +1,6 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/escaping/1.0.0"; - pub mod demoattr; - pub mod meter; - - - pub mod demometric; diff --git a/templates/code/rust/tests/metrics/expected/authattr.rs b/templates/code/rust/tests/metrics/expected/authattr.rs index 29f94b7..1da69fc 100644 --- a/templates/code/rust/tests/metrics/expected/authattr.rs +++ b/templates/code/rust/tests/metrics/expected/authattr.rs @@ -1,35 +1,23 @@ // Generated by OpenTelemetry Weaver. - /// How the user was authenticated. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum MethodAttr { - /// A password was checked. Password, - /// A bearer token was checked. Token, - } - #[allow(deprecated)] impl MethodAttr { pub const KEY: &'static str = "auth.method"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Password => "password".into(), - Self::Token => "token".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } @@ -39,26 +27,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Whether the attempt succeeded. #[derive(Debug, Clone, PartialEq)] - pub struct SuccessAttr(bool); - #[allow(deprecated)] impl SuccessAttr { pub const KEY: &'static str = "auth.success"; - pub fn new(value: bool) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/metrics/expected/authmetric.rs b/templates/code/rust/tests/metrics/expected/authmetric.rs index 21a3fc0..7567d6c 100644 --- a/templates/code/rust/tests/metrics/expected/authmetric.rs +++ b/templates/code/rust/tests/metrics/expected/authmetric.rs @@ -1,12 +1,4 @@ #![allow(deprecated)] - - - - - - - - /// Number of authentication attempts. #[derive(Clone)] pub struct AttemptsCounter { instrument: ::opentelemetry::metrics::Counter } @@ -15,25 +7,20 @@ impl AttemptsCounter { Self { instrument: meter.inner().u64_counter("auth.attempts") .with_description("Number of authentication attempts.") .with_unit("{attempt}") - .build() } } pub fn add(&self, value: u64, r#auth_method: super::authattr::MethodAttr, r#auth_success: super::authattr::SuccessAttr) { let attributes = vec![r#auth_method.key_value(), r#auth_success.key_value()]; - self.instrument.add(value, &attributes); } } impl Default for AttemptsCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - pub struct AttemptsCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl AttemptsCounterObserver<'_> { pub fn observe(&self, value: u64, r#auth_method: super::authattr::MethodAttr, r#auth_success: super::authattr::SuccessAttr) { let attributes = vec![r#auth_method.key_value(), r#auth_success.key_value()]; - self.observer.observe(value, &attributes); } } diff --git a/templates/code/rust/tests/metrics/expected/mod.rs b/templates/code/rust/tests/metrics/expected/mod.rs index 11b41ec..57229fc 100644 --- a/templates/code/rust/tests/metrics/expected/mod.rs +++ b/templates/code/rust/tests/metrics/expected/mod.rs @@ -1,19 +1,9 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/metrics/1.0.0"; - pub mod authattr; - pub mod myappattr; - pub mod meter; - - - pub mod authmetric; - pub mod myappmetric; - pub mod workermetric; diff --git a/templates/code/rust/tests/metrics/expected/myappattr.rs b/templates/code/rust/tests/metrics/expected/myappattr.rs index 4b9c416..cc7d9fe 100644 --- a/templates/code/rust/tests/metrics/expected/myappattr.rs +++ b/templates/code/rust/tests/metrics/expected/myappattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] - pub struct TaskIdAttr(String); - #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -28,37 +21,25 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum TaskStateAttr { - /// The task is waiting to run. Queued, - /// The task finished. Done, - } - #[allow(deprecated)] impl TaskStateAttr { pub const KEY: &'static str = "myapp.task.state"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Queued => "queued".into(), - Self::Done => "done".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } diff --git a/templates/code/rust/tests/metrics/expected/myappmetric.rs b/templates/code/rust/tests/metrics/expected/myappmetric.rs index 6eeaaca..bc10bbd 100644 --- a/templates/code/rust/tests/metrics/expected/myappmetric.rs +++ b/templates/code/rust/tests/metrics/expected/myappmetric.rs @@ -1,12 +1,4 @@ #![allow(deprecated)] - - - - - - - - /// Number of tasks waiting in the queue. #[deprecated(note = "Replaced by `myapp.task.active`.")] #[derive(Clone)] @@ -16,25 +8,20 @@ impl QueueDepthGauge { Self { instrument: meter.inner().i64_gauge("myapp.queue.depth") .with_description("Number of tasks waiting in the queue.") .with_unit("{task}") - .build() } } pub fn record(&self, value: i64) { let attributes = vec![]; - self.instrument.record(value, &attributes); } } impl Default for QueueDepthGauge { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - pub struct QueueDepthGaugeObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl QueueDepthGaugeObserver<'_> { pub fn observe(&self, value: i64) { let attributes = vec![]; - self.observer.observe(value, &attributes); } } @@ -53,14 +40,6 @@ impl QueueDepthObservableGauge { impl Default for QueueDepthObservableGauge { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } - - - - - - - - /// Number of tasks currently running. #[derive(Clone)] pub struct TaskActiveUpDownCounter { instrument: ::opentelemetry::metrics::UpDownCounter } @@ -69,25 +48,20 @@ impl TaskActiveUpDownCounter { Self { instrument: meter.inner().i64_up_down_counter("myapp.task.active") .with_description("Number of tasks currently running.") .with_unit("{task}") - .build() } } pub fn add(&self, value: i64, r#myapp_task_state: super::myappattr::TaskStateAttr) { let attributes = vec![r#myapp_task_state.key_value()]; - self.instrument.add(value, &attributes); } } impl Default for TaskActiveUpDownCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - pub struct TaskActiveUpDownCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskActiveUpDownCounterObserver<'_> { pub fn observe(&self, value: i64, r#myapp_task_state: super::myappattr::TaskStateAttr) { let attributes = vec![r#myapp_task_state.key_value()]; - self.observer.observe(value, &attributes); } } @@ -106,36 +80,21 @@ impl TaskActiveObservableUpDownCounter { impl Default for TaskActiveObservableUpDownCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } - - - - - - - - #[derive(Clone, Debug)] pub enum TaskDurationHistogramAttr { - /// Opt-in: the convention records it only when a user asks for it. Method(super::authattr::MethodAttr), - /// Conditionally required: If the task reached a final state. TaskState(super::myappattr::TaskStateAttr), - } impl TaskDurationHistogramAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::Method(value) => value.key_value(), - Self::TaskState(value) => value.key_value(), - } } } - /// Time a task took from start to finish. /// /// Measured by the worker that ran the task. @@ -146,30 +105,18 @@ impl TaskDurationHistogram { Self { instrument: meter.inner().f64_histogram("myapp.task.duration") .with_description("Time a task took from start to finish.") .with_unit("s") - .with_boundaries(vec![0_f64, 0.005_f64, 0.01_f64, 0.1_f64, 1_f64, 10_f64]) - .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { let mut attributes = vec![r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskDurationHistogramAttr::key_value)); - self.instrument.record(value, &attributes); } } impl Default for TaskDurationHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - - - - - - - /// Fractional active task adjustment. #[derive(Clone)] pub struct TaskFloatActiveUpDownCounter { instrument: ::opentelemetry::metrics::UpDownCounter } @@ -178,25 +125,20 @@ impl TaskFloatActiveUpDownCounter { Self { instrument: meter.inner().f64_up_down_counter("myapp.task.float.active") .with_description("Fractional active task adjustment.") .with_unit("{task}") - .build() } } pub fn add(&self, value: f64) { let attributes = vec![]; - self.instrument.add(value, &attributes); } } impl Default for TaskFloatActiveUpDownCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - pub struct TaskFloatActiveUpDownCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskFloatActiveUpDownCounterObserver<'_> { pub fn observe(&self, value: f64) { let attributes = vec![]; - self.observer.observe(value, &attributes); } } @@ -215,14 +157,6 @@ impl TaskFloatActiveObservableUpDownCounter { impl Default for TaskFloatActiveObservableUpDownCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } - - - - - - - - /// Fractional queue depth. #[derive(Clone)] pub struct TaskFloatDepthGauge { instrument: ::opentelemetry::metrics::Gauge } @@ -231,25 +165,20 @@ impl TaskFloatDepthGauge { Self { instrument: meter.inner().f64_gauge("myapp.task.float.depth") .with_description("Fractional queue depth.") .with_unit("{task}") - .build() } } pub fn record(&self, value: f64) { let attributes = vec![]; - self.instrument.record(value, &attributes); } } impl Default for TaskFloatDepthGauge { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - pub struct TaskFloatDepthGaugeObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskFloatDepthGaugeObserver<'_> { pub fn observe(&self, value: f64) { let attributes = vec![]; - self.observer.observe(value, &attributes); } } @@ -268,14 +197,6 @@ impl TaskFloatDepthObservableGauge { impl Default for TaskFloatDepthObservableGauge { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } - - - - - - - - /// Fractional tasks started. #[derive(Clone)] pub struct TaskFloatStartedCounter { instrument: ::opentelemetry::metrics::Counter } @@ -284,25 +205,20 @@ impl TaskFloatStartedCounter { Self { instrument: meter.inner().f64_counter("myapp.task.float.started") .with_description("Fractional tasks started.") .with_unit("{task}") - .build() } } pub fn add(&self, value: f64) { let attributes = vec![]; - self.instrument.add(value, &attributes); } } impl Default for TaskFloatStartedCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - pub struct TaskFloatStartedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskFloatStartedCounterObserver<'_> { pub fn observe(&self, value: f64) { let attributes = vec![]; - self.observer.observe(value, &attributes); } } @@ -321,14 +237,6 @@ impl TaskFloatStartedObservableCounter { impl Default for TaskFloatStartedObservableCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } - - - - - - - - /// Task payload size. #[derive(Clone)] pub struct TaskPayloadHistogram { instrument: ::opentelemetry::metrics::Histogram } @@ -337,45 +245,29 @@ impl TaskPayloadHistogram { Self { instrument: meter.inner().u64_histogram("myapp.task.payload") .with_description("Task payload size.") .with_unit("By") - .with_boundaries(vec![128_f64, 256_f64, 1024_f64]) - .build() } } pub fn record(&self, value: u64) { let attributes = vec![]; - self.instrument.record(value, &attributes); } } impl Default for TaskPayloadHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - - - - - - - #[derive(Clone, Debug)] pub enum TaskRetryDurationHistogramAttr { - /// Opt-in: the convention records it only when a user asks for it. Method(super::authattr::MethodAttr), - } impl TaskRetryDurationHistogramAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::Method(value) => value.key_value(), - } } } - /// Time a retried task took from start to finish. /// /// Recorded only for tasks that ran more than once. @@ -386,47 +278,30 @@ impl TaskRetryDurationHistogram { Self { instrument: meter.inner().f64_histogram("myapp.task.duration") .with_description("Time a task took from start to finish.") .with_unit("s") - .with_boundaries(vec![0_f64, 0.005_f64, 0.01_f64, 0.1_f64, 1_f64, 10_f64]) - .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) { let mut attributes = vec![r#myapp_task_id.key_value(), r#myapp_task_state.key_value()]; - attributes.extend(options.into_iter().map(TaskRetryDurationHistogramAttr::key_value)); - self.instrument.record(value, &attributes); } } impl Default for TaskRetryDurationHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - - - - - - - #[derive(Clone, Debug)] pub enum TaskStartedCounterAttr { - /// Recommended: When the scheduler assigned an id before the task started. TaskId(super::myappattr::TaskIdAttr), - } impl TaskStartedCounterAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::TaskId(value) => value.key_value(), - } } } - /// Number of tasks started. /// Opt-in: record only when the user requests it. #[derive(Clone)] @@ -436,29 +311,22 @@ impl TaskStartedCounter { Self { instrument: meter.inner().u64_counter("myapp.task.started") .with_description("Number of tasks started.") .with_unit("{task}") - .build() } } pub fn add(&self, value: u64, options: impl IntoIterator) { let mut attributes = vec![]; - attributes.extend(options.into_iter().map(TaskStartedCounterAttr::key_value)); - self.instrument.add(value, &attributes); } } impl Default for TaskStartedCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - pub struct TaskStartedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskStartedCounterObserver<'_> { pub fn observe(&self, value: u64, options: impl IntoIterator) { let mut attributes = vec![]; - attributes.extend(options.into_iter().map(TaskStartedCounterAttr::key_value)); - self.observer.observe(value, &attributes); } } diff --git a/templates/code/rust/tests/metrics/expected/workermetric.rs b/templates/code/rust/tests/metrics/expected/workermetric.rs index 1f8a287..8c2a870 100644 --- a/templates/code/rust/tests/metrics/expected/workermetric.rs +++ b/templates/code/rust/tests/metrics/expected/workermetric.rs @@ -1,34 +1,19 @@ #![allow(deprecated)] - - - - - - - - #[derive(Clone, Debug)] pub enum TaskDurationHistogramAttr { - /// Opt-in: the convention records it only when a user asks for it. Method(super::authattr::MethodAttr), - /// Conditionally required: If the task reached a final state. TaskState(super::myappattr::TaskStateAttr), - } impl TaskDurationHistogramAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::Method(value) => value.key_value(), - Self::TaskState(value) => value.key_value(), - } } } - /// Time a task took on the worker that ran it. /// /// Measured by the worker that ran the task. @@ -39,16 +24,12 @@ impl TaskDurationHistogram { Self { instrument: meter.inner().f64_histogram("myapp.task.duration") .with_description("Time a task took from start to finish.") .with_unit("s") - .with_boundaries(vec![0_f64, 0.005_f64, 0.01_f64, 0.1_f64, 1_f64, 10_f64]) - .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { let mut attributes = vec![r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskDurationHistogramAttr::key_value)); - self.instrument.record(value, &attributes); } } diff --git a/templates/code/rust/tests/naming/expected/capsattr.rs b/templates/code/rust/tests/naming/expected/capsattr.rs index 7c4dd81..41faecb 100644 --- a/templates/code/rust/tests/naming/expected/capsattr.rs +++ b/templates/code/rust/tests/naming/expected/capsattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Synthetic identifier. #[derive(Debug, Clone, PartialEq)] - pub struct Http2STATUSApiIDAttr(String); - #[allow(deprecated)] impl Http2STATUSApiIDAttr { pub const KEY: &'static str = "caps.http2_STATUS.api_ID"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -28,32 +21,22 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Synthetic mode. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum Mode2STATEAttr { - /// Synthetic state. HTTP2ReadySTATE, - } - #[allow(deprecated)] impl Mode2STATEAttr { pub const KEY: &'static str = "caps.mode2_STATE"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::HTTP2ReadySTATE => "ready".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } diff --git a/templates/code/rust/tests/naming/expected/capsmetric.rs b/templates/code/rust/tests/naming/expected/capsmetric.rs index 35b461e..59d3cbb 100644 --- a/templates/code/rust/tests/naming/expected/capsmetric.rs +++ b/templates/code/rust/tests/naming/expected/capsmetric.rs @@ -1,12 +1,4 @@ #![allow(deprecated)] - - - - - - - - /// Synthetic count. #[derive(Clone)] pub struct Http2STATUSCountCounter { instrument: ::opentelemetry::metrics::Counter } @@ -15,25 +7,20 @@ impl Http2STATUSCountCounter { Self { instrument: meter.inner().u64_counter("caps.http2_STATUS.count") .with_description("Synthetic count.") .with_unit("{item}") - .build() } } pub fn add(&self, value: u64, r#caps_http2_status_api_id: super::capsattr::Http2STATUSApiIDAttr, r#caps_mode2_state: super::capsattr::Mode2STATEAttr) { let attributes = vec![r#caps_http2_status_api_id.key_value(), r#caps_mode2_state.key_value()]; - self.instrument.add(value, &attributes); } } impl Default for Http2STATUSCountCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } - - pub struct Http2STATUSCountCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl Http2STATUSCountCounterObserver<'_> { pub fn observe(&self, value: u64, r#caps_http2_status_api_id: super::capsattr::Http2STATUSApiIDAttr, r#caps_mode2_state: super::capsattr::Mode2STATEAttr) { let attributes = vec![r#caps_http2_status_api_id.key_value(), r#caps_mode2_state.key_value()]; - self.observer.observe(value, &attributes); } } diff --git a/templates/code/rust/tests/naming/expected/mod.rs b/templates/code/rust/tests/naming/expected/mod.rs index 79da2c3..5062b2c 100644 --- a/templates/code/rust/tests/naming/expected/mod.rs +++ b/templates/code/rust/tests/naming/expected/mod.rs @@ -1,13 +1,6 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/naming/1.0.0"; - pub mod capsattr; - pub mod meter; - - - pub mod capsmetric; diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs index d6830da..14918fd 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// The exception message. #[derive(Debug, Clone, PartialEq)] - pub struct MessageAttr(String); - #[allow(deprecated)] impl MessageAttr { pub const KEY: &'static str = "exception.message"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -28,26 +21,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// The type of the exception. #[derive(Debug, Clone, PartialEq)] - pub struct TypeAttr(String); - #[allow(deprecated)] impl TypeAttr { pub const KEY: &'static str = "exception.type"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs index 3437543..c8c6014 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs @@ -1,15 +1,10 @@ #![allow(deprecated)] - - - #[derive(Clone, Debug)] pub enum Option { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - Message(super::exceptionattr::MessageAttr), - } /// A noteworthy exception occurred. pub fn r#emit_(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#exception_type: super::exceptionattr::TypeAttr, options: impl IntoIterator) { @@ -23,9 +18,7 @@ pub fn r#emit_(context: &::opentelemetry::Cont match option { Option::Severity(value) => severity = value, Option::Timestamp(value) => timestamp = Some(value), - Option::Message(value) => attributes.push(value.key_value()), - } } if !logger.inner().event_enabled(severity, "", Some("exception")) { return; } diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs index 03b0638..4a898c9 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Sequence number of the heartbeat. #[derive(Debug, Clone, PartialEq)] - pub struct SequenceAttr(i64); - #[allow(deprecated)] impl SequenceAttr { pub const KEY: &'static str = "heartbeat.sequence"; - pub fn new(value: i64) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -28,26 +21,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Name of the component that sent the heartbeat. #[derive(Debug, Clone, PartialEq)] - pub struct SourceAttr(String); - #[allow(deprecated)] impl SourceAttr { pub const KEY: &'static str = "heartbeat.source"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs index dbe6b1e..0a81838 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs @@ -1,50 +1,32 @@ #![allow(deprecated)] - - - - - #[derive(Clone, Debug)] pub enum StartAttr { - Source(super::heartbeatattr::SourceAttr), - } impl StartAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::Source(value) => value.key_value(), - } } } - - #[derive(Clone, Debug)] pub enum Attr { - Source(super::heartbeatattr::SourceAttr), - } impl From for StartAttr { fn from(value: Attr) -> Self { match value { - Attr::Source(value) => Self::Source(value), - } } } - - #[derive(Clone, Debug, Default)] pub struct Name(String); impl Name { pub fn new(value: impl Into) -> Self { Self(value.into()) } } - /// A periodic liveness signal. pub struct Span { span: ::opentelemetry::global::BoxedSpan } impl Span { @@ -57,11 +39,9 @@ impl Span { pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } - pub fn set_attributes(&mut self, attributes: impl IntoIterator) { for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, StartAttr::from(attribute).key_value()); } } - } impl Default for Span { fn default() -> Self { @@ -72,13 +52,9 @@ impl Default for Span { pub fn r#start_(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: Name, r#heartbeat_sequence: super::heartbeatattr::SequenceAttr, options: impl IntoIterator) -> Span { use ::opentelemetry::trace::Tracer; - let name = if name.0.is_empty() { "heartbeat".to_owned() } else { name.0 }; - let mut attributes = vec![r#heartbeat_sequence.key_value()]; - attributes.extend(options.into_iter().map(StartAttr::key_value)); - let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) diff --git a/templates/code/rust/tests/no_namespace/expected/hostattr.rs b/templates/code/rust/tests/no_namespace/expected/hostattr.rs index 4278d02..4674a46 100644 --- a/templates/code/rust/tests/no_namespace/expected/hostattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/hostattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Unique identifier of the host. #[derive(Debug, Clone, PartialEq)] - pub struct IdAttr(String); - #[allow(deprecated)] impl IdAttr { pub const KEY: &'static str = "host.id"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -28,26 +21,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Name of the host. #[derive(Debug, Clone, PartialEq)] - pub struct NameAttr(String); - #[allow(deprecated)] impl NameAttr { pub const KEY: &'static str = "host.name"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/no_namespace/expected/hostentity.rs b/templates/code/rust/tests/no_namespace/expected/hostentity.rs index 668852f..3bda27d 100644 --- a/templates/code/rust/tests/no_namespace/expected/hostentity.rs +++ b/templates/code/rust/tests/no_namespace/expected/hostentity.rs @@ -1,25 +1,18 @@ // Code generated by weaver. DO NOT EDIT. #![allow(deprecated)] - - #[derive(Clone, Debug)] pub enum EntityAttr { - Name(super::hostattr::NameAttr), - } impl EntityAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::Name(value) => value.key_value(), - } } } - /// A physical or virtual machine. /// Identifies the entity: `host.id`. /// Describes the entity: `host.name`. @@ -31,9 +24,7 @@ pub struct Entity { impl Entity { pub fn new(r#host_id: super::hostattr::IdAttr, options: impl IntoIterator) -> Self { let mut attributes = vec![ - r#host_id.key_value(), - ]; attributes.extend(options.into_iter().map(EntityAttr::key_value)); Self { attributes } diff --git a/templates/code/rust/tests/no_namespace/expected/mod.rs b/templates/code/rust/tests/no_namespace/expected/mod.rs index e481b66..5f85d2b 100644 --- a/templates/code/rust/tests/no_namespace/expected/mod.rs +++ b/templates/code/rust/tests/no_namespace/expected/mod.rs @@ -1,21 +1,11 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/no_namespace/1.0.0"; - pub mod exceptionattr; - pub mod heartbeatattr; - pub mod hostattr; - - pub mod tracer; pub mod logger; - pub mod exceptionevent; - pub mod heartbeatspan; - pub mod hostentity; diff --git a/templates/code/rust/tests/params/expected/billingattr.rs b/templates/code/rust/tests/params/expected/billingattr.rs index 8e1db27..a9de7f7 100644 --- a/templates/code/rust/tests/params/expected/billingattr.rs +++ b/templates/code/rust/tests/params/expected/billingattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Identifier of the invoice. #[derive(Debug, Clone, PartialEq)] - pub struct InvoiceIdAttr(String); - #[allow(deprecated)] impl InvoiceIdAttr { pub const KEY: &'static str = "acme.billing.invoice.id"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -28,26 +21,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// ISO 4217 currency code of the amount. #[derive(Debug, Clone, PartialEq)] - pub struct CurrencyAttr(String); - #[allow(deprecated)] impl CurrencyAttr { pub const KEY: &'static str = "billing.currency"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/params/expected/billingmetric.rs b/templates/code/rust/tests/params/expected/billingmetric.rs index 2b0f812..0c13de3 100644 --- a/templates/code/rust/tests/params/expected/billingmetric.rs +++ b/templates/code/rust/tests/params/expected/billingmetric.rs @@ -1,34 +1,19 @@ #![allow(deprecated)] - - - - - - - - #[derive(Clone, Debug)] pub enum InvoiceAmountHistogramAttr { - Currency(super::billingattr::CurrencyAttr), - RequestUrl(super::myappattr::RequestUrlAttr), - } impl InvoiceAmountHistogramAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::Currency(value) => value.key_value(), - Self::RequestUrl(value) => value.key_value(), - } } } - /// Amount of each issued invoice. #[derive(Clone)] pub struct InvoiceAmountHistogram { instrument: ::opentelemetry::metrics::Histogram } @@ -37,14 +22,11 @@ impl InvoiceAmountHistogram { Self { instrument: meter.inner().f64_histogram("acme.billing.invoice.amount") .with_description("Amount of each issued invoice.") .with_unit("{currency_unit}") - .build() } } pub fn record(&self, value: f64, r#billing_invoice_id: super::billingattr::InvoiceIdAttr, options: impl IntoIterator) { let mut attributes = vec![r#billing_invoice_id.key_value()]; - attributes.extend(options.into_iter().map(InvoiceAmountHistogramAttr::key_value)); - self.instrument.record(value, &attributes); } } diff --git a/templates/code/rust/tests/params/expected/mod.rs b/templates/code/rust/tests/params/expected/mod.rs index 5f81689..421154e 100644 --- a/templates/code/rust/tests/params/expected/mod.rs +++ b/templates/code/rust/tests/params/expected/mod.rs @@ -1,18 +1,10 @@ //! Typed telemetry for a synthetic registry. // Generated by OpenTelemetry Weaver. // Source: model/ - // Regenerate: mise run generate - pub const SCHEMA_URL: &str = "https://example.com/schemas/params/1.0.0"; - pub mod billingattr; - pub mod myappattr; - pub mod meter; - - - pub mod billingmetric; diff --git a/templates/code/rust/tests/params/expected/myappattr.rs b/templates/code/rust/tests/params/expected/myappattr.rs index 0560b99..565c45e 100644 --- a/templates/code/rust/tests/params/expected/myappattr.rs +++ b/templates/code/rust/tests/params/expected/myappattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// URL the request was sent to. #[derive(Debug, Clone, PartialEq)] - pub struct RequestUrlAttr(String); - #[allow(deprecated)] impl RequestUrlAttr { pub const KEY: &'static str = "myapp.request.url"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/spans/expected/mod.rs b/templates/code/rust/tests/spans/expected/mod.rs index 212d15d..6149b46 100644 --- a/templates/code/rust/tests/spans/expected/mod.rs +++ b/templates/code/rust/tests/spans/expected/mod.rs @@ -1,17 +1,8 @@ // Generated by OpenTelemetry Weaver. - - pub const SCHEMA_URL: &str = "https://example.com/schemas/spans/1.0.0"; - pub mod myappattr; - pub mod workerattr; - - pub mod tracer; - - pub mod myappspan; - pub mod workerspan; diff --git a/templates/code/rust/tests/spans/expected/myappattr.rs b/templates/code/rust/tests/spans/expected/myappattr.rs index a3c8d6e..d354091 100644 --- a/templates/code/rust/tests/spans/expected/myappattr.rs +++ b/templates/code/rust/tests/spans/expected/myappattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Name of the queue the task came from. #[derive(Debug, Clone, PartialEq)] - pub struct QueueNameAttr(String); - #[allow(deprecated)] impl QueueNameAttr { pub const KEY: &'static str = "myapp.queue.name"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -28,26 +21,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Number of the attempt, starting at one. #[derive(Debug, Clone, PartialEq)] - pub struct TaskAttemptAttr(i64); - #[allow(deprecated)] impl TaskAttemptAttr { pub const KEY: &'static str = "myapp.task.attempt"; - pub fn new(value: i64) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -57,26 +43,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] - pub struct TaskIdAttr(String); - #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -86,37 +65,25 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] - pub enum TaskStateAttr { - /// The task is waiting to run. Queued, - /// The task finished. Done, - } - #[allow(deprecated)] impl TaskStateAttr { pub const KEY: &'static str = "myapp.task.state"; - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Queued => "queued".into(), - Self::Done => "done".into(), - }; ::opentelemetry::KeyValue::new(Self::KEY, value) - } } diff --git a/templates/code/rust/tests/spans/expected/myappspan.rs b/templates/code/rust/tests/spans/expected/myappspan.rs index 258bfd7..c2adf95 100644 --- a/templates/code/rust/tests/spans/expected/myappspan.rs +++ b/templates/code/rust/tests/spans/expected/myappspan.rs @@ -1,11 +1,4 @@ #![allow(deprecated)] - - - - - - - /// Synthetic escaped name. pub struct NameApostropheSpan { span: ::opentelemetry::global::BoxedSpan } impl NameApostropheSpan { @@ -18,7 +11,6 @@ impl NameApostropheSpan { pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } - } impl Default for NameApostropheSpan { fn default() -> Self { @@ -29,34 +21,16 @@ impl Default for NameApostropheSpan { pub fn r#start_name_apostrophe(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameApostropheSpan { use ::opentelemetry::trace::Tracer; - let mut name = String::new(); - - - name.push('\u{0027}'); - - - - name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); - - - let attributes = vec![r#worker_host_port.key_value()]; - let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) .start_with_context(tracer.inner(), context); NameApostropheSpan { span } } - - - - - - /// Synthetic escaped name. pub struct NameBackslashSpan { span: ::opentelemetry::global::BoxedSpan } impl NameBackslashSpan { @@ -69,7 +43,6 @@ impl NameBackslashSpan { pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } - } impl Default for NameBackslashSpan { fn default() -> Self { @@ -80,34 +53,16 @@ impl Default for NameBackslashSpan { pub fn r#start_name_backslash(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameBackslashSpan { use ::opentelemetry::trace::Tracer; - let mut name = String::new(); - - - name.push('\\'); - - - - name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); - - - let attributes = vec![r#worker_host_port.key_value()]; - let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) .start_with_context(tracer.inner(), context); NameBackslashSpan { span } } - - - - - - /// Synthetic escaped name. pub struct NameControlSpan { span: ::opentelemetry::global::BoxedSpan } impl NameControlSpan { @@ -120,7 +75,6 @@ impl NameControlSpan { pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } - } impl Default for NameControlSpan { fn default() -> Self { @@ -131,34 +85,16 @@ impl Default for NameControlSpan { pub fn r#start_name_control(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameControlSpan { use ::opentelemetry::trace::Tracer; - let mut name = String::new(); - - - name.push('\u{0008}'); - - - - name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); - - - let attributes = vec![r#worker_host_port.key_value()]; - let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) .start_with_context(tracer.inner(), context); NameControlSpan { span } } - - - - - - /// Synthetic escaped name. pub struct NameUnicodeSpan { span: ::opentelemetry::global::BoxedSpan } impl NameUnicodeSpan { @@ -171,7 +107,6 @@ impl NameUnicodeSpan { pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } - } impl Default for NameUnicodeSpan { fn default() -> Self { @@ -182,40 +117,21 @@ impl Default for NameUnicodeSpan { pub fn r#start_name_unicode(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameUnicodeSpan { use ::opentelemetry::trace::Tracer; - let mut name = String::new(); - - - name.push('é'); - - - - name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); - - - let attributes = vec![r#worker_host_port.key_value()]; - let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) .start_with_context(tracer.inner(), context); NameUnicodeSpan { span } } - - - - - - #[derive(Clone, Debug, Default)] pub struct QueueDrainName(String); impl QueueDrainName { pub fn new(value: impl Into) -> Self { Self(value.into()) } } - /// Removing every task from a queue. /// Opt-in: record only when the user requests it. #[deprecated(note = "Drain queues by dispatching their tasks instead.")] @@ -230,7 +146,6 @@ impl QueueDrainSpan { pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } - } impl Default for QueueDrainSpan { fn default() -> Self { @@ -241,70 +156,45 @@ impl Default for QueueDrainSpan { #[deprecated(note = "Drain queues by dispatching their tasks instead.")] pub fn r#start_queue_drain(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: QueueDrainName) -> QueueDrainSpan { use ::opentelemetry::trace::Tracer; - let name = if name.0.is_empty() { "myapp.queue.drain".to_owned() } else { name.0 }; - let attributes = vec![]; - let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Consumer) .with_attributes(attributes) .start_with_context(tracer.inner(), context); QueueDrainSpan { span } } - - - - #[derive(Clone, Debug)] pub enum TaskDispatchStartAttr { - /// Recommended: When the task came from a named queue. QueueName(super::myappattr::QueueNameAttr), - /// Opt-in: the convention records it only when a user asks for it. TaskAttempt(super::myappattr::TaskAttemptAttr), - TaskId(super::myappattr::TaskIdAttr), - } impl TaskDispatchStartAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::QueueName(value) => value.key_value(), - Self::TaskAttempt(value) => value.key_value(), - Self::TaskId(value) => value.key_value(), - } } } - - #[derive(Clone, Debug)] pub enum TaskDispatchAttr { - QueueName(super::myappattr::QueueNameAttr), - TaskAttempt(super::myappattr::TaskAttemptAttr), - } impl From for TaskDispatchStartAttr { fn from(value: TaskDispatchAttr) -> Self { match value { - TaskDispatchAttr::QueueName(value) => Self::QueueName(value), - TaskDispatchAttr::TaskAttempt(value) => Self::TaskAttempt(value), - } } } - - /// The scheduler handing a task to a worker. /// /// Ends when the worker accepts the task. @@ -319,11 +209,9 @@ impl TaskDispatchSpan { pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } - pub fn set_attributes(&mut self, attributes: impl IntoIterator) { for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, TaskDispatchStartAttr::from(attribute).key_value()); } } - } impl Default for TaskDispatchSpan { fn default() -> Self { @@ -334,85 +222,47 @@ impl Default for TaskDispatchSpan { pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_name: super::workerattr::HostNameAttr, r#worker_host_port: super::workerattr::HostPortAttr, options: impl IntoIterator) -> TaskDispatchSpan { use ::opentelemetry::trace::Tracer; - let mut name = String::new(); - - - name.push_str("dispatch "); - - - - name.push_str(&r#worker_host_name.clone().key_value().value.to_string()); - - - - name.push(':'); - - - - name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); - - - let mut attributes = vec![r#worker_host_name.key_value(), r#worker_host_port.key_value()]; - attributes.extend(options.into_iter().map(TaskDispatchStartAttr::key_value)); - let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Client) .with_attributes(attributes) .start_with_context(tracer.inner(), context); TaskDispatchSpan { span } } - - - - #[derive(Clone, Debug)] pub enum TaskRunStartAttr { - TaskId(super::myappattr::TaskIdAttr), - } impl TaskRunStartAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::TaskId(value) => value.key_value(), - } } } - - #[derive(Clone, Debug)] pub enum TaskRunAttr { - TaskId(super::myappattr::TaskIdAttr), - } impl From for TaskRunStartAttr { fn from(value: TaskRunAttr) -> Self { match value { - TaskRunAttr::TaskId(value) => Self::TaskId(value), - } } } - - #[derive(Clone, Debug, Default)] pub struct TaskRunName(String); impl TaskRunName { pub fn new(value: impl Into) -> Self { Self(value.into()) } } - /// One run of a task. pub struct TaskRunSpan { span: ::opentelemetry::global::BoxedSpan } impl TaskRunSpan { @@ -425,11 +275,9 @@ impl TaskRunSpan { pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } - pub fn set_attributes(&mut self, attributes: impl IntoIterator) { for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, TaskRunStartAttr::from(attribute).key_value()); } } - } impl Default for TaskRunSpan { fn default() -> Self { @@ -440,13 +288,9 @@ impl Default for TaskRunSpan { pub fn r#start_task_run(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: TaskRunName, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) -> TaskRunSpan { use ::opentelemetry::trace::Tracer; - let name = if name.0.is_empty() { "myapp.task.run".to_owned() } else { name.0 }; - let mut attributes = vec![r#myapp_task_state.key_value()]; - attributes.extend(options.into_iter().map(TaskRunStartAttr::key_value)); - let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) diff --git a/templates/code/rust/tests/spans/expected/workerattr.rs b/templates/code/rust/tests/spans/expected/workerattr.rs index 242e2b0..face693 100644 --- a/templates/code/rust/tests/spans/expected/workerattr.rs +++ b/templates/code/rust/tests/spans/expected/workerattr.rs @@ -1,24 +1,17 @@ // Generated by OpenTelemetry Weaver. - /// Host name of the worker. #[derive(Debug, Clone, PartialEq)] - pub struct HostNameAttr(String); - #[allow(deprecated)] impl HostNameAttr { pub const KEY: &'static str = "worker.host.name"; - pub fn new(value: impl Into) -> Self { Self(value.into()) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } @@ -28,26 +21,19 @@ impl From for ::opentelemetry::KeyValue { value.key_value() } } - /// Port the worker listens on. #[derive(Debug, Clone, PartialEq)] - pub struct HostPortAttr(i64); - #[allow(deprecated)] impl HostPortAttr { pub const KEY: &'static str = "worker.host.port"; - pub fn new(value: i64) -> Self { Self(value) } - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } diff --git a/templates/code/rust/tests/spans/expected/workerspan.rs b/templates/code/rust/tests/spans/expected/workerspan.rs index b27676f..e1a284f 100644 --- a/templates/code/rust/tests/spans/expected/workerspan.rs +++ b/templates/code/rust/tests/spans/expected/workerspan.rs @@ -1,49 +1,30 @@ #![allow(deprecated)] - - - - - #[derive(Clone, Debug)] pub enum TaskDispatchStartAttr { - /// Recommended: When the task came from a named queue. QueueName(super::myappattr::QueueNameAttr), - TaskId(super::myappattr::TaskIdAttr), - } impl TaskDispatchStartAttr { fn key_value(self) -> ::opentelemetry::KeyValue { match self { - Self::QueueName(value) => value.key_value(), - Self::TaskId(value) => value.key_value(), - } } } - - #[derive(Clone, Debug)] pub enum TaskDispatchAttr { - QueueName(super::myappattr::QueueNameAttr), - } impl From for TaskDispatchStartAttr { fn from(value: TaskDispatchAttr) -> Self { match value { - TaskDispatchAttr::QueueName(value) => Self::QueueName(value), - } } } - - /// The scheduler handing a task to a worker. /// /// Ends when the worker accepts the task. @@ -58,11 +39,9 @@ impl TaskDispatchSpan { pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } - pub fn set_attributes(&mut self, attributes: impl IntoIterator) { for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, TaskDispatchStartAttr::from(attribute).key_value()); } } - } impl Default for TaskDispatchSpan { fn default() -> Self { @@ -73,34 +52,13 @@ impl Default for TaskDispatchSpan { pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#myapp_task_attempt: super::myappattr::TaskAttemptAttr, r#worker_host_name: super::workerattr::HostNameAttr, r#worker_host_port: super::workerattr::HostPortAttr, options: impl IntoIterator) -> TaskDispatchSpan { use ::opentelemetry::trace::Tracer; - let mut name = String::new(); - - - name.push_str("dispatch "); - - - - name.push_str(&r#worker_host_name.clone().key_value().value.to_string()); - - - - name.push(':'); - - - - name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); - - - let mut attributes = vec![r#myapp_task_attempt.key_value(), r#worker_host_name.key_value(), r#worker_host_port.key_value()]; - attributes.extend(options.into_iter().map(TaskDispatchStartAttr::key_value)); - let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Client) .with_attributes(attributes) diff --git a/templates/code/rust/weaver.yaml b/templates/code/rust/weaver.yaml index d45e154..e50ea24 100644 --- a/templates/code/rust/weaver.yaml +++ b/templates/code/rust/weaver.yaml @@ -1,3 +1,7 @@ +whitespace_control: + trim_blocks: true + lstrip_blocks: true + params: module_description: "" histogram_boundaries_by_unit: From 00e0e501ddfb1c9077ae9e862a6e12151266f017 Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Sun, 4 Oct 2026 21:35:10 -0400 Subject: [PATCH 04/14] fix: keep generated Rust variant docs readable Signed-off-by: Yordis Prieto --- templates/code/rust/attributes.rs.j2 | 5 ++++- templates/code/rust/entities.rs.j2 | 4 +++- templates/code/rust/events.rs.j2 | 4 +++- templates/code/rust/metrics.rs.j2 | 4 +++- templates/code/rust/spans.rs.j2 | 4 +++- .../code/rust/tests/entities/expected/myappentity.rs | 7 ++----- templates/code/rust/tests/events/expected/myappevent.rs | 8 ++------ templates/code/rust/tests/events/expected/workerevent.rs | 6 +----- templates/code/rust/tests/imported/expected/edgeevent.rs | 1 - templates/code/rust/tests/imported/expected/edgemetric.rs | 1 - templates/code/rust/tests/imported/expected/edgespan.rs | 3 +-- .../code/rust/tests/imported/expected/myappmetric.rs | 1 - .../code/rust/tests/imported_typed/expected/myappevent.rs | 1 - .../rust/tests/imported_typed/expected/myappmetric.rs | 1 - .../code/rust/tests/imported_typed/expected/myappspan.rs | 1 - templates/code/rust/tests/metrics/expected/myappmetric.rs | 8 ++++---- .../code/rust/tests/metrics/expected/workermetric.rs | 4 ++-- .../rust/tests/no_namespace/expected/exceptionevent.rs | 1 - .../rust/tests/no_namespace/expected/heartbeatspan.rs | 1 - .../code/rust/tests/no_namespace/expected/hostentity.rs | 1 - .../code/rust/tests/params/expected/billingmetric.rs | 2 -- templates/code/rust/tests/spans/expected/myappspan.rs | 6 ++---- templates/code/rust/tests/spans/expected/workerspan.rs | 3 +-- 23 files changed, 31 insertions(+), 46 deletions(-) diff --git a/templates/code/rust/attributes.rs.j2 b/templates/code/rust/attributes.rs.j2 index 5f07737..d6c0ac3 100644 --- a/templates/code/rust/attributes.rs.j2 +++ b/templates/code/rust/attributes.rs.j2 @@ -6,7 +6,10 @@ {% if attr.type is mapping %} pub enum {{ attr.name }} { {% for member in attr.type.members %} - {{ [member.brief, member.note] | select | join("\n\n") | comment | indent(4) }} +{% set member_doc = [member.brief, member.note] | select | join("\n\n") %} +{% if member_doc %} + {{ member_doc | comment | indent(4) }} +{% endif %} {{ ("#[deprecated(note = " ~ member.deprecated_literal ~ ")]\n ") if member.deprecated_literal else "" }}{{ member.name }}, {% endfor %} } diff --git a/templates/code/rust/entities.rs.j2 b/templates/code/rust/entities.rs.j2 index 2cde8f8..c5ef7b6 100644 --- a/templates/code/rust/entities.rs.j2 +++ b/templates/code/rust/entities.rs.j2 @@ -9,7 +9,9 @@ #[derive(Clone, Debug)] pub enum {{ name }}Attr { {% for opt in def.optional %} -{{ opt.requirement_doc | comment if opt.requirement_doc else '' }} +{% if opt.requirement_doc %} + {{ opt.requirement_doc | comment | indent(4) }} +{% endif %} {{ s.exported(opt.attr_short_name) }}({{ s.attr_type(opt) }}), {% endfor %} } diff --git a/templates/code/rust/events.rs.j2 b/templates/code/rust/events.rs.j2 index 20a0172..81976f5 100644 --- a/templates/code/rust/events.rs.j2 +++ b/templates/code/rust/events.rs.j2 @@ -8,7 +8,9 @@ pub enum {{ name }}Option { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), {% for opt in def.optional %} -{{ opt.requirement_doc | comment if opt.requirement_doc else '' }} +{% if opt.requirement_doc %} + {{ opt.requirement_doc | comment | indent(4) }} +{% endif %} {{ h.exported(opt.attr_short_name) }}({{ h.attr_type(opt) }}), {% endfor %} } diff --git a/templates/code/rust/metrics.rs.j2 b/templates/code/rust/metrics.rs.j2 index 806b348..1bc7977 100644 --- a/templates/code/rust/metrics.rs.j2 +++ b/templates/code/rust/metrics.rs.j2 @@ -11,7 +11,9 @@ #[derive(Clone, Debug)] pub enum {{ name }}Attr { {% for opt in def.optional %} -{{ opt.requirement_doc | comment if opt.requirement_doc else '' }} +{% if opt.requirement_doc %} + {{ opt.requirement_doc | comment | indent(4) }} +{% endif %} {{ h.exported(opt.attr_short_name) }}({{ h.attr_type(opt) }}), {% endfor %} } diff --git a/templates/code/rust/spans.rs.j2 b/templates/code/rust/spans.rs.j2 index 60167d3..4d0cca4 100644 --- a/templates/code/rust/spans.rs.j2 +++ b/templates/code/rust/spans.rs.j2 @@ -8,7 +8,9 @@ #[derive(Clone, Debug)] pub enum {{ name }}StartAttr { {% for opt in def.optional %} -{{ opt.requirement_doc | comment if opt.requirement_doc else '' }} +{% if opt.requirement_doc %} + {{ opt.requirement_doc | comment | indent(4) }} +{% endif %} {{ h.exported(opt.attr_short_name) }}({{ h.attr_type(opt) }}), {% endfor %} } diff --git a/templates/code/rust/tests/entities/expected/myappentity.rs b/templates/code/rust/tests/entities/expected/myappentity.rs index 6ea9c0b..57f28e2 100644 --- a/templates/code/rust/tests/entities/expected/myappentity.rs +++ b/templates/code/rust/tests/entities/expected/myappentity.rs @@ -2,9 +2,8 @@ #![allow(deprecated)] #[derive(Clone, Debug)] pub enum HostEntityAttr { -/// Opt-in: the convention records it only when a user asks for it. + /// Opt-in: the convention records it only when a user asks for it. HostCpuCount(super::myappattr::HostCpuCountAttr), - HostType(super::myappattr::HostTypeAttr), } @@ -47,9 +46,8 @@ impl HostEntity { } #[derive(Clone, Debug)] pub enum HostWorkerEntityAttr { -/// Opt-in: the convention records it only when a user asks for it. + /// Opt-in: the convention records it only when a user asks for it. HostCpuCount(super::myappattr::HostCpuCountAttr), - HostType(super::myappattr::HostTypeAttr), } @@ -94,7 +92,6 @@ impl HostWorkerEntity { } #[derive(Clone, Debug)] pub enum QueueEntityAttr { - QueueSize(super::myappattr::QueueSizeAttr), } diff --git a/templates/code/rust/tests/events/expected/myappevent.rs b/templates/code/rust/tests/events/expected/myappevent.rs index f5cc294..fd83424 100644 --- a/templates/code/rust/tests/events/expected/myappevent.rs +++ b/templates/code/rust/tests/events/expected/myappevent.rs @@ -3,17 +3,13 @@ pub enum TaskFinishedOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - BoolValues(super::myappattr::BoolValuesAttr), - DoubleValues(super::myappattr::DoubleValuesAttr), - IntValues(super::myappattr::IntValuesAttr), - StringValues(super::myappattr::StringValuesAttr), -/// Recommended: When the task ran more than once. + /// Recommended: When the task ran more than once. TaskAttempt(super::myappattr::TaskAttemptAttr), -/// Opt-in: the convention records it only when a user asks for it. + /// Opt-in: the convention records it only when a user asks for it. HostName(super::workerattr::HostNameAttr), } /// A task reached a final state. diff --git a/templates/code/rust/tests/events/expected/workerevent.rs b/templates/code/rust/tests/events/expected/workerevent.rs index 2bc40db..32e5a5a 100644 --- a/templates/code/rust/tests/events/expected/workerevent.rs +++ b/templates/code/rust/tests/events/expected/workerevent.rs @@ -34,15 +34,11 @@ pub fn r#emit_host_started(context: &::opentel pub enum TaskFinishedOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - BoolValues(super::myappattr::BoolValuesAttr), - DoubleValues(super::myappattr::DoubleValuesAttr), - IntValues(super::myappattr::IntValuesAttr), - StringValues(super::myappattr::StringValuesAttr), -/// Recommended: When the task ran more than once. + /// Recommended: When the task ran more than once. TaskAttempt(super::myappattr::TaskAttemptAttr), } /// A task reached a final state on a worker. diff --git a/templates/code/rust/tests/imported/expected/edgeevent.rs b/templates/code/rust/tests/imported/expected/edgeevent.rs index 404d356..bc9550c 100644 --- a/templates/code/rust/tests/imported/expected/edgeevent.rs +++ b/templates/code/rust/tests/imported/expected/edgeevent.rs @@ -3,7 +3,6 @@ pub enum UpstreamFailedOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - ServerAddress(String), } /// A request to an upstream server failed. diff --git a/templates/code/rust/tests/imported/expected/edgemetric.rs b/templates/code/rust/tests/imported/expected/edgemetric.rs index e83ee6b..8388614 100644 --- a/templates/code/rust/tests/imported/expected/edgemetric.rs +++ b/templates/code/rust/tests/imported/expected/edgemetric.rs @@ -1,7 +1,6 @@ #![allow(deprecated)] #[derive(Clone, Debug)] pub enum UpstreamDurationHistogramAttr { - ServerPort(i64), } impl UpstreamDurationHistogramAttr { diff --git a/templates/code/rust/tests/imported/expected/edgespan.rs b/templates/code/rust/tests/imported/expected/edgespan.rs index 68d2ec7..70a3cbb 100644 --- a/templates/code/rust/tests/imported/expected/edgespan.rs +++ b/templates/code/rust/tests/imported/expected/edgespan.rs @@ -1,9 +1,8 @@ #![allow(deprecated)] #[derive(Clone, Debug)] pub enum UpstreamRequestStartAttr { -/// Conditionally required: If the request failed. + /// Conditionally required: If the request failed. ErrorType(String), - HttpRequestMethodList(Vec), } impl UpstreamRequestStartAttr { diff --git a/templates/code/rust/tests/imported/expected/myappmetric.rs b/templates/code/rust/tests/imported/expected/myappmetric.rs index 9c71ac1..46fec37 100644 --- a/templates/code/rust/tests/imported/expected/myappmetric.rs +++ b/templates/code/rust/tests/imported/expected/myappmetric.rs @@ -1,7 +1,6 @@ #![allow(deprecated)] #[derive(Clone, Debug)] pub enum TaskFailedCounterAttr { - HttpRequestMethodList(Vec), } impl TaskFailedCounterAttr { diff --git a/templates/code/rust/tests/imported_typed/expected/myappevent.rs b/templates/code/rust/tests/imported_typed/expected/myappevent.rs index 5dc334a..ba2f3b9 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappevent.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappevent.rs @@ -3,7 +3,6 @@ pub enum TaskErroredOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - ServerPort(i64), } /// A task failed with an error. diff --git a/templates/code/rust/tests/imported_typed/expected/myappmetric.rs b/templates/code/rust/tests/imported_typed/expected/myappmetric.rs index c797eca..0baba9e 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappmetric.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappmetric.rs @@ -1,7 +1,6 @@ #![allow(deprecated)] #[derive(Clone, Debug)] pub enum TaskFailedCounterAttr { - ServerPort(i64), } impl TaskFailedCounterAttr { diff --git a/templates/code/rust/tests/imported_typed/expected/myappspan.rs b/templates/code/rust/tests/imported_typed/expected/myappspan.rs index 35275a8..a7ddbd5 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappspan.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappspan.rs @@ -1,7 +1,6 @@ #![allow(deprecated)] #[derive(Clone, Debug)] pub enum TaskDispatchStartAttr { - ServerPort(i64), } impl TaskDispatchStartAttr { diff --git a/templates/code/rust/tests/metrics/expected/myappmetric.rs b/templates/code/rust/tests/metrics/expected/myappmetric.rs index bc10bbd..386e8f5 100644 --- a/templates/code/rust/tests/metrics/expected/myappmetric.rs +++ b/templates/code/rust/tests/metrics/expected/myappmetric.rs @@ -82,9 +82,9 @@ impl Default for TaskActiveObservableUpDownCounter { } #[derive(Clone, Debug)] pub enum TaskDurationHistogramAttr { -/// Opt-in: the convention records it only when a user asks for it. + /// Opt-in: the convention records it only when a user asks for it. Method(super::authattr::MethodAttr), -/// Conditionally required: If the task reached a final state. + /// Conditionally required: If the task reached a final state. TaskState(super::myappattr::TaskStateAttr), } impl TaskDurationHistogramAttr { @@ -258,7 +258,7 @@ impl Default for TaskPayloadHistogram { } #[derive(Clone, Debug)] pub enum TaskRetryDurationHistogramAttr { -/// Opt-in: the convention records it only when a user asks for it. + /// Opt-in: the convention records it only when a user asks for it. Method(super::authattr::MethodAttr), } impl TaskRetryDurationHistogramAttr { @@ -292,7 +292,7 @@ impl Default for TaskRetryDurationHistogram { } #[derive(Clone, Debug)] pub enum TaskStartedCounterAttr { -/// Recommended: When the scheduler assigned an id before the task started. + /// Recommended: When the scheduler assigned an id before the task started. TaskId(super::myappattr::TaskIdAttr), } impl TaskStartedCounterAttr { diff --git a/templates/code/rust/tests/metrics/expected/workermetric.rs b/templates/code/rust/tests/metrics/expected/workermetric.rs index 8c2a870..3d2472b 100644 --- a/templates/code/rust/tests/metrics/expected/workermetric.rs +++ b/templates/code/rust/tests/metrics/expected/workermetric.rs @@ -1,9 +1,9 @@ #![allow(deprecated)] #[derive(Clone, Debug)] pub enum TaskDurationHistogramAttr { -/// Opt-in: the convention records it only when a user asks for it. + /// Opt-in: the convention records it only when a user asks for it. Method(super::authattr::MethodAttr), -/// Conditionally required: If the task reached a final state. + /// Conditionally required: If the task reached a final state. TaskState(super::myappattr::TaskStateAttr), } impl TaskDurationHistogramAttr { diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs index c8c6014..80e8544 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs @@ -3,7 +3,6 @@ pub enum Option { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - Message(super::exceptionattr::MessageAttr), } /// A noteworthy exception occurred. diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs index 0a81838..ee1d8e0 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs @@ -1,7 +1,6 @@ #![allow(deprecated)] #[derive(Clone, Debug)] pub enum StartAttr { - Source(super::heartbeatattr::SourceAttr), } impl StartAttr { diff --git a/templates/code/rust/tests/no_namespace/expected/hostentity.rs b/templates/code/rust/tests/no_namespace/expected/hostentity.rs index 3bda27d..42ded38 100644 --- a/templates/code/rust/tests/no_namespace/expected/hostentity.rs +++ b/templates/code/rust/tests/no_namespace/expected/hostentity.rs @@ -2,7 +2,6 @@ #![allow(deprecated)] #[derive(Clone, Debug)] pub enum EntityAttr { - Name(super::hostattr::NameAttr), } diff --git a/templates/code/rust/tests/params/expected/billingmetric.rs b/templates/code/rust/tests/params/expected/billingmetric.rs index 0c13de3..3c436b9 100644 --- a/templates/code/rust/tests/params/expected/billingmetric.rs +++ b/templates/code/rust/tests/params/expected/billingmetric.rs @@ -1,9 +1,7 @@ #![allow(deprecated)] #[derive(Clone, Debug)] pub enum InvoiceAmountHistogramAttr { - Currency(super::billingattr::CurrencyAttr), - RequestUrl(super::myappattr::RequestUrlAttr), } impl InvoiceAmountHistogramAttr { diff --git a/templates/code/rust/tests/spans/expected/myappspan.rs b/templates/code/rust/tests/spans/expected/myappspan.rs index c2adf95..12f2ce0 100644 --- a/templates/code/rust/tests/spans/expected/myappspan.rs +++ b/templates/code/rust/tests/spans/expected/myappspan.rs @@ -166,11 +166,10 @@ pub fn r#start_queue_drain(context: &::opentelemetry::Context, tracer: &super::t } #[derive(Clone, Debug)] pub enum TaskDispatchStartAttr { -/// Recommended: When the task came from a named queue. + /// Recommended: When the task came from a named queue. QueueName(super::myappattr::QueueNameAttr), -/// Opt-in: the convention records it only when a user asks for it. + /// Opt-in: the convention records it only when a user asks for it. TaskAttempt(super::myappattr::TaskAttemptAttr), - TaskId(super::myappattr::TaskIdAttr), } impl TaskDispatchStartAttr { @@ -237,7 +236,6 @@ pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super: } #[derive(Clone, Debug)] pub enum TaskRunStartAttr { - TaskId(super::myappattr::TaskIdAttr), } impl TaskRunStartAttr { diff --git a/templates/code/rust/tests/spans/expected/workerspan.rs b/templates/code/rust/tests/spans/expected/workerspan.rs index e1a284f..7a7259e 100644 --- a/templates/code/rust/tests/spans/expected/workerspan.rs +++ b/templates/code/rust/tests/spans/expected/workerspan.rs @@ -1,9 +1,8 @@ #![allow(deprecated)] #[derive(Clone, Debug)] pub enum TaskDispatchStartAttr { -/// Recommended: When the task came from a named queue. + /// Recommended: When the task came from a named queue. QueueName(super::myappattr::QueueNameAttr), - TaskId(super::myappattr::TaskIdAttr), } impl TaskDispatchStartAttr { From 6b76f708effdae2866b08da2b8d9a99dcc7ccc6d Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Sun, 4 Oct 2026 21:57:02 -0400 Subject: [PATCH 05/14] refactor: keep attribute construction idiomatic Signed-off-by: Yordis Prieto --- templates/code/rust/README.md | 7 +- templates/code/rust/attributes.rs.j2 | 22 +++- .../wrong_scalar.expected-error.txt | 2 +- .../attributes/compile-fail/wrong_scalar.rs | 2 +- .../tests/attributes/expected/authattr.rs | 16 ++- .../tests/attributes/expected/myappattr.rs | 118 +++++++++++++----- templates/code/rust/tests/attributes/test.rs | 47 +++++-- .../compile-fail/excluded_attribute.rs | 2 +- .../codegen_exclusion/expected/demoattr.rs | 16 ++- .../code/rust/tests/codegen_exclusion/test.rs | 2 +- .../entities/compile-fail/wrong_identity.rs | 2 +- .../rust/tests/entities/expected/myappattr.rs | 68 +++++++--- templates/code/rust/tests/entities/test.rs | 6 +- .../rust/tests/events/expected/myappattr.rs | 50 +++++--- .../rust/tests/events/expected/workerattr.rs | 16 ++- templates/code/rust/tests/events/test.rs | 14 +-- .../rust/tests/filtering/expected/authattr.rs | 16 ++- .../rust/tests/filtering/expected/taskattr.rs | 72 ++++++++--- templates/code/rust/tests/filtering/test.rs | 2 +- .../expected/myappattr.rs | 16 ++- .../expected/myappattr.rs | 16 ++- .../rust/tests/imported/expected/myappattr.rs | 16 ++- .../imported_typed/expected/myappattr.rs | 16 ++- .../compile-fail/unrelated_optional.rs | 2 +- .../rust/tests/metrics/expected/authattr.rs | 10 +- .../rust/tests/metrics/expected/myappattr.rs | 16 ++- templates/code/rust/tests/metrics/test.rs | 14 +-- .../rust/tests/naming/expected/capsattr.rs | 16 ++- templates/code/rust/tests/naming/test.rs | 2 +- .../no_namespace/expected/exceptionattr.rs | 32 ++++- .../no_namespace/expected/heartbeatattr.rs | 26 +++- .../tests/no_namespace/expected/hostattr.rs | 32 ++++- .../rust/tests/params/expected/billingattr.rs | 32 ++++- .../rust/tests/params/expected/myappattr.rs | 16 ++- .../compile-fail/sampling_attribute_late.rs | 2 +- .../rust/tests/spans/expected/myappattr.rs | 42 +++++-- .../rust/tests/spans/expected/workerattr.rs | 26 +++- templates/code/rust/tests/spans/test.rs | 22 ++-- 38 files changed, 629 insertions(+), 205 deletions(-) diff --git a/templates/code/rust/README.md b/templates/code/rust/README.md index a8eb8ae..8c3db2c 100644 --- a/templates/code/rust/README.md +++ b/templates/code/rust/README.md @@ -61,8 +61,11 @@ Attribute keys, metric names, and event names retain their full registry names. ### Typed attributes An attribute such as `myapp.task.id` becomes -`myappattr::TaskIdAttr::new("task-1")`. Its `key_value()` method consumes the -value and returns an OpenTelemetry `KeyValue`. Enums expose named variants, +`myappattr::TaskIdAttr::from("task-1")`. Its `key_value()` method consumes the +value and returns an OpenTelemetry `KeyValue`. String attributes implement +`From` and `From<&str>`; scalar and array attributes implement `From` +for their exact backing types. Use `Attr::from(value)` or `value.into()` when +the attribute type is known. Enums expose named variants, such as `myappattr::TaskStateAttr::Running`, rather than arbitrary constructors. Supported backing types are `String`, `i64`, `f64`, `bool`, and their `Vec` diff --git a/templates/code/rust/attributes.rs.j2 b/templates/code/rust/attributes.rs.j2 index d6c0ac3..0343d1d 100644 --- a/templates/code/rust/attributes.rs.j2 +++ b/templates/code/rust/attributes.rs.j2 @@ -20,11 +20,6 @@ pub struct {{ attr.name }}({{ attr.value_type | map_text("rust_type") }}); #[allow(deprecated)] impl {{ attr.name }} { pub const KEY: &'static str = {{ attr.key_literal }}; -{% if attr.type is not mapping %} - pub fn new(value: {% if attr.value_type == "string" %}impl Into{% else %}{{ attr.value_type | map_text("rust_type") }}{% endif %}) -> Self { - Self(value{% if attr.value_type == "string" %}.into(){% endif %}) - } -{% endif %} pub fn key_value(self) -> ::opentelemetry::KeyValue { {% if attr.type is mapping %} @@ -41,6 +36,23 @@ impl {{ attr.name }} { {% endif %} } } +{% if attr.type is not mapping %} + +#[allow(deprecated)] +impl From<{{ attr.value_type | map_text("rust_type") }}> for {{ attr.name }} { + fn from(value: {{ attr.value_type | map_text("rust_type") }}) -> Self { + Self(value) + } +} +{% if attr.value_type == "string" %} +#[allow(deprecated)] +impl From<&str> for {{ attr.name }} { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} +{% endif %} +{% endif %} #[allow(deprecated)] impl From<{{ attr.name }}> for ::opentelemetry::KeyValue { diff --git a/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.expected-error.txt b/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.expected-error.txt index 26b75eb..d96698e 100644 --- a/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.expected-error.txt +++ b/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.expected-error.txt @@ -1 +1 @@ -mismatched types +the trait bound `TaskRetriesAttr: From<&str>` is not satisfied diff --git a/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.rs b/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.rs index c1e5aee..1c753de 100644 --- a/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.rs +++ b/templates/code/rust/tests/attributes/compile-fail/wrong_scalar.rs @@ -1,3 +1,3 @@ fn main() { - let _ = generated_semconv::myappattr::TaskRetriesAttr::new("three"); + let _ = generated_semconv::myappattr::TaskRetriesAttr::from("three"); } diff --git a/templates/code/rust/tests/attributes/expected/authattr.rs b/templates/code/rust/tests/attributes/expected/authattr.rs index 9af5ebe..089bc89 100644 --- a/templates/code/rust/tests/attributes/expected/authattr.rs +++ b/templates/code/rust/tests/attributes/expected/authattr.rs @@ -62,15 +62,25 @@ pub struct UserIdAttr(String); #[allow(deprecated)] impl UserIdAttr { pub const KEY: &'static str = "auth.user.id"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for UserIdAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for UserIdAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: UserIdAttr) -> Self { diff --git a/templates/code/rust/tests/attributes/expected/myappattr.rs b/templates/code/rust/tests/attributes/expected/myappattr.rs index a943b9f..8c089e3 100644 --- a/templates/code/rust/tests/attributes/expected/myappattr.rs +++ b/templates/code/rust/tests/attributes/expected/myappattr.rs @@ -8,15 +8,25 @@ pub struct TaskAssignedByAttr(String); #[allow(deprecated)] impl TaskAssignedByAttr { pub const KEY: &'static str = "myapp.task.assigned_by"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskAssignedByAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for TaskAssignedByAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskAssignedByAttr) -> Self { @@ -30,15 +40,19 @@ pub struct TaskCancelledAttr(bool); #[allow(deprecated)] impl TaskCancelledAttr { pub const KEY: &'static str = "myapp.task.cancelled"; - pub fn new(value: bool) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskCancelledAttr { + fn from(value: bool) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskCancelledAttr) -> Self { @@ -77,15 +91,19 @@ pub struct TaskFlagsAttr(Vec); #[allow(deprecated)] impl TaskFlagsAttr { pub const KEY: &'static str = "myapp.task.flags"; - pub fn new(value: Vec) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(self.0))) } } +#[allow(deprecated)] +impl From> for TaskFlagsAttr { + fn from(value: Vec) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskFlagsAttr) -> Self { @@ -101,15 +119,25 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskIdAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for TaskIdAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { @@ -155,15 +183,25 @@ pub struct TaskOwnerAttr(String); #[allow(deprecated)] impl TaskOwnerAttr { pub const KEY: &'static str = "myapp.task.owner"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskOwnerAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for TaskOwnerAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskOwnerAttr) -> Self { @@ -205,15 +243,19 @@ pub struct TaskProgressAttr(f64); #[allow(deprecated)] impl TaskProgressAttr { pub const KEY: &'static str = "myapp.task.progress"; - pub fn new(value: f64) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskProgressAttr { + fn from(value: f64) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskProgressAttr) -> Self { @@ -227,15 +269,19 @@ pub struct TaskRetriesAttr(i64); #[allow(deprecated)] impl TaskRetriesAttr { pub const KEY: &'static str = "myapp.task.retries"; - pub fn new(value: i64) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskRetriesAttr { + fn from(value: i64) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskRetriesAttr) -> Self { @@ -277,15 +323,19 @@ pub struct TaskShardIdsAttr(Vec); #[allow(deprecated)] impl TaskShardIdsAttr { pub const KEY: &'static str = "myapp.task.shard_ids"; - pub fn new(value: Vec) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) } } +#[allow(deprecated)] +impl From> for TaskShardIdsAttr { + fn from(value: Vec) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskShardIdsAttr) -> Self { @@ -333,15 +383,19 @@ pub struct TaskTagsAttr(Vec); #[allow(deprecated)] impl TaskTagsAttr { pub const KEY: &'static str = "myapp.task.tags"; - pub fn new(value: Vec) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) } } +#[allow(deprecated)] +impl From> for TaskTagsAttr { + fn from(value: Vec) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskTagsAttr) -> Self { @@ -355,15 +409,19 @@ pub struct TaskWeightsAttr(Vec); #[allow(deprecated)] impl TaskWeightsAttr { pub const KEY: &'static str = "myapp.task.weights"; - pub fn new(value: Vec) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(self.0))) } } +#[allow(deprecated)] +impl From> for TaskWeightsAttr { + fn from(value: Vec) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskWeightsAttr) -> Self { diff --git a/templates/code/rust/tests/attributes/test.rs b/templates/code/rust/tests/attributes/test.rs index 8181741..18ee46a 100644 --- a/templates/code/rust/tests/attributes/test.rs +++ b/templates/code/rust/tests/attributes/test.rs @@ -4,40 +4,42 @@ use opentelemetry::{Array, KeyValue, Value}; #[test] fn typed_attributes_preserve_keys_values_and_schema() { assert_eq!(SCHEMA_URL, "https://example.com/schemas/attributes/1.0.0"); - let value: KeyValue = myappattr::TaskIdAttr::new("task").into(); + let value: KeyValue = myappattr::TaskIdAttr::from("task").into(); assert_eq!(value, KeyValue::new("myapp.task.id", "task")); assert_eq!( - myappattr::TaskRetriesAttr::new(4).key_value(), + myappattr::TaskRetriesAttr::from(4).key_value(), KeyValue::new("myapp.task.retries", 4_i64) ); assert_eq!( - myappattr::TaskCancelledAttr::new(true).key_value().value, + myappattr::TaskCancelledAttr::from(true).key_value().value, Value::Bool(true) ); assert_eq!( - myappattr::TaskProgressAttr::new(0.5).key_value().value, + myappattr::TaskProgressAttr::from(0.5).key_value().value, Value::F64(0.5) ); assert_eq!( - myappattr::TaskTagsAttr::new(vec!["tag".into()]) + myappattr::TaskTagsAttr::from(vec!["tag".into()]) .key_value() .value, Value::Array(Array::String(vec!["tag".into()])) ); assert_eq!( - myappattr::TaskShardIdsAttr::new(vec![1, 2]) + myappattr::TaskShardIdsAttr::from(vec![1, 2]) .key_value() .value, Value::Array(Array::I64(vec![1, 2])) ); assert_eq!( - myappattr::TaskWeightsAttr::new(vec![0.25]) + myappattr::TaskWeightsAttr::from(vec![0.25]) .key_value() .value, Value::Array(Array::F64(vec![0.25])) ); assert_eq!( - myappattr::TaskFlagsAttr::new(vec![false]).key_value().value, + myappattr::TaskFlagsAttr::from(vec![false]) + .key_value() + .value, Value::Array(Array::Bool(vec![false])) ); assert_eq!( @@ -55,3 +57,32 @@ fn typed_attributes_preserve_keys_values_and_schema() { Value::F64(1.0) ); } + +#[test] +fn string_attributes_accept_borrowed_owned_and_inferred_conversions() { + let owned = String::from("owned"); + let borrowed: myappattr::TaskIdAttr = { + let source = String::from("borrowed"); + source.as_str().into() + }; + assert_eq!( + myappattr::TaskIdAttr::from(owned).key_value(), + KeyValue::new("myapp.task.id", "owned") + ); + assert_eq!( + borrowed.key_value(), + KeyValue::new("myapp.task.id", "borrowed") + ); + let inferred: myappattr::TaskIdAttr = "inferred".into(); + assert_eq!( + inferred.key_value(), + KeyValue::new("myapp.task.id", "inferred") + ); + let retries: myappattr::TaskRetriesAttr = 7_i64.into(); + assert_eq!(retries.key_value().value, Value::I64(7)); + let tags: myappattr::TaskTagsAttr = vec![String::from("tag")].into(); + assert_eq!( + tags.key_value().value, + Value::Array(Array::String(vec!["tag".into()])) + ); +} diff --git a/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_attribute.rs b/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_attribute.rs index 4d59195..85f82cf 100644 --- a/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_attribute.rs +++ b/templates/code/rust/tests/codegen_exclusion/compile-fail/excluded_attribute.rs @@ -1,3 +1,3 @@ fn main() { - let _ = generated_semconv::demoattr::HiddenAttr::new("value"); + let _ = generated_semconv::demoattr::HiddenAttr::from("value"); } diff --git a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs index fc868b9..3315e9a 100644 --- a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs +++ b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs @@ -6,15 +6,25 @@ pub struct KeptAttr(String); #[allow(deprecated)] impl KeptAttr { pub const KEY: &'static str = "demo.kept"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for KeptAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for KeptAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: KeptAttr) -> Self { diff --git a/templates/code/rust/tests/codegen_exclusion/test.rs b/templates/code/rust/tests/codegen_exclusion/test.rs index b84f50b..fe7148d 100644 --- a/templates/code/rust/tests/codegen_exclusion/test.rs +++ b/templates/code/rust/tests/codegen_exclusion/test.rs @@ -3,7 +3,7 @@ use opentelemetry::KeyValue; #[test] fn explicit_false_keeps_attributes_and_enum_members() { assert_eq!( - KeptAttr::new("value").key_value(), + KeptAttr::from("value").key_value(), KeyValue::new("demo.kept", "value") ); assert_eq!( diff --git a/templates/code/rust/tests/entities/compile-fail/wrong_identity.rs b/templates/code/rust/tests/entities/compile-fail/wrong_identity.rs index ad3f36e..96041aa 100644 --- a/templates/code/rust/tests/entities/compile-fail/wrong_identity.rs +++ b/templates/code/rust/tests/entities/compile-fail/wrong_identity.rs @@ -1,5 +1,5 @@ use generated_semconv::{myappattr, myappentity}; fn main() { - let _ = myappentity::HostEntity::new(myappattr::QueueNameAttr::new("queue-1"), []); + let _ = myappentity::HostEntity::new(myappattr::QueueNameAttr::from("queue-1"), []); } diff --git a/templates/code/rust/tests/entities/expected/myappattr.rs b/templates/code/rust/tests/entities/expected/myappattr.rs index a3d2152..3a1c29d 100644 --- a/templates/code/rust/tests/entities/expected/myappattr.rs +++ b/templates/code/rust/tests/entities/expected/myappattr.rs @@ -7,15 +7,19 @@ pub struct HostCpuCountAttr(i64); #[allow(deprecated)] impl HostCpuCountAttr { pub const KEY: &'static str = "myapp.host.cpu.count"; - pub fn new(value: i64) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for HostCpuCountAttr { + fn from(value: i64) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostCpuCountAttr) -> Self { @@ -29,15 +33,25 @@ pub struct HostNameAttr(String); #[allow(deprecated)] impl HostNameAttr { pub const KEY: &'static str = "myapp.host.name"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for HostNameAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for HostNameAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostNameAttr) -> Self { @@ -51,15 +65,25 @@ pub struct HostRoleAttr(String); #[allow(deprecated)] impl HostRoleAttr { pub const KEY: &'static str = "myapp.host.role"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for HostRoleAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for HostRoleAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostRoleAttr) -> Self { @@ -101,15 +125,25 @@ pub struct QueueNameAttr(String); #[allow(deprecated)] impl QueueNameAttr { pub const KEY: &'static str = "myapp.queue.name"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for QueueNameAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for QueueNameAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: QueueNameAttr) -> Self { @@ -123,15 +157,19 @@ pub struct QueueSizeAttr(i64); #[allow(deprecated)] impl QueueSizeAttr { pub const KEY: &'static str = "myapp.queue.size"; - pub fn new(value: i64) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for QueueSizeAttr { + fn from(value: i64) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: QueueSizeAttr) -> Self { diff --git a/templates/code/rust/tests/entities/test.rs b/templates/code/rust/tests/entities/test.rs index e38d54d..2bf7fee 100644 --- a/templates/code/rust/tests/entities/test.rs +++ b/templates/code/rust/tests/entities/test.rs @@ -3,7 +3,7 @@ use generated_semconv::{myappattr, myappentity, SCHEMA_URL}; #[test] fn entity_resource_keeps_identity_description_and_schema() { let entity = myappentity::HostEntity::new( - myappattr::HostNameAttr::new("worker-1"), + myappattr::HostNameAttr::from("worker-1"), [myappentity::HostEntityAttr::HostType( myappattr::HostTypeAttr::Virtual, )], @@ -24,8 +24,8 @@ fn entity_resource_keeps_identity_description_and_schema() { #[test] fn refinement_requires_its_description_attribute() { let entity = myappentity::HostWorkerEntity::new( - myappattr::HostNameAttr::new("worker-2"), - myappattr::HostRoleAttr::new("worker"), + myappattr::HostNameAttr::from("worker-2"), + myappattr::HostRoleAttr::from("worker"), [], ); assert_eq!(entity.attributes().len(), 2); diff --git a/templates/code/rust/tests/events/expected/myappattr.rs b/templates/code/rust/tests/events/expected/myappattr.rs index ba1e59b..20e55b9 100644 --- a/templates/code/rust/tests/events/expected/myappattr.rs +++ b/templates/code/rust/tests/events/expected/myappattr.rs @@ -6,15 +6,19 @@ pub struct BoolValuesAttr(Vec); #[allow(deprecated)] impl BoolValuesAttr { pub const KEY: &'static str = "myapp.bool.values"; - pub fn new(value: Vec) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(self.0))) } } +#[allow(deprecated)] +impl From> for BoolValuesAttr { + fn from(value: Vec) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: BoolValuesAttr) -> Self { @@ -28,15 +32,19 @@ pub struct DoubleValuesAttr(Vec); #[allow(deprecated)] impl DoubleValuesAttr { pub const KEY: &'static str = "myapp.double.values"; - pub fn new(value: Vec) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(self.0))) } } +#[allow(deprecated)] +impl From> for DoubleValuesAttr { + fn from(value: Vec) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: DoubleValuesAttr) -> Self { @@ -50,15 +58,19 @@ pub struct IntValuesAttr(Vec); #[allow(deprecated)] impl IntValuesAttr { pub const KEY: &'static str = "myapp.int.values"; - pub fn new(value: Vec) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) } } +#[allow(deprecated)] +impl From> for IntValuesAttr { + fn from(value: Vec) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: IntValuesAttr) -> Self { @@ -72,15 +84,19 @@ pub struct StringValuesAttr(Vec); #[allow(deprecated)] impl StringValuesAttr { pub const KEY: &'static str = "myapp.string.values"; - pub fn new(value: Vec) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) } } +#[allow(deprecated)] +impl From> for StringValuesAttr { + fn from(value: Vec) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: StringValuesAttr) -> Self { @@ -94,15 +110,19 @@ pub struct TaskAttemptAttr(i64); #[allow(deprecated)] impl TaskAttemptAttr { pub const KEY: &'static str = "myapp.task.attempt"; - pub fn new(value: i64) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskAttemptAttr { + fn from(value: i64) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskAttemptAttr) -> Self { diff --git a/templates/code/rust/tests/events/expected/workerattr.rs b/templates/code/rust/tests/events/expected/workerattr.rs index c39d1b4..b2b1b5f 100644 --- a/templates/code/rust/tests/events/expected/workerattr.rs +++ b/templates/code/rust/tests/events/expected/workerattr.rs @@ -6,15 +6,25 @@ pub struct HostNameAttr(String); #[allow(deprecated)] impl HostNameAttr { pub const KEY: &'static str = "worker.host.name"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for HostNameAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for HostNameAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostNameAttr) -> Self { diff --git a/templates/code/rust/tests/events/test.rs b/templates/code/rust/tests/events/test.rs index a197451..d68062a 100644 --- a/templates/code/rust/tests/events/test.rs +++ b/templates/code/rust/tests/events/test.rs @@ -31,16 +31,16 @@ fn typed_events_have_schema_timestamps_severity_attributes_and_trace_context() { &logger, myappattr::TaskStateAttr::Done, [ - myappevent::TaskFinishedOption::TaskAttempt(myappattr::TaskAttemptAttr::new(2)), - myappevent::TaskFinishedOption::HostName(workerattr::HostNameAttr::new("worker-1")), + myappevent::TaskFinishedOption::TaskAttempt(myappattr::TaskAttemptAttr::from(2)), + myappevent::TaskFinishedOption::HostName(workerattr::HostNameAttr::from("worker-1")), myappevent::TaskFinishedOption::Severity(Severity::Warn), myappevent::TaskFinishedOption::Timestamp(timestamp), - myappevent::TaskFinishedOption::BoolValues(myappattr::BoolValuesAttr::new(vec![true])), - myappevent::TaskFinishedOption::IntValues(myappattr::IntValuesAttr::new(vec![1])), - myappevent::TaskFinishedOption::DoubleValues(myappattr::DoubleValuesAttr::new(vec![ + myappevent::TaskFinishedOption::BoolValues(myappattr::BoolValuesAttr::from(vec![true])), + myappevent::TaskFinishedOption::IntValues(myappattr::IntValuesAttr::from(vec![1])), + myappevent::TaskFinishedOption::DoubleValues(myappattr::DoubleValuesAttr::from(vec![ 1.5, ])), - myappevent::TaskFinishedOption::StringValues(myappattr::StringValuesAttr::new(vec![ + myappevent::TaskFinishedOption::StringValues(myappattr::StringValuesAttr::from(vec![ "fetch".into(), ])), ], @@ -49,7 +49,7 @@ fn typed_events_have_schema_timestamps_severity_attributes_and_trace_context() { &context, &logger, myappattr::TaskStateAttr::Done, - workerattr::HostNameAttr::new("worker-1"), + workerattr::HostNameAttr::from("worker-1"), [], ); provider.force_flush().unwrap(); diff --git a/templates/code/rust/tests/filtering/expected/authattr.rs b/templates/code/rust/tests/filtering/expected/authattr.rs index fe1b41f..98dfefc 100644 --- a/templates/code/rust/tests/filtering/expected/authattr.rs +++ b/templates/code/rust/tests/filtering/expected/authattr.rs @@ -34,15 +34,25 @@ pub struct UserIdAttr(String); #[allow(deprecated)] impl UserIdAttr { pub const KEY: &'static str = "auth.user.id"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for UserIdAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for UserIdAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: UserIdAttr) -> Self { diff --git a/templates/code/rust/tests/filtering/expected/taskattr.rs b/templates/code/rust/tests/filtering/expected/taskattr.rs index 900647f..28cf123 100644 --- a/templates/code/rust/tests/filtering/expected/taskattr.rs +++ b/templates/code/rust/tests/filtering/expected/taskattr.rs @@ -8,15 +8,25 @@ pub struct AssignedByAttr(String); #[allow(deprecated)] impl AssignedByAttr { pub const KEY: &'static str = "myapp.task.assigned_by"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for AssignedByAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for AssignedByAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: AssignedByAttr) -> Self { @@ -30,15 +40,19 @@ pub struct CancelledAttr(bool); #[allow(deprecated)] impl CancelledAttr { pub const KEY: &'static str = "myapp.task.cancelled"; - pub fn new(value: bool) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for CancelledAttr { + fn from(value: bool) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: CancelledAttr) -> Self { @@ -54,15 +68,25 @@ pub struct IdAttr(String); #[allow(deprecated)] impl IdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for IdAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for IdAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: IdAttr) -> Self { @@ -104,15 +128,19 @@ pub struct RetriesAttr(i64); #[allow(deprecated)] impl RetriesAttr { pub const KEY: &'static str = "myapp.task.retries"; - pub fn new(value: i64) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for RetriesAttr { + fn from(value: i64) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: RetriesAttr) -> Self { @@ -154,15 +182,19 @@ pub struct ShardIdsAttr(Vec); #[allow(deprecated)] impl ShardIdsAttr { pub const KEY: &'static str = "myapp.task.shard_ids"; - pub fn new(value: Vec) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) } } +#[allow(deprecated)] +impl From> for ShardIdsAttr { + fn from(value: Vec) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: ShardIdsAttr) -> Self { @@ -206,15 +238,19 @@ pub struct TagsAttr(Vec); #[allow(deprecated)] impl TagsAttr { pub const KEY: &'static str = "myapp.task.tags"; - pub fn new(value: Vec) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) } } +#[allow(deprecated)] +impl From> for TagsAttr { + fn from(value: Vec) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TagsAttr) -> Self { diff --git a/templates/code/rust/tests/filtering/test.rs b/templates/code/rust/tests/filtering/test.rs index 1336487..6291169 100644 --- a/templates/code/rust/tests/filtering/test.rs +++ b/templates/code/rust/tests/filtering/test.rs @@ -4,7 +4,7 @@ use opentelemetry::{KeyValue, Value}; #[test] fn vendor_prefix_changes_types_but_preserves_telemetry_keys() { assert_eq!( - IdAttr::new("task").key_value(), + IdAttr::from("task").key_value(), KeyValue::new("myapp.task.id", "task") ); assert_eq!( diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs index 33632e5..89bc164 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs @@ -6,15 +6,25 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskIdAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for TaskIdAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs index 33632e5..89bc164 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs @@ -6,15 +6,25 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskIdAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for TaskIdAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { diff --git a/templates/code/rust/tests/imported/expected/myappattr.rs b/templates/code/rust/tests/imported/expected/myappattr.rs index 33632e5..89bc164 100644 --- a/templates/code/rust/tests/imported/expected/myappattr.rs +++ b/templates/code/rust/tests/imported/expected/myappattr.rs @@ -6,15 +6,25 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskIdAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for TaskIdAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { diff --git a/templates/code/rust/tests/imported_typed/expected/myappattr.rs b/templates/code/rust/tests/imported_typed/expected/myappattr.rs index 33632e5..89bc164 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappattr.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappattr.rs @@ -6,15 +6,25 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskIdAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for TaskIdAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { diff --git a/templates/code/rust/tests/metrics/compile-fail/unrelated_optional.rs b/templates/code/rust/tests/metrics/compile-fail/unrelated_optional.rs index 0ba50d3..667cb94 100644 --- a/templates/code/rust/tests/metrics/compile-fail/unrelated_optional.rs +++ b/templates/code/rust/tests/metrics/compile-fail/unrelated_optional.rs @@ -1,5 +1,5 @@ use generated_semconv::{authattr, myappmetric}; fn main() { - let _ = myappmetric::TaskDurationHistogramAttr::Success(authattr::SuccessAttr::new(true)); + let _ = myappmetric::TaskDurationHistogramAttr::Success(authattr::SuccessAttr::from(true)); } diff --git a/templates/code/rust/tests/metrics/expected/authattr.rs b/templates/code/rust/tests/metrics/expected/authattr.rs index 1da69fc..bb93c31 100644 --- a/templates/code/rust/tests/metrics/expected/authattr.rs +++ b/templates/code/rust/tests/metrics/expected/authattr.rs @@ -34,15 +34,19 @@ pub struct SuccessAttr(bool); #[allow(deprecated)] impl SuccessAttr { pub const KEY: &'static str = "auth.success"; - pub fn new(value: bool) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for SuccessAttr { + fn from(value: bool) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: SuccessAttr) -> Self { diff --git a/templates/code/rust/tests/metrics/expected/myappattr.rs b/templates/code/rust/tests/metrics/expected/myappattr.rs index cc7d9fe..e0d37b5 100644 --- a/templates/code/rust/tests/metrics/expected/myappattr.rs +++ b/templates/code/rust/tests/metrics/expected/myappattr.rs @@ -6,15 +6,25 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskIdAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for TaskIdAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { diff --git a/templates/code/rust/tests/metrics/test.rs b/templates/code/rust/tests/metrics/test.rs index 3341631..46fc832 100644 --- a/templates/code/rust/tests/metrics/test.rs +++ b/templates/code/rust/tests/metrics/test.rs @@ -30,7 +30,7 @@ fn synchronous_metrics_export_types_values_attributes_and_refinements() { ); myappmetric::TaskDurationHistogram::new(&meter).record( 0.1, - myappattr::TaskIdAttr::new("base"), + myappattr::TaskIdAttr::from("base"), [ myappmetric::TaskDurationHistogramAttr::TaskState(myappattr::TaskStateAttr::Queued), myappmetric::TaskDurationHistogramAttr::Method(authattr::MethodAttr::Password), @@ -38,7 +38,7 @@ fn synchronous_metrics_export_types_values_attributes_and_refinements() { ); myappmetric::TaskRetryDurationHistogram::new(&meter).record( 0.2, - myappattr::TaskIdAttr::new("retry"), + myappattr::TaskIdAttr::from("retry"), myappattr::TaskStateAttr::Done, [myappmetric::TaskRetryDurationHistogramAttr::Method( authattr::MethodAttr::Token, @@ -46,13 +46,13 @@ fn synchronous_metrics_export_types_values_attributes_and_refinements() { ); workermetric::TaskDurationHistogram::new(&meter).record( 0.3, - myappattr::TaskIdAttr::new("worker"), + myappattr::TaskIdAttr::from("worker"), [], ); myappmetric::TaskStartedCounter::new(&meter).add( 7, [myappmetric::TaskStartedCounterAttr::TaskId( - myappattr::TaskIdAttr::new("started"), + myappattr::TaskIdAttr::from("started"), )], ); myappmetric::TaskActiveUpDownCounter::new(&meter).add(-2, myappattr::TaskStateAttr::Queued); @@ -60,7 +60,7 @@ fn synchronous_metrics_export_types_values_attributes_and_refinements() { authmetric::AttemptsCounter::new(&meter).add( 3, authattr::MethodAttr::Password, - authattr::SuccessAttr::new(true), + authattr::SuccessAttr::from(true), ); provider.force_flush().unwrap(); @@ -193,7 +193,7 @@ fn observable_callbacks_export_values_and_typed_attributes() { observer.observe( 11, [myappmetric::TaskStartedCounterAttr::TaskId( - myappattr::TaskIdAttr::new("observed"), + myappattr::TaskIdAttr::from("observed"), )], ); }); @@ -207,7 +207,7 @@ fn observable_callbacks_export_values_and_typed_attributes() { observer.observe( 13, authattr::MethodAttr::Token, - authattr::SuccessAttr::new(false), + authattr::SuccessAttr::from(false), ); }); provider.force_flush().unwrap(); diff --git a/templates/code/rust/tests/naming/expected/capsattr.rs b/templates/code/rust/tests/naming/expected/capsattr.rs index 41faecb..3595895 100644 --- a/templates/code/rust/tests/naming/expected/capsattr.rs +++ b/templates/code/rust/tests/naming/expected/capsattr.rs @@ -6,15 +6,25 @@ pub struct Http2STATUSApiIDAttr(String); #[allow(deprecated)] impl Http2STATUSApiIDAttr { pub const KEY: &'static str = "caps.http2_STATUS.api_ID"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for Http2STATUSApiIDAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for Http2STATUSApiIDAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: Http2STATUSApiIDAttr) -> Self { diff --git a/templates/code/rust/tests/naming/test.rs b/templates/code/rust/tests/naming/test.rs index 002ca7e..57187fc 100644 --- a/templates/code/rust/tests/naming/test.rs +++ b/templates/code/rust/tests/naming/test.rs @@ -4,7 +4,7 @@ use opentelemetry::KeyValue; #[test] fn names_preserve_capitalization_and_digits_in_attributes_and_signals() { - let identifier = capsattr::Http2STATUSApiIDAttr::new("value"); + let identifier = capsattr::Http2STATUSApiIDAttr::from("value"); assert_eq!( identifier.clone().key_value(), KeyValue::new("caps.http2_STATUS.api_ID", "value") diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs index 14918fd..c638abe 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs @@ -6,15 +6,25 @@ pub struct MessageAttr(String); #[allow(deprecated)] impl MessageAttr { pub const KEY: &'static str = "exception.message"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for MessageAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for MessageAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: MessageAttr) -> Self { @@ -28,15 +38,25 @@ pub struct TypeAttr(String); #[allow(deprecated)] impl TypeAttr { pub const KEY: &'static str = "exception.type"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TypeAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for TypeAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TypeAttr) -> Self { diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs index 4a898c9..966ad8a 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs @@ -6,15 +6,19 @@ pub struct SequenceAttr(i64); #[allow(deprecated)] impl SequenceAttr { pub const KEY: &'static str = "heartbeat.sequence"; - pub fn new(value: i64) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for SequenceAttr { + fn from(value: i64) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: SequenceAttr) -> Self { @@ -28,15 +32,25 @@ pub struct SourceAttr(String); #[allow(deprecated)] impl SourceAttr { pub const KEY: &'static str = "heartbeat.source"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for SourceAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for SourceAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: SourceAttr) -> Self { diff --git a/templates/code/rust/tests/no_namespace/expected/hostattr.rs b/templates/code/rust/tests/no_namespace/expected/hostattr.rs index 4674a46..f53f9ab 100644 --- a/templates/code/rust/tests/no_namespace/expected/hostattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/hostattr.rs @@ -6,15 +6,25 @@ pub struct IdAttr(String); #[allow(deprecated)] impl IdAttr { pub const KEY: &'static str = "host.id"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for IdAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for IdAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: IdAttr) -> Self { @@ -28,15 +38,25 @@ pub struct NameAttr(String); #[allow(deprecated)] impl NameAttr { pub const KEY: &'static str = "host.name"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for NameAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for NameAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: NameAttr) -> Self { diff --git a/templates/code/rust/tests/params/expected/billingattr.rs b/templates/code/rust/tests/params/expected/billingattr.rs index a9de7f7..bd61d6f 100644 --- a/templates/code/rust/tests/params/expected/billingattr.rs +++ b/templates/code/rust/tests/params/expected/billingattr.rs @@ -6,15 +6,25 @@ pub struct InvoiceIdAttr(String); #[allow(deprecated)] impl InvoiceIdAttr { pub const KEY: &'static str = "acme.billing.invoice.id"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for InvoiceIdAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for InvoiceIdAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: InvoiceIdAttr) -> Self { @@ -28,15 +38,25 @@ pub struct CurrencyAttr(String); #[allow(deprecated)] impl CurrencyAttr { pub const KEY: &'static str = "billing.currency"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for CurrencyAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for CurrencyAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: CurrencyAttr) -> Self { diff --git a/templates/code/rust/tests/params/expected/myappattr.rs b/templates/code/rust/tests/params/expected/myappattr.rs index 565c45e..57a6255 100644 --- a/templates/code/rust/tests/params/expected/myappattr.rs +++ b/templates/code/rust/tests/params/expected/myappattr.rs @@ -6,15 +6,25 @@ pub struct RequestUrlAttr(String); #[allow(deprecated)] impl RequestUrlAttr { pub const KEY: &'static str = "myapp.request.url"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for RequestUrlAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for RequestUrlAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: RequestUrlAttr) -> Self { diff --git a/templates/code/rust/tests/spans/compile-fail/sampling_attribute_late.rs b/templates/code/rust/tests/spans/compile-fail/sampling_attribute_late.rs index a99f5b0..7a50d5b 100644 --- a/templates/code/rust/tests/spans/compile-fail/sampling_attribute_late.rs +++ b/templates/code/rust/tests/spans/compile-fail/sampling_attribute_late.rs @@ -2,6 +2,6 @@ use generated_semconv::{myappattr, myappspan}; fn main() { let mut span = myappspan::TaskDispatchSpan::default(); span.set_attributes([myappspan::TaskDispatchStartAttr::TaskId( - myappattr::TaskIdAttr::new("task-1"), + myappattr::TaskIdAttr::from("task-1"), )]); } diff --git a/templates/code/rust/tests/spans/expected/myappattr.rs b/templates/code/rust/tests/spans/expected/myappattr.rs index d354091..0ad9da8 100644 --- a/templates/code/rust/tests/spans/expected/myappattr.rs +++ b/templates/code/rust/tests/spans/expected/myappattr.rs @@ -6,15 +6,25 @@ pub struct QueueNameAttr(String); #[allow(deprecated)] impl QueueNameAttr { pub const KEY: &'static str = "myapp.queue.name"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for QueueNameAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for QueueNameAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: QueueNameAttr) -> Self { @@ -28,15 +38,19 @@ pub struct TaskAttemptAttr(i64); #[allow(deprecated)] impl TaskAttemptAttr { pub const KEY: &'static str = "myapp.task.attempt"; - pub fn new(value: i64) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskAttemptAttr { + fn from(value: i64) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskAttemptAttr) -> Self { @@ -50,15 +64,25 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for TaskIdAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for TaskIdAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { diff --git a/templates/code/rust/tests/spans/expected/workerattr.rs b/templates/code/rust/tests/spans/expected/workerattr.rs index face693..a7d3030 100644 --- a/templates/code/rust/tests/spans/expected/workerattr.rs +++ b/templates/code/rust/tests/spans/expected/workerattr.rs @@ -6,15 +6,25 @@ pub struct HostNameAttr(String); #[allow(deprecated)] impl HostNameAttr { pub const KEY: &'static str = "worker.host.name"; - pub fn new(value: impl Into) -> Self { - Self(value.into()) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for HostNameAttr { + fn from(value: String) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From<&str> for HostNameAttr { + fn from(value: &str) -> Self { + Self(value.to_owned()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostNameAttr) -> Self { @@ -28,15 +38,19 @@ pub struct HostPortAttr(i64); #[allow(deprecated)] impl HostPortAttr { pub const KEY: &'static str = "worker.host.port"; - pub fn new(value: i64) -> Self { - Self(value) - } pub fn key_value(self) -> ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Self::KEY, self.0) } } +#[allow(deprecated)] +impl From for HostPortAttr { + fn from(value: i64) -> Self { + Self(value) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostPortAttr) -> Self { diff --git a/templates/code/rust/tests/spans/test.rs b/templates/code/rust/tests/spans/test.rs index df382be..07a80cc 100644 --- a/templates/code/rust/tests/spans/test.rs +++ b/templates/code/rust/tests/spans/test.rs @@ -19,10 +19,10 @@ fn derived_names_refinements_parent_context_and_late_attributes() { let parent = myappspan::start_task_dispatch( &opentelemetry::Context::new(), &tracer, - workerattr::HostNameAttr::new("worker-1"), - workerattr::HostPortAttr::new(8080), + workerattr::HostNameAttr::from("worker-1"), + workerattr::HostPortAttr::from(8080), [myappspan::TaskDispatchStartAttr::TaskId( - myappattr::TaskIdAttr::new("task-1"), + myappattr::TaskIdAttr::from("task-1"), )], ); let context = parent.into_context(&opentelemetry::Context::new()); @@ -33,7 +33,7 @@ fn derived_names_refinements_parent_context_and_late_attributes() { myappattr::TaskStateAttr::Done, [], ); - child.set_attributes([myappspan::TaskRunAttr::TaskId(myappattr::TaskIdAttr::new( + child.set_attributes([myappspan::TaskRunAttr::TaskId(myappattr::TaskIdAttr::from( "task-1", ))]); child.set_status(opentelemetry::trace::Status::Ok); @@ -42,9 +42,9 @@ fn derived_names_refinements_parent_context_and_late_attributes() { let mut refined = workerspan::start_task_dispatch( &opentelemetry::Context::new(), &tracer, - myappattr::TaskAttemptAttr::new(3), - workerattr::HostNameAttr::new("worker-2"), - workerattr::HostPortAttr::new(9090), + myappattr::TaskAttemptAttr::from(3), + workerattr::HostNameAttr::from("worker-2"), + workerattr::HostPortAttr::from(9090), [], ); refined.end(); @@ -59,25 +59,25 @@ fn derived_names_refinements_parent_context_and_late_attributes() { myappspan::start_name_apostrophe( &opentelemetry::Context::new(), &tracer, - workerattr::HostPortAttr::new(1), + workerattr::HostPortAttr::from(1), ) .end(); myappspan::start_name_backslash( &opentelemetry::Context::new(), &tracer, - workerattr::HostPortAttr::new(1), + workerattr::HostPortAttr::from(1), ) .end(); myappspan::start_name_unicode( &opentelemetry::Context::new(), &tracer, - workerattr::HostPortAttr::new(1), + workerattr::HostPortAttr::from(1), ) .end(); myappspan::start_name_control( &opentelemetry::Context::new(), &tracer, - workerattr::HostPortAttr::new(1), + workerattr::HostPortAttr::from(1), ) .end(); provider.force_flush().unwrap(); From ab790756024594cd680dea37e855304ace565b28 Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Mon, 5 Oct 2026 09:31:22 -0400 Subject: [PATCH 06/14] refactor: keep telemetry conversions idiomatic Signed-off-by: Yordis Prieto --- templates/code/rust/README.md | 6 +- templates/code/rust/attributes.rs.j2 | 28 ++-- templates/code/rust/entities.rs.j2 | 10 +- templates/code/rust/metrics.rs.j2 | 12 +- templates/code/rust/signal_helpers.j2 | 2 +- templates/code/rust/spans.rs.j2 | 12 +- .../tests/attributes/expected/authattr.rs | 34 ++--- .../tests/attributes/expected/myappattr.rs | 130 +++++------------- templates/code/rust/tests/attributes/test.rs | 45 +++--- .../codegen_exclusion/expected/demoattr.rs | 18 +-- .../code/rust/tests/codegen_exclusion/test.rs | 4 +- .../rust/tests/entities/expected/myappattr.rs | 44 ++---- .../tests/entities/expected/myappentity.rs | 42 +++--- .../rust/tests/events/expected/myappattr.rs | 44 ++---- .../rust/tests/events/expected/myappevent.rs | 16 +-- .../rust/tests/events/expected/workerattr.rs | 6 +- .../rust/tests/events/expected/workerevent.rs | 12 +- .../rust/tests/filtering/expected/authattr.rs | 20 +-- .../rust/tests/filtering/expected/taskattr.rs | 78 +++-------- templates/code/rust/tests/filtering/test.rs | 4 +- .../expected/myappattr.rs | 6 +- .../expected/myappmetric.rs | 8 +- .../expected/myappattr.rs | 6 +- .../expected/myappmetric.rs | 4 +- .../tests/imported/expected/edgemetric.rs | 10 +- .../rust/tests/imported/expected/edgespan.rs | 14 +- .../rust/tests/imported/expected/myappattr.rs | 6 +- .../tests/imported/expected/myappmetric.rs | 16 +-- .../imported_typed/expected/myappattr.rs | 6 +- .../imported_typed/expected/myappevent.rs | 2 +- .../imported_typed/expected/myappmetric.rs | 16 +-- .../imported_typed/expected/myappspan.rs | 18 +-- .../integer_boundaries/expected/demoattr.rs | 14 +- .../rust/tests/integer_boundaries/test.rs | 4 +- .../literal_escaping/expected/demoattr.rs | 14 +- .../literal_escaping/expected/demometric.rs | 4 +- .../code/rust/tests/literal_escaping/test.rs | 4 +- .../rust/tests/metrics/expected/authattr.rs | 20 +-- .../rust/tests/metrics/expected/authmetric.rs | 4 +- .../rust/tests/metrics/expected/myappattr.rs | 20 +-- .../tests/metrics/expected/myappmetric.rs | 42 +++--- .../tests/metrics/expected/workermetric.rs | 14 +- .../rust/tests/naming/expected/capsattr.rs | 18 +-- .../rust/tests/naming/expected/capsmetric.rs | 4 +- templates/code/rust/tests/naming/test.rs | 2 +- .../no_namespace/expected/exceptionattr.rs | 12 +- .../no_namespace/expected/exceptionevent.rs | 4 +- .../no_namespace/expected/heartbeatattr.rs | 12 +- .../no_namespace/expected/heartbeatspan.rs | 14 +- .../tests/no_namespace/expected/hostattr.rs | 12 +- .../tests/no_namespace/expected/hostentity.rs | 12 +- .../rust/tests/params/expected/billingattr.rs | 12 +- .../tests/params/expected/billingmetric.rs | 14 +- .../rust/tests/params/expected/myappattr.rs | 6 +- .../rust/tests/spans/expected/myappattr.rs | 32 ++--- .../rust/tests/spans/expected/myappspan.rs | 52 +++---- .../rust/tests/spans/expected/workerattr.rs | 12 +- .../rust/tests/spans/expected/workerspan.rs | 20 +-- 58 files changed, 382 insertions(+), 675 deletions(-) diff --git a/templates/code/rust/README.md b/templates/code/rust/README.md index 8c3db2c..fcc6929 100644 --- a/templates/code/rust/README.md +++ b/templates/code/rust/README.md @@ -43,7 +43,7 @@ before choosing that namespace. | Module | API | | ------------------- | -------------------------------------------------------------------------------------------- | -| `attr` | Attribute newtypes and enum variants, `KEY`, `key_value`, and conversion into `KeyValue`. | +| `attr` | Attribute newtypes and enum variants, `KEY` and conversion into `KeyValue`. | | `meter` | Schema-aware `Meter`, with `new`, `new_with_scope`, `inner`, and a no-op `Default`. | | `tracer` | Schema-aware `Tracer`, with `new`, `new_with_scope`, `inner`, and a no-op `Default`. | | `logger` | Schema-aware generic `Logger`, with `new`, `new_with_scope`, `inner`, and a no-op `Default`. | @@ -61,8 +61,8 @@ Attribute keys, metric names, and event names retain their full registry names. ### Typed attributes An attribute such as `myapp.task.id` becomes -`myappattr::TaskIdAttr::from("task-1")`. Its `key_value()` method consumes the -value and returns an OpenTelemetry `KeyValue`. String attributes implement +`myappattr::TaskIdAttr::from("task-1")`. Convert the attribute into an OpenTelemetry `KeyValue` with +`KeyValue::from(attribute)` or `attribute.into()`. String attributes implement `From` and `From<&str>`; scalar and array attributes implement `From` for their exact backing types. Use `Attr::from(value)` or `value.into()` when the attribute type is known. Enums expose named variants, diff --git a/templates/code/rust/attributes.rs.j2 b/templates/code/rust/attributes.rs.j2 index 0343d1d..f3ccf30 100644 --- a/templates/code/rust/attributes.rs.j2 +++ b/templates/code/rust/attributes.rs.j2 @@ -20,21 +20,6 @@ pub struct {{ attr.name }}({{ attr.value_type | map_text("rust_type") }}); #[allow(deprecated)] impl {{ attr.name }} { pub const KEY: &'static str = {{ attr.key_literal }}; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { -{% if attr.type is mapping %} - let value: {{ attr.value_type | map_text("rust_type") }} = match self { -{% for member in attr.type.members %} - Self::{{ member.name }} => {{ member.literal }}{% if attr.value_type == "string" %}.into(){% elif attr.value_type == "double" %}_f64{% endif %}, -{% endfor %} - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) -{% elif "[]" in attr.value_type %} - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::{{ attr.value_type | map_text("rust_array") }}(self.0{% if attr.value_type == "string[]" %}.into_iter().map(Into::into).collect(){% endif %}))) -{% else %} - ::opentelemetry::KeyValue::new(Self::KEY, self.0) -{% endif %} - } } {% if attr.type is not mapping %} @@ -57,7 +42,18 @@ impl From<&str> for {{ attr.name }} { #[allow(deprecated)] impl From<{{ attr.name }}> for ::opentelemetry::KeyValue { fn from(value: {{ attr.name }}) -> Self { - value.key_value() +{% if attr.type is mapping %} + let value: {{ attr.value_type | map_text("rust_type") }} = match value { +{% for member in attr.type.members %} + {{ attr.name }}::{{ member.name }} => {{ member.literal }}{% if attr.value_type == "string" %}.into(){% elif attr.value_type == "double" %}_f64{% endif %}, +{% endfor %} + }; + ::opentelemetry::KeyValue::new({{ attr.name }}::KEY, value) +{% elif "[]" in attr.value_type %} + ::opentelemetry::KeyValue::new({{ attr.name }}::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::{{ attr.value_type | map_text("rust_array") }}(value.0{% if attr.value_type == "string[]" %}.into_iter().map(Into::into).collect(){% endif %}))) +{% else %} + ::opentelemetry::KeyValue::new({{ attr.name }}::KEY, value.0) +{% endif %} } } {% endfor %} diff --git a/templates/code/rust/entities.rs.j2 b/templates/code/rust/entities.rs.j2 index c5ef7b6..8242a3b 100644 --- a/templates/code/rust/entities.rs.j2 +++ b/templates/code/rust/entities.rs.j2 @@ -16,11 +16,11 @@ pub enum {{ name }}Attr { {% endfor %} } -impl {{ name }}Attr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { +impl From<{{ name }}Attr> for ::opentelemetry::KeyValue { + fn from(value: {{ name }}Attr) -> Self { + match value { {% for opt in def.optional %} - Self::{{ s.exported(opt.attr_short_name) }}(value) => {{ s.attr_kv(opt, "value") }}, + {{ name }}Attr::{{ s.exported(opt.attr_short_name) }}(value) => {{ s.attr_kv(opt, "value") }}, {% endfor %} } } @@ -44,7 +44,7 @@ impl {{ name }} { {{ s.attr_kv(req, s.ident(req.attr_param)) }}, {% endfor %} ]; -{% if def.optional %} attributes.extend(options.into_iter().map({{ name }}Attr::key_value)); +{% if def.optional %} attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); {% endif %} Self { attributes } {% else %} Self::default() {% endif %} } diff --git a/templates/code/rust/metrics.rs.j2 b/templates/code/rust/metrics.rs.j2 index 1bc7977..2fc5f90 100644 --- a/templates/code/rust/metrics.rs.j2 +++ b/templates/code/rust/metrics.rs.j2 @@ -17,11 +17,11 @@ pub enum {{ name }}Attr { {{ h.exported(opt.attr_short_name) }}({{ h.attr_type(opt) }}), {% endfor %} } -impl {{ name }}Attr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { +impl From<{{ name }}Attr> for ::opentelemetry::KeyValue { + fn from(value: {{ name }}Attr) -> Self { + match value { {% for opt in def.optional %} - Self::{{ h.exported(opt.attr_short_name) }}(value) => {{ h.attr_kv(opt, 'value') }}, + {{ name }}Attr::{{ h.exported(opt.attr_short_name) }}(value) => {{ h.attr_kv(opt, 'value') }}, {% endfor %} } } @@ -43,7 +43,7 @@ impl {{ name }} { pub fn {{ method }}(&self, value: {{ value_type }}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) { let {% if def.optional %}mut {% endif %}attributes = vec![{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; {% if def.optional %} - attributes.extend(options.into_iter().map({{ name }}Attr::key_value)); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); {% endif %} self.instrument.{{ method }}(value, &attributes); } @@ -58,7 +58,7 @@ impl {{ name }}Observer<'_> { pub fn observe(&self, value: {{ value_type }}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) { let {% if def.optional %}mut {% endif %}attributes = vec![{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; {% if def.optional %} - attributes.extend(options.into_iter().map({{ name }}Attr::key_value)); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); {% endif %} self.observer.observe(value, &attributes); } diff --git a/templates/code/rust/signal_helpers.j2 b/templates/code/rust/signal_helpers.j2 index 494e8b6..d576d34 100644 --- a/templates/code/rust/signal_helpers.j2 +++ b/templates/code/rust/signal_helpers.j2 @@ -10,7 +10,7 @@ {%- endmacro %} {% macro attr_kv(a, value) -%} {%- if a.imported -%}::opentelemetry::KeyValue::new({{ literal(a.key) }}, {% if "[]" in a.attr_type %}::opentelemetry::Value::Array(::opentelemetry::Array::{{ a.attr_type | map_text("rust_array") }}({{ value }}{% if a.attr_type == "string[]" %}.into_iter().map(Into::into).collect(){% endif %})){% else %}{{ value }}{% endif %}) -{%- else -%}{{ value }}.key_value() +{%- else -%}::opentelemetry::KeyValue::from({{ value }}) {%- endif -%} {%- endmacro %} {% macro deprecated(def) -%} diff --git a/templates/code/rust/spans.rs.j2 b/templates/code/rust/spans.rs.j2 index 4d0cca4..e9bab1a 100644 --- a/templates/code/rust/spans.rs.j2 +++ b/templates/code/rust/spans.rs.j2 @@ -14,11 +14,11 @@ pub enum {{ name }}StartAttr { {{ h.exported(opt.attr_short_name) }}({{ h.attr_type(opt) }}), {% endfor %} } -impl {{ name }}StartAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { +impl From<{{ name }}StartAttr> for ::opentelemetry::KeyValue { + fn from(value: {{ name }}StartAttr) -> Self { + match value { {% for opt in def.optional %} - Self::{{ h.exported(opt.attr_short_name) }}(value) => {{ h.attr_kv(opt, 'value') }}, + {{ name }}StartAttr::{{ h.exported(opt.attr_short_name) }}(value) => {{ h.attr_kv(opt, 'value') }}, {% endfor %} } } @@ -62,7 +62,7 @@ impl {{ span }} { pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } {% if def.has_late_attrs %} pub fn set_attributes(&mut self, attributes: impl IntoIterator) { - for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, {{ name }}StartAttr::from(attribute).key_value()); } + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from({{ name }}StartAttr::from(attribute))); } } {% endif %} } @@ -93,7 +93,7 @@ pub fn {{ h.ident('start.' ~ def.short_name) }}(context: &::opentelemetry::Conte {% endif %} let {% if def.optional %}mut {% endif %}attributes = vec![{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; {% if def.optional %} - attributes.extend(options.into_iter().map({{ name }}StartAttr::key_value)); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); {% endif %} let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::{{ def.kind | pascal_case }}) diff --git a/templates/code/rust/tests/attributes/expected/authattr.rs b/templates/code/rust/tests/attributes/expected/authattr.rs index 089bc89..2104493 100644 --- a/templates/code/rust/tests/attributes/expected/authattr.rs +++ b/templates/code/rust/tests/attributes/expected/authattr.rs @@ -11,20 +11,16 @@ pub enum LevelAttr { #[allow(deprecated)] impl LevelAttr { pub const KEY: &'static str = "auth.level"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: i64 = match self { - Self::Low => 1, - Self::High => 2, - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: LevelAttr) -> Self { - value.key_value() + let value: i64 = match value { + LevelAttr::Low => 1, + LevelAttr::High => 2, + }; + ::opentelemetry::KeyValue::new(LevelAttr::KEY, value) } } /// How the user was authenticated. @@ -39,20 +35,16 @@ pub enum MethodAttr { #[allow(deprecated)] impl MethodAttr { pub const KEY: &'static str = "auth.method"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Password => "password".into(), - Self::Token => "token".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: MethodAttr) -> Self { - value.key_value() + let value: String = match value { + MethodAttr::Password => "password".into(), + MethodAttr::Token => "token".into(), + }; + ::opentelemetry::KeyValue::new(MethodAttr::KEY, value) } } /// Identifier of the authenticated user. @@ -62,10 +54,6 @@ pub struct UserIdAttr(String); #[allow(deprecated)] impl UserIdAttr { pub const KEY: &'static str = "auth.user.id"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -84,6 +72,6 @@ impl From<&str> for UserIdAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: UserIdAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(UserIdAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/attributes/expected/myappattr.rs b/templates/code/rust/tests/attributes/expected/myappattr.rs index 8c089e3..54148ea 100644 --- a/templates/code/rust/tests/attributes/expected/myappattr.rs +++ b/templates/code/rust/tests/attributes/expected/myappattr.rs @@ -8,10 +8,6 @@ pub struct TaskAssignedByAttr(String); #[allow(deprecated)] impl TaskAssignedByAttr { pub const KEY: &'static str = "myapp.task.assigned_by"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -30,7 +26,7 @@ impl From<&str> for TaskAssignedByAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskAssignedByAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskAssignedByAttr::KEY, value.0) } } /// Whether the task was cancelled. @@ -40,10 +36,6 @@ pub struct TaskCancelledAttr(bool); #[allow(deprecated)] impl TaskCancelledAttr { pub const KEY: &'static str = "myapp.task.cancelled"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -56,7 +48,7 @@ impl From for TaskCancelledAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskCancelledAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskCancelledAttr::KEY, value.0) } } /// Tests Rust string literals. @@ -69,19 +61,15 @@ pub enum TaskEscapedAttr { #[allow(deprecated)] impl TaskEscapedAttr { pub const KEY: &'static str = "myapp.task.escaped"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Quoted => "quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskEscapedAttr) -> Self { - value.key_value() + let value: String = match value { + TaskEscapedAttr::Quoted => "quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃".into(), + }; + ::opentelemetry::KeyValue::new(TaskEscapedAttr::KEY, value) } } /// Feature flags evaluated for the task. @@ -91,10 +79,6 @@ pub struct TaskFlagsAttr(Vec); #[allow(deprecated)] impl TaskFlagsAttr { pub const KEY: &'static str = "myapp.task.flags"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(self.0))) - } } #[allow(deprecated)] @@ -107,7 +91,7 @@ impl From> for TaskFlagsAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskFlagsAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskFlagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(value.0))) } } /// Unique identifier of the task. @@ -119,10 +103,6 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -141,7 +121,7 @@ impl From<&str> for TaskIdAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } /// Lane the task was scheduled in. @@ -159,20 +139,16 @@ pub enum TaskLaneAttr { #[allow(deprecated)] impl TaskLaneAttr { pub const KEY: &'static str = "myapp.task.lane"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Fast => "fast".into(), - Self::Slow => "slow".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskLaneAttr) -> Self { - value.key_value() + let value: String = match value { + TaskLaneAttr::Fast => "fast".into(), + TaskLaneAttr::Slow => "slow".into(), + }; + ::opentelemetry::KeyValue::new(TaskLaneAttr::KEY, value) } } /// Owner of the task. @@ -183,10 +159,6 @@ pub struct TaskOwnerAttr(String); #[allow(deprecated)] impl TaskOwnerAttr { pub const KEY: &'static str = "myapp.task.owner"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -205,7 +177,7 @@ impl From<&str> for TaskOwnerAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskOwnerAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskOwnerAttr::KEY, value.0) } } /// Whether the scheduler may preempt the task. @@ -220,20 +192,16 @@ pub enum TaskPreemptibleAttr { #[allow(deprecated)] impl TaskPreemptibleAttr { pub const KEY: &'static str = "myapp.task.preemptible"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: bool = match self { - Self::Allowed => true, - Self::Forbidden => false, - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskPreemptibleAttr) -> Self { - value.key_value() + let value: bool = match value { + TaskPreemptibleAttr::Allowed => true, + TaskPreemptibleAttr::Forbidden => false, + }; + ::opentelemetry::KeyValue::new(TaskPreemptibleAttr::KEY, value) } } /// Fraction of the task that has completed, between 0 and 1. @@ -243,10 +211,6 @@ pub struct TaskProgressAttr(f64); #[allow(deprecated)] impl TaskProgressAttr { pub const KEY: &'static str = "myapp.task.progress"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -259,7 +223,7 @@ impl From for TaskProgressAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskProgressAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskProgressAttr::KEY, value.0) } } /// Number of times the task was retried. @@ -269,10 +233,6 @@ pub struct TaskRetriesAttr(i64); #[allow(deprecated)] impl TaskRetriesAttr { pub const KEY: &'static str = "myapp.task.retries"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -285,7 +245,7 @@ impl From for TaskRetriesAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskRetriesAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskRetriesAttr::KEY, value.0) } } /// Fraction of tasks whose telemetry is sampled. @@ -300,20 +260,16 @@ pub enum TaskSampleRateAttr { #[allow(deprecated)] impl TaskSampleRateAttr { pub const KEY: &'static str = "myapp.task.sample_rate"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: f64 = match self { - Self::Tenth => 0.1_f64, - Self::All => 1_f64, - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskSampleRateAttr) -> Self { - value.key_value() + let value: f64 = match value { + TaskSampleRateAttr::Tenth => 0.1_f64, + TaskSampleRateAttr::All => 1_f64, + }; + ::opentelemetry::KeyValue::new(TaskSampleRateAttr::KEY, value) } } /// Shards the task touched. @@ -323,10 +279,6 @@ pub struct TaskShardIdsAttr(Vec); #[allow(deprecated)] impl TaskShardIdsAttr { pub const KEY: &'static str = "myapp.task.shard_ids"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) - } } #[allow(deprecated)] @@ -339,7 +291,7 @@ impl From> for TaskShardIdsAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskShardIdsAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskShardIdsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) } } /// Current state of the task. @@ -359,21 +311,17 @@ pub enum TaskStateAttr { #[allow(deprecated)] impl TaskStateAttr { pub const KEY: &'static str = "myapp.task.state"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Queued => "queued".into(), - Self::Running => "running".into(), - Self::Paused => "paused".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskStateAttr) -> Self { - value.key_value() + let value: String = match value { + TaskStateAttr::Queued => "queued".into(), + TaskStateAttr::Running => "running".into(), + TaskStateAttr::Paused => "paused".into(), + }; + ::opentelemetry::KeyValue::new(TaskStateAttr::KEY, value) } } /// Tags attached to the task. @@ -383,10 +331,6 @@ pub struct TaskTagsAttr(Vec); #[allow(deprecated)] impl TaskTagsAttr { pub const KEY: &'static str = "myapp.task.tags"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) - } } #[allow(deprecated)] @@ -399,7 +343,7 @@ impl From> for TaskTagsAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskTagsAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskTagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0.into_iter().map(Into::into).collect()))) } } /// Scheduling weights applied to the task. @@ -409,10 +353,6 @@ pub struct TaskWeightsAttr(Vec); #[allow(deprecated)] impl TaskWeightsAttr { pub const KEY: &'static str = "myapp.task.weights"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(self.0))) - } } #[allow(deprecated)] @@ -425,6 +365,6 @@ impl From> for TaskWeightsAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskWeightsAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskWeightsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(value.0))) } } diff --git a/templates/code/rust/tests/attributes/test.rs b/templates/code/rust/tests/attributes/test.rs index 18ee46a..6d3eaf5 100644 --- a/templates/code/rust/tests/attributes/test.rs +++ b/templates/code/rust/tests/attributes/test.rs @@ -7,53 +7,48 @@ fn typed_attributes_preserve_keys_values_and_schema() { let value: KeyValue = myappattr::TaskIdAttr::from("task").into(); assert_eq!(value, KeyValue::new("myapp.task.id", "task")); assert_eq!( - myappattr::TaskRetriesAttr::from(4).key_value(), + KeyValue::from(myappattr::TaskRetriesAttr::from(4)), KeyValue::new("myapp.task.retries", 4_i64) ); assert_eq!( - myappattr::TaskCancelledAttr::from(true).key_value().value, + KeyValue::from(myappattr::TaskCancelledAttr::from(true)).value, Value::Bool(true) ); assert_eq!( - myappattr::TaskProgressAttr::from(0.5).key_value().value, + KeyValue::from(myappattr::TaskProgressAttr::from(0.5)).value, Value::F64(0.5) ); assert_eq!( - myappattr::TaskTagsAttr::from(vec!["tag".into()]) - .key_value() - .value, + KeyValue::from(myappattr::TaskTagsAttr::from(vec!["tag".into()])).value, Value::Array(Array::String(vec!["tag".into()])) ); assert_eq!( - myappattr::TaskShardIdsAttr::from(vec![1, 2]) - .key_value() - .value, + KeyValue::from(myappattr::TaskShardIdsAttr::from(vec![1, 2])).value, Value::Array(Array::I64(vec![1, 2])) ); assert_eq!( - myappattr::TaskWeightsAttr::from(vec![0.25]) - .key_value() - .value, + KeyValue::from(myappattr::TaskWeightsAttr::from(vec![0.25])).value, Value::Array(Array::F64(vec![0.25])) ); assert_eq!( - myappattr::TaskFlagsAttr::from(vec![false]) - .key_value() - .value, + KeyValue::from(myappattr::TaskFlagsAttr::from(vec![false])).value, Value::Array(Array::Bool(vec![false])) ); assert_eq!( - myappattr::TaskStateAttr::Running.key_value().value, + KeyValue::from(myappattr::TaskStateAttr::Running).value, Value::String("running".into()) ); - assert_eq!(myappattr::TaskEscapedAttr::Quoted.key_value().value, Value::String("quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃".into())); - assert_eq!(authattr::LevelAttr::High.key_value().value, Value::I64(2)); + assert_eq!(KeyValue::from(myappattr::TaskEscapedAttr::Quoted).value, Value::String("quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃".into())); assert_eq!( - myappattr::TaskPreemptibleAttr::Allowed.key_value().value, + KeyValue::from(authattr::LevelAttr::High).value, + Value::I64(2) + ); + assert_eq!( + KeyValue::from(myappattr::TaskPreemptibleAttr::Allowed).value, Value::Bool(true) ); assert_eq!( - myappattr::TaskSampleRateAttr::All.key_value().value, + KeyValue::from(myappattr::TaskSampleRateAttr::All).value, Value::F64(1.0) ); } @@ -66,23 +61,23 @@ fn string_attributes_accept_borrowed_owned_and_inferred_conversions() { source.as_str().into() }; assert_eq!( - myappattr::TaskIdAttr::from(owned).key_value(), + KeyValue::from(myappattr::TaskIdAttr::from(owned)), KeyValue::new("myapp.task.id", "owned") ); assert_eq!( - borrowed.key_value(), + KeyValue::from(borrowed), KeyValue::new("myapp.task.id", "borrowed") ); let inferred: myappattr::TaskIdAttr = "inferred".into(); assert_eq!( - inferred.key_value(), + KeyValue::from(inferred), KeyValue::new("myapp.task.id", "inferred") ); let retries: myappattr::TaskRetriesAttr = 7_i64.into(); - assert_eq!(retries.key_value().value, Value::I64(7)); + assert_eq!(KeyValue::from(retries).value, Value::I64(7)); let tags: myappattr::TaskTagsAttr = vec![String::from("tag")].into(); assert_eq!( - tags.key_value().value, + KeyValue::from(tags).value, Value::Array(Array::String(vec!["tag".into()])) ); } diff --git a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs index 3315e9a..1a6121a 100644 --- a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs +++ b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs @@ -6,10 +6,6 @@ pub struct KeptAttr(String); #[allow(deprecated)] impl KeptAttr { pub const KEY: &'static str = "demo.kept"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,7 +24,7 @@ impl From<&str> for KeptAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: KeptAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(KeptAttr::KEY, value.0) } } /// Synthetic mode. @@ -41,18 +37,14 @@ pub enum ModeAttr { #[allow(deprecated)] impl ModeAttr { pub const KEY: &'static str = "demo.mode"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Kept => "kept".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: ModeAttr) -> Self { - value.key_value() + let value: String = match value { + ModeAttr::Kept => "kept".into(), + }; + ::opentelemetry::KeyValue::new(ModeAttr::KEY, value) } } diff --git a/templates/code/rust/tests/codegen_exclusion/test.rs b/templates/code/rust/tests/codegen_exclusion/test.rs index fe7148d..9ba5c22 100644 --- a/templates/code/rust/tests/codegen_exclusion/test.rs +++ b/templates/code/rust/tests/codegen_exclusion/test.rs @@ -3,11 +3,11 @@ use opentelemetry::KeyValue; #[test] fn explicit_false_keeps_attributes_and_enum_members() { assert_eq!( - KeptAttr::from("value").key_value(), + KeyValue::from(KeptAttr::from("value")), KeyValue::new("demo.kept", "value") ); assert_eq!( - ModeAttr::Kept.key_value(), + KeyValue::from(ModeAttr::Kept), KeyValue::new("demo.mode", "kept") ); } diff --git a/templates/code/rust/tests/entities/expected/myappattr.rs b/templates/code/rust/tests/entities/expected/myappattr.rs index 3a1c29d..714adf5 100644 --- a/templates/code/rust/tests/entities/expected/myappattr.rs +++ b/templates/code/rust/tests/entities/expected/myappattr.rs @@ -7,10 +7,6 @@ pub struct HostCpuCountAttr(i64); #[allow(deprecated)] impl HostCpuCountAttr { pub const KEY: &'static str = "myapp.host.cpu.count"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -23,7 +19,7 @@ impl From for HostCpuCountAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostCpuCountAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(HostCpuCountAttr::KEY, value.0) } } /// Name of the host. @@ -33,10 +29,6 @@ pub struct HostNameAttr(String); #[allow(deprecated)] impl HostNameAttr { pub const KEY: &'static str = "myapp.host.name"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -55,7 +47,7 @@ impl From<&str> for HostNameAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostNameAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(HostNameAttr::KEY, value.0) } } /// Role the host plays in the cluster. @@ -65,10 +57,6 @@ pub struct HostRoleAttr(String); #[allow(deprecated)] impl HostRoleAttr { pub const KEY: &'static str = "myapp.host.role"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -87,7 +75,7 @@ impl From<&str> for HostRoleAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostRoleAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(HostRoleAttr::KEY, value.0) } } /// Type of the host. @@ -102,20 +90,16 @@ pub enum HostTypeAttr { #[allow(deprecated)] impl HostTypeAttr { pub const KEY: &'static str = "myapp.host.type"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Physical => "physical".into(), - Self::Virtual => "virtual".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostTypeAttr) -> Self { - value.key_value() + let value: String = match value { + HostTypeAttr::Physical => "physical".into(), + HostTypeAttr::Virtual => "virtual".into(), + }; + ::opentelemetry::KeyValue::new(HostTypeAttr::KEY, value) } } /// Name of the queue. @@ -125,10 +109,6 @@ pub struct QueueNameAttr(String); #[allow(deprecated)] impl QueueNameAttr { pub const KEY: &'static str = "myapp.queue.name"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -147,7 +127,7 @@ impl From<&str> for QueueNameAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: QueueNameAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(QueueNameAttr::KEY, value.0) } } /// Number of items currently in the queue. @@ -157,10 +137,6 @@ pub struct QueueSizeAttr(i64); #[allow(deprecated)] impl QueueSizeAttr { pub const KEY: &'static str = "myapp.queue.size"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -173,6 +149,6 @@ impl From for QueueSizeAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: QueueSizeAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(QueueSizeAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/entities/expected/myappentity.rs b/templates/code/rust/tests/entities/expected/myappentity.rs index 57f28e2..de36304 100644 --- a/templates/code/rust/tests/entities/expected/myappentity.rs +++ b/templates/code/rust/tests/entities/expected/myappentity.rs @@ -7,11 +7,11 @@ pub enum HostEntityAttr { HostType(super::myappattr::HostTypeAttr), } -impl HostEntityAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::HostCpuCount(value) => value.key_value(), - Self::HostType(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: HostEntityAttr) -> Self { + match value { + HostEntityAttr::HostCpuCount(value) => ::opentelemetry::KeyValue::from(value), + HostEntityAttr::HostType(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -28,9 +28,9 @@ pub struct HostEntity { impl HostEntity { pub fn new(r#myapp_host_name: super::myappattr::HostNameAttr, options: impl IntoIterator) -> Self { let mut attributes = vec![ - r#myapp_host_name.key_value(), + ::opentelemetry::KeyValue::from(r#myapp_host_name), ]; - attributes.extend(options.into_iter().map(HostEntityAttr::key_value)); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); Self { attributes } } @@ -51,11 +51,11 @@ pub enum HostWorkerEntityAttr { HostType(super::myappattr::HostTypeAttr), } -impl HostWorkerEntityAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::HostCpuCount(value) => value.key_value(), - Self::HostType(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: HostWorkerEntityAttr) -> Self { + match value { + HostWorkerEntityAttr::HostCpuCount(value) => ::opentelemetry::KeyValue::from(value), + HostWorkerEntityAttr::HostType(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -73,10 +73,10 @@ pub struct HostWorkerEntity { impl HostWorkerEntity { pub fn new(r#myapp_host_name: super::myappattr::HostNameAttr, r#myapp_host_role: super::myappattr::HostRoleAttr, options: impl IntoIterator) -> Self { let mut attributes = vec![ - r#myapp_host_name.key_value(), - r#myapp_host_role.key_value(), + ::opentelemetry::KeyValue::from(r#myapp_host_name), + ::opentelemetry::KeyValue::from(r#myapp_host_role), ]; - attributes.extend(options.into_iter().map(HostWorkerEntityAttr::key_value)); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); Self { attributes } } @@ -95,10 +95,10 @@ pub enum QueueEntityAttr { QueueSize(super::myappattr::QueueSizeAttr), } -impl QueueEntityAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::QueueSize(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: QueueEntityAttr) -> Self { + match value { + QueueEntityAttr::QueueSize(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -113,9 +113,9 @@ pub struct QueueEntity { impl QueueEntity { pub fn new(r#myapp_queue_name: super::myappattr::QueueNameAttr, options: impl IntoIterator) -> Self { let mut attributes = vec![ - r#myapp_queue_name.key_value(), + ::opentelemetry::KeyValue::from(r#myapp_queue_name), ]; - attributes.extend(options.into_iter().map(QueueEntityAttr::key_value)); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); Self { attributes } } diff --git a/templates/code/rust/tests/events/expected/myappattr.rs b/templates/code/rust/tests/events/expected/myappattr.rs index 20e55b9..594e302 100644 --- a/templates/code/rust/tests/events/expected/myappattr.rs +++ b/templates/code/rust/tests/events/expected/myappattr.rs @@ -6,10 +6,6 @@ pub struct BoolValuesAttr(Vec); #[allow(deprecated)] impl BoolValuesAttr { pub const KEY: &'static str = "myapp.bool.values"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(self.0))) - } } #[allow(deprecated)] @@ -22,7 +18,7 @@ impl From> for BoolValuesAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: BoolValuesAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(BoolValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(value.0))) } } /// Synthetic double values. @@ -32,10 +28,6 @@ pub struct DoubleValuesAttr(Vec); #[allow(deprecated)] impl DoubleValuesAttr { pub const KEY: &'static str = "myapp.double.values"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(self.0))) - } } #[allow(deprecated)] @@ -48,7 +40,7 @@ impl From> for DoubleValuesAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: DoubleValuesAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(DoubleValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(value.0))) } } /// Synthetic int values. @@ -58,10 +50,6 @@ pub struct IntValuesAttr(Vec); #[allow(deprecated)] impl IntValuesAttr { pub const KEY: &'static str = "myapp.int.values"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) - } } #[allow(deprecated)] @@ -74,7 +62,7 @@ impl From> for IntValuesAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: IntValuesAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(IntValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) } } /// Synthetic string values. @@ -84,10 +72,6 @@ pub struct StringValuesAttr(Vec); #[allow(deprecated)] impl StringValuesAttr { pub const KEY: &'static str = "myapp.string.values"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) - } } #[allow(deprecated)] @@ -100,7 +84,7 @@ impl From> for StringValuesAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: StringValuesAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(StringValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0.into_iter().map(Into::into).collect()))) } } /// Number of the attempt, starting at 1. @@ -110,10 +94,6 @@ pub struct TaskAttemptAttr(i64); #[allow(deprecated)] impl TaskAttemptAttr { pub const KEY: &'static str = "myapp.task.attempt"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -126,7 +106,7 @@ impl From for TaskAttemptAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskAttemptAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskAttemptAttr::KEY, value.0) } } /// Current state of the task. @@ -141,19 +121,15 @@ pub enum TaskStateAttr { #[allow(deprecated)] impl TaskStateAttr { pub const KEY: &'static str = "myapp.task.state"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Done => "done".into(), - Self::Failed => "failed".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskStateAttr) -> Self { - value.key_value() + let value: String = match value { + TaskStateAttr::Done => "done".into(), + TaskStateAttr::Failed => "failed".into(), + }; + ::opentelemetry::KeyValue::new(TaskStateAttr::KEY, value) } } diff --git a/templates/code/rust/tests/events/expected/myappevent.rs b/templates/code/rust/tests/events/expected/myappevent.rs index fd83424..7377b7d 100644 --- a/templates/code/rust/tests/events/expected/myappevent.rs +++ b/templates/code/rust/tests/events/expected/myappevent.rs @@ -21,17 +21,17 @@ pub fn r#emit_task_finished(context: &::opente let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let mut attributes: Vec<::opentelemetry::KeyValue> = vec![r#myapp_task_state.key_value()]; + let mut attributes: Vec<::opentelemetry::KeyValue> = vec![::opentelemetry::KeyValue::from(r#myapp_task_state)]; for option in options { match option { TaskFinishedOption::Severity(value) => severity = value, TaskFinishedOption::Timestamp(value) => timestamp = Some(value), - TaskFinishedOption::BoolValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::DoubleValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::IntValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::StringValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::TaskAttempt(value) => attributes.push(value.key_value()), - TaskFinishedOption::HostName(value) => attributes.push(value.key_value()), + TaskFinishedOption::BoolValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), + TaskFinishedOption::DoubleValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), + TaskFinishedOption::IntValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), + TaskFinishedOption::StringValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), + TaskFinishedOption::TaskAttempt(value) => attributes.push(::opentelemetry::KeyValue::from(value)), + TaskFinishedOption::HostName(value) => attributes.push(::opentelemetry::KeyValue::from(value)), } } if !logger.inner().event_enabled(severity, "", Some("myapp.task.finished")) { return; } @@ -60,7 +60,7 @@ pub fn r#emit_task_retried(context: &::opentel let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let attributes: Vec<::opentelemetry::KeyValue> = vec![r#myapp_task_attempt.key_value()]; + let attributes: Vec<::opentelemetry::KeyValue> = vec![::opentelemetry::KeyValue::from(r#myapp_task_attempt)]; for option in options { match option { TaskRetriedOption::Severity(value) => severity = value, diff --git a/templates/code/rust/tests/events/expected/workerattr.rs b/templates/code/rust/tests/events/expected/workerattr.rs index b2b1b5f..a3521b2 100644 --- a/templates/code/rust/tests/events/expected/workerattr.rs +++ b/templates/code/rust/tests/events/expected/workerattr.rs @@ -6,10 +6,6 @@ pub struct HostNameAttr(String); #[allow(deprecated)] impl HostNameAttr { pub const KEY: &'static str = "worker.host.name"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,6 +24,6 @@ impl From<&str> for HostNameAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostNameAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(HostNameAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/events/expected/workerevent.rs b/templates/code/rust/tests/events/expected/workerevent.rs index 32e5a5a..cff32ca 100644 --- a/templates/code/rust/tests/events/expected/workerevent.rs +++ b/templates/code/rust/tests/events/expected/workerevent.rs @@ -50,16 +50,16 @@ pub fn r#emit_task_finished(context: &::opente let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let mut attributes: Vec<::opentelemetry::KeyValue> = vec![r#myapp_task_state.key_value(), r#worker_host_name.key_value()]; + let mut attributes: Vec<::opentelemetry::KeyValue> = vec![::opentelemetry::KeyValue::from(r#myapp_task_state), ::opentelemetry::KeyValue::from(r#worker_host_name)]; for option in options { match option { TaskFinishedOption::Severity(value) => severity = value, TaskFinishedOption::Timestamp(value) => timestamp = Some(value), - TaskFinishedOption::BoolValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::DoubleValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::IntValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::StringValues(value) => attributes.push(value.key_value()), - TaskFinishedOption::TaskAttempt(value) => attributes.push(value.key_value()), + TaskFinishedOption::BoolValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), + TaskFinishedOption::DoubleValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), + TaskFinishedOption::IntValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), + TaskFinishedOption::StringValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), + TaskFinishedOption::TaskAttempt(value) => attributes.push(::opentelemetry::KeyValue::from(value)), } } if !logger.inner().event_enabled(severity, "", Some("worker.task.finished")) { return; } diff --git a/templates/code/rust/tests/filtering/expected/authattr.rs b/templates/code/rust/tests/filtering/expected/authattr.rs index 98dfefc..4c02410 100644 --- a/templates/code/rust/tests/filtering/expected/authattr.rs +++ b/templates/code/rust/tests/filtering/expected/authattr.rs @@ -11,20 +11,16 @@ pub enum MethodAttr { #[allow(deprecated)] impl MethodAttr { pub const KEY: &'static str = "auth.method"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Password => "password".into(), - Self::Token => "token".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: MethodAttr) -> Self { - value.key_value() + let value: String = match value { + MethodAttr::Password => "password".into(), + MethodAttr::Token => "token".into(), + }; + ::opentelemetry::KeyValue::new(MethodAttr::KEY, value) } } /// Identifier of the authenticated user. @@ -34,10 +30,6 @@ pub struct UserIdAttr(String); #[allow(deprecated)] impl UserIdAttr { pub const KEY: &'static str = "auth.user.id"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -56,6 +48,6 @@ impl From<&str> for UserIdAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: UserIdAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(UserIdAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/filtering/expected/taskattr.rs b/templates/code/rust/tests/filtering/expected/taskattr.rs index 28cf123..39f6f5d 100644 --- a/templates/code/rust/tests/filtering/expected/taskattr.rs +++ b/templates/code/rust/tests/filtering/expected/taskattr.rs @@ -8,10 +8,6 @@ pub struct AssignedByAttr(String); #[allow(deprecated)] impl AssignedByAttr { pub const KEY: &'static str = "myapp.task.assigned_by"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -30,7 +26,7 @@ impl From<&str> for AssignedByAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: AssignedByAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(AssignedByAttr::KEY, value.0) } } /// Whether the task was cancelled. @@ -40,10 +36,6 @@ pub struct CancelledAttr(bool); #[allow(deprecated)] impl CancelledAttr { pub const KEY: &'static str = "myapp.task.cancelled"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -56,7 +48,7 @@ impl From for CancelledAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: CancelledAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(CancelledAttr::KEY, value.0) } } /// Unique identifier of the task. @@ -68,10 +60,6 @@ pub struct IdAttr(String); #[allow(deprecated)] impl IdAttr { pub const KEY: &'static str = "myapp.task.id"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -90,7 +78,7 @@ impl From<&str> for IdAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: IdAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(IdAttr::KEY, value.0) } } /// Whether the scheduler may preempt the task. @@ -105,20 +93,16 @@ pub enum PreemptibleAttr { #[allow(deprecated)] impl PreemptibleAttr { pub const KEY: &'static str = "myapp.task.preemptible"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: bool = match self { - Self::Allowed => true, - Self::Forbidden => false, - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: PreemptibleAttr) -> Self { - value.key_value() + let value: bool = match value { + PreemptibleAttr::Allowed => true, + PreemptibleAttr::Forbidden => false, + }; + ::opentelemetry::KeyValue::new(PreemptibleAttr::KEY, value) } } /// Number of times the task was retried. @@ -128,10 +112,6 @@ pub struct RetriesAttr(i64); #[allow(deprecated)] impl RetriesAttr { pub const KEY: &'static str = "myapp.task.retries"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -144,7 +124,7 @@ impl From for RetriesAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: RetriesAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(RetriesAttr::KEY, value.0) } } /// Fraction of tasks whose telemetry is sampled. @@ -159,20 +139,16 @@ pub enum SampleRateAttr { #[allow(deprecated)] impl SampleRateAttr { pub const KEY: &'static str = "myapp.task.sample_rate"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: f64 = match self { - Self::Tenth => 0.1_f64, - Self::All => 1_f64, - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: SampleRateAttr) -> Self { - value.key_value() + let value: f64 = match value { + SampleRateAttr::Tenth => 0.1_f64, + SampleRateAttr::All => 1_f64, + }; + ::opentelemetry::KeyValue::new(SampleRateAttr::KEY, value) } } /// Shards the task touched. @@ -182,10 +158,6 @@ pub struct ShardIdsAttr(Vec); #[allow(deprecated)] impl ShardIdsAttr { pub const KEY: &'static str = "myapp.task.shard_ids"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(self.0))) - } } #[allow(deprecated)] @@ -198,7 +170,7 @@ impl From> for ShardIdsAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: ShardIdsAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(ShardIdsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) } } /// Current state of the task. @@ -215,20 +187,16 @@ pub enum StateAttr { #[allow(deprecated)] impl StateAttr { pub const KEY: &'static str = "myapp.task.state"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Queued => "queued".into(), - Self::Running => "running".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: StateAttr) -> Self { - value.key_value() + let value: String = match value { + StateAttr::Queued => "queued".into(), + StateAttr::Running => "running".into(), + }; + ::opentelemetry::KeyValue::new(StateAttr::KEY, value) } } /// Tags attached to the task. @@ -238,10 +206,6 @@ pub struct TagsAttr(Vec); #[allow(deprecated)] impl TagsAttr { pub const KEY: &'static str = "myapp.task.tags"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(self.0.into_iter().map(Into::into).collect()))) - } } #[allow(deprecated)] @@ -254,6 +218,6 @@ impl From> for TagsAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TagsAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0.into_iter().map(Into::into).collect()))) } } diff --git a/templates/code/rust/tests/filtering/test.rs b/templates/code/rust/tests/filtering/test.rs index 6291169..8ee0762 100644 --- a/templates/code/rust/tests/filtering/test.rs +++ b/templates/code/rust/tests/filtering/test.rs @@ -4,11 +4,11 @@ use opentelemetry::{KeyValue, Value}; #[test] fn vendor_prefix_changes_types_but_preserves_telemetry_keys() { assert_eq!( - IdAttr::from("task").key_value(), + ::opentelemetry::KeyValue::from(IdAttr::from("task")), KeyValue::new("myapp.task.id", "task") ); assert_eq!( - StateAttr::Queued.key_value().value, + ::opentelemetry::KeyValue::from(StateAttr::Queued).value, Value::String("queued".into()) ); } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs index 89bc164..3b1f7f5 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs @@ -6,10 +6,6 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,6 +24,6 @@ impl From<&str> for TaskIdAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs index 7aabf28..2f8d42e 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs @@ -11,7 +11,7 @@ impl TaskDurationHistogram { .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { - let attributes = vec![r#myapp_task_id.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; self.instrument.record(value, &attributes); } } @@ -30,7 +30,7 @@ impl TaskLatencyHistogram { .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { - let attributes = vec![r#myapp_task_id.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; self.instrument.record(value, &attributes); } } @@ -49,7 +49,7 @@ impl TaskRetryDurationHistogram { .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { - let attributes = vec![r#myapp_task_id.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; self.instrument.record(value, &attributes); } } @@ -67,7 +67,7 @@ impl TaskSizeHistogram { .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { - let attributes = vec![r#myapp_task_id.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; self.instrument.record(value, &attributes); } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs index 89bc164..3b1f7f5 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs @@ -6,10 +6,6 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,6 +24,6 @@ impl From<&str> for TaskIdAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs index fc27488..be6b988 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs @@ -10,7 +10,7 @@ impl TaskDurationHistogram { .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { - let attributes = vec![r#myapp_task_id.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; self.instrument.record(value, &attributes); } } @@ -29,7 +29,7 @@ impl TaskQueueWaitHistogram { .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { - let attributes = vec![r#myapp_task_id.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; self.instrument.record(value, &attributes); } } diff --git a/templates/code/rust/tests/imported/expected/edgemetric.rs b/templates/code/rust/tests/imported/expected/edgemetric.rs index 8388614..1bb88d0 100644 --- a/templates/code/rust/tests/imported/expected/edgemetric.rs +++ b/templates/code/rust/tests/imported/expected/edgemetric.rs @@ -3,10 +3,10 @@ pub enum UpstreamDurationHistogramAttr { ServerPort(i64), } -impl UpstreamDurationHistogramAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), +impl From for ::opentelemetry::KeyValue { + fn from(value: UpstreamDurationHistogramAttr) -> Self { + match value { + UpstreamDurationHistogramAttr::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), } } } @@ -23,7 +23,7 @@ impl UpstreamDurationHistogram { } pub fn record(&self, value: f64, r#server_address: String, options: impl IntoIterator) { let mut attributes = vec![::opentelemetry::KeyValue::new("server.address", r#server_address)]; - attributes.extend(options.into_iter().map(UpstreamDurationHistogramAttr::key_value)); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.record(value, &attributes); } } diff --git a/templates/code/rust/tests/imported/expected/edgespan.rs b/templates/code/rust/tests/imported/expected/edgespan.rs index 70a3cbb..7d7661d 100644 --- a/templates/code/rust/tests/imported/expected/edgespan.rs +++ b/templates/code/rust/tests/imported/expected/edgespan.rs @@ -5,11 +5,11 @@ pub enum UpstreamRequestStartAttr { ErrorType(String), HttpRequestMethodList(Vec), } -impl UpstreamRequestStartAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::ErrorType(value) => ::opentelemetry::KeyValue::new("error.type", value), - Self::HttpRequestMethodList(value) => ::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.into_iter().map(Into::into).collect()))), +impl From for ::opentelemetry::KeyValue { + fn from(value: UpstreamRequestStartAttr) -> Self { + match value { + UpstreamRequestStartAttr::ErrorType(value) => ::opentelemetry::KeyValue::new("error.type", value), + UpstreamRequestStartAttr::HttpRequestMethodList(value) => ::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.into_iter().map(Into::into).collect()))), } } } @@ -37,7 +37,7 @@ impl UpstreamRequestSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } pub fn set_attributes(&mut self, attributes: impl IntoIterator) { - for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, UpstreamRequestStartAttr::from(attribute).key_value()); } + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from(UpstreamRequestStartAttr::from(attribute))); } } } impl Default for UpstreamRequestSpan { @@ -54,7 +54,7 @@ pub fn r#start_upstream_request(context: &::opentelemetry::Context, tracer: &sup name.push(':'); name.push_str(&::opentelemetry::KeyValue::new("server.port", r#server_port).value.to_string()); let mut attributes = vec![::opentelemetry::KeyValue::new("server.address", r#server_address), ::opentelemetry::KeyValue::new("server.port", r#server_port)]; - attributes.extend(options.into_iter().map(UpstreamRequestStartAttr::key_value)); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Client) .with_attributes(attributes) diff --git a/templates/code/rust/tests/imported/expected/myappattr.rs b/templates/code/rust/tests/imported/expected/myappattr.rs index 89bc164..3b1f7f5 100644 --- a/templates/code/rust/tests/imported/expected/myappattr.rs +++ b/templates/code/rust/tests/imported/expected/myappattr.rs @@ -6,10 +6,6 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,6 +24,6 @@ impl From<&str> for TaskIdAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/imported/expected/myappmetric.rs b/templates/code/rust/tests/imported/expected/myappmetric.rs index 46fec37..47a7e48 100644 --- a/templates/code/rust/tests/imported/expected/myappmetric.rs +++ b/templates/code/rust/tests/imported/expected/myappmetric.rs @@ -3,10 +3,10 @@ pub enum TaskFailedCounterAttr { HttpRequestMethodList(Vec), } -impl TaskFailedCounterAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::HttpRequestMethodList(value) => ::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.into_iter().map(Into::into).collect()))), +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskFailedCounterAttr) -> Self { + match value { + TaskFailedCounterAttr::HttpRequestMethodList(value) => ::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.into_iter().map(Into::into).collect()))), } } } @@ -21,8 +21,8 @@ impl TaskFailedCounter { .build() } } pub fn add(&self, value: u64, r#error_type: String, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { - let mut attributes = vec![::opentelemetry::KeyValue::new("error.type", r#error_type), r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskFailedCounterAttr::key_value)); + let mut attributes = vec![::opentelemetry::KeyValue::new("error.type", r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.add(value, &attributes); } } @@ -32,8 +32,8 @@ impl Default for TaskFailedCounter { pub struct TaskFailedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskFailedCounterObserver<'_> { pub fn observe(&self, value: u64, r#error_type: String, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { - let mut attributes = vec![::opentelemetry::KeyValue::new("error.type", r#error_type), r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskFailedCounterAttr::key_value)); + let mut attributes = vec![::opentelemetry::KeyValue::new("error.type", r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.observer.observe(value, &attributes); } } diff --git a/templates/code/rust/tests/imported_typed/expected/myappattr.rs b/templates/code/rust/tests/imported_typed/expected/myappattr.rs index 89bc164..3b1f7f5 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappattr.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappattr.rs @@ -6,10 +6,6 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,6 +24,6 @@ impl From<&str> for TaskIdAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/imported_typed/expected/myappevent.rs b/templates/code/rust/tests/imported_typed/expected/myappevent.rs index ba2f3b9..145705c 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappevent.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappevent.rs @@ -12,7 +12,7 @@ pub fn r#emit_task_errored(context: &::opentel let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let mut attributes: Vec<::opentelemetry::KeyValue> = vec![r#error_type.key_value()]; + let mut attributes: Vec<::opentelemetry::KeyValue> = vec![::opentelemetry::KeyValue::from(r#error_type)]; for option in options { match option { TaskErroredOption::Severity(value) => severity = value, diff --git a/templates/code/rust/tests/imported_typed/expected/myappmetric.rs b/templates/code/rust/tests/imported_typed/expected/myappmetric.rs index 0baba9e..2694242 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappmetric.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappmetric.rs @@ -3,10 +3,10 @@ pub enum TaskFailedCounterAttr { ServerPort(i64), } -impl TaskFailedCounterAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskFailedCounterAttr) -> Self { + match value { + TaskFailedCounterAttr::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), } } } @@ -21,8 +21,8 @@ impl TaskFailedCounter { .build() } } pub fn add(&self, value: u64, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { - let mut attributes = vec![r#error_type.key_value(), r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskFailedCounterAttr::key_value)); + let mut attributes = vec![::opentelemetry::KeyValue::from(r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.add(value, &attributes); } } @@ -32,8 +32,8 @@ impl Default for TaskFailedCounter { pub struct TaskFailedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskFailedCounterObserver<'_> { pub fn observe(&self, value: u64, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { - let mut attributes = vec![r#error_type.key_value(), r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskFailedCounterAttr::key_value)); + let mut attributes = vec![::opentelemetry::KeyValue::from(r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.observer.observe(value, &attributes); } } diff --git a/templates/code/rust/tests/imported_typed/expected/myappspan.rs b/templates/code/rust/tests/imported_typed/expected/myappspan.rs index a7ddbd5..eee4a9b 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappspan.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappspan.rs @@ -3,10 +3,10 @@ pub enum TaskDispatchStartAttr { ServerPort(i64), } -impl TaskDispatchStartAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskDispatchStartAttr) -> Self { + match value { + TaskDispatchStartAttr::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), } } } @@ -34,7 +34,7 @@ impl TaskDispatchSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } pub fn set_attributes(&mut self, attributes: impl IntoIterator) { - for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, TaskDispatchStartAttr::from(attribute).key_value()); } + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from(TaskDispatchStartAttr::from(attribute))); } } } impl Default for TaskDispatchSpan { @@ -48,11 +48,11 @@ pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super: use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push_str("task "); - name.push_str(&r#myapp_task_id.clone().key_value().value.to_string()); + name.push_str(&::opentelemetry::KeyValue::from(r#myapp_task_id.clone()).value.to_string()); name.push_str(" failed with "); - name.push_str(&r#error_type.key_value().value.to_string()); - let mut attributes = vec![r#error_type.key_value(), r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskDispatchStartAttr::key_value)); + name.push_str(&::opentelemetry::KeyValue::from(r#error_type).value.to_string()); + let mut attributes = vec![::opentelemetry::KeyValue::from(r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) diff --git a/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs b/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs index aa3ef6c..28efa9c 100644 --- a/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs +++ b/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs @@ -11,19 +11,15 @@ pub enum BoundaryAttr { #[allow(deprecated)] impl BoundaryAttr { pub const KEY: &'static str = "demo.boundary"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: i64 = match self { - Self::Minimum => -9223372036854775808, - Self::Maximum => 9223372036854775807, - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: BoundaryAttr) -> Self { - value.key_value() + let value: i64 = match value { + BoundaryAttr::Minimum => -9223372036854775808, + BoundaryAttr::Maximum => 9223372036854775807, + }; + ::opentelemetry::KeyValue::new(BoundaryAttr::KEY, value) } } diff --git a/templates/code/rust/tests/integer_boundaries/test.rs b/templates/code/rust/tests/integer_boundaries/test.rs index f6e52b8..c320747 100644 --- a/templates/code/rust/tests/integer_boundaries/test.rs +++ b/templates/code/rust/tests/integer_boundaries/test.rs @@ -3,11 +3,11 @@ use opentelemetry::Value; #[test] fn integer_enum_preserves_signed_64_bit_limits() { assert_eq!( - BoundaryAttr::Minimum.key_value().value, + ::opentelemetry::KeyValue::from(BoundaryAttr::Minimum).value, Value::I64(i64::MIN) ); assert_eq!( - BoundaryAttr::Maximum.key_value().value, + ::opentelemetry::KeyValue::from(BoundaryAttr::Maximum).value, Value::I64(i64::MAX) ); } diff --git a/templates/code/rust/tests/literal_escaping/expected/demoattr.rs b/templates/code/rust/tests/literal_escaping/expected/demoattr.rs index 1500e97..a07ed4d 100644 --- a/templates/code/rust/tests/literal_escaping/expected/demoattr.rs +++ b/templates/code/rust/tests/literal_escaping/expected/demoattr.rs @@ -11,19 +11,15 @@ pub enum LiteralAttr { #[allow(deprecated)] impl LiteralAttr { pub const KEY: &'static str = "demo.literal"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Literal => "backspace\\b formfeed\\f unicode\\u1234 doubled\\\\b tripled\\\\\\u0000".into(), - Self::Controls => "backspace\u{0008} formfeed\u{000c} unicode\u{0001} slash\\b".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: LiteralAttr) -> Self { - value.key_value() + let value: String = match value { + LiteralAttr::Literal => "backspace\\b formfeed\\f unicode\\u1234 doubled\\\\b tripled\\\\\\u0000".into(), + LiteralAttr::Controls => "backspace\u{0008} formfeed\u{000c} unicode\u{0001} slash\\b".into(), + }; + ::opentelemetry::KeyValue::new(LiteralAttr::KEY, value) } } diff --git a/templates/code/rust/tests/literal_escaping/expected/demometric.rs b/templates/code/rust/tests/literal_escaping/expected/demometric.rs index 9d4b3cb..e84fc8c 100644 --- a/templates/code/rust/tests/literal_escaping/expected/demometric.rs +++ b/templates/code/rust/tests/literal_escaping/expected/demometric.rs @@ -10,7 +10,7 @@ impl LiteralCountCounter { .build() } } pub fn add(&self, value: u64, r#demo_literal: super::demoattr::LiteralAttr) { - let attributes = vec![r#demo_literal.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#demo_literal)]; self.instrument.add(value, &attributes); } } @@ -20,7 +20,7 @@ impl Default for LiteralCountCounter { pub struct LiteralCountCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl LiteralCountCounterObserver<'_> { pub fn observe(&self, value: u64, r#demo_literal: super::demoattr::LiteralAttr) { - let attributes = vec![r#demo_literal.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#demo_literal)]; self.observer.observe(value, &attributes); } } diff --git a/templates/code/rust/tests/literal_escaping/test.rs b/templates/code/rust/tests/literal_escaping/test.rs index 9d57b39..ff04712 100644 --- a/templates/code/rust/tests/literal_escaping/test.rs +++ b/templates/code/rust/tests/literal_escaping/test.rs @@ -3,11 +3,11 @@ use opentelemetry::Value; #[test] fn literal_backslashes_and_actual_control_characters_are_distinct() { assert_eq!( - LiteralAttr::Literal.key_value().value, + ::opentelemetry::KeyValue::from(LiteralAttr::Literal).value, Value::String(r"backspace\b formfeed\f unicode\u1234 doubled\\b tripled\\\u0000".into()) ); assert_eq!( - LiteralAttr::Controls.key_value().value, + ::opentelemetry::KeyValue::from(LiteralAttr::Controls).value, Value::String("backspace\u{0008} formfeed\u{000c} unicode\u{0001} slash\\b".into()) ); } diff --git a/templates/code/rust/tests/metrics/expected/authattr.rs b/templates/code/rust/tests/metrics/expected/authattr.rs index bb93c31..acbcc1a 100644 --- a/templates/code/rust/tests/metrics/expected/authattr.rs +++ b/templates/code/rust/tests/metrics/expected/authattr.rs @@ -11,20 +11,16 @@ pub enum MethodAttr { #[allow(deprecated)] impl MethodAttr { pub const KEY: &'static str = "auth.method"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Password => "password".into(), - Self::Token => "token".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: MethodAttr) -> Self { - value.key_value() + let value: String = match value { + MethodAttr::Password => "password".into(), + MethodAttr::Token => "token".into(), + }; + ::opentelemetry::KeyValue::new(MethodAttr::KEY, value) } } /// Whether the attempt succeeded. @@ -34,10 +30,6 @@ pub struct SuccessAttr(bool); #[allow(deprecated)] impl SuccessAttr { pub const KEY: &'static str = "auth.success"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -50,6 +42,6 @@ impl From for SuccessAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: SuccessAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(SuccessAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/metrics/expected/authmetric.rs b/templates/code/rust/tests/metrics/expected/authmetric.rs index 7567d6c..3bd980d 100644 --- a/templates/code/rust/tests/metrics/expected/authmetric.rs +++ b/templates/code/rust/tests/metrics/expected/authmetric.rs @@ -10,7 +10,7 @@ impl AttemptsCounter { .build() } } pub fn add(&self, value: u64, r#auth_method: super::authattr::MethodAttr, r#auth_success: super::authattr::SuccessAttr) { - let attributes = vec![r#auth_method.key_value(), r#auth_success.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#auth_method), ::opentelemetry::KeyValue::from(r#auth_success)]; self.instrument.add(value, &attributes); } } @@ -20,7 +20,7 @@ impl Default for AttemptsCounter { pub struct AttemptsCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl AttemptsCounterObserver<'_> { pub fn observe(&self, value: u64, r#auth_method: super::authattr::MethodAttr, r#auth_success: super::authattr::SuccessAttr) { - let attributes = vec![r#auth_method.key_value(), r#auth_success.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#auth_method), ::opentelemetry::KeyValue::from(r#auth_success)]; self.observer.observe(value, &attributes); } } diff --git a/templates/code/rust/tests/metrics/expected/myappattr.rs b/templates/code/rust/tests/metrics/expected/myappattr.rs index e0d37b5..b327b3b 100644 --- a/templates/code/rust/tests/metrics/expected/myappattr.rs +++ b/templates/code/rust/tests/metrics/expected/myappattr.rs @@ -6,10 +6,6 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,7 +24,7 @@ impl From<&str> for TaskIdAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } /// Current state of the task. @@ -43,19 +39,15 @@ pub enum TaskStateAttr { #[allow(deprecated)] impl TaskStateAttr { pub const KEY: &'static str = "myapp.task.state"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Queued => "queued".into(), - Self::Done => "done".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskStateAttr) -> Self { - value.key_value() + let value: String = match value { + TaskStateAttr::Queued => "queued".into(), + TaskStateAttr::Done => "done".into(), + }; + ::opentelemetry::KeyValue::new(TaskStateAttr::KEY, value) } } diff --git a/templates/code/rust/tests/metrics/expected/myappmetric.rs b/templates/code/rust/tests/metrics/expected/myappmetric.rs index 386e8f5..008c8fe 100644 --- a/templates/code/rust/tests/metrics/expected/myappmetric.rs +++ b/templates/code/rust/tests/metrics/expected/myappmetric.rs @@ -51,7 +51,7 @@ impl TaskActiveUpDownCounter { .build() } } pub fn add(&self, value: i64, r#myapp_task_state: super::myappattr::TaskStateAttr) { - let attributes = vec![r#myapp_task_state.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_state)]; self.instrument.add(value, &attributes); } } @@ -61,7 +61,7 @@ impl Default for TaskActiveUpDownCounter { pub struct TaskActiveUpDownCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskActiveUpDownCounterObserver<'_> { pub fn observe(&self, value: i64, r#myapp_task_state: super::myappattr::TaskStateAttr) { - let attributes = vec![r#myapp_task_state.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_state)]; self.observer.observe(value, &attributes); } } @@ -87,11 +87,11 @@ pub enum TaskDurationHistogramAttr { /// Conditionally required: If the task reached a final state. TaskState(super::myappattr::TaskStateAttr), } -impl TaskDurationHistogramAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::Method(value) => value.key_value(), - Self::TaskState(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskDurationHistogramAttr) -> Self { + match value { + TaskDurationHistogramAttr::Method(value) => ::opentelemetry::KeyValue::from(value), + TaskDurationHistogramAttr::TaskState(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -109,8 +109,8 @@ impl TaskDurationHistogram { .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { - let mut attributes = vec![r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskDurationHistogramAttr::key_value)); + let mut attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.record(value, &attributes); } } @@ -261,10 +261,10 @@ pub enum TaskRetryDurationHistogramAttr { /// Opt-in: the convention records it only when a user asks for it. Method(super::authattr::MethodAttr), } -impl TaskRetryDurationHistogramAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::Method(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskRetryDurationHistogramAttr) -> Self { + match value { + TaskRetryDurationHistogramAttr::Method(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -282,8 +282,8 @@ impl TaskRetryDurationHistogram { .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) { - let mut attributes = vec![r#myapp_task_id.key_value(), r#myapp_task_state.key_value()]; - attributes.extend(options.into_iter().map(TaskRetryDurationHistogramAttr::key_value)); + let mut attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id), ::opentelemetry::KeyValue::from(r#myapp_task_state)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.record(value, &attributes); } } @@ -295,10 +295,10 @@ pub enum TaskStartedCounterAttr { /// Recommended: When the scheduler assigned an id before the task started. TaskId(super::myappattr::TaskIdAttr), } -impl TaskStartedCounterAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::TaskId(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskStartedCounterAttr) -> Self { + match value { + TaskStartedCounterAttr::TaskId(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -315,7 +315,7 @@ impl TaskStartedCounter { } pub fn add(&self, value: u64, options: impl IntoIterator) { let mut attributes = vec![]; - attributes.extend(options.into_iter().map(TaskStartedCounterAttr::key_value)); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.add(value, &attributes); } } @@ -326,7 +326,7 @@ pub struct TaskStartedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::m impl TaskStartedCounterObserver<'_> { pub fn observe(&self, value: u64, options: impl IntoIterator) { let mut attributes = vec![]; - attributes.extend(options.into_iter().map(TaskStartedCounterAttr::key_value)); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.observer.observe(value, &attributes); } } diff --git a/templates/code/rust/tests/metrics/expected/workermetric.rs b/templates/code/rust/tests/metrics/expected/workermetric.rs index 3d2472b..88dc405 100644 --- a/templates/code/rust/tests/metrics/expected/workermetric.rs +++ b/templates/code/rust/tests/metrics/expected/workermetric.rs @@ -6,11 +6,11 @@ pub enum TaskDurationHistogramAttr { /// Conditionally required: If the task reached a final state. TaskState(super::myappattr::TaskStateAttr), } -impl TaskDurationHistogramAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::Method(value) => value.key_value(), - Self::TaskState(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskDurationHistogramAttr) -> Self { + match value { + TaskDurationHistogramAttr::Method(value) => ::opentelemetry::KeyValue::from(value), + TaskDurationHistogramAttr::TaskState(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -28,8 +28,8 @@ impl TaskDurationHistogram { .build() } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { - let mut attributes = vec![r#myapp_task_id.key_value()]; - attributes.extend(options.into_iter().map(TaskDurationHistogramAttr::key_value)); + let mut attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.record(value, &attributes); } } diff --git a/templates/code/rust/tests/naming/expected/capsattr.rs b/templates/code/rust/tests/naming/expected/capsattr.rs index 3595895..c7f265a 100644 --- a/templates/code/rust/tests/naming/expected/capsattr.rs +++ b/templates/code/rust/tests/naming/expected/capsattr.rs @@ -6,10 +6,6 @@ pub struct Http2STATUSApiIDAttr(String); #[allow(deprecated)] impl Http2STATUSApiIDAttr { pub const KEY: &'static str = "caps.http2_STATUS.api_ID"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,7 +24,7 @@ impl From<&str> for Http2STATUSApiIDAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: Http2STATUSApiIDAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(Http2STATUSApiIDAttr::KEY, value.0) } } /// Synthetic mode. @@ -41,18 +37,14 @@ pub enum Mode2STATEAttr { #[allow(deprecated)] impl Mode2STATEAttr { pub const KEY: &'static str = "caps.mode2_STATE"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::HTTP2ReadySTATE => "ready".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: Mode2STATEAttr) -> Self { - value.key_value() + let value: String = match value { + Mode2STATEAttr::HTTP2ReadySTATE => "ready".into(), + }; + ::opentelemetry::KeyValue::new(Mode2STATEAttr::KEY, value) } } diff --git a/templates/code/rust/tests/naming/expected/capsmetric.rs b/templates/code/rust/tests/naming/expected/capsmetric.rs index 59d3cbb..11b46d0 100644 --- a/templates/code/rust/tests/naming/expected/capsmetric.rs +++ b/templates/code/rust/tests/naming/expected/capsmetric.rs @@ -10,7 +10,7 @@ impl Http2STATUSCountCounter { .build() } } pub fn add(&self, value: u64, r#caps_http2_status_api_id: super::capsattr::Http2STATUSApiIDAttr, r#caps_mode2_state: super::capsattr::Mode2STATEAttr) { - let attributes = vec![r#caps_http2_status_api_id.key_value(), r#caps_mode2_state.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#caps_http2_status_api_id), ::opentelemetry::KeyValue::from(r#caps_mode2_state)]; self.instrument.add(value, &attributes); } } @@ -20,7 +20,7 @@ impl Default for Http2STATUSCountCounter { pub struct Http2STATUSCountCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl Http2STATUSCountCounterObserver<'_> { pub fn observe(&self, value: u64, r#caps_http2_status_api_id: super::capsattr::Http2STATUSApiIDAttr, r#caps_mode2_state: super::capsattr::Mode2STATEAttr) { - let attributes = vec![r#caps_http2_status_api_id.key_value(), r#caps_mode2_state.key_value()]; + let attributes = vec![::opentelemetry::KeyValue::from(r#caps_http2_status_api_id), ::opentelemetry::KeyValue::from(r#caps_mode2_state)]; self.observer.observe(value, &attributes); } } diff --git a/templates/code/rust/tests/naming/test.rs b/templates/code/rust/tests/naming/test.rs index 57187fc..2d31a00 100644 --- a/templates/code/rust/tests/naming/test.rs +++ b/templates/code/rust/tests/naming/test.rs @@ -6,7 +6,7 @@ use opentelemetry::KeyValue; fn names_preserve_capitalization_and_digits_in_attributes_and_signals() { let identifier = capsattr::Http2STATUSApiIDAttr::from("value"); assert_eq!( - identifier.clone().key_value(), + KeyValue::from(identifier.clone()), KeyValue::new("caps.http2_STATUS.api_ID", "value") ); let mode = capsattr::Mode2STATEAttr::HTTP2ReadySTATE; diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs index c638abe..b3982cb 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs @@ -6,10 +6,6 @@ pub struct MessageAttr(String); #[allow(deprecated)] impl MessageAttr { pub const KEY: &'static str = "exception.message"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,7 +24,7 @@ impl From<&str> for MessageAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: MessageAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(MessageAttr::KEY, value.0) } } /// The type of the exception. @@ -38,10 +34,6 @@ pub struct TypeAttr(String); #[allow(deprecated)] impl TypeAttr { pub const KEY: &'static str = "exception.type"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -60,6 +52,6 @@ impl From<&str> for TypeAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TypeAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TypeAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs index 80e8544..21da536 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs @@ -12,12 +12,12 @@ pub fn r#emit_(context: &::opentelemetry::Cont let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let mut attributes: Vec<::opentelemetry::KeyValue> = vec![r#exception_type.key_value()]; + let mut attributes: Vec<::opentelemetry::KeyValue> = vec![::opentelemetry::KeyValue::from(r#exception_type)]; for option in options { match option { Option::Severity(value) => severity = value, Option::Timestamp(value) => timestamp = Some(value), - Option::Message(value) => attributes.push(value.key_value()), + Option::Message(value) => attributes.push(::opentelemetry::KeyValue::from(value)), } } if !logger.inner().event_enabled(severity, "", Some("exception")) { return; } diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs index 966ad8a..7f6e0da 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs @@ -6,10 +6,6 @@ pub struct SequenceAttr(i64); #[allow(deprecated)] impl SequenceAttr { pub const KEY: &'static str = "heartbeat.sequence"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -22,7 +18,7 @@ impl From for SequenceAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: SequenceAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(SequenceAttr::KEY, value.0) } } /// Name of the component that sent the heartbeat. @@ -32,10 +28,6 @@ pub struct SourceAttr(String); #[allow(deprecated)] impl SourceAttr { pub const KEY: &'static str = "heartbeat.source"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -54,6 +46,6 @@ impl From<&str> for SourceAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: SourceAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(SourceAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs index ee1d8e0..fcbf08f 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs @@ -3,10 +3,10 @@ pub enum StartAttr { Source(super::heartbeatattr::SourceAttr), } -impl StartAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::Source(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: StartAttr) -> Self { + match value { + StartAttr::Source(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -39,7 +39,7 @@ impl Span { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } pub fn set_attributes(&mut self, attributes: impl IntoIterator) { - for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, StartAttr::from(attribute).key_value()); } + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from(StartAttr::from(attribute))); } } } impl Default for Span { @@ -52,8 +52,8 @@ impl Default for Span { pub fn r#start_(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: Name, r#heartbeat_sequence: super::heartbeatattr::SequenceAttr, options: impl IntoIterator) -> Span { use ::opentelemetry::trace::Tracer; let name = if name.0.is_empty() { "heartbeat".to_owned() } else { name.0 }; - let mut attributes = vec![r#heartbeat_sequence.key_value()]; - attributes.extend(options.into_iter().map(StartAttr::key_value)); + let mut attributes = vec![::opentelemetry::KeyValue::from(r#heartbeat_sequence)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) diff --git a/templates/code/rust/tests/no_namespace/expected/hostattr.rs b/templates/code/rust/tests/no_namespace/expected/hostattr.rs index f53f9ab..7489472 100644 --- a/templates/code/rust/tests/no_namespace/expected/hostattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/hostattr.rs @@ -6,10 +6,6 @@ pub struct IdAttr(String); #[allow(deprecated)] impl IdAttr { pub const KEY: &'static str = "host.id"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,7 +24,7 @@ impl From<&str> for IdAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: IdAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(IdAttr::KEY, value.0) } } /// Name of the host. @@ -38,10 +34,6 @@ pub struct NameAttr(String); #[allow(deprecated)] impl NameAttr { pub const KEY: &'static str = "host.name"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -60,6 +52,6 @@ impl From<&str> for NameAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: NameAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(NameAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/no_namespace/expected/hostentity.rs b/templates/code/rust/tests/no_namespace/expected/hostentity.rs index 42ded38..62ae58e 100644 --- a/templates/code/rust/tests/no_namespace/expected/hostentity.rs +++ b/templates/code/rust/tests/no_namespace/expected/hostentity.rs @@ -5,10 +5,10 @@ pub enum EntityAttr { Name(super::hostattr::NameAttr), } -impl EntityAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::Name(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: EntityAttr) -> Self { + match value { + EntityAttr::Name(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -23,9 +23,9 @@ pub struct Entity { impl Entity { pub fn new(r#host_id: super::hostattr::IdAttr, options: impl IntoIterator) -> Self { let mut attributes = vec![ - r#host_id.key_value(), + ::opentelemetry::KeyValue::from(r#host_id), ]; - attributes.extend(options.into_iter().map(EntityAttr::key_value)); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); Self { attributes } } diff --git a/templates/code/rust/tests/params/expected/billingattr.rs b/templates/code/rust/tests/params/expected/billingattr.rs index bd61d6f..ca483cf 100644 --- a/templates/code/rust/tests/params/expected/billingattr.rs +++ b/templates/code/rust/tests/params/expected/billingattr.rs @@ -6,10 +6,6 @@ pub struct InvoiceIdAttr(String); #[allow(deprecated)] impl InvoiceIdAttr { pub const KEY: &'static str = "acme.billing.invoice.id"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,7 +24,7 @@ impl From<&str> for InvoiceIdAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: InvoiceIdAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(InvoiceIdAttr::KEY, value.0) } } /// ISO 4217 currency code of the amount. @@ -38,10 +34,6 @@ pub struct CurrencyAttr(String); #[allow(deprecated)] impl CurrencyAttr { pub const KEY: &'static str = "billing.currency"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -60,6 +52,6 @@ impl From<&str> for CurrencyAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: CurrencyAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(CurrencyAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/params/expected/billingmetric.rs b/templates/code/rust/tests/params/expected/billingmetric.rs index 3c436b9..d2bf001 100644 --- a/templates/code/rust/tests/params/expected/billingmetric.rs +++ b/templates/code/rust/tests/params/expected/billingmetric.rs @@ -4,11 +4,11 @@ pub enum InvoiceAmountHistogramAttr { Currency(super::billingattr::CurrencyAttr), RequestUrl(super::myappattr::RequestUrlAttr), } -impl InvoiceAmountHistogramAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::Currency(value) => value.key_value(), - Self::RequestUrl(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: InvoiceAmountHistogramAttr) -> Self { + match value { + InvoiceAmountHistogramAttr::Currency(value) => ::opentelemetry::KeyValue::from(value), + InvoiceAmountHistogramAttr::RequestUrl(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -23,8 +23,8 @@ impl InvoiceAmountHistogram { .build() } } pub fn record(&self, value: f64, r#billing_invoice_id: super::billingattr::InvoiceIdAttr, options: impl IntoIterator) { - let mut attributes = vec![r#billing_invoice_id.key_value()]; - attributes.extend(options.into_iter().map(InvoiceAmountHistogramAttr::key_value)); + let mut attributes = vec![::opentelemetry::KeyValue::from(r#billing_invoice_id)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.record(value, &attributes); } } diff --git a/templates/code/rust/tests/params/expected/myappattr.rs b/templates/code/rust/tests/params/expected/myappattr.rs index 57a6255..a4d03d2 100644 --- a/templates/code/rust/tests/params/expected/myappattr.rs +++ b/templates/code/rust/tests/params/expected/myappattr.rs @@ -6,10 +6,6 @@ pub struct RequestUrlAttr(String); #[allow(deprecated)] impl RequestUrlAttr { pub const KEY: &'static str = "myapp.request.url"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,6 +24,6 @@ impl From<&str> for RequestUrlAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: RequestUrlAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(RequestUrlAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/spans/expected/myappattr.rs b/templates/code/rust/tests/spans/expected/myappattr.rs index 0ad9da8..ff00b86 100644 --- a/templates/code/rust/tests/spans/expected/myappattr.rs +++ b/templates/code/rust/tests/spans/expected/myappattr.rs @@ -6,10 +6,6 @@ pub struct QueueNameAttr(String); #[allow(deprecated)] impl QueueNameAttr { pub const KEY: &'static str = "myapp.queue.name"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,7 +24,7 @@ impl From<&str> for QueueNameAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: QueueNameAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(QueueNameAttr::KEY, value.0) } } /// Number of the attempt, starting at one. @@ -38,10 +34,6 @@ pub struct TaskAttemptAttr(i64); #[allow(deprecated)] impl TaskAttemptAttr { pub const KEY: &'static str = "myapp.task.attempt"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -54,7 +46,7 @@ impl From for TaskAttemptAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskAttemptAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskAttemptAttr::KEY, value.0) } } /// Unique identifier of the task. @@ -64,10 +56,6 @@ pub struct TaskIdAttr(String); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -86,7 +74,7 @@ impl From<&str> for TaskIdAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskIdAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } /// Current state of the task. @@ -101,19 +89,15 @@ pub enum TaskStateAttr { #[allow(deprecated)] impl TaskStateAttr { pub const KEY: &'static str = "myapp.task.state"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - let value: String = match self { - Self::Queued => "queued".into(), - Self::Done => "done".into(), - }; - ::opentelemetry::KeyValue::new(Self::KEY, value) - } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: TaskStateAttr) -> Self { - value.key_value() + let value: String = match value { + TaskStateAttr::Queued => "queued".into(), + TaskStateAttr::Done => "done".into(), + }; + ::opentelemetry::KeyValue::new(TaskStateAttr::KEY, value) } } diff --git a/templates/code/rust/tests/spans/expected/myappspan.rs b/templates/code/rust/tests/spans/expected/myappspan.rs index 12f2ce0..3137195 100644 --- a/templates/code/rust/tests/spans/expected/myappspan.rs +++ b/templates/code/rust/tests/spans/expected/myappspan.rs @@ -23,8 +23,8 @@ pub fn r#start_name_apostrophe(context: &::opentelemetry::Context, tracer: &supe use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push('\u{0027}'); - name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); - let attributes = vec![r#worker_host_port.key_value()]; + name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); + let attributes = vec![::opentelemetry::KeyValue::from(r#worker_host_port)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) @@ -55,8 +55,8 @@ pub fn r#start_name_backslash(context: &::opentelemetry::Context, tracer: &super use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push('\\'); - name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); - let attributes = vec![r#worker_host_port.key_value()]; + name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); + let attributes = vec![::opentelemetry::KeyValue::from(r#worker_host_port)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) @@ -87,8 +87,8 @@ pub fn r#start_name_control(context: &::opentelemetry::Context, tracer: &super:: use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push('\u{0008}'); - name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); - let attributes = vec![r#worker_host_port.key_value()]; + name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); + let attributes = vec![::opentelemetry::KeyValue::from(r#worker_host_port)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) @@ -119,8 +119,8 @@ pub fn r#start_name_unicode(context: &::opentelemetry::Context, tracer: &super:: use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push('é'); - name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); - let attributes = vec![r#worker_host_port.key_value()]; + name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); + let attributes = vec![::opentelemetry::KeyValue::from(r#worker_host_port)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) @@ -172,12 +172,12 @@ pub enum TaskDispatchStartAttr { TaskAttempt(super::myappattr::TaskAttemptAttr), TaskId(super::myappattr::TaskIdAttr), } -impl TaskDispatchStartAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::QueueName(value) => value.key_value(), - Self::TaskAttempt(value) => value.key_value(), - Self::TaskId(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskDispatchStartAttr) -> Self { + match value { + TaskDispatchStartAttr::QueueName(value) => ::opentelemetry::KeyValue::from(value), + TaskDispatchStartAttr::TaskAttempt(value) => ::opentelemetry::KeyValue::from(value), + TaskDispatchStartAttr::TaskId(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -209,7 +209,7 @@ impl TaskDispatchSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } pub fn set_attributes(&mut self, attributes: impl IntoIterator) { - for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, TaskDispatchStartAttr::from(attribute).key_value()); } + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from(TaskDispatchStartAttr::from(attribute))); } } } impl Default for TaskDispatchSpan { @@ -223,11 +223,11 @@ pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super: use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push_str("dispatch "); - name.push_str(&r#worker_host_name.clone().key_value().value.to_string()); + name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_name.clone()).value.to_string()); name.push(':'); - name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); - let mut attributes = vec![r#worker_host_name.key_value(), r#worker_host_port.key_value()]; - attributes.extend(options.into_iter().map(TaskDispatchStartAttr::key_value)); + name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); + let mut attributes = vec![::opentelemetry::KeyValue::from(r#worker_host_name), ::opentelemetry::KeyValue::from(r#worker_host_port)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Client) .with_attributes(attributes) @@ -238,10 +238,10 @@ pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super: pub enum TaskRunStartAttr { TaskId(super::myappattr::TaskIdAttr), } -impl TaskRunStartAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::TaskId(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskRunStartAttr) -> Self { + match value { + TaskRunStartAttr::TaskId(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -274,7 +274,7 @@ impl TaskRunSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } pub fn set_attributes(&mut self, attributes: impl IntoIterator) { - for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, TaskRunStartAttr::from(attribute).key_value()); } + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from(TaskRunStartAttr::from(attribute))); } } } impl Default for TaskRunSpan { @@ -287,8 +287,8 @@ impl Default for TaskRunSpan { pub fn r#start_task_run(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: TaskRunName, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) -> TaskRunSpan { use ::opentelemetry::trace::Tracer; let name = if name.0.is_empty() { "myapp.task.run".to_owned() } else { name.0 }; - let mut attributes = vec![r#myapp_task_state.key_value()]; - attributes.extend(options.into_iter().map(TaskRunStartAttr::key_value)); + let mut attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_state)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) diff --git a/templates/code/rust/tests/spans/expected/workerattr.rs b/templates/code/rust/tests/spans/expected/workerattr.rs index a7d3030..64d7cdc 100644 --- a/templates/code/rust/tests/spans/expected/workerattr.rs +++ b/templates/code/rust/tests/spans/expected/workerattr.rs @@ -6,10 +6,6 @@ pub struct HostNameAttr(String); #[allow(deprecated)] impl HostNameAttr { pub const KEY: &'static str = "worker.host.name"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -28,7 +24,7 @@ impl From<&str> for HostNameAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostNameAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(HostNameAttr::KEY, value.0) } } /// Port the worker listens on. @@ -38,10 +34,6 @@ pub struct HostPortAttr(i64); #[allow(deprecated)] impl HostPortAttr { pub const KEY: &'static str = "worker.host.port"; - - pub fn key_value(self) -> ::opentelemetry::KeyValue { - ::opentelemetry::KeyValue::new(Self::KEY, self.0) - } } #[allow(deprecated)] @@ -54,6 +46,6 @@ impl From for HostPortAttr { #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { fn from(value: HostPortAttr) -> Self { - value.key_value() + ::opentelemetry::KeyValue::new(HostPortAttr::KEY, value.0) } } diff --git a/templates/code/rust/tests/spans/expected/workerspan.rs b/templates/code/rust/tests/spans/expected/workerspan.rs index 7a7259e..e3e4824 100644 --- a/templates/code/rust/tests/spans/expected/workerspan.rs +++ b/templates/code/rust/tests/spans/expected/workerspan.rs @@ -5,11 +5,11 @@ pub enum TaskDispatchStartAttr { QueueName(super::myappattr::QueueNameAttr), TaskId(super::myappattr::TaskIdAttr), } -impl TaskDispatchStartAttr { - fn key_value(self) -> ::opentelemetry::KeyValue { - match self { - Self::QueueName(value) => value.key_value(), - Self::TaskId(value) => value.key_value(), +impl From for ::opentelemetry::KeyValue { + fn from(value: TaskDispatchStartAttr) -> Self { + match value { + TaskDispatchStartAttr::QueueName(value) => ::opentelemetry::KeyValue::from(value), + TaskDispatchStartAttr::TaskId(value) => ::opentelemetry::KeyValue::from(value), } } } @@ -39,7 +39,7 @@ impl TaskDispatchSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } pub fn set_attributes(&mut self, attributes: impl IntoIterator) { - for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, TaskDispatchStartAttr::from(attribute).key_value()); } + for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from(TaskDispatchStartAttr::from(attribute))); } } } impl Default for TaskDispatchSpan { @@ -53,11 +53,11 @@ pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super: use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push_str("dispatch "); - name.push_str(&r#worker_host_name.clone().key_value().value.to_string()); + name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_name.clone()).value.to_string()); name.push(':'); - name.push_str(&r#worker_host_port.clone().key_value().value.to_string()); - let mut attributes = vec![r#myapp_task_attempt.key_value(), r#worker_host_name.key_value(), r#worker_host_port.key_value()]; - attributes.extend(options.into_iter().map(TaskDispatchStartAttr::key_value)); + name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); + let mut attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_attempt), ::opentelemetry::KeyValue::from(r#worker_host_name), ::opentelemetry::KeyValue::from(r#worker_host_port)]; + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Client) .with_attributes(attributes) From 900a28b69f96849102094e1023eb0b6eaed7b2fa Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Mon, 5 Oct 2026 09:35:47 -0400 Subject: [PATCH 07/14] refactor: keep generated imports easy to find Signed-off-by: Yordis Prieto --- templates/code/rust/events.rs.j2 | 5 ++-- templates/code/rust/logger.rs.j2 | 5 ++-- templates/code/rust/spans.rs.j2 | 5 ++-- .../code/rust/tests/events/expected/logger.rs | 5 ++-- .../rust/tests/events/expected/myappevent.rs | 7 +++--- .../rust/tests/events/expected/workerevent.rs | 7 +++--- .../rust/tests/imported/expected/edgeevent.rs | 5 ++-- .../rust/tests/imported/expected/edgespan.rs | 5 ++-- .../rust/tests/imported/expected/logger.rs | 5 ++-- .../tests/imported_typed/expected/logger.rs | 5 ++-- .../imported_typed/expected/myappevent.rs | 5 ++-- .../imported_typed/expected/myappspan.rs | 5 ++-- .../code/rust/tests/literal_escaping/test.rs | 4 ++-- .../no_namespace/expected/exceptionevent.rs | 5 ++-- .../no_namespace/expected/heartbeatspan.rs | 5 ++-- .../tests/no_namespace/expected/logger.rs | 5 ++-- .../rust/tests/spans/expected/myappspan.rs | 23 ++----------------- .../rust/tests/spans/expected/workerspan.rs | 5 ++-- 18 files changed, 47 insertions(+), 64 deletions(-) diff --git a/templates/code/rust/events.rs.j2 b/templates/code/rust/events.rs.j2 index 81976f5..fc8ede7 100644 --- a/templates/code/rust/events.rs.j2 +++ b/templates/code/rust/events.rs.j2 @@ -1,5 +1,8 @@ {%- filter trim %} #![allow(deprecated)] +use ::opentelemetry::logs::LogRecord; +use ::opentelemetry::trace::TraceContextExt; + {% import "signal_helpers.j2" as h %} {% for def in ctx.events %} {% set name = h.exported(def.short_name) %} @@ -16,8 +19,6 @@ pub enum {{ name }}Option { } {{ (h.docs(def) ~ "\n" ~ h.deprecated(def)) | trim }} pub fn {{ h.ident('emit.' ~ def.short_name) }}(context: &::opentelemetry::Context, logger: &super::logger::Logger{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}, options: impl IntoIterator) { - use ::opentelemetry::logs::LogRecord; - use ::opentelemetry::trace::TraceContextExt; let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; diff --git a/templates/code/rust/logger.rs.j2 b/templates/code/rust/logger.rs.j2 index 7688d56..6a3f62a 100644 --- a/templates/code/rust/logger.rs.j2 +++ b/templates/code/rust/logger.rs.j2 @@ -1,4 +1,7 @@ {%- filter trim %} +use opentelemetry::logs::AnyValue; +use opentelemetry::{Array, Value}; + #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { @@ -14,8 +17,6 @@ impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { - use opentelemetry::{Value, Array}; - use opentelemetry::logs::AnyValue; match value { Value::Bool(value) => value.into(), Value::I64(value) => value.into(), diff --git a/templates/code/rust/spans.rs.j2 b/templates/code/rust/spans.rs.j2 index e9bab1a..1f12a70 100644 --- a/templates/code/rust/spans.rs.j2 +++ b/templates/code/rust/spans.rs.j2 @@ -1,5 +1,7 @@ {%- filter trim %} #![allow(deprecated)] +use ::opentelemetry::trace::{TraceContextExt, Tracer}; + {% import "signal_helpers.j2" as h %} {% for def in ctx.spans %} {% set name = h.exported(def.short_name) %} @@ -52,7 +54,6 @@ impl {{ name }}Name { pub struct {{ span }} { span: ::opentelemetry::global::BoxedSpan } impl {{ span }} { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { - use ::opentelemetry::trace::TraceContextExt; parent.with_span(self.span) } pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } @@ -68,13 +69,11 @@ impl {{ span }} { } impl Default for {{ span }} { fn default() -> Self { - use ::opentelemetry::trace::Tracer; Self { span: super::tracer::Tracer::default().inner().start({{ h.literal(def.type) }}) } } } {{ h.deprecated(def) }} pub fn {{ h.ident('start.' ~ def.short_name) }}(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer{% if not def.name_parts %}, name: {{ name }}Name{% endif %}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) -> {{ span }} { - use ::opentelemetry::trace::Tracer; {% if def.name_parts %} let mut name = String::new(); {% for part in def.name_parts %} diff --git a/templates/code/rust/tests/events/expected/logger.rs b/templates/code/rust/tests/events/expected/logger.rs index c7a2373..175c830 100644 --- a/templates/code/rust/tests/events/expected/logger.rs +++ b/templates/code/rust/tests/events/expected/logger.rs @@ -1,3 +1,6 @@ +use opentelemetry::logs::AnyValue; +use opentelemetry::{Array, Value}; + #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { @@ -13,8 +16,6 @@ impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { - use opentelemetry::{Value, Array}; - use opentelemetry::logs::AnyValue; match value { Value::Bool(value) => value.into(), Value::I64(value) => value.into(), diff --git a/templates/code/rust/tests/events/expected/myappevent.rs b/templates/code/rust/tests/events/expected/myappevent.rs index 7377b7d..0d2cb22 100644 --- a/templates/code/rust/tests/events/expected/myappevent.rs +++ b/templates/code/rust/tests/events/expected/myappevent.rs @@ -1,4 +1,7 @@ #![allow(deprecated)] +use ::opentelemetry::logs::LogRecord; +use ::opentelemetry::trace::TraceContextExt; + #[derive(Clone, Debug)] pub enum TaskFinishedOption { Severity(::opentelemetry::logs::Severity), @@ -16,8 +19,6 @@ pub enum TaskFinishedOption { /// /// Emitted once per task, after its last attempt. pub fn r#emit_task_finished(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) { - use ::opentelemetry::logs::LogRecord; - use ::opentelemetry::trace::TraceContextExt; let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; @@ -55,8 +56,6 @@ pub enum TaskRetriedOption { /// Opt-in: record only when the user requests it. #[deprecated(note = "Read the attempt from `myapp.task.finished` instead.")] pub fn r#emit_task_retried(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#myapp_task_attempt: super::myappattr::TaskAttemptAttr, options: impl IntoIterator) { - use ::opentelemetry::logs::LogRecord; - use ::opentelemetry::trace::TraceContextExt; let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; diff --git a/templates/code/rust/tests/events/expected/workerevent.rs b/templates/code/rust/tests/events/expected/workerevent.rs index cff32ca..b926f0f 100644 --- a/templates/code/rust/tests/events/expected/workerevent.rs +++ b/templates/code/rust/tests/events/expected/workerevent.rs @@ -1,4 +1,7 @@ #![allow(deprecated)] +use ::opentelemetry::logs::LogRecord; +use ::opentelemetry::trace::TraceContextExt; + #[derive(Clone, Debug)] pub enum HostStartedOption { Severity(::opentelemetry::logs::Severity), @@ -6,8 +9,6 @@ pub enum HostStartedOption { } /// A worker host started taking tasks. pub fn r#emit_host_started(context: &::opentelemetry::Context, logger: &super::logger::Logger, options: impl IntoIterator) { - use ::opentelemetry::logs::LogRecord; - use ::opentelemetry::trace::TraceContextExt; let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; @@ -45,8 +46,6 @@ pub enum TaskFinishedOption { /// /// Emitted once per task, after its last attempt. pub fn r#emit_task_finished(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#myapp_task_state: super::myappattr::TaskStateAttr, r#worker_host_name: super::workerattr::HostNameAttr, options: impl IntoIterator) { - use ::opentelemetry::logs::LogRecord; - use ::opentelemetry::trace::TraceContextExt; let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; diff --git a/templates/code/rust/tests/imported/expected/edgeevent.rs b/templates/code/rust/tests/imported/expected/edgeevent.rs index bc9550c..11549dc 100644 --- a/templates/code/rust/tests/imported/expected/edgeevent.rs +++ b/templates/code/rust/tests/imported/expected/edgeevent.rs @@ -1,4 +1,7 @@ #![allow(deprecated)] +use ::opentelemetry::logs::LogRecord; +use ::opentelemetry::trace::TraceContextExt; + #[derive(Clone, Debug)] pub enum UpstreamFailedOption { Severity(::opentelemetry::logs::Severity), @@ -7,8 +10,6 @@ pub enum UpstreamFailedOption { } /// A request to an upstream server failed. pub fn r#emit_upstream_failed(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#error_type: String, options: impl IntoIterator) { - use ::opentelemetry::logs::LogRecord; - use ::opentelemetry::trace::TraceContextExt; let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; diff --git a/templates/code/rust/tests/imported/expected/edgespan.rs b/templates/code/rust/tests/imported/expected/edgespan.rs index 7d7661d..6149379 100644 --- a/templates/code/rust/tests/imported/expected/edgespan.rs +++ b/templates/code/rust/tests/imported/expected/edgespan.rs @@ -1,4 +1,6 @@ #![allow(deprecated)] +use ::opentelemetry::trace::{TraceContextExt, Tracer}; + #[derive(Clone, Debug)] pub enum UpstreamRequestStartAttr { /// Conditionally required: If the request failed. @@ -28,7 +30,6 @@ impl From for UpstreamRequestStartAttr { pub struct UpstreamRequestSpan { span: ::opentelemetry::global::BoxedSpan } impl UpstreamRequestSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { - use ::opentelemetry::trace::TraceContextExt; parent.with_span(self.span) } pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } @@ -42,13 +43,11 @@ impl UpstreamRequestSpan { } impl Default for UpstreamRequestSpan { fn default() -> Self { - use ::opentelemetry::trace::Tracer; Self { span: super::tracer::Tracer::default().inner().start("edge.upstream.request") } } } pub fn r#start_upstream_request(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#server_address: String, r#server_port: i64, options: impl IntoIterator) -> UpstreamRequestSpan { - use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push_str(&::opentelemetry::KeyValue::new("server.address", r#server_address.clone()).value.to_string()); name.push(':'); diff --git a/templates/code/rust/tests/imported/expected/logger.rs b/templates/code/rust/tests/imported/expected/logger.rs index c7a2373..175c830 100644 --- a/templates/code/rust/tests/imported/expected/logger.rs +++ b/templates/code/rust/tests/imported/expected/logger.rs @@ -1,3 +1,6 @@ +use opentelemetry::logs::AnyValue; +use opentelemetry::{Array, Value}; + #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { @@ -13,8 +16,6 @@ impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { - use opentelemetry::{Value, Array}; - use opentelemetry::logs::AnyValue; match value { Value::Bool(value) => value.into(), Value::I64(value) => value.into(), diff --git a/templates/code/rust/tests/imported_typed/expected/logger.rs b/templates/code/rust/tests/imported_typed/expected/logger.rs index c7a2373..175c830 100644 --- a/templates/code/rust/tests/imported_typed/expected/logger.rs +++ b/templates/code/rust/tests/imported_typed/expected/logger.rs @@ -1,3 +1,6 @@ +use opentelemetry::logs::AnyValue; +use opentelemetry::{Array, Value}; + #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { @@ -13,8 +16,6 @@ impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { - use opentelemetry::{Value, Array}; - use opentelemetry::logs::AnyValue; match value { Value::Bool(value) => value.into(), Value::I64(value) => value.into(), diff --git a/templates/code/rust/tests/imported_typed/expected/myappevent.rs b/templates/code/rust/tests/imported_typed/expected/myappevent.rs index 145705c..a170dc4 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappevent.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappevent.rs @@ -1,4 +1,7 @@ #![allow(deprecated)] +use ::opentelemetry::logs::LogRecord; +use ::opentelemetry::trace::TraceContextExt; + #[derive(Clone, Debug)] pub enum TaskErroredOption { Severity(::opentelemetry::logs::Severity), @@ -7,8 +10,6 @@ pub enum TaskErroredOption { } /// A task failed with an error. pub fn r#emit_task_errored(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#error_type: upstream::errorattr::TypeAttr, options: impl IntoIterator) { - use ::opentelemetry::logs::LogRecord; - use ::opentelemetry::trace::TraceContextExt; let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; diff --git a/templates/code/rust/tests/imported_typed/expected/myappspan.rs b/templates/code/rust/tests/imported_typed/expected/myappspan.rs index eee4a9b..2aeceed 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappspan.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappspan.rs @@ -1,4 +1,6 @@ #![allow(deprecated)] +use ::opentelemetry::trace::{TraceContextExt, Tracer}; + #[derive(Clone, Debug)] pub enum TaskDispatchStartAttr { ServerPort(i64), @@ -25,7 +27,6 @@ impl From for TaskDispatchStartAttr { pub struct TaskDispatchSpan { span: ::opentelemetry::global::BoxedSpan } impl TaskDispatchSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { - use ::opentelemetry::trace::TraceContextExt; parent.with_span(self.span) } pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } @@ -39,13 +40,11 @@ impl TaskDispatchSpan { } impl Default for TaskDispatchSpan { fn default() -> Self { - use ::opentelemetry::trace::Tracer; Self { span: super::tracer::Tracer::default().inner().start("myapp.task.dispatch") } } } pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) -> TaskDispatchSpan { - use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push_str("task "); name.push_str(&::opentelemetry::KeyValue::from(r#myapp_task_id.clone()).value.to_string()); diff --git a/templates/code/rust/tests/literal_escaping/test.rs b/templates/code/rust/tests/literal_escaping/test.rs index ff04712..b400c34 100644 --- a/templates/code/rust/tests/literal_escaping/test.rs +++ b/templates/code/rust/tests/literal_escaping/test.rs @@ -1,5 +1,7 @@ use generated_semconv::demoattr::LiteralAttr; +use generated_semconv::{demometric::LiteralCountCounter, meter::Meter}; use opentelemetry::Value; +use opentelemetry_sdk::metrics::{InMemoryMetricExporter, PeriodicReader, SdkMeterProvider}; #[test] fn literal_backslashes_and_actual_control_characters_are_distinct() { assert_eq!( @@ -14,8 +16,6 @@ fn literal_backslashes_and_actual_control_characters_are_distinct() { #[test] fn signal_metadata_preserves_literal_backslash_sequences() { - use generated_semconv::{demometric::LiteralCountCounter, meter::Meter}; - use opentelemetry_sdk::metrics::{InMemoryMetricExporter, PeriodicReader, SdkMeterProvider}; let exporter = InMemoryMetricExporter::default(); let provider = SdkMeterProvider::builder() .with_reader(PeriodicReader::builder(exporter.clone()).build()) diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs index 21da536..f52df3a 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs @@ -1,4 +1,7 @@ #![allow(deprecated)] +use ::opentelemetry::logs::LogRecord; +use ::opentelemetry::trace::TraceContextExt; + #[derive(Clone, Debug)] pub enum Option { Severity(::opentelemetry::logs::Severity), @@ -7,8 +10,6 @@ pub enum Option { } /// A noteworthy exception occurred. pub fn r#emit_(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#exception_type: super::exceptionattr::TypeAttr, options: impl IntoIterator) { - use ::opentelemetry::logs::LogRecord; - use ::opentelemetry::trace::TraceContextExt; let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs index fcbf08f..cb99671 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs @@ -1,4 +1,6 @@ #![allow(deprecated)] +use ::opentelemetry::trace::{TraceContextExt, Tracer}; + #[derive(Clone, Debug)] pub enum StartAttr { Source(super::heartbeatattr::SourceAttr), @@ -30,7 +32,6 @@ impl Name { pub struct Span { span: ::opentelemetry::global::BoxedSpan } impl Span { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { - use ::opentelemetry::trace::TraceContextExt; parent.with_span(self.span) } pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } @@ -44,13 +45,11 @@ impl Span { } impl Default for Span { fn default() -> Self { - use ::opentelemetry::trace::Tracer; Self { span: super::tracer::Tracer::default().inner().start("heartbeat") } } } pub fn r#start_(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: Name, r#heartbeat_sequence: super::heartbeatattr::SequenceAttr, options: impl IntoIterator) -> Span { - use ::opentelemetry::trace::Tracer; let name = if name.0.is_empty() { "heartbeat".to_owned() } else { name.0 }; let mut attributes = vec![::opentelemetry::KeyValue::from(r#heartbeat_sequence)]; attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); diff --git a/templates/code/rust/tests/no_namespace/expected/logger.rs b/templates/code/rust/tests/no_namespace/expected/logger.rs index c7a2373..175c830 100644 --- a/templates/code/rust/tests/no_namespace/expected/logger.rs +++ b/templates/code/rust/tests/no_namespace/expected/logger.rs @@ -1,3 +1,6 @@ +use opentelemetry::logs::AnyValue; +use opentelemetry::{Array, Value}; + #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { @@ -13,8 +16,6 @@ impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { - use opentelemetry::{Value, Array}; - use opentelemetry::logs::AnyValue; match value { Value::Bool(value) => value.into(), Value::I64(value) => value.into(), diff --git a/templates/code/rust/tests/spans/expected/myappspan.rs b/templates/code/rust/tests/spans/expected/myappspan.rs index 3137195..00ef698 100644 --- a/templates/code/rust/tests/spans/expected/myappspan.rs +++ b/templates/code/rust/tests/spans/expected/myappspan.rs @@ -1,9 +1,10 @@ #![allow(deprecated)] +use ::opentelemetry::trace::{TraceContextExt, Tracer}; + /// Synthetic escaped name. pub struct NameApostropheSpan { span: ::opentelemetry::global::BoxedSpan } impl NameApostropheSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { - use ::opentelemetry::trace::TraceContextExt; parent.with_span(self.span) } pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } @@ -14,13 +15,11 @@ impl NameApostropheSpan { } impl Default for NameApostropheSpan { fn default() -> Self { - use ::opentelemetry::trace::Tracer; Self { span: super::tracer::Tracer::default().inner().start("myapp.name.apostrophe") } } } pub fn r#start_name_apostrophe(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameApostropheSpan { - use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push('\u{0027}'); name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); @@ -35,7 +34,6 @@ pub fn r#start_name_apostrophe(context: &::opentelemetry::Context, tracer: &supe pub struct NameBackslashSpan { span: ::opentelemetry::global::BoxedSpan } impl NameBackslashSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { - use ::opentelemetry::trace::TraceContextExt; parent.with_span(self.span) } pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } @@ -46,13 +44,11 @@ impl NameBackslashSpan { } impl Default for NameBackslashSpan { fn default() -> Self { - use ::opentelemetry::trace::Tracer; Self { span: super::tracer::Tracer::default().inner().start("myapp.name.backslash") } } } pub fn r#start_name_backslash(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameBackslashSpan { - use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push('\\'); name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); @@ -67,7 +63,6 @@ pub fn r#start_name_backslash(context: &::opentelemetry::Context, tracer: &super pub struct NameControlSpan { span: ::opentelemetry::global::BoxedSpan } impl NameControlSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { - use ::opentelemetry::trace::TraceContextExt; parent.with_span(self.span) } pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } @@ -78,13 +73,11 @@ impl NameControlSpan { } impl Default for NameControlSpan { fn default() -> Self { - use ::opentelemetry::trace::Tracer; Self { span: super::tracer::Tracer::default().inner().start("myapp.name.control") } } } pub fn r#start_name_control(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameControlSpan { - use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push('\u{0008}'); name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); @@ -99,7 +92,6 @@ pub fn r#start_name_control(context: &::opentelemetry::Context, tracer: &super:: pub struct NameUnicodeSpan { span: ::opentelemetry::global::BoxedSpan } impl NameUnicodeSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { - use ::opentelemetry::trace::TraceContextExt; parent.with_span(self.span) } pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } @@ -110,13 +102,11 @@ impl NameUnicodeSpan { } impl Default for NameUnicodeSpan { fn default() -> Self { - use ::opentelemetry::trace::Tracer; Self { span: super::tracer::Tracer::default().inner().start("myapp.name.unicode") } } } pub fn r#start_name_unicode(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameUnicodeSpan { - use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push('é'); name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); @@ -138,7 +128,6 @@ impl QueueDrainName { pub struct QueueDrainSpan { span: ::opentelemetry::global::BoxedSpan } impl QueueDrainSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { - use ::opentelemetry::trace::TraceContextExt; parent.with_span(self.span) } pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } @@ -149,13 +138,11 @@ impl QueueDrainSpan { } impl Default for QueueDrainSpan { fn default() -> Self { - use ::opentelemetry::trace::Tracer; Self { span: super::tracer::Tracer::default().inner().start("myapp.queue.drain") } } } #[deprecated(note = "Drain queues by dispatching their tasks instead.")] pub fn r#start_queue_drain(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: QueueDrainName) -> QueueDrainSpan { - use ::opentelemetry::trace::Tracer; let name = if name.0.is_empty() { "myapp.queue.drain".to_owned() } else { name.0 }; let attributes = vec![]; let span = tracer.inner().span_builder(name) @@ -200,7 +187,6 @@ impl From for TaskDispatchStartAttr { pub struct TaskDispatchSpan { span: ::opentelemetry::global::BoxedSpan } impl TaskDispatchSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { - use ::opentelemetry::trace::TraceContextExt; parent.with_span(self.span) } pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } @@ -214,13 +200,11 @@ impl TaskDispatchSpan { } impl Default for TaskDispatchSpan { fn default() -> Self { - use ::opentelemetry::trace::Tracer; Self { span: super::tracer::Tracer::default().inner().start("myapp.task.dispatch") } } } pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_name: super::workerattr::HostNameAttr, r#worker_host_port: super::workerattr::HostPortAttr, options: impl IntoIterator) -> TaskDispatchSpan { - use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push_str("dispatch "); name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_name.clone()).value.to_string()); @@ -265,7 +249,6 @@ impl TaskRunName { pub struct TaskRunSpan { span: ::opentelemetry::global::BoxedSpan } impl TaskRunSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { - use ::opentelemetry::trace::TraceContextExt; parent.with_span(self.span) } pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } @@ -279,13 +262,11 @@ impl TaskRunSpan { } impl Default for TaskRunSpan { fn default() -> Self { - use ::opentelemetry::trace::Tracer; Self { span: super::tracer::Tracer::default().inner().start("myapp.task.run") } } } pub fn r#start_task_run(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: TaskRunName, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) -> TaskRunSpan { - use ::opentelemetry::trace::Tracer; let name = if name.0.is_empty() { "myapp.task.run".to_owned() } else { name.0 }; let mut attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_state)]; attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); diff --git a/templates/code/rust/tests/spans/expected/workerspan.rs b/templates/code/rust/tests/spans/expected/workerspan.rs index e3e4824..c8de1e9 100644 --- a/templates/code/rust/tests/spans/expected/workerspan.rs +++ b/templates/code/rust/tests/spans/expected/workerspan.rs @@ -1,4 +1,6 @@ #![allow(deprecated)] +use ::opentelemetry::trace::{TraceContextExt, Tracer}; + #[derive(Clone, Debug)] pub enum TaskDispatchStartAttr { /// Recommended: When the task came from a named queue. @@ -30,7 +32,6 @@ impl From for TaskDispatchStartAttr { pub struct TaskDispatchSpan { span: ::opentelemetry::global::BoxedSpan } impl TaskDispatchSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { - use ::opentelemetry::trace::TraceContextExt; parent.with_span(self.span) } pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } @@ -44,13 +45,11 @@ impl TaskDispatchSpan { } impl Default for TaskDispatchSpan { fn default() -> Self { - use ::opentelemetry::trace::Tracer; Self { span: super::tracer::Tracer::default().inner().start("myapp.task.dispatch") } } } pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#myapp_task_attempt: super::myappattr::TaskAttemptAttr, r#worker_host_name: super::workerattr::HostNameAttr, r#worker_host_port: super::workerattr::HostPortAttr, options: impl IntoIterator) -> TaskDispatchSpan { - use ::opentelemetry::trace::Tracer; let mut name = String::new(); name.push_str("dispatch "); name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_name.clone()).value.to_string()); From 1fb50c83dea340d4e15be198455bf303b9d60da8 Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Mon, 5 Oct 2026 10:51:16 -0400 Subject: [PATCH 08/14] perf: keep registry telemetry recording lightweight Signed-off-by: Yordis Prieto --- buildscripts/check_rust_output.sh | 10 +- templates/code/rust/README.md | 69 ++- templates/code/rust/attributes.rs.j2 | 103 +++- templates/code/rust/entities.rs.j2 | 49 +- templates/code/rust/events.rs.j2 | 28 +- templates/code/rust/logger.rs.j2 | 7 +- templates/code/rust/meter.rs.j2 | 3 +- templates/code/rust/metrics.rs.j2 | 24 +- templates/code/rust/signal_helpers.j2 | 4 +- templates/code/rust/spans.rs.j2 | 74 ++- .../rust/tests/allocations/expected/logger.rs | 42 ++ .../rust/tests/allocations/expected/meter.rs | 23 + .../rust/tests/allocations/expected/mod.rs | 8 + .../tests/allocations/expected/probeattr.rs | 111 +++++ .../tests/allocations/expected/probeevent.rs | 45 ++ .../tests/allocations/expected/probemetric.rs | 100 ++++ .../tests/allocations/registry/manifest.yaml | 2 + .../tests/allocations/registry/model.yaml | 55 +++ templates/code/rust/tests/allocations/test.rs | 438 ++++++++++++++++++ .../dynamic_borrow.expected-error.txt | 1 + .../attributes/compile-fail/dynamic_borrow.rs | 4 + .../tests/attributes/expected/authattr.rs | 76 ++- .../tests/attributes/expected/myappattr.rs | 359 ++++++++++++-- templates/code/rust/tests/attributes/test.rs | 67 ++- .../tests/attributes/tests/allocations.rs | 74 +++ .../codegen_exclusion/expected/demoattr.rs | 60 ++- .../required_default.expected-error.txt | 1 + .../entities/compile-fail/required_default.rs | 3 + .../rust/tests/entities/expected/myappattr.rs | 161 ++++++- .../tests/entities/expected/myappentity.rs | 136 ++++-- .../rust/tests/entities/registry/model.yaml | 10 + templates/code/rust/tests/entities/test.rs | 71 ++- .../event_no_attributes/expected/logger.rs | 23 + .../tests/event_no_attributes/expected/mod.rs | 5 + .../expected/probeevent.rs | 31 ++ .../registry/manifest.yaml | 2 + .../event_no_attributes/registry/model.yaml | 5 + .../rust/tests/event_no_attributes/test.rs | 27 ++ .../code/rust/tests/events/expected/logger.rs | 3 +- .../rust/tests/events/expected/myappattr.rs | 146 +++++- .../rust/tests/events/expected/myappevent.rs | 32 +- .../rust/tests/events/expected/workerattr.rs | 37 +- .../rust/tests/events/expected/workerevent.rs | 30 +- templates/code/rust/tests/events/test.rs | 2 +- .../rust/tests/filtering/expected/authattr.rs | 63 ++- .../rust/tests/filtering/expected/taskattr.rs | 210 ++++++++- .../expected/meter.rs | 3 +- .../expected/myappattr.rs | 37 +- .../expected/myappmetric.rs | 28 +- .../expected/meter.rs | 3 +- .../expected/myappattr.rs | 37 +- .../expected/myappmetric.rs | 14 +- .../rust/tests/imported/expected/edgeevent.rs | 20 +- .../tests/imported/expected/edgemetric.rs | 10 +- .../rust/tests/imported/expected/edgespan.rs | 67 ++- .../rust/tests/imported/expected/logger.rs | 3 +- .../rust/tests/imported/expected/meter.rs | 3 +- .../rust/tests/imported/expected/myappattr.rs | 37 +- .../tests/imported/expected/myappmetric.rs | 24 +- .../rust/tests/imported/expected/tracer.rs | 24 +- .../rust/tests/imported/registry/model.yaml | 10 + templates/code/rust/tests/imported/test.rs | 64 +++ .../tests/imported_typed/expected/logger.rs | 3 +- .../tests/imported_typed/expected/meter.rs | 3 +- .../imported_typed/expected/myappattr.rs | 37 +- .../imported_typed/expected/myappevent.rs | 16 +- .../imported_typed/expected/myappmetric.rs | 16 +- .../imported_typed/expected/myappspan.rs | 24 +- .../tests/imported_typed/expected/tracer.rs | 24 +- .../code/rust/tests/imported_typed/test.rs | 32 ++ .../integer_boundaries/expected/demoattr.rs | 13 + .../literal_escaping/expected/demoattr.rs | 26 +- .../literal_escaping/expected/demometric.rs | 14 +- .../tests/literal_escaping/expected/meter.rs | 3 +- .../rust/tests/metrics/expected/authattr.rs | 38 +- .../rust/tests/metrics/expected/authmetric.rs | 14 +- .../code/rust/tests/metrics/expected/meter.rs | 3 +- .../rust/tests/metrics/expected/myappattr.rs | 63 ++- .../tests/metrics/expected/myappmetric.rs | 107 +++-- .../tests/metrics/expected/workermetric.rs | 8 +- .../rust/tests/naming/expected/capsattr.rs | 60 ++- .../rust/tests/naming/expected/capsmetric.rs | 14 +- .../code/rust/tests/naming/expected/meter.rs | 3 +- .../no_namespace/expected/exceptionattr.rs | 74 ++- .../no_namespace/expected/exceptionevent.rs | 16 +- .../no_namespace/expected/heartbeatattr.rs | 49 +- .../no_namespace/expected/heartbeatspan.rs | 31 +- .../tests/no_namespace/expected/hostattr.rs | 74 ++- .../tests/no_namespace/expected/hostentity.rs | 29 +- .../tests/no_namespace/expected/logger.rs | 3 +- .../tests/no_namespace/expected/tracer.rs | 24 +- .../rust/tests/params/expected/billingattr.rs | 74 ++- .../tests/params/expected/billingmetric.rs | 8 +- .../code/rust/tests/params/expected/meter.rs | 3 +- .../rust/tests/params/expected/myappattr.rs | 37 +- .../rust/tests/spans/expected/myappattr.rs | 334 ++++++++++++- .../rust/tests/spans/expected/myappspan.rs | 261 ++++++++--- .../code/rust/tests/spans/expected/tracer.rs | 24 +- .../rust/tests/spans/expected/workerattr.rs | 49 +- .../rust/tests/spans/expected/workerspan.rs | 24 +- .../code/rust/tests/spans/registry/model.yaml | 58 +++ templates/code/rust/tests/spans/test.rs | 45 +- .../rust/tests/spans/tests/allocations.rs | 115 +++++ templates/code/rust/tracer.rs.j2 | 24 +- templates/code/rust/weaver.yaml | 8 +- 105 files changed, 4422 insertions(+), 681 deletions(-) create mode 100644 templates/code/rust/tests/allocations/expected/logger.rs create mode 100644 templates/code/rust/tests/allocations/expected/meter.rs create mode 100644 templates/code/rust/tests/allocations/expected/mod.rs create mode 100644 templates/code/rust/tests/allocations/expected/probeattr.rs create mode 100644 templates/code/rust/tests/allocations/expected/probeevent.rs create mode 100644 templates/code/rust/tests/allocations/expected/probemetric.rs create mode 100644 templates/code/rust/tests/allocations/registry/manifest.yaml create mode 100644 templates/code/rust/tests/allocations/registry/model.yaml create mode 100644 templates/code/rust/tests/allocations/test.rs create mode 100644 templates/code/rust/tests/attributes/compile-fail/dynamic_borrow.expected-error.txt create mode 100644 templates/code/rust/tests/attributes/compile-fail/dynamic_borrow.rs create mode 100644 templates/code/rust/tests/attributes/tests/allocations.rs create mode 100644 templates/code/rust/tests/entities/compile-fail/required_default.expected-error.txt create mode 100644 templates/code/rust/tests/entities/compile-fail/required_default.rs create mode 100644 templates/code/rust/tests/event_no_attributes/expected/logger.rs create mode 100644 templates/code/rust/tests/event_no_attributes/expected/mod.rs create mode 100644 templates/code/rust/tests/event_no_attributes/expected/probeevent.rs create mode 100644 templates/code/rust/tests/event_no_attributes/registry/manifest.yaml create mode 100644 templates/code/rust/tests/event_no_attributes/registry/model.yaml create mode 100644 templates/code/rust/tests/event_no_attributes/test.rs create mode 100644 templates/code/rust/tests/imported/test.rs create mode 100644 templates/code/rust/tests/imported_typed/test.rs create mode 100644 templates/code/rust/tests/spans/tests/allocations.rs diff --git a/buildscripts/check_rust_output.sh b/buildscripts/check_rust_output.sh index b0d5415..47a2bf4 100755 --- a/buildscripts/check_rust_output.sh +++ b/buildscripts/check_rust_output.sh @@ -10,7 +10,7 @@ TEMPLATES_ROOT="$(realpath "${PACKAGE_DIR}/../..")" WORK_DIR="$(mktemp -d "${TMPDIR:-/tmp}/weaver-rust.XXXXXX")" trap 'rm -rf "${WORK_DIR}"' EXIT -export CARGO_TARGET_DIR="${WORK_DIR}/target" +export CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-${WORK_DIR}/target}" for test_dir in "${PACKAGE_DIR}"/tests/*/; do test_name="$(basename "${test_dir}")" @@ -45,6 +45,7 @@ publish = false [dependencies] opentelemetry = { version = "=${OTEL_RUST_VERSION}", features = ["logs", "metrics", "trace"] } opentelemetry_sdk = { version = "=${OTEL_RUST_VERSION}", features = ["logs", "metrics", "trace", "testing"] } +smallvec = { version = "=1.16.2", features = ["const_generics"] } EOF if [[ -f "${test_dir}dependency-params.yaml" ]]; then @@ -67,6 +68,7 @@ publish = false [dependencies] opentelemetry = "=${OTEL_RUST_VERSION}" opentelemetry_sdk = "=${OTEL_RUST_VERSION}" +smallvec = { version = "=1.16.2", features = ["const_generics"] } EOF printf '\nupstream = { path = "upstream" }\n' >>"${crate_dir}/Cargo.toml" ( @@ -81,7 +83,11 @@ EOF cd "${crate_dir}" cargo fmt --all || exit 1 cargo fmt --all --check || exit 1 - cargo test || exit 1 + if [[ "${test_name}" == allocations || -f "${test_dir}tests/allocations.rs" ]]; then + cargo test --release -- --nocapture || exit 1 + else + cargo test || exit 1 + fi cargo clippy --all-targets -- -D warnings || exit 1 for invalid_consumer in "${test_dir}"compile-fail/*.rs; do [[ -f "${invalid_consumer}" ]] || continue diff --git a/templates/code/rust/README.md b/templates/code/rust/README.md index fcc6929..c8d76ea 100644 --- a/templates/code/rust/README.md +++ b/templates/code/rust/README.md @@ -27,6 +27,7 @@ Declare `mod semconv;` in the consuming crate and add its dependencies: [dependencies] opentelemetry = "0.33.0" opentelemetry_sdk = "0.33.0" +smallvec = { version = "=1.16.2", features = ["const_generics"] } ``` Run `cargo fmt` after generation. Weaver writes only the files it produces, so @@ -50,7 +51,7 @@ before choosing that namespace. | `metric` | Synchronous instruments and observable counters, up-down counters, and gauges. | | `span` | Span starters, typed names, start attributes, and attributes allowed after starting. | | `event` | Typed log event emitters and options for attributes, severity, and timestamp. | -| `entity` | Entity values, attribute copies, and resources carrying the registry schema URL. | +| `entity` | Typed entity values, attribute iterators, and resources carrying the registry schema URL. | Handle modules are emitted when the registry includes their corresponding signals. They set the registry schema URL on their instrumentation scope. @@ -63,13 +64,21 @@ Attribute keys, metric names, and event names retain their full registry names. An attribute such as `myapp.task.id` becomes `myappattr::TaskIdAttr::from("task-1")`. Convert the attribute into an OpenTelemetry `KeyValue` with `KeyValue::from(attribute)` or `attribute.into()`. String attributes implement -`From` and `From<&str>`; scalar and array attributes implement `From` -for their exact backing types. Use `Attr::from(value)` or `value.into()` when +`From`, `From<&'static str>`, and `From`. +Static strings retain their static storage. Own a dynamic borrowed string +explicitly, such as `Attr::from(text.to_owned())`. Scalar and array attributes +implement `From` for their backing types; string arrays accept `Vec` +and native `Vec`. Native storage moves into the SDK +without rebuilding the vector. Use `Attr::from(value)` or `value.into()` when the attribute type is known. Enums expose named variants, such as `myappattr::TaskStateAttr::Running`, rather than arbitrary constructors. -Supported backing types are `String`, `i64`, `f64`, `bool`, and their `Vec` +Supported backing types are `StringValue`, `i64`, `f64`, `bool`, and their `Vec` forms. Enums can have string, integer, fractional, or boolean values. +String attributes implement `AsRef`; arrays expose their borrowed slices +through `AsRef<[T]>`. Attributes implement `Display` +without building a temporary `KeyValue`; arrays follow OpenTelemetry's array +formatting. Boolean, integer, floating-point and enum attributes are `Copy`. Deprecation metadata becomes Rust deprecation annotations. ### Metrics @@ -80,6 +89,13 @@ attributes are variants of the instrument's `Attr` enum, passed as an iterator. Observable constructors register a callback whose typed observer has the same required arguments and optional attribute contract. +Recording required attributes uses a stack array. Optional attributes use an +inline buffer sized for the required attributes and the lesser of the declared +optional attributes or eight. Larger inputs spill to the heap; duplicate +attributes retain their order. This avoids generated buffer allocations for +ordinary attribute sets while preserving iterator input. Attribute values and +the SDK may still require ownership or aggregation allocations. + Set `annotations.code_generation.metric_value_type` to `int` or `double`. Rust's integer counters and histograms use `u64`; integer up-down counters and gauges use `i64`. Double instruments use `f64`. Constructors follow the Rust @@ -95,15 +111,25 @@ provides unit-specific boundaries; units absent from that map use SDK defaults. A span starter takes a parent `Context`, a generated tracer, required typed attributes, and optional start attributes. A registry name template whose placeholders refer to required attributes is expanded from those values. -Otherwise the starter takes a typed `Name`; an empty name falls back to the -span's registry type. +Otherwise the starter takes a typed `Name`, constructed with `From` for a static +string, owned `String`, or `Cow<'static, str>`. An empty name borrows the span's +registry type; static names stay borrowed and owned names move into the span. All starter attributes are present before sampling. Sampling-relevant attributes appear only in the start attribute enum. The separate late attribute enum is accepted by `set_attributes`. The wrapper exposes `end`, `end_with_timestamp`, `record_error`, `set_status`, and the underlying span. `into_context` transfers the span into a parent context for nested spans and -normal OpenTelemetry context attachment. +normal OpenTelemetry context attachment. The generated tracer and span wrappers +retain the provider's concrete types. Their default type is the no-op API type; +`into_context` uses OpenTelemetry's synchronization and type erasure when +context integration is needed. + +Derived names borrow attribute values and write directly into a preallocated +`String`, reserving known literal and string lengths plus space for other +values. Nonempty derived names allocate their output buffer. Required attributes use a +stack array and optional iterators, which the span builder collects into its +owned attribute buffer. ### Events @@ -113,12 +139,28 @@ and timestamp. Severity defaults to Info. The emitter checks whether the logger accepts the event, sets the observed timestamp, and copies a valid trace context from the supplied `Context`. +The last severity and timestamp options win. Declared attribute options remain +typed until the enabled check succeeds, so disabled events avoid attribute +conversion and context attachment. Optional attributes use inline storage for +the lesser of the declared optional attributes or eight, with heap overflow +for larger inputs. Enabled emitters add required attributes and then optional +attributes directly to the record, preserving duplicates and their order. + ### Entities Entity constructors take required identity attributes before required -description attributes, followed by optional attributes. `attributes()` returns -a copy. `resource()` creates a resource with the registry schema URL and no -implicit SDK detector attributes. `Default` carries no attributes. +description attributes, followed by optional attributes. Required attributes +remain typed fields, and optional attributes remain variants of the entity's +attribute enum. Optional storage uses a bounded inline buffer and supports +heap overflow when the caller supplies more values. + +`attributes()` returns an iterator over SDK-owned `KeyValue` values. Borrowed +export clones only the values needed to give the SDK ownership, without +building an intermediate attribute vector. Convert an entity with +`Resource::from(entity)` or `entity.into()` to consume its fields and optional +values without cloning them. The resource retains the registry schema URL and +has no implicit SDK detector attributes. `Default` is available only when the +entity has no required attributes. ### Refinements and dependencies @@ -138,6 +180,9 @@ params: That mapping refers to `upstream::errorattr` in the consuming crate. Both registries must use compatible namespace and vendor-prefix settings. +Plain imported strings use `opentelemetry::StringValue`, and string arrays use +`Vec`, preserving their SDK storage. Convert a static +string with `.into()` or `StringValue::from` at the call site. ## Parameters @@ -175,3 +220,7 @@ mise run weaver:test:rust The Rust check formats generated fixture code in temporary crates, runs consumer and documentation tests, verifies compile-fail examples, and runs Clippy with warnings denied. Snapshot checks compare the original Weaver output. +The allocation fixture runs in release mode with a thread-local counting +allocator and custom providers that do not allocate while recording. It checks +generated buffer costs separately from SDK storage costs and verifies duplicate +attributes beyond inline capacity. diff --git a/templates/code/rust/attributes.rs.j2 b/templates/code/rust/attributes.rs.j2 index f3ccf30..7227dd8 100644 --- a/templates/code/rust/attributes.rs.j2 +++ b/templates/code/rust/attributes.rs.j2 @@ -1,8 +1,9 @@ {%- filter trim %} // Generated by OpenTelemetry Weaver. {% for attr in ctx.attributes %} +{% set rust_type = "::opentelemetry::StringValue" if attr.value_type == "string" else ("Vec<::opentelemetry::StringValue>" if attr.value_type == "string[]" else attr.value_type | map_text("rust_type")) %} {{ [attr.brief, attr.note] | select | join("\n\n") | comment | indent(0) }} -{{ ("#[deprecated(note = " ~ attr.deprecated_literal ~ ")]\n") if attr.deprecated_literal else "" }}#[derive(Debug, Clone, PartialEq{% if attr.type is mapping %}, Copy{% endif %})] +{{ ("#[deprecated(note = " ~ attr.deprecated_literal ~ ")]\n") if attr.deprecated_literal else "" }}#[derive(Debug, Clone, PartialEq{% if attr.type is mapping or attr.value_type in ["int", "double", "boolean"] %}, Copy{% endif %})] {% if attr.type is mapping %} pub enum {{ attr.name }} { {% for member in attr.type.members %} @@ -14,7 +15,7 @@ pub enum {{ attr.name }} { {% endfor %} } {% else %} -pub struct {{ attr.name }}({{ attr.value_type | map_text("rust_type") }}); +pub struct {{ attr.name }}({{ rust_type }}); {% endif %} #[allow(deprecated)] @@ -24,33 +25,115 @@ impl {{ attr.name }} { {% if attr.type is not mapping %} #[allow(deprecated)] -impl From<{{ attr.value_type | map_text("rust_type") }}> for {{ attr.name }} { - fn from(value: {{ attr.value_type | map_text("rust_type") }}) -> Self { +impl From<{{ rust_type }}> for {{ attr.name }} { + #[inline] + fn from(value: {{ rust_type }}) -> Self { Self(value) } } {% if attr.value_type == "string" %} #[allow(deprecated)] -impl From<&str> for {{ attr.name }} { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl From for {{ attr.name }} { + #[inline] + fn from(value: String) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for {{ attr.name }} { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} +{% elif attr.value_type == "string[]" %} +#[allow(deprecated)] +impl From> for {{ attr.name }} { + fn from(value: Vec) -> Self { + Self(value.into_iter().map(Into::into).collect()) + } +} +{% endif %} +{% endif %} +{% if attr.value_type == "string" %} + +#[allow(deprecated)] +impl AsRef for {{ attr.name }} { + #[inline] + fn as_ref(&self) -> &str { +{% if attr.type is mapping %} + match self { +{% for member in attr.type.members %} + {{ attr.name }}::{{ member.name }} => {{ member.literal }}, +{% endfor %} + } +{% else %} + self.0.as_str() +{% endif %} + } +} +{% elif "[]" in attr.value_type %} +{% set element_type = "::opentelemetry::StringValue" if attr.value_type == "string[]" else attr.value_type[:-2] | map_text("rust_type") %} + +#[allow(deprecated)] +impl AsRef<[{{ element_type }}]> for {{ attr.name }} { + #[inline] + fn as_ref(&self) -> &[{{ element_type }}] { + &self.0 } } {% endif %} + +#[allow(deprecated)] +impl ::std::fmt::Display for {{ attr.name }} { +{% if "[]" not in attr.value_type and (attr.type is not mapping or attr.type.members | length <= 8) %} + #[inline] {% endif %} + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { +{% if attr.value_type == "string" %} + formatter.write_str(self.as_ref()) +{% elif attr.type is mapping %} + let value: {{ attr.value_type | map_text("rust_type") }} = match self { +{% for member in attr.type.members %} + {{ attr.name }}::{{ member.name }} => {{ member.literal }}{% if attr.value_type == "double" %}_f64{% endif %}, +{% endfor %} + }; + ::std::fmt::Display::fmt(&value, formatter) +{% elif "[]" in attr.value_type %} + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } +{% if attr.value_type == "string[]" %} + write!(formatter, "\"{value}\"")?; +{% else %} + ::std::fmt::Display::fmt(value, formatter)?; +{% endif %} + } + formatter.write_str("]") +{% else %} + ::std::fmt::Display::fmt(&self.0, formatter) +{% endif %} + } +} #[allow(deprecated)] impl From<{{ attr.name }}> for ::opentelemetry::KeyValue { +{% if attr.type is not mapping or attr.type.members | length <= 8 %} + #[inline] +{% endif %} fn from(value: {{ attr.name }}) -> Self { {% if attr.type is mapping %} - let value: {{ attr.value_type | map_text("rust_type") }} = match value { + let value: {{ "&'static str" if attr.value_type == "string" else attr.value_type | map_text("rust_type") }} = match value { {% for member in attr.type.members %} - {{ attr.name }}::{{ member.name }} => {{ member.literal }}{% if attr.value_type == "string" %}.into(){% elif attr.value_type == "double" %}_f64{% endif %}, + {{ attr.name }}::{{ member.name }} => {{ member.literal }}{% if attr.value_type == "double" %}_f64{% endif %}, {% endfor %} }; ::opentelemetry::KeyValue::new({{ attr.name }}::KEY, value) {% elif "[]" in attr.value_type %} - ::opentelemetry::KeyValue::new({{ attr.name }}::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::{{ attr.value_type | map_text("rust_array") }}(value.0{% if attr.value_type == "string[]" %}.into_iter().map(Into::into).collect(){% endif %}))) + ::opentelemetry::KeyValue::new({{ attr.name }}::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::{{ attr.value_type | map_text("rust_array") }}(value.0))) {% else %} ::opentelemetry::KeyValue::new({{ attr.name }}::KEY, value.0) {% endif %} diff --git a/templates/code/rust/entities.rs.j2 b/templates/code/rust/entities.rs.j2 index 8242a3b..7483a33 100644 --- a/templates/code/rust/entities.rs.j2 +++ b/templates/code/rust/entities.rs.j2 @@ -1,5 +1,9 @@ {%- filter trim %} {% import "signal_helpers.j2" as s -%} +{% macro borrowed(a, expression) -%} +{%- set kind = a.attr_type if a.imported else a.type -%} +{{ expression }}{% if kind is not mapping and kind not in ["int", "double", "boolean"] %}.clone(){% endif %} +{%- endmacro %} {% filter regex_replace("(?m)(^[ \\t]*///[^\\n]*\\n)([ \\t]*\\n)+", "${1}") %} // Code generated by weaver. DO NOT EDIT. #![allow(deprecated)] @@ -31,31 +35,48 @@ impl From<{{ name }}Attr> for ::opentelemetry::KeyValue { {{ def.description_doc | comment if def.description_doc else '' }} {% if def.refines %}{{ ("Refines `" ~ def.refines ~ "`.") | comment }}{% endif %} {{ s.deprecated(def) }} -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug{% if not def.required %}, Default{% endif %})] pub struct {{ name }} { - attributes: Vec<::opentelemetry::KeyValue>, +{% for req in def.required %} + {{ s.ident(req.attr_param) }}: {{ s.attr_type(req) }}, +{% endfor %} +{% if def.optional %} + options: ::smallvec::SmallVec<[{{ name }}Attr; {{ 8 if def.optional | length > 8 else def.optional | length }}]>, +{% endif %} } impl {{ name }} { pub fn new({% for req in def.required %}{{ s.ident(req.attr_param) }}: {{ s.attr_type(req) }}, {% endfor %}{% if def.optional %}options: impl IntoIterator{% endif %}) -> Self { -{% if def.required or def.optional %} - let {% if def.optional %}mut {% endif %}attributes = vec![ + Self { {% for req in def.required %} - {{ s.attr_kv(req, s.ident(req.attr_param)) }}, + {{ s.ident(req.attr_param) }}, {% endfor %} - ]; -{% if def.optional %} attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); -{% endif %} Self { attributes } -{% else %} Self::default() -{% endif %} } +{% if def.optional %} + options: options.into_iter().collect(), +{% endif %} + } + } - pub fn attributes(&self) -> Vec<::opentelemetry::KeyValue> { - self.attributes.clone() + pub fn attributes(&self) -> impl Iterator + '_ { + ::std::iter::empty() +{% for req in def.required %} + .chain(::std::iter::once_with(move || {{ s.attr_kv(req, borrowed(req, "self." ~ s.ident(req.attr_param))) }})) +{% endfor %} +{% if def.optional %} + .chain(self.options.iter().cloned().map(::opentelemetry::KeyValue::from)) +{% endif %} } +} - pub fn resource(&self) -> ::opentelemetry_sdk::Resource { +impl From<{{ name }}> for ::opentelemetry_sdk::Resource { + fn from({{ "value" if def.required or def.optional else "_value" }}: {{ name }}) -> Self { + let attributes = [ +{% for req in def.required %} + {{ s.attr_kv(req, "value." ~ s.ident(req.attr_param)) }}, +{% endfor %} + ].into_iter(){% if def.optional %}.chain(value.options.into_iter().map(::opentelemetry::KeyValue::from)){% endif %}; ::opentelemetry_sdk::Resource::builder_empty() - .with_schema_url(self.attributes(), super::SCHEMA_URL) + .with_schema_url(attributes, super::SCHEMA_URL) .build() } } diff --git a/templates/code/rust/events.rs.j2 b/templates/code/rust/events.rs.j2 index fc8ede7..db50914 100644 --- a/templates/code/rust/events.rs.j2 +++ b/templates/code/rust/events.rs.j2 @@ -19,20 +19,22 @@ pub enum {{ name }}Option { } {{ (h.docs(def) ~ "\n" ~ h.deprecated(def)) | trim }} pub fn {{ h.ident('emit.' ~ def.short_name) }}(context: &::opentelemetry::Context, logger: &super::logger::Logger{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}, options: impl IntoIterator) { - let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let {% if def.optional %}mut {% endif %}attributes: Vec<::opentelemetry::KeyValue> = vec![{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; +{% if def.optional %} + let mut attributes = ::smallvec::SmallVec::<[{{ name }}Option; {{ [def.optional | length, 8] | min }}]>::new(); +{% endif %} for option in options { match option { {{ name }}Option::Severity(value) => severity = value, {{ name }}Option::Timestamp(value) => timestamp = Some(value), -{% for opt in def.optional %} - {{ name }}Option::{{ h.exported(opt.attr_short_name) }}(value) => attributes.push({{ h.attr_kv(opt, 'value') }}), -{% endfor %} +{% if def.optional %} + attribute => attributes.push(attribute), +{% endif %} } } if !logger.inner().event_enabled(severity, "", Some({{ h.literal(def.name) }})) { return; } + let _context_guard = context.clone().attach(); let mut record = logger.inner().create_log_record(); record.set_event_name({{ h.literal(def.name) }}); record.set_severity_number(severity); @@ -41,7 +43,21 @@ pub fn {{ h.ident('emit.' ~ def.short_name) }} let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } +{% for req in def.required %} + let attribute = {{ h.attr_kv(req, h.ident(req.attr_param)) }}; + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); +{% endfor %} +{% if def.optional %} + for option in attributes { + let attribute = match option { +{% for opt in def.optional %} + {{ name }}Option::{{ h.exported(opt.attr_short_name) }}(value) => {{ h.attr_kv(opt, 'value') }}, +{% endfor %} + {{ name }}Option::Severity(_) | {{ name }}Option::Timestamp(_) => continue, + }; + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } +{% endif %} logger.inner().emit(record); } {% endfor %} diff --git a/templates/code/rust/logger.rs.j2 b/templates/code/rust/logger.rs.j2 index 6a3f62a..b2a7260 100644 --- a/templates/code/rust/logger.rs.j2 +++ b/templates/code/rust/logger.rs.j2 @@ -1,12 +1,14 @@ {%- filter trim %} +{% if ctx.has_attributes %} use opentelemetry::logs::AnyValue; use opentelemetry::{Array, Value}; +{% endif %} #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.logger_with_scope(registry_scope(scope))) @@ -16,6 +18,7 @@ impl Logger { impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } } +{% if ctx.has_attributes %} pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { match value { Value::Bool(value) => value.into(), @@ -32,8 +35,10 @@ pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::Any _ => AnyValue::String(value.to_string().into()), } } +{% endif %} fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/meter.rs.j2 b/templates/code/rust/meter.rs.j2 index 41f6596..97a3f58 100644 --- a/templates/code/rust/meter.rs.j2 +++ b/templates/code/rust/meter.rs.j2 @@ -3,7 +3,7 @@ pub struct Meter(opentelemetry::metrics::Meter); impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.meter_with_scope(registry_scope(scope))) @@ -15,6 +15,7 @@ impl Default for Meter { } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/metrics.rs.j2 b/templates/code/rust/metrics.rs.j2 index 2fc5f90..dad2bf1 100644 --- a/templates/code/rust/metrics.rs.j2 +++ b/templates/code/rust/metrics.rs.j2 @@ -32,18 +32,24 @@ impl From<{{ name }}Attr> for ::opentelemetry::KeyValue { pub struct {{ name }} { instrument: ::opentelemetry::metrics::{{ suffix }}<{{ value_type }}> } impl {{ name }} { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().{{ builder }}({{ h.literal(def.instrument_name) }}) + let instrument = meter.inner().{{ builder }}({{ h.literal(def.instrument_name) }}) .with_description({{ h.literal(def.description | trim) }}) .with_unit({{ h.literal(def.unit) }}) {% if def.bucket_boundaries %} .with_boundaries(vec![{% for bound in def.bucket_boundaries %}{{ bound }}_f64{% if not loop.last %}, {% endif %}{% endfor %}]) {% endif %} - .build() } + .build(); + Self { instrument } } pub fn {{ method }}(&self, value: {{ value_type }}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) { - let {% if def.optional %}mut {% endif %}attributes = vec![{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; {% if def.optional %} + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; {{ def.required | length + ([def.optional | length, 8] | min) }}]>::new(); +{% if def.required %} + attributes.extend([{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]); +{% endif %} attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); +{% else %} + let attributes = [{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; {% endif %} self.instrument.{{ method }}(value, &attributes); } @@ -56,9 +62,14 @@ impl Default for {{ name }} { pub struct {{ name }}Observer<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument<{{ value_type }}> } impl {{ name }}Observer<'_> { pub fn observe(&self, value: {{ value_type }}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) { - let {% if def.optional %}mut {% endif %}attributes = vec![{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; {% if def.optional %} + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; {{ def.required | length + ([def.optional | length, 8] | min) }}]>::new(); +{% if def.required %} + attributes.extend([{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]); +{% endif %} attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); +{% else %} + let attributes = [{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; {% endif %} self.observer.observe(value, &attributes); } @@ -68,11 +79,12 @@ impl {{ name }}Observer<'_> { pub struct {{ observable }} { _instrument: ::opentelemetry::metrics::Observable{{ suffix }}<{{ value_type }}> } impl {{ observable }} { pub fn new(meter: &super::meter::Meter, callback: impl Fn({{ name }}Observer<'_>) + Send + Sync + 'static) -> Self { - Self { _instrument: meter.inner().{{ value_type }}_observable_{{ 'up_down_counter' if def.instrument == 'updowncounter' else def.instrument }}({{ h.literal(def.instrument_name) }}) + let instrument = meter.inner().{{ value_type }}_observable_{{ 'up_down_counter' if def.instrument == 'updowncounter' else def.instrument }}({{ h.literal(def.instrument_name) }}) .with_description({{ h.literal(def.description | trim) }}) .with_unit({{ h.literal(def.unit) }}) .with_callback(move |observer| callback({{ name }}Observer { observer })) - .build() } + .build(); + Self { _instrument: instrument } } } impl Default for {{ observable }} { diff --git a/templates/code/rust/signal_helpers.j2 b/templates/code/rust/signal_helpers.j2 index d576d34..a01c3f1 100644 --- a/templates/code/rust/signal_helpers.j2 +++ b/templates/code/rust/signal_helpers.j2 @@ -4,12 +4,12 @@ {% macro exported(value) -%}{% for dotted in value.split(".") %}{% for segment in dotted.split("_") %}{{ segment[:1] | upper }}{{ segment[1:] }}{% endfor %}{% endfor %}{%- endmacro %} {% macro ident(value) -%}r#{{ value | snake_case }}{%- endmacro %} {% macro attr_type(a) -%} -{%- if a.imported -%}{{ a.attr_type | map_text("rust_type") }} +{%- if a.imported -%}{{ "::opentelemetry::StringValue" if a.attr_type == "string" else ("Vec<::opentelemetry::StringValue>" if a.attr_type == "string[]" else a.attr_type | map_text("rust_type")) }} {%- else -%}{{ a.attr_import_path if a.attr_import_path else 'super::' ~ a.attr_namespace ~ 'attr' }}::{{ exported(a.attr_short_name) }}Attr {%- endif -%} {%- endmacro %} {% macro attr_kv(a, value) -%} -{%- if a.imported -%}::opentelemetry::KeyValue::new({{ literal(a.key) }}, {% if "[]" in a.attr_type %}::opentelemetry::Value::Array(::opentelemetry::Array::{{ a.attr_type | map_text("rust_array") }}({{ value }}{% if a.attr_type == "string[]" %}.into_iter().map(Into::into).collect(){% endif %})){% else %}{{ value }}{% endif %}) +{%- if a.imported -%}::opentelemetry::KeyValue::new({{ literal(a.key) }}, {% if "[]" in a.attr_type %}::opentelemetry::Value::Array(::opentelemetry::Array::{{ a.attr_type | map_text("rust_array") }}({{ value }})){% else %}{{ value }}{% endif %}) {%- else -%}::opentelemetry::KeyValue::from({{ value }}) {%- endif -%} {%- endmacro %} diff --git a/templates/code/rust/spans.rs.j2 b/templates/code/rust/spans.rs.j2 index 1f12a70..436ca1b 100644 --- a/templates/code/rust/spans.rs.j2 +++ b/templates/code/rust/spans.rs.j2 @@ -1,8 +1,36 @@ {%- filter trim %} #![allow(deprecated)] use ::opentelemetry::trace::{TraceContextExt, Tracer}; +{% macro needs_name_formatting(definitions) -%} +{%- for definition in definitions -%} +{%- for part in definition.name_parts or [] -%} +{%- if part.attr -%}yes{%- endif -%} +{%- endfor -%} +{%- endfor -%} +{%- endmacro %} +{% if needs_name_formatting(ctx.spans) %} +use ::std::fmt::Write; +{% endif %} {% import "signal_helpers.j2" as h %} +{# Floating-point names need space for full decimal notation, including subnormals. #} +{% macro name_capacity(a, value) -%} +{% set t = a.attr_type if a.imported else a.type %} +{%- if t == 'string' or (t is mapping and t.members[0].value is string) -%} +{% if a.imported %}{{ value }}.as_str().len(){% else %}::std::convert::AsRef::::as_ref(&{{ value }}).len(){% endif %} +{%- elif t in ['string[]', 'int[]', 'double[]', 'boolean[]'] -%} +{%- set element = '::opentelemetry::StringValue' if t == 'string[]' else ('i64' if t == 'int[]' else ('f64' if t == 'double[]' else 'bool')) -%} +{%- set values = value if a.imported else '::std::convert::AsRef::<[' ~ element ~ ']>::as_ref(&' ~ value ~ ')' -%} +{%- if t == 'string[]' -%} +{{ values }}.iter().map(|value| value.as_str().len() + 3).sum::() + 2 +{%- else -%} +{{ values }}.len() * {{ 328 if t == 'double[]' else (21 if t == 'int[]' else 6) }} + 2 +{%- endif -%} +{%- elif t == 'int' -%}20 +{%- elif t == 'double' or t is mapping and t.members[0].value is number -%}328 +{%- else -%}5 +{%- endif -%} +{%- endmacro %} {% for def in ctx.spans %} {% set name = h.exported(def.short_name) %} {% set span = name ~ 'Span' %} @@ -45,18 +73,26 @@ impl From<{{ name }}Attr> for {{ name }}StartAttr { {% endif %} {% if not def.name_parts %} #[derive(Clone, Debug, Default)] -pub struct {{ name }}Name(String); -impl {{ name }}Name { - pub fn new(value: impl Into) -> Self { Self(value.into()) } +pub struct {{ name }}Name(::std::borrow::Cow<'static, str>); +impl From<&'static str> for {{ name }}Name { + fn from(value: &'static str) -> Self { Self(::std::borrow::Cow::Borrowed(value)) } +} +impl From for {{ name }}Name { + fn from(value: String) -> Self { Self(::std::borrow::Cow::Owned(value)) } +} +impl From<::std::borrow::Cow<'static, str>> for {{ name }}Name { + fn from(value: ::std::borrow::Cow<'static, str>) -> Self { Self(value) } } {% endif %} {{ (h.docs(def) ~ "\n" ~ h.deprecated(def)) | trim }} -pub struct {{ span }} { span: ::opentelemetry::global::BoxedSpan } -impl {{ span }} { - pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { +pub struct {{ span }} { span: S } +impl {{ span }} { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { parent.with_span(self.span) } - pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn span(&mut self) -> &mut S { &mut self.span } pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } @@ -73,12 +109,21 @@ impl Default for {{ span }} { } } {{ h.deprecated(def) }} -pub fn {{ h.ident('start.' ~ def.short_name) }}(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer{% if not def.name_parts %}, name: {{ name }}Name{% endif %}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) -> {{ span }} { +pub fn {{ h.ident('start.' ~ def.short_name) }}(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer{% if not def.name_parts %}, name: {{ name }}Name{% endif %}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) -> {{ span }} { {% if def.name_parts %} - let mut name = String::new(); + let mut name = String::with_capacity({% for part in def.name_parts %}{% if not loop.first %} + {% endif %}{% if part.attr %}{{ name_capacity(part.attr, h.ident(part.attr.attr_param)) }}{% else %}{{ h.literal(part.text) }}.len(){% endif %}{% endfor %}); {% for part in def.name_parts %} {% if part.attr %} - name.push_str(&{{ h.attr_kv(part.attr, h.ident(part.attr.attr_param) ~ ('' if (part.attr.type is mapping and not part.attr.imported) or (part.attr.imported and part.attr.attr_type in ['int', 'double', 'boolean']) else '.clone()')) }}.value.to_string()); +{% if part.attr.imported and '[]' in part.attr.attr_type %} + name.push('['); + for (index, value) in {{ h.ident(part.attr.attr_param) }}.iter().enumerate() { + if index > 0 { name.push(','); } + write!(&mut name, {% if part.attr.attr_type == 'string[]' %}"\"{}\""{% else %}"{}"{% endif %}, value).expect("writing a span name to String cannot fail"); + } + name.push(']'); +{% else %} + write!(&mut name, "{}", {{ h.ident(part.attr.attr_param) }}).expect("writing a span name to String cannot fail"); +{% endif %} {% else %} {% if part.text | length == 1 %} name.push('{{ h.literal(part.text)[1:-1] | replace("'", "\\'") }}'); @@ -88,15 +133,12 @@ pub fn {{ h.ident('start.' ~ def.short_name) }}(context: &::opentelemetry::Conte {% endif %} {% endfor %} {% else %} - let name = if name.0.is_empty() { {{ h.literal(def.type) }}.to_owned() } else { name.0 }; -{% endif %} - let {% if def.optional %}mut {% endif %}attributes = vec![{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; -{% if def.optional %} - attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); + let name = if name.0.is_empty() { ::std::borrow::Cow::Borrowed({{ h.literal(def.type) }}) } else { name.0 }; {% endif %} + let attributes: [::opentelemetry::KeyValue; {{ def.required | length }}] = [{% for req in def.required %}{{ h.attr_kv(req, h.ident(req.attr_param)) }}{% if not loop.last %}, {% endif %}{% endfor %}]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::{{ def.kind | pascal_case }}) - .with_attributes(attributes) + .with_attributes(attributes{% if def.optional %}.into_iter().chain(options.into_iter().map(::opentelemetry::KeyValue::from)){% endif %}) .start_with_context(tracer.inner(), context); {{ span }} { span } } diff --git a/templates/code/rust/tests/allocations/expected/logger.rs b/templates/code/rust/tests/allocations/expected/logger.rs new file mode 100644 index 0000000..179c64c --- /dev/null +++ b/templates/code/rust/tests/allocations/expected/logger.rs @@ -0,0 +1,42 @@ +use opentelemetry::logs::AnyValue; +use opentelemetry::{Array, Value}; + +#[derive(Clone, Debug)] +pub struct Logger::Logger>(L); +impl Logger { + pub fn new>(provider: &P, scope: impl Into>) -> Self { + Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) + } + pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.logger_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &L { &self.0 } +} +impl Default for Logger { + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } +} +pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { + match value { + Value::Bool(value) => value.into(), + Value::I64(value) => value.into(), + Value::F64(value) => value.into(), + Value::String(value) => value.into(), + Value::Array(array) => match array { + Array::Bool(values) => values.into_iter().collect::(), + Array::I64(values) => values.into_iter().collect::(), + Array::F64(values) => values.into_iter().collect::(), + Array::String(values) => values.into_iter().collect::(), + _ => AnyValue::String(array.to_string().into()), + }, + _ => AnyValue::String(value.to_string().into()), + } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/allocations/expected/meter.rs b/templates/code/rust/tests/allocations/expected/meter.rs new file mode 100644 index 0000000..2607994 --- /dev/null +++ b/templates/code/rust/tests/allocations/expected/meter.rs @@ -0,0 +1,23 @@ +#[derive(Clone, Debug)] +pub struct Meter(opentelemetry::metrics::Meter); +impl Meter { + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { + Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) + } + pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.meter_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } +} +impl Default for Meter { + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/allocations/expected/mod.rs b/templates/code/rust/tests/allocations/expected/mod.rs new file mode 100644 index 0000000..6a65324 --- /dev/null +++ b/templates/code/rust/tests/allocations/expected/mod.rs @@ -0,0 +1,8 @@ +// Generated by OpenTelemetry Weaver. +pub const SCHEMA_URL: &str = "https://example.com/schemas/allocations/1.0.0"; +pub mod probeattr; + +pub mod meter; +pub mod logger; +pub mod probeevent; +pub mod probemetric; diff --git a/templates/code/rust/tests/allocations/expected/probeattr.rs b/templates/code/rust/tests/allocations/expected/probeattr.rs new file mode 100644 index 0000000..9c7a207 --- /dev/null +++ b/templates/code/rust/tests/allocations/expected/probeattr.rs @@ -0,0 +1,111 @@ +// Generated by OpenTelemetry Weaver. +/// Optional numeric measurement identity. +#[derive(Debug, Clone, PartialEq, Copy)] +pub struct OptionalAttr(i64); + +#[allow(deprecated)] +impl OptionalAttr { + pub const KEY: &'static str = "probe.optional"; +} + +#[allow(deprecated)] +impl From for OptionalAttr { + #[inline] + fn from(value: i64) -> Self { + Self(value) + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for OptionalAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + #[inline] + fn from(value: OptionalAttr) -> Self { + ::opentelemetry::KeyValue::new(OptionalAttr::KEY, value.0) + } +} +/// Required numeric measurement identity. +#[derive(Debug, Clone, PartialEq, Copy)] +pub struct RequiredAttr(i64); + +#[allow(deprecated)] +impl RequiredAttr { + pub const KEY: &'static str = "probe.required"; +} + +#[allow(deprecated)] +impl From for RequiredAttr { + #[inline] + fn from(value: i64) -> Self { + Self(value) + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for RequiredAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + #[inline] + fn from(value: RequiredAttr) -> Self { + ::opentelemetry::KeyValue::new(RequiredAttr::KEY, value.0) + } +} +/// Numeric values attached to an event. +#[derive(Debug, Clone, PartialEq)] +pub struct ValuesAttr(Vec); + +#[allow(deprecated)] +impl ValuesAttr { + pub const KEY: &'static str = "probe.values"; +} + +#[allow(deprecated)] +impl From> for ValuesAttr { + #[inline] + fn from(value: Vec) -> Self { + Self(value) + } +} + +#[allow(deprecated)] +impl AsRef<[i64]> for ValuesAttr { + #[inline] + fn as_ref(&self) -> &[i64] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for ValuesAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + ::std::fmt::Display::fmt(value, formatter)?; + } + formatter.write_str("]") + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + #[inline] + fn from(value: ValuesAttr) -> Self { + ::opentelemetry::KeyValue::new(ValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) + } +} diff --git a/templates/code/rust/tests/allocations/expected/probeevent.rs b/templates/code/rust/tests/allocations/expected/probeevent.rs new file mode 100644 index 0000000..be2ebfc --- /dev/null +++ b/templates/code/rust/tests/allocations/expected/probeevent.rs @@ -0,0 +1,45 @@ +#![allow(deprecated)] +use ::opentelemetry::logs::LogRecord; +use ::opentelemetry::trace::TraceContextExt; + +#[derive(Clone, Debug)] +pub enum RecordedOption { + Severity(::opentelemetry::logs::Severity), + Timestamp(::std::time::SystemTime), + Optional(super::probeattr::OptionalAttr), + Values(super::probeattr::ValuesAttr), +} +/// A measurement was recorded. +pub fn r#emit_recorded(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#probe_required: super::probeattr::RequiredAttr, options: impl IntoIterator) { + let mut severity = ::opentelemetry::logs::Severity::Info; + let mut timestamp = None; + let mut attributes = ::smallvec::SmallVec::<[RecordedOption; 2]>::new(); + for option in options { + match option { + RecordedOption::Severity(value) => severity = value, + RecordedOption::Timestamp(value) => timestamp = Some(value), + attribute => attributes.push(attribute), + } + } + if !logger.inner().event_enabled(severity, "", Some("probe.recorded")) { return; } + let _context_guard = context.clone().attach(); + let mut record = logger.inner().create_log_record(); + record.set_event_name("probe.recorded"); + record.set_severity_number(severity); + record.set_observed_timestamp(::std::time::SystemTime::now()); + if let Some(timestamp) = timestamp { record.set_timestamp(timestamp); } + let span = context.span(); + let span_context = span.span_context(); + if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } + let attribute = ::opentelemetry::KeyValue::from(r#probe_required); + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + for option in attributes { + let attribute = match option { + RecordedOption::Optional(value) => ::opentelemetry::KeyValue::from(value), + RecordedOption::Values(value) => ::opentelemetry::KeyValue::from(value), + RecordedOption::Severity(_) | RecordedOption::Timestamp(_) => continue, + }; + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } + logger.inner().emit(record); +} diff --git a/templates/code/rust/tests/allocations/expected/probemetric.rs b/templates/code/rust/tests/allocations/expected/probemetric.rs new file mode 100644 index 0000000..f047133 --- /dev/null +++ b/templates/code/rust/tests/allocations/expected/probemetric.rs @@ -0,0 +1,100 @@ +#![allow(deprecated)] +#[derive(Clone, Debug)] +pub enum OptionalCounterAttr { + Optional(super::probeattr::OptionalAttr), +} +impl From for ::opentelemetry::KeyValue { + fn from(value: OptionalCounterAttr) -> Self { + match value { + OptionalCounterAttr::Optional(value) => ::opentelemetry::KeyValue::from(value), + } + } +} +/// Measurements with optional numeric attributes. +#[derive(Clone)] +pub struct OptionalCounter { instrument: ::opentelemetry::metrics::Counter } +impl OptionalCounter { + pub fn new(meter: &super::meter::Meter) -> Self { + let instrument = meter.inner().u64_counter("probe.optional") + .with_description("Measurements with optional numeric attributes.") + .with_unit("{measurement}") + .build(); + Self { instrument } + } + pub fn add(&self, value: u64, r#probe_required: super::probeattr::RequiredAttr, options: impl IntoIterator) { + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 2]>::new(); + attributes.extend([::opentelemetry::KeyValue::from(r#probe_required)]); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); + self.instrument.add(value, &attributes); + } +} +impl Default for OptionalCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} +pub struct OptionalCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl OptionalCounterObserver<'_> { + pub fn observe(&self, value: u64, r#probe_required: super::probeattr::RequiredAttr, options: impl IntoIterator) { + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 2]>::new(); + attributes.extend([::opentelemetry::KeyValue::from(r#probe_required)]); + attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); + self.observer.observe(value, &attributes); + } +} + +#[derive(Clone)] +pub struct OptionalObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +impl OptionalObservableCounter { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(OptionalCounterObserver<'_>) + Send + Sync + 'static) -> Self { + let instrument = meter.inner().u64_observable_counter("probe.optional") + .with_description("Measurements with optional numeric attributes.") + .with_unit("{measurement}") + .with_callback(move |observer| callback(OptionalCounterObserver { observer })) + .build(); + Self { _instrument: instrument } + } +} +impl Default for OptionalObservableCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} +/// Measurements with a required numeric attribute. +#[derive(Clone)] +pub struct RequiredCounter { instrument: ::opentelemetry::metrics::Counter } +impl RequiredCounter { + pub fn new(meter: &super::meter::Meter) -> Self { + let instrument = meter.inner().u64_counter("probe.required") + .with_description("Measurements with a required numeric attribute.") + .with_unit("{measurement}") + .build(); + Self { instrument } + } + pub fn add(&self, value: u64, r#probe_required: super::probeattr::RequiredAttr) { + let attributes = [::opentelemetry::KeyValue::from(r#probe_required)]; + self.instrument.add(value, &attributes); + } +} +impl Default for RequiredCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default()) } +} +pub struct RequiredCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +impl RequiredCounterObserver<'_> { + pub fn observe(&self, value: u64, r#probe_required: super::probeattr::RequiredAttr) { + let attributes = [::opentelemetry::KeyValue::from(r#probe_required)]; + self.observer.observe(value, &attributes); + } +} + +#[derive(Clone)] +pub struct RequiredObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +impl RequiredObservableCounter { + pub fn new(meter: &super::meter::Meter, callback: impl Fn(RequiredCounterObserver<'_>) + Send + Sync + 'static) -> Self { + let instrument = meter.inner().u64_observable_counter("probe.required") + .with_description("Measurements with a required numeric attribute.") + .with_unit("{measurement}") + .with_callback(move |observer| callback(RequiredCounterObserver { observer })) + .build(); + Self { _instrument: instrument } + } +} +impl Default for RequiredObservableCounter { + fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } +} diff --git a/templates/code/rust/tests/allocations/registry/manifest.yaml b/templates/code/rust/tests/allocations/registry/manifest.yaml new file mode 100644 index 0000000..8eb25e8 --- /dev/null +++ b/templates/code/rust/tests/allocations/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: synthetic-allocation-fixture +schema_url: https://example.com/schemas/allocations/1.0.0 diff --git a/templates/code/rust/tests/allocations/registry/model.yaml b/templates/code/rust/tests/allocations/registry/model.yaml new file mode 100644 index 0000000..7ef9979 --- /dev/null +++ b/templates/code/rust/tests/allocations/registry/model.yaml @@ -0,0 +1,55 @@ +file_format: definition/2 +attributes: + - key: probe.required + type: int + stability: stable + brief: Required numeric measurement identity. + examples: 1 + - key: probe.optional + type: int + stability: stable + brief: Optional numeric measurement identity. + examples: 2 + - key: probe.values + type: int[] + stability: stable + brief: Numeric values attached to an event. + examples: [1, 2] +metrics: + - name: probe.required + requirement_level: recommended + instrument: counter + unit: "{measurement}" + stability: stable + brief: Measurements with a required numeric attribute. + annotations: + code_generation: + metric_value_type: int + attributes: + - ref: probe.required + requirement_level: required + - name: probe.optional + requirement_level: recommended + instrument: counter + unit: "{measurement}" + stability: stable + brief: Measurements with optional numeric attributes. + annotations: + code_generation: + metric_value_type: int + attributes: + - ref: probe.required + requirement_level: required + - ref: probe.optional + requirement_level: recommended +events: + - name: probe.recorded + stability: stable + brief: A measurement was recorded. + attributes: + - ref: probe.required + requirement_level: required + - ref: probe.optional + requirement_level: recommended + - ref: probe.values + requirement_level: recommended diff --git a/templates/code/rust/tests/allocations/test.rs b/templates/code/rust/tests/allocations/test.rs new file mode 100644 index 0000000..96fcca7 --- /dev/null +++ b/templates/code/rust/tests/allocations/test.rs @@ -0,0 +1,438 @@ +use generated_semconv::{logger, meter, probeattr, probeevent, probemetric}; +use opentelemetry::logs::{AnyValue, LogRecord, Logger, LoggerProvider, Severity}; +use opentelemetry::metrics::{ + AsyncInstrument, AsyncInstrumentBuilder, Callback, Counter, InstrumentBuilder, + InstrumentProvider, Meter, MeterProvider, ObservableCounter, SyncInstrument, +}; +use opentelemetry::{Context, InstrumentationScope, Key, KeyValue}; +use std::alloc::{GlobalAlloc, Layout, System}; +use std::borrow::Cow; +use std::cell::Cell; +use std::hint::black_box; +use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU64, AtomicUsize, Ordering}; +use std::sync::{Arc, Mutex}; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +thread_local! { + static ALLOCATIONS: Cell> = const { Cell::new(None) }; +} + +struct AllocationCounter; + +unsafe impl GlobalAlloc for AllocationCounter { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let _ = ALLOCATIONS.try_with(|count| { + if let Some(value) = count.get() { + count.set(Some(value + 1)); + } + }); + unsafe { System.alloc(layout) } + } + + unsafe fn dealloc(&self, pointer: *mut u8, layout: Layout) { + unsafe { System.dealloc(pointer, layout) } + } + + unsafe fn realloc(&self, pointer: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + let _ = ALLOCATIONS.try_with(|count| { + if let Some(value) = count.get() { + count.set(Some(value + 1)); + } + }); + unsafe { System.realloc(pointer, layout, new_size) } + } +} + +#[global_allocator] +static ALLOCATOR: AllocationCounter = AllocationCounter; + +fn allocations(work: impl FnOnce()) -> usize { + ALLOCATIONS.with(|count| count.set(Some(0))); + work(); + ALLOCATIONS.with(|count| count.replace(None).unwrap()) +} + +#[derive(Default)] +struct MetricState { + attribute_count: AtomicUsize, + sum: AtomicI64, + order: AtomicU64, + callbacks: Mutex>>, +} + +struct MetricProvider(Arc); + +impl MeterProvider for MetricProvider { + fn meter_with_scope(&self, _: InstrumentationScope) -> Meter { + Meter::new(Arc::new(Self(self.0.clone()))) + } +} + +impl InstrumentProvider for MetricProvider { + fn u64_counter(&self, _: InstrumentBuilder<'_, Counter>) -> Counter { + Counter::new(Arc::new(Self(self.0.clone()))) + } + fn u64_observable_counter( + &self, + builder: AsyncInstrumentBuilder<'_, ObservableCounter, u64>, + ) -> ObservableCounter { + self.0.callbacks.lock().unwrap().extend(builder.callbacks); + ObservableCounter::new() + } +} + +impl AsyncInstrument for MetricProvider { + fn observe(&self, value: u64, attributes: &[KeyValue]) { + self.measure(value, attributes); + } +} + +struct BorrowedMeterProvider { + meter: Meter, + scope: Mutex>, +} + +impl MeterProvider for BorrowedMeterProvider { + fn meter_with_scope(&self, scope: InstrumentationScope) -> Meter { + *self.scope.lock().unwrap() = Some(scope); + self.meter.clone() + } +} + +impl SyncInstrument for MetricProvider { + fn measure(&self, _: u64, attributes: &[KeyValue]) { + black_box(attributes); + self.0 + .attribute_count + .store(attributes.len(), Ordering::Relaxed); + self.0.sum.store( + attributes + .iter() + .map(|attr| match attr.value { + opentelemetry::Value::I64(value) => value, + _ => 0, + }) + .sum(), + Ordering::Relaxed, + ); + self.0.order.store( + attributes + .iter() + .fold(0_u64, |hash, attr| match attr.value { + opentelemetry::Value::I64(value) => { + hash.wrapping_mul(31).wrapping_add(value as u64) + } + _ => hash, + }), + Ordering::Relaxed, + ); + } +} + +#[derive(Default)] +struct LogState { + enabled: AtomicBool, + attribute_count: AtomicUsize, + attribute_sum: AtomicI64, + severity: AtomicUsize, + context_attached_during_check: AtomicBool, + order: AtomicU64, + timestamp: AtomicU64, + scope: Mutex>, +} + +struct ExplicitContext; +struct LogProvider(Arc); +struct FakeLogger(Arc); + +impl LoggerProvider for LogProvider { + type Logger = FakeLogger; + + fn logger_with_scope(&self, scope: InstrumentationScope) -> Self::Logger { + *self.0.scope.lock().unwrap() = Some(scope); + FakeLogger(self.0.clone()) + } +} + +#[derive(Default)] +struct FakeRecord { + attributes: usize, + sum: i64, + severity: usize, + order: u64, + timestamp: u64, +} + +impl LogRecord for FakeRecord { + fn set_event_name(&mut self, _: &'static str) {} + fn set_target>>(&mut self, _: T) {} + fn set_timestamp(&mut self, value: SystemTime) { + self.timestamp = value.duration_since(UNIX_EPOCH).unwrap().as_secs(); + } + fn set_observed_timestamp(&mut self, _: SystemTime) {} + fn set_severity_text(&mut self, _: &'static str) {} + fn set_severity_number(&mut self, value: Severity) { + self.severity = value as usize; + } + fn set_body(&mut self, _: AnyValue) {} + fn add_attributes(&mut self, values: I) + where + I: IntoIterator, + K: Into, + V: Into, + { + for (key, value) in values { + self.add_attribute(key, value); + } + } + fn add_attribute, V: Into>(&mut self, key: K, value: V) { + black_box(key.into()); + self.attributes += 1; + if let AnyValue::Int(value) = value.into() { + self.sum += value; + self.order = self.order.wrapping_mul(31).wrapping_add(value as u64); + } + } +} + +impl Logger for FakeLogger { + type LogRecord = FakeRecord; + fn create_log_record(&self) -> FakeRecord { + FakeRecord::default() + } + fn emit(&self, record: FakeRecord) { + self.0 + .attribute_count + .store(record.attributes, Ordering::Relaxed); + self.0.attribute_sum.store(record.sum, Ordering::Relaxed); + self.0.severity.store(record.severity, Ordering::Relaxed); + self.0.order.store(record.order, Ordering::Relaxed); + self.0.timestamp.store(record.timestamp, Ordering::Relaxed); + } + fn event_enabled(&self, _: Severity, _: &str, _: Option<&str>) -> bool { + self.0.context_attached_during_check.store( + Context::current().get::().is_some(), + Ordering::Relaxed, + ); + self.0.enabled.load(Ordering::Relaxed) + } +} + +#[test] +fn metrics_use_no_generated_heap_for_required_or_typical_optional_attributes() { + let state = Arc::new(MetricState::default()); + let meter = meter::Meter::new(&MetricProvider(state.clone()), "allocation-test"); + let required = probemetric::RequiredCounter::new(&meter); + let optional = probemetric::OptionalCounter::new(&meter); + let required_count = allocations(|| required.add(1, probeattr::RequiredAttr::from(3))); + assert_eq!( + required_count, 0, + "required metric attribute buffer allocated" + ); + let optional_count = allocations(|| { + optional.add( + 1, + probeattr::RequiredAttr::from(3), + [probemetric::OptionalCounterAttr::Optional( + probeattr::OptionalAttr::from(5), + )], + ) + }); + assert_eq!( + optional_count, 0, + "ordinary optional metric attributes allocated" + ); + assert_eq!(state.attribute_count.load(Ordering::Relaxed), 2); + assert_eq!(state.sum.load(Ordering::Relaxed), 8); + optional.add( + 1, + probeattr::RequiredAttr::from(3), + (0..20).map(|value| { + probemetric::OptionalCounterAttr::Optional(probeattr::OptionalAttr::from(value)) + }), + ); + assert_eq!(state.attribute_count.load(Ordering::Relaxed), 21); + assert_eq!(state.sum.load(Ordering::Relaxed), 193); + assert_eq!( + state.order.load(Ordering::Relaxed), + (0..20_u64).fold(3_u64, |hash, value| hash + .wrapping_mul(31) + .wrapping_add(value)) + ); + println!("generated metric allocations: required={required_count}, optional={optional_count}"); +} + +#[test] +fn observable_measurements_use_stack_attribute_storage() { + let state = Arc::new(MetricState::default()); + let provider = MetricProvider(state.clone()); + let meter = meter::Meter::new(&provider, "allocation-test"); + let _required = probemetric::RequiredObservableCounter::new(&meter, |observer| { + observer.observe(1, probeattr::RequiredAttr::from(3)); + }); + let _optional = probemetric::OptionalObservableCounter::new(&meter, |observer| { + observer.observe( + 1, + probeattr::RequiredAttr::from(3), + [probemetric::OptionalCounterAttr::Optional( + probeattr::OptionalAttr::from(5), + )], + ); + }); + let callbacks = state.callbacks.lock().unwrap(); + let count = allocations(|| { + for callback in callbacks.iter() { + callback(&provider); + } + }); + assert_eq!(count, 0); + assert_eq!(state.attribute_count.load(Ordering::Relaxed), 2); + assert_eq!(state.sum.load(Ordering::Relaxed), 8); + println!("generated observable metric allocations: {count}"); +} + +#[test] +fn static_meter_and_logger_scope_names_remain_borrowed() { + let metric_provider = BorrowedMeterProvider { + meter: Meter::new(Arc::new(MetricProvider(Arc::new(MetricState::default())))), + scope: Mutex::new(None), + }; + drop(metric_provider.scope.lock().unwrap()); + let metric_count = allocations(|| { + black_box(meter::Meter::new(&metric_provider, "allocation-test")); + }); + let log_provider = LogProvider(Arc::new(LogState::default())); + drop(log_provider.0.scope.lock().unwrap()); + let log_count = allocations(|| { + black_box(logger::Logger::new(&log_provider, "allocation-test")); + }); + assert_eq!(metric_count, 0); + assert_eq!(log_count, 0); + println!("generated static scope allocations: meter={metric_count}, logger={log_count}"); +} + +#[test] +fn matching_scopes_move_metadata_without_rebuilding_storage() { + let metric_provider = BorrowedMeterProvider { + meter: Meter::new(Arc::new(MetricProvider(Arc::new(MetricState::default())))), + scope: Mutex::new(None), + }; + let log_provider = LogProvider(Arc::new(LogState::default())); + drop(metric_provider.scope.lock().unwrap()); + drop(log_provider.0.scope.lock().unwrap()); + let scope = || { + InstrumentationScope::builder("allocation-test") + .with_version("1.2.3") + .with_schema_url(generated_semconv::SCHEMA_URL) + .with_attributes([KeyValue::new("scope.identity", 7_i64)]) + .build() + }; + let metric_scope = scope(); + let log_scope = scope(); + let metric_count = allocations(|| { + black_box(meter::Meter::new_with_scope(&metric_provider, metric_scope)); + }); + let log_count = allocations(|| { + black_box(logger::Logger::new_with_scope(&log_provider, log_scope)); + }); + assert_eq!(metric_count, 0); + assert_eq!(log_count, 0); + for stored in [ + metric_provider.scope.lock().unwrap(), + log_provider.0.scope.lock().unwrap(), + ] { + let scope = stored.as_ref().unwrap(); + assert_eq!(scope.name(), "allocation-test"); + assert_eq!(scope.version(), Some("1.2.3")); + assert_eq!(scope.schema_url(), Some(generated_semconv::SCHEMA_URL)); + assert_eq!( + scope.attributes().collect::>(), + [&KeyValue::new("scope.identity", 7_i64)] + ); + } + println!("generated matching scope allocations: meter={metric_count}, logger={log_count}"); +} + +#[test] +fn enabled_events_use_no_generated_heap_and_preserve_duplicate_attributes() { + let state = Arc::new(LogState::default()); + state.enabled.store(true, Ordering::Relaxed); + let logger = logger::Logger::new(&LogProvider(state.clone()), "allocation-test"); + let context = Context::new(); + probeevent::emit_recorded(&context, &logger, probeattr::RequiredAttr::from(3), []); + let count = allocations(|| { + probeevent::emit_recorded( + &context, + &logger, + probeattr::RequiredAttr::from(3), + [probeevent::RecordedOption::Optional( + probeattr::OptionalAttr::from(5), + )], + ) + }); + assert_eq!(count, 0, "ordinary enabled event attributes allocated"); + assert_eq!(state.attribute_count.load(Ordering::Relaxed), 2); + assert_eq!(state.attribute_sum.load(Ordering::Relaxed), 8); + probeevent::emit_recorded( + &context, + &logger, + probeattr::RequiredAttr::from(3), + (0..20).map(|value| { + probeevent::RecordedOption::Optional(probeattr::OptionalAttr::from(value)) + }), + ); + assert_eq!(state.attribute_count.load(Ordering::Relaxed), 21); + assert_eq!(state.attribute_sum.load(Ordering::Relaxed), 193); + assert_eq!( + state.order.load(Ordering::Relaxed), + (0..20_u64).fold(3_u64, |hash, value| hash + .wrapping_mul(31) + .wrapping_add(value)) + ); + let configuration_count = allocations(|| { + probeevent::emit_recorded( + &context, + &logger, + probeattr::RequiredAttr::from(3), + [ + probeevent::RecordedOption::Severity(Severity::Warn), + probeevent::RecordedOption::Timestamp(UNIX_EPOCH + Duration::from_secs(10)), + probeevent::RecordedOption::Severity(Severity::Error), + probeevent::RecordedOption::Timestamp(UNIX_EPOCH + Duration::from_secs(20)), + ], + ) + }); + assert_eq!(configuration_count, 0); + assert_eq!( + state.severity.load(Ordering::Relaxed), + Severity::Error as usize + ); + assert_eq!(state.timestamp.load(Ordering::Relaxed), 20); + println!("generated enabled event allocations: attributes={count}, configuration={configuration_count}"); +} + +#[test] +fn disabled_events_defer_context_attachment_and_attribute_conversion() { + let state = Arc::new(LogState::default()); + let logger = logger::Logger::new(&LogProvider(state.clone()), "allocation-test"); + let context = Context::new().with_value(ExplicitContext); + let values = probeattr::ValuesAttr::from(vec![1, 2, 3]); + probeevent::emit_recorded( + &Context::new(), + &logger, + probeattr::RequiredAttr::from(0), + [], + ); + let count = allocations(|| { + probeevent::emit_recorded( + &context, + &logger, + probeattr::RequiredAttr::from(3), + [probeevent::RecordedOption::Values(values)], + ) + }); + assert_eq!(count, 0, "disabled event attributes allocated"); + assert!(!state.context_attached_during_check.load(Ordering::Relaxed)); + assert_eq!(state.attribute_count.load(Ordering::Relaxed), 0); + println!("generated disabled event allocations: {count}"); +} diff --git a/templates/code/rust/tests/attributes/compile-fail/dynamic_borrow.expected-error.txt b/templates/code/rust/tests/attributes/compile-fail/dynamic_borrow.expected-error.txt new file mode 100644 index 0000000..1a48ea1 --- /dev/null +++ b/templates/code/rust/tests/attributes/compile-fail/dynamic_borrow.expected-error.txt @@ -0,0 +1 @@ +does not live long enough diff --git a/templates/code/rust/tests/attributes/compile-fail/dynamic_borrow.rs b/templates/code/rust/tests/attributes/compile-fail/dynamic_borrow.rs new file mode 100644 index 0000000..0816e72 --- /dev/null +++ b/templates/code/rust/tests/attributes/compile-fail/dynamic_borrow.rs @@ -0,0 +1,4 @@ +fn main() { + let source = String::from("dynamic"); + let _ = generated_semconv::myappattr::TaskIdAttr::from(source.as_str()); +} diff --git a/templates/code/rust/tests/attributes/expected/authattr.rs b/templates/code/rust/tests/attributes/expected/authattr.rs index 2104493..bfc631a 100644 --- a/templates/code/rust/tests/attributes/expected/authattr.rs +++ b/templates/code/rust/tests/attributes/expected/authattr.rs @@ -13,8 +13,21 @@ impl LevelAttr { pub const KEY: &'static str = "auth.level"; } +#[allow(deprecated)] +impl ::std::fmt::Display for LevelAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + let value: i64 = match self { + LevelAttr::Low => 1, + LevelAttr::High => 2, + }; + ::std::fmt::Display::fmt(&value, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: LevelAttr) -> Self { let value: i64 = match value { LevelAttr::Low => 1, @@ -37,40 +50,87 @@ impl MethodAttr { pub const KEY: &'static str = "auth.method"; } +#[allow(deprecated)] +impl AsRef for MethodAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + MethodAttr::Password => "password", + MethodAttr::Token => "token", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for MethodAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: MethodAttr) -> Self { - let value: String = match value { - MethodAttr::Password => "password".into(), - MethodAttr::Token => "token".into(), + let value: &'static str = match value { + MethodAttr::Password => "password", + MethodAttr::Token => "token", }; ::opentelemetry::KeyValue::new(MethodAttr::KEY, value) } } /// Identifier of the authenticated user. #[derive(Debug, Clone, PartialEq)] -pub struct UserIdAttr(String); +pub struct UserIdAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl UserIdAttr { pub const KEY: &'static str = "auth.user.id"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for UserIdAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for UserIdAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for UserIdAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for UserIdAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for UserIdAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for UserIdAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: UserIdAttr) -> Self { ::opentelemetry::KeyValue::new(UserIdAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/attributes/expected/myappattr.rs b/templates/code/rust/tests/attributes/expected/myappattr.rs index 54148ea..fe74394 100644 --- a/templates/code/rust/tests/attributes/expected/myappattr.rs +++ b/templates/code/rust/tests/attributes/expected/myappattr.rs @@ -3,34 +3,61 @@ /// /// The scheduler sets it on every task it passes along to `myapp.task.state`. Workers never set it themselves. #[derive(Debug, Clone, PartialEq)] -pub struct TaskAssignedByAttr(String); +pub struct TaskAssignedByAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl TaskAssignedByAttr { pub const KEY: &'static str = "myapp.task.assigned_by"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for TaskAssignedByAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for TaskAssignedByAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) } } + #[allow(deprecated)] -impl From<&str> for TaskAssignedByAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl From<&'static str> for TaskAssignedByAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl AsRef for TaskAssignedByAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskAssignedByAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskAssignedByAttr) -> Self { ::opentelemetry::KeyValue::new(TaskAssignedByAttr::KEY, value.0) } } /// Whether the task was cancelled. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskCancelledAttr(bool); #[allow(deprecated)] @@ -40,13 +67,23 @@ impl TaskCancelledAttr { #[allow(deprecated)] impl From for TaskCancelledAttr { + #[inline] fn from(value: bool) -> Self { Self(value) } } +#[allow(deprecated)] +impl ::std::fmt::Display for TaskCancelledAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskCancelledAttr) -> Self { ::opentelemetry::KeyValue::new(TaskCancelledAttr::KEY, value.0) } @@ -63,11 +100,30 @@ impl TaskEscapedAttr { pub const KEY: &'static str = "myapp.task.escaped"; } +#[allow(deprecated)] +impl AsRef for TaskEscapedAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + TaskEscapedAttr::Quoted => "quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskEscapedAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskEscapedAttr) -> Self { - let value: String = match value { - TaskEscapedAttr::Quoted => "quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃".into(), + let value: &'static str = match value { + TaskEscapedAttr::Quoted => "quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃", }; ::opentelemetry::KeyValue::new(TaskEscapedAttr::KEY, value) } @@ -83,13 +139,37 @@ impl TaskFlagsAttr { #[allow(deprecated)] impl From> for TaskFlagsAttr { + #[inline] fn from(value: Vec) -> Self { Self(value) } } +#[allow(deprecated)] +impl AsRef<[bool]> for TaskFlagsAttr { + #[inline] + fn as_ref(&self) -> &[bool] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskFlagsAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + ::std::fmt::Display::fmt(value, formatter)?; + } + formatter.write_str("]") + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskFlagsAttr) -> Self { ::opentelemetry::KeyValue::new(TaskFlagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(value.0))) } @@ -98,28 +178,55 @@ impl From for ::opentelemetry::KeyValue { /// /// The identifier is assigned by the scheduler and stays stable across retries. #[derive(Debug, Clone, PartialEq)] -pub struct TaskIdAttr(String); +pub struct TaskIdAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for TaskIdAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for TaskIdAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) } } + #[allow(deprecated)] -impl From<&str> for TaskIdAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl From<&'static str> for TaskIdAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl AsRef for TaskIdAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskIdAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskIdAttr) -> Self { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } @@ -141,12 +248,32 @@ impl TaskLaneAttr { pub const KEY: &'static str = "myapp.task.lane"; } +#[allow(deprecated)] +impl AsRef for TaskLaneAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + TaskLaneAttr::Fast => "fast", + TaskLaneAttr::Slow => "slow", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskLaneAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskLaneAttr) -> Self { - let value: String = match value { - TaskLaneAttr::Fast => "fast".into(), - TaskLaneAttr::Slow => "slow".into(), + let value: &'static str = match value { + TaskLaneAttr::Fast => "fast", + TaskLaneAttr::Slow => "slow", }; ::opentelemetry::KeyValue::new(TaskLaneAttr::KEY, value) } @@ -154,28 +281,55 @@ impl From for ::opentelemetry::KeyValue { /// Owner of the task. #[deprecated(note = "Replaced by `auth.user.id`.")] #[derive(Debug, Clone, PartialEq)] -pub struct TaskOwnerAttr(String); +pub struct TaskOwnerAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl TaskOwnerAttr { pub const KEY: &'static str = "myapp.task.owner"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for TaskOwnerAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for TaskOwnerAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for TaskOwnerAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + #[allow(deprecated)] -impl From<&str> for TaskOwnerAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl AsRef for TaskOwnerAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskOwnerAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskOwnerAttr) -> Self { ::opentelemetry::KeyValue::new(TaskOwnerAttr::KEY, value.0) } @@ -194,8 +348,21 @@ impl TaskPreemptibleAttr { pub const KEY: &'static str = "myapp.task.preemptible"; } +#[allow(deprecated)] +impl ::std::fmt::Display for TaskPreemptibleAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + let value: bool = match self { + TaskPreemptibleAttr::Allowed => true, + TaskPreemptibleAttr::Forbidden => false, + }; + ::std::fmt::Display::fmt(&value, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskPreemptibleAttr) -> Self { let value: bool = match value { TaskPreemptibleAttr::Allowed => true, @@ -205,7 +372,7 @@ impl From for ::opentelemetry::KeyValue { } } /// Fraction of the task that has completed, between 0 and 1. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskProgressAttr(f64); #[allow(deprecated)] @@ -215,19 +382,29 @@ impl TaskProgressAttr { #[allow(deprecated)] impl From for TaskProgressAttr { + #[inline] fn from(value: f64) -> Self { Self(value) } } +#[allow(deprecated)] +impl ::std::fmt::Display for TaskProgressAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskProgressAttr) -> Self { ::opentelemetry::KeyValue::new(TaskProgressAttr::KEY, value.0) } } /// Number of times the task was retried. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskRetriesAttr(i64); #[allow(deprecated)] @@ -237,13 +414,23 @@ impl TaskRetriesAttr { #[allow(deprecated)] impl From for TaskRetriesAttr { + #[inline] fn from(value: i64) -> Self { Self(value) } } +#[allow(deprecated)] +impl ::std::fmt::Display for TaskRetriesAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskRetriesAttr) -> Self { ::opentelemetry::KeyValue::new(TaskRetriesAttr::KEY, value.0) } @@ -262,8 +449,21 @@ impl TaskSampleRateAttr { pub const KEY: &'static str = "myapp.task.sample_rate"; } +#[allow(deprecated)] +impl ::std::fmt::Display for TaskSampleRateAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + let value: f64 = match self { + TaskSampleRateAttr::Tenth => 0.1_f64, + TaskSampleRateAttr::All => 1_f64, + }; + ::std::fmt::Display::fmt(&value, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskSampleRateAttr) -> Self { let value: f64 = match value { TaskSampleRateAttr::Tenth => 0.1_f64, @@ -283,13 +483,37 @@ impl TaskShardIdsAttr { #[allow(deprecated)] impl From> for TaskShardIdsAttr { + #[inline] fn from(value: Vec) -> Self { Self(value) } } +#[allow(deprecated)] +impl AsRef<[i64]> for TaskShardIdsAttr { + #[inline] + fn as_ref(&self) -> &[i64] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskShardIdsAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + ::std::fmt::Display::fmt(value, formatter)?; + } + formatter.write_str("]") + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskShardIdsAttr) -> Self { ::opentelemetry::KeyValue::new(TaskShardIdsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) } @@ -313,37 +537,88 @@ impl TaskStateAttr { pub const KEY: &'static str = "myapp.task.state"; } +#[allow(deprecated)] +impl AsRef for TaskStateAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + TaskStateAttr::Queued => "queued", + TaskStateAttr::Running => "running", + TaskStateAttr::Paused => "paused", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskStateAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskStateAttr) -> Self { - let value: String = match value { - TaskStateAttr::Queued => "queued".into(), - TaskStateAttr::Running => "running".into(), - TaskStateAttr::Paused => "paused".into(), + let value: &'static str = match value { + TaskStateAttr::Queued => "queued", + TaskStateAttr::Running => "running", + TaskStateAttr::Paused => "paused", }; ::opentelemetry::KeyValue::new(TaskStateAttr::KEY, value) } } /// Tags attached to the task. #[derive(Debug, Clone, PartialEq)] -pub struct TaskTagsAttr(Vec); +pub struct TaskTagsAttr(Vec<::opentelemetry::StringValue>); #[allow(deprecated)] impl TaskTagsAttr { pub const KEY: &'static str = "myapp.task.tags"; } +#[allow(deprecated)] +impl From> for TaskTagsAttr { + #[inline] + fn from(value: Vec<::opentelemetry::StringValue>) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From> for TaskTagsAttr { fn from(value: Vec) -> Self { - Self(value) + Self(value.into_iter().map(Into::into).collect()) + } +} + +#[allow(deprecated)] +impl AsRef<[::opentelemetry::StringValue]> for TaskTagsAttr { + #[inline] + fn as_ref(&self) -> &[::opentelemetry::StringValue] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskTagsAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + write!(formatter, "\"{value}\"")?; + } + formatter.write_str("]") } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskTagsAttr) -> Self { - ::opentelemetry::KeyValue::new(TaskTagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0.into_iter().map(Into::into).collect()))) + ::opentelemetry::KeyValue::new(TaskTagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0))) } } /// Scheduling weights applied to the task. @@ -357,13 +632,37 @@ impl TaskWeightsAttr { #[allow(deprecated)] impl From> for TaskWeightsAttr { + #[inline] fn from(value: Vec) -> Self { Self(value) } } +#[allow(deprecated)] +impl AsRef<[f64]> for TaskWeightsAttr { + #[inline] + fn as_ref(&self) -> &[f64] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskWeightsAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + ::std::fmt::Display::fmt(value, formatter)?; + } + formatter.write_str("]") + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskWeightsAttr) -> Self { ::opentelemetry::KeyValue::new(TaskWeightsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(value.0))) } diff --git a/templates/code/rust/tests/attributes/test.rs b/templates/code/rust/tests/attributes/test.rs index 6d3eaf5..bba8a21 100644 --- a/templates/code/rust/tests/attributes/test.rs +++ b/templates/code/rust/tests/attributes/test.rs @@ -19,7 +19,7 @@ fn typed_attributes_preserve_keys_values_and_schema() { Value::F64(0.5) ); assert_eq!( - KeyValue::from(myappattr::TaskTagsAttr::from(vec!["tag".into()])).value, + KeyValue::from(myappattr::TaskTagsAttr::from(vec![String::from("tag")])).value, Value::Array(Array::String(vec!["tag".into()])) ); assert_eq!( @@ -54,11 +54,11 @@ fn typed_attributes_preserve_keys_values_and_schema() { } #[test] -fn string_attributes_accept_borrowed_owned_and_inferred_conversions() { +fn string_attributes_accept_explicit_owned_and_inferred_conversions() { let owned = String::from("owned"); let borrowed: myappattr::TaskIdAttr = { let source = String::from("borrowed"); - source.as_str().into() + source.into() }; assert_eq!( KeyValue::from(myappattr::TaskIdAttr::from(owned)), @@ -81,3 +81,64 @@ fn string_attributes_accept_borrowed_owned_and_inferred_conversions() { Value::Array(Array::String(vec!["tag".into()])) ); } + +#[test] +fn static_and_native_strings_preserve_their_storage() { + const STATIC: &str = "static-task"; + let attribute = myappattr::TaskIdAttr::from(STATIC); + assert_eq!(attribute.as_ref().as_ptr(), STATIC.as_ptr()); + let Value::String(text) = KeyValue::from(attribute).value else { + panic!("expected string"); + }; + assert_eq!(text.as_str().as_ptr(), STATIC.as_ptr()); + let Value::String(text) = KeyValue::from(myappattr::TaskStateAttr::Running).value else { + panic!("expected string"); + }; + assert_eq!(text.as_str(), myappattr::TaskStateAttr::Running.as_ref()); + + let shared: std::sync::Arc = std::sync::Arc::from("shared-task"); + let native = opentelemetry::StringValue::from(shared.clone()); + let attribute = myappattr::TaskIdAttr::from(native); + assert_eq!(attribute.as_ref().as_ptr(), shared.as_ptr()); + let Value::String(text) = KeyValue::from(attribute).value else { + panic!("expected string"); + }; + assert_eq!(text.as_str().as_ptr(), shared.as_ptr()); + assert_eq!(std::sync::Arc::strong_count(&shared), 2); + + let native = vec![opentelemetry::StringValue::from("tag")]; + let original = native.as_ptr(); + let Value::Array(Array::String(values)) = + KeyValue::from(myappattr::TaskTagsAttr::from(native)).value + else { + panic!("expected string array"); + }; + assert_eq!(values.as_ptr(), original); +} + +#[test] +fn copy_scalars_and_borrowed_display_preserve_telemetry_formatting() { + fn assert_copy() {} + assert_copy::(); + assert_copy::(); + assert_copy::(); + assert_copy::(); + let retries = myappattr::TaskRetriesAttr::from(7); + let _: KeyValue = retries.into(); + assert_eq!(retries.to_string(), "7"); + assert_eq!(myappattr::TaskCancelledAttr::from(true).to_string(), "true"); + assert_eq!(myappattr::TaskProgressAttr::from(0.5).to_string(), "0.5"); + assert_eq!(myappattr::TaskStateAttr::Running.to_string(), "running"); + assert_eq!(authattr::LevelAttr::High.to_string(), "2"); + assert_eq!(myappattr::TaskSampleRateAttr::Tenth.to_string(), "0.1"); + let string = myappattr::TaskIdAttr::from(String::from("dynamic")); + assert_eq!(string.to_string(), string.as_ref()); + let array = myappattr::TaskTagsAttr::from(vec![String::from("a"), String::from("b")]); + assert_eq!(array.to_string(), KeyValue::from(array).value.to_string()); + let array = myappattr::TaskShardIdsAttr::from(vec![1, 2]); + assert_eq!(array.to_string(), "[1,2]"); + let array = myappattr::TaskWeightsAttr::from(vec![0.25, 0.5]); + assert_eq!(array.to_string(), "[0.25,0.5]"); + let array = myappattr::TaskFlagsAttr::from(vec![true, false]); + assert_eq!(array.to_string(), "[true,false]"); +} diff --git a/templates/code/rust/tests/attributes/tests/allocations.rs b/templates/code/rust/tests/attributes/tests/allocations.rs new file mode 100644 index 0000000..f415263 --- /dev/null +++ b/templates/code/rust/tests/attributes/tests/allocations.rs @@ -0,0 +1,74 @@ +use generated_semconv::myappattr; +use opentelemetry::{KeyValue, Value}; +use std::alloc::{GlobalAlloc, Layout, System}; +use std::cell::Cell; +use std::hint::black_box; + +struct CountingAllocator; +thread_local! { + static ALLOCATIONS: Cell> = const { Cell::new(None) }; +} +fn record_allocation() { + let _ = ALLOCATIONS.try_with(|count| { + if let Some(value) = count.get() { + count.set(Some(value + 1)); + } + }); +} +unsafe impl GlobalAlloc for CountingAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + record_allocation(); + unsafe { System.alloc(layout) } + } + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + unsafe { System.dealloc(ptr, layout) } + } + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, size: usize) -> *mut u8 { + record_allocation(); + unsafe { System.realloc(ptr, layout, size) } + } +} +#[global_allocator] +static ALLOCATOR: CountingAllocator = CountingAllocator; +fn allocations(operation: impl FnOnce() -> T) -> (T, usize) { + ALLOCATIONS.with(|count| count.set(Some(0))); + let value = operation(); + let count = ALLOCATIONS.with(|count| count.replace(None).unwrap()); + (value, count) +} + +#[test] +fn string_enum_conversion_has_no_heap_allocation() { + let (value, count) = + allocations(|| KeyValue::from(black_box(myappattr::TaskStateAttr::Running))); + assert_eq!(black_box(count), 0); + assert_eq!(value.value, Value::String("running".into())); +} + +#[test] +fn static_string_construction_and_conversion_have_no_heap_allocation() { + let (value, count) = allocations(|| { + let attribute = myappattr::TaskIdAttr::from(black_box("static-task")); + black_box(KeyValue::from(attribute)) + }); + assert_eq!(black_box(count), 0); + assert_eq!(value.value, Value::String("static-task".into())); +} + +#[test] +fn exact_capacity_owned_string_moves_without_another_allocation() { + let mut text = String::from("owned-task"); + text.shrink_to_fit(); + let (value, count) = + allocations(|| KeyValue::from(myappattr::TaskIdAttr::from(black_box(text)))); + assert_eq!(black_box(count), 0); + assert_eq!(value.value, Value::String("owned-task".into())); +} + +#[test] +fn native_string_array_moves_without_another_allocation() { + let values = vec![opentelemetry::StringValue::from("static-tag")]; + let (_, count) = + allocations(|| KeyValue::from(myappattr::TaskTagsAttr::from(black_box(values)))); + assert_eq!(black_box(count), 0); +} diff --git a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs index 1a6121a..d5c49a0 100644 --- a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs +++ b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs @@ -1,28 +1,55 @@ // Generated by OpenTelemetry Weaver. /// Synthetic kept attribute. #[derive(Debug, Clone, PartialEq)] -pub struct KeptAttr(String); +pub struct KeptAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl KeptAttr { pub const KEY: &'static str = "demo.kept"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for KeptAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for KeptAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for KeptAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl AsRef for KeptAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() } } + #[allow(deprecated)] -impl From<&str> for KeptAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for KeptAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: KeptAttr) -> Self { ::opentelemetry::KeyValue::new(KeptAttr::KEY, value.0) } @@ -39,11 +66,30 @@ impl ModeAttr { pub const KEY: &'static str = "demo.mode"; } +#[allow(deprecated)] +impl AsRef for ModeAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + ModeAttr::Kept => "kept", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for ModeAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: ModeAttr) -> Self { - let value: String = match value { - ModeAttr::Kept => "kept".into(), + let value: &'static str = match value { + ModeAttr::Kept => "kept", }; ::opentelemetry::KeyValue::new(ModeAttr::KEY, value) } diff --git a/templates/code/rust/tests/entities/compile-fail/required_default.expected-error.txt b/templates/code/rust/tests/entities/compile-fail/required_default.expected-error.txt new file mode 100644 index 0000000..c16c206 --- /dev/null +++ b/templates/code/rust/tests/entities/compile-fail/required_default.expected-error.txt @@ -0,0 +1 @@ +no associated function or constant named `default` diff --git a/templates/code/rust/tests/entities/compile-fail/required_default.rs b/templates/code/rust/tests/entities/compile-fail/required_default.rs new file mode 100644 index 0000000..648643c --- /dev/null +++ b/templates/code/rust/tests/entities/compile-fail/required_default.rs @@ -0,0 +1,3 @@ +fn main() { + let _ = generated_semconv::myappentity::HostEntity::default(); +} diff --git a/templates/code/rust/tests/entities/expected/myappattr.rs b/templates/code/rust/tests/entities/expected/myappattr.rs index 714adf5..df868b2 100644 --- a/templates/code/rust/tests/entities/expected/myappattr.rs +++ b/templates/code/rust/tests/entities/expected/myappattr.rs @@ -1,7 +1,7 @@ // Generated by OpenTelemetry Weaver. /// Number of CPUs the host has. #[deprecated(note = "Use `myapp.host.cpu.logical_count` instead.")] -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct HostCpuCountAttr(i64); #[allow(deprecated)] @@ -11,69 +11,133 @@ impl HostCpuCountAttr { #[allow(deprecated)] impl From for HostCpuCountAttr { + #[inline] fn from(value: i64) -> Self { Self(value) } } +#[allow(deprecated)] +impl ::std::fmt::Display for HostCpuCountAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: HostCpuCountAttr) -> Self { ::opentelemetry::KeyValue::new(HostCpuCountAttr::KEY, value.0) } } /// Name of the host. #[derive(Debug, Clone, PartialEq)] -pub struct HostNameAttr(String); +pub struct HostNameAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl HostNameAttr { pub const KEY: &'static str = "myapp.host.name"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for HostNameAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for HostNameAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for HostNameAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + #[allow(deprecated)] -impl From<&str> for HostNameAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl AsRef for HostNameAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for HostNameAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: HostNameAttr) -> Self { ::opentelemetry::KeyValue::new(HostNameAttr::KEY, value.0) } } /// Role the host plays in the cluster. #[derive(Debug, Clone, PartialEq)] -pub struct HostRoleAttr(String); +pub struct HostRoleAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl HostRoleAttr { pub const KEY: &'static str = "myapp.host.role"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for HostRoleAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for HostRoleAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for HostRoleAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl AsRef for HostRoleAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() } } + #[allow(deprecated)] -impl From<&str> for HostRoleAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for HostRoleAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: HostRoleAttr) -> Self { ::opentelemetry::KeyValue::new(HostRoleAttr::KEY, value.0) } @@ -92,46 +156,93 @@ impl HostTypeAttr { pub const KEY: &'static str = "myapp.host.type"; } +#[allow(deprecated)] +impl AsRef for HostTypeAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + HostTypeAttr::Physical => "physical", + HostTypeAttr::Virtual => "virtual", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for HostTypeAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: HostTypeAttr) -> Self { - let value: String = match value { - HostTypeAttr::Physical => "physical".into(), - HostTypeAttr::Virtual => "virtual".into(), + let value: &'static str = match value { + HostTypeAttr::Physical => "physical", + HostTypeAttr::Virtual => "virtual", }; ::opentelemetry::KeyValue::new(HostTypeAttr::KEY, value) } } /// Name of the queue. #[derive(Debug, Clone, PartialEq)] -pub struct QueueNameAttr(String); +pub struct QueueNameAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl QueueNameAttr { pub const KEY: &'static str = "myapp.queue.name"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for QueueNameAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for QueueNameAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) } } + +#[allow(deprecated)] +impl From<&'static str> for QueueNameAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + #[allow(deprecated)] -impl From<&str> for QueueNameAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl AsRef for QueueNameAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for QueueNameAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: QueueNameAttr) -> Self { ::opentelemetry::KeyValue::new(QueueNameAttr::KEY, value.0) } } /// Number of items currently in the queue. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct QueueSizeAttr(i64); #[allow(deprecated)] @@ -141,13 +252,23 @@ impl QueueSizeAttr { #[allow(deprecated)] impl From for QueueSizeAttr { + #[inline] fn from(value: i64) -> Self { Self(value) } } +#[allow(deprecated)] +impl ::std::fmt::Display for QueueSizeAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: QueueSizeAttr) -> Self { ::opentelemetry::KeyValue::new(QueueSizeAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/entities/expected/myappentity.rs b/templates/code/rust/tests/entities/expected/myappentity.rs index de36304..4971fe9 100644 --- a/templates/code/rust/tests/entities/expected/myappentity.rs +++ b/templates/code/rust/tests/entities/expected/myappentity.rs @@ -20,27 +20,34 @@ impl From for ::opentelemetry::KeyValue { /// Identified by its name across its lifetime. /// Identifies the entity: `myapp.host.name`. /// Describes the entity: `myapp.host.cpu.count`, `myapp.host.type`. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct HostEntity { - attributes: Vec<::opentelemetry::KeyValue>, + r#myapp_host_name: super::myappattr::HostNameAttr, + options: ::smallvec::SmallVec<[HostEntityAttr; 2]>, } impl HostEntity { pub fn new(r#myapp_host_name: super::myappattr::HostNameAttr, options: impl IntoIterator) -> Self { - let mut attributes = vec![ - ::opentelemetry::KeyValue::from(r#myapp_host_name), - ]; - attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); - Self { attributes } + Self { + r#myapp_host_name, + options: options.into_iter().collect(), + } } - pub fn attributes(&self) -> Vec<::opentelemetry::KeyValue> { - self.attributes.clone() + pub fn attributes(&self) -> impl Iterator + '_ { + ::std::iter::empty() + .chain(::std::iter::once_with(move || ::opentelemetry::KeyValue::from(self.r#myapp_host_name.clone()))) + .chain(self.options.iter().cloned().map(::opentelemetry::KeyValue::from)) } +} - pub fn resource(&self) -> ::opentelemetry_sdk::Resource { +impl From for ::opentelemetry_sdk::Resource { + fn from(value: HostEntity) -> Self { + let attributes = [ + ::opentelemetry::KeyValue::from(value.r#myapp_host_name), + ].into_iter().chain(value.options.into_iter().map(::opentelemetry::KeyValue::from)); ::opentelemetry_sdk::Resource::builder_empty() - .with_schema_url(self.attributes(), super::SCHEMA_URL) + .with_schema_url(attributes, super::SCHEMA_URL) .build() } } @@ -65,28 +72,82 @@ impl From for ::opentelemetry::KeyValue { /// Identifies the entity: `myapp.host.name`. /// Describes the entity: `myapp.host.cpu.count`, `myapp.host.role`, `myapp.host.type`. /// Refines `myapp.host`. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct HostWorkerEntity { - attributes: Vec<::opentelemetry::KeyValue>, + r#myapp_host_name: super::myappattr::HostNameAttr, + r#myapp_host_role: super::myappattr::HostRoleAttr, + options: ::smallvec::SmallVec<[HostWorkerEntityAttr; 2]>, } impl HostWorkerEntity { pub fn new(r#myapp_host_name: super::myappattr::HostNameAttr, r#myapp_host_role: super::myappattr::HostRoleAttr, options: impl IntoIterator) -> Self { - let mut attributes = vec![ - ::opentelemetry::KeyValue::from(r#myapp_host_name), - ::opentelemetry::KeyValue::from(r#myapp_host_role), - ]; - attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); - Self { attributes } + Self { + r#myapp_host_name, + r#myapp_host_role, + options: options.into_iter().collect(), + } } - pub fn attributes(&self) -> Vec<::opentelemetry::KeyValue> { - self.attributes.clone() + pub fn attributes(&self) -> impl Iterator + '_ { + ::std::iter::empty() + .chain(::std::iter::once_with(move || ::opentelemetry::KeyValue::from(self.r#myapp_host_name.clone()))) + .chain(::std::iter::once_with(move || ::opentelemetry::KeyValue::from(self.r#myapp_host_role.clone()))) + .chain(self.options.iter().cloned().map(::opentelemetry::KeyValue::from)) } +} - pub fn resource(&self) -> ::opentelemetry_sdk::Resource { +impl From for ::opentelemetry_sdk::Resource { + fn from(value: HostWorkerEntity) -> Self { + let attributes = [ + ::opentelemetry::KeyValue::from(value.r#myapp_host_name), + ::opentelemetry::KeyValue::from(value.r#myapp_host_role), + ].into_iter().chain(value.options.into_iter().map(::opentelemetry::KeyValue::from)); ::opentelemetry_sdk::Resource::builder_empty() - .with_schema_url(self.attributes(), super::SCHEMA_URL) + .with_schema_url(attributes, super::SCHEMA_URL) + .build() + } +} +#[derive(Clone, Debug)] +pub enum OptionalEntityAttr { + QueueName(super::myappattr::QueueNameAttr), + QueueSize(super::myappattr::QueueSizeAttr), +} + +impl From for ::opentelemetry::KeyValue { + fn from(value: OptionalEntityAttr) -> Self { + match value { + OptionalEntityAttr::QueueName(value) => ::opentelemetry::KeyValue::from(value), + OptionalEntityAttr::QueueSize(value) => ::opentelemetry::KeyValue::from(value), + } + } +} +/// An entity with optional description only. +/// Identifies the entity: `myapp.queue.name`. +/// Describes the entity: `myapp.queue.size`. +#[derive(Clone, Debug, Default)] +pub struct OptionalEntity { + options: ::smallvec::SmallVec<[OptionalEntityAttr; 2]>, +} + +impl OptionalEntity { + pub fn new(options: impl IntoIterator) -> Self { + Self { + options: options.into_iter().collect(), + } + } + + pub fn attributes(&self) -> impl Iterator + '_ { + ::std::iter::empty() + .chain(self.options.iter().cloned().map(::opentelemetry::KeyValue::from)) + } +} + +impl From for ::opentelemetry_sdk::Resource { + fn from(value: OptionalEntity) -> Self { + let attributes = [ + ].into_iter().chain(value.options.into_iter().map(::opentelemetry::KeyValue::from)); + ::opentelemetry_sdk::Resource::builder_empty() + .with_schema_url(attributes, super::SCHEMA_URL) .build() } } @@ -105,27 +166,34 @@ impl From for ::opentelemetry::KeyValue { /// A queue of tasks. /// Identifies the entity: `myapp.queue.name`. /// Describes the entity: `myapp.queue.size`. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct QueueEntity { - attributes: Vec<::opentelemetry::KeyValue>, + r#myapp_queue_name: super::myappattr::QueueNameAttr, + options: ::smallvec::SmallVec<[QueueEntityAttr; 1]>, } impl QueueEntity { pub fn new(r#myapp_queue_name: super::myappattr::QueueNameAttr, options: impl IntoIterator) -> Self { - let mut attributes = vec![ - ::opentelemetry::KeyValue::from(r#myapp_queue_name), - ]; - attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); - Self { attributes } + Self { + r#myapp_queue_name, + options: options.into_iter().collect(), + } } - pub fn attributes(&self) -> Vec<::opentelemetry::KeyValue> { - self.attributes.clone() + pub fn attributes(&self) -> impl Iterator + '_ { + ::std::iter::empty() + .chain(::std::iter::once_with(move || ::opentelemetry::KeyValue::from(self.r#myapp_queue_name.clone()))) + .chain(self.options.iter().cloned().map(::opentelemetry::KeyValue::from)) } +} - pub fn resource(&self) -> ::opentelemetry_sdk::Resource { +impl From for ::opentelemetry_sdk::Resource { + fn from(value: QueueEntity) -> Self { + let attributes = [ + ::opentelemetry::KeyValue::from(value.r#myapp_queue_name), + ].into_iter().chain(value.options.into_iter().map(::opentelemetry::KeyValue::from)); ::opentelemetry_sdk::Resource::builder_empty() - .with_schema_url(self.attributes(), super::SCHEMA_URL) + .with_schema_url(attributes, super::SCHEMA_URL) .build() } } diff --git a/templates/code/rust/tests/entities/registry/model.yaml b/templates/code/rust/tests/entities/registry/model.yaml index 3fb41a1..a9e9417 100644 --- a/templates/code/rust/tests/entities/registry/model.yaml +++ b/templates/code/rust/tests/entities/registry/model.yaml @@ -64,6 +64,16 @@ entities: requirement_level: required description: - ref: myapp.queue.size + - type: myapp.optional + requirement_level: recommended + stability: stable + brief: An entity with optional description only. + identity: + - ref: myapp.queue.name + requirement_level: recommended + description: + - ref: myapp.queue.size + requirement_level: recommended entity_refinements: - id: myapp.host.worker ref: myapp.host diff --git a/templates/code/rust/tests/entities/test.rs b/templates/code/rust/tests/entities/test.rs index 2bf7fee..71ad6be 100644 --- a/templates/code/rust/tests/entities/test.rs +++ b/templates/code/rust/tests/entities/test.rs @@ -1,24 +1,24 @@ use generated_semconv::{myappattr, myappentity, SCHEMA_URL}; +use opentelemetry::{Key, Value}; +use opentelemetry_sdk::Resource; #[test] -fn entity_resource_keeps_identity_description_and_schema() { +fn entity_exports_identity_description_and_schema() { let entity = myappentity::HostEntity::new( myappattr::HostNameAttr::from("worker-1"), [myappentity::HostEntityAttr::HostType( myappattr::HostTypeAttr::Virtual, )], ); - let attributes = entity.attributes(); + let attributes: Vec<_> = entity.attributes().collect(); assert_eq!(attributes.len(), 2); assert_eq!(attributes[0].key.as_str(), "myapp.host.name"); assert_eq!(attributes[0].value.as_str(), "worker-1"); assert_eq!(attributes[1].value.as_str(), "virtual"); - let resource = entity.resource(); + assert_eq!(entity.attributes().count(), 2); + let resource = Resource::from(entity); assert_eq!(resource.schema_url(), Some(SCHEMA_URL)); assert_eq!(resource.len(), 2); - let mut copy = entity.attributes(); - copy.clear(); - assert_eq!(entity.attributes().len(), 2); } #[test] @@ -28,7 +28,60 @@ fn refinement_requires_its_description_attribute() { myappattr::HostRoleAttr::from("worker"), [], ); - assert_eq!(entity.attributes().len(), 2); - assert_eq!(entity.attributes()[1].key.as_str(), "myapp.host.role"); - assert_eq!(myappentity::HostEntity::default().resource().len(), 0); + assert_eq!(entity.attributes().count(), 2); + assert_eq!( + entity.attributes().nth(1).unwrap().key.as_str(), + "myapp.host.role" + ); + assert_eq!(Resource::from(entity).len(), 2); +} + +#[test] +fn consuming_export_preserves_owned_string_storage() { + let mut owned = String::from("dynamic-worker"); + owned.shrink_to_fit(); + let original = owned.as_ptr(); + let entity = myappentity::HostEntity::new(myappattr::HostNameAttr::from(owned), []); + let resource: Resource = entity.into(); + let value = resource + .iter() + .find(|(key, _)| **key == Key::from("myapp.host.name")) + .unwrap() + .1; + let Value::String(text) = value else { + panic!("expected string"); + }; + assert_eq!(text.as_str().as_ptr(), original); +} + +#[test] +fn default_is_available_when_no_attributes_are_required() { + let empty = myappentity::OptionalEntity::default(); + assert_eq!(empty.attributes().count(), 0); + let resource = Resource::from(empty); + assert_eq!(resource.len(), 0); + assert_eq!(resource.schema_url(), Some(SCHEMA_URL)); +} + +#[test] +fn optional_attribute_overflow_preserves_values_and_order() { + let options = (0..15).map(|index| { + myappentity::HostEntityAttr::HostType(if index == 14 { + myappattr::HostTypeAttr::Physical + } else { + myappattr::HostTypeAttr::Virtual + }) + }); + let entity = myappentity::HostEntity::new(myappattr::HostNameAttr::from("overflow"), options); + let attributes: Vec<_> = entity.attributes().collect(); + assert_eq!(attributes.len(), 16); + assert_eq!( + attributes.last().unwrap().value, + Value::String("physical".into()) + ); + let resource: Resource = entity.into(); + assert_eq!( + resource.get(&Key::from("myapp.host.type")), + Some(Value::String("physical".into())) + ); } diff --git a/templates/code/rust/tests/event_no_attributes/expected/logger.rs b/templates/code/rust/tests/event_no_attributes/expected/logger.rs new file mode 100644 index 0000000..9468744 --- /dev/null +++ b/templates/code/rust/tests/event_no_attributes/expected/logger.rs @@ -0,0 +1,23 @@ +#[derive(Clone, Debug)] +pub struct Logger::Logger>(L); +impl Logger { + pub fn new>(provider: &P, scope: impl Into>) -> Self { + Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) + } + pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.logger_with_scope(registry_scope(scope))) + } + pub fn inner(&self) -> &L { &self.0 } +} +impl Default for Logger { + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } +} + +fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } + let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(scope.attributes().cloned()); + if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } + builder.build() +} diff --git a/templates/code/rust/tests/event_no_attributes/expected/mod.rs b/templates/code/rust/tests/event_no_attributes/expected/mod.rs new file mode 100644 index 0000000..4a3f109 --- /dev/null +++ b/templates/code/rust/tests/event_no_attributes/expected/mod.rs @@ -0,0 +1,5 @@ +// Generated by OpenTelemetry Weaver. +pub const SCHEMA_URL: &str = "https://example.com/schemas/event-no-attributes/1.0.0"; + +pub mod logger; +pub mod probeevent; diff --git a/templates/code/rust/tests/event_no_attributes/expected/probeevent.rs b/templates/code/rust/tests/event_no_attributes/expected/probeevent.rs new file mode 100644 index 0000000..873ac71 --- /dev/null +++ b/templates/code/rust/tests/event_no_attributes/expected/probeevent.rs @@ -0,0 +1,31 @@ +#![allow(deprecated)] +use ::opentelemetry::logs::LogRecord; +use ::opentelemetry::trace::TraceContextExt; + +#[derive(Clone, Debug)] +pub enum TickOption { + Severity(::opentelemetry::logs::Severity), + Timestamp(::std::time::SystemTime), +} +/// A synthetic tick occurred. +pub fn r#emit_tick(context: &::opentelemetry::Context, logger: &super::logger::Logger, options: impl IntoIterator) { + let mut severity = ::opentelemetry::logs::Severity::Info; + let mut timestamp = None; + for option in options { + match option { + TickOption::Severity(value) => severity = value, + TickOption::Timestamp(value) => timestamp = Some(value), + } + } + if !logger.inner().event_enabled(severity, "", Some("probe.tick")) { return; } + let _context_guard = context.clone().attach(); + let mut record = logger.inner().create_log_record(); + record.set_event_name("probe.tick"); + record.set_severity_number(severity); + record.set_observed_timestamp(::std::time::SystemTime::now()); + if let Some(timestamp) = timestamp { record.set_timestamp(timestamp); } + let span = context.span(); + let span_context = span.span_context(); + if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } + logger.inner().emit(record); +} diff --git a/templates/code/rust/tests/event_no_attributes/registry/manifest.yaml b/templates/code/rust/tests/event_no_attributes/registry/manifest.yaml new file mode 100644 index 0000000..209c36a --- /dev/null +++ b/templates/code/rust/tests/event_no_attributes/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: synthetic-empty-event-fixture +schema_url: https://example.com/schemas/event-no-attributes/1.0.0 diff --git a/templates/code/rust/tests/event_no_attributes/registry/model.yaml b/templates/code/rust/tests/event_no_attributes/registry/model.yaml new file mode 100644 index 0000000..b9120fb --- /dev/null +++ b/templates/code/rust/tests/event_no_attributes/registry/model.yaml @@ -0,0 +1,5 @@ +file_format: definition/2 +events: + - name: probe.tick + stability: stable + brief: A synthetic tick occurred. diff --git a/templates/code/rust/tests/event_no_attributes/test.rs b/templates/code/rust/tests/event_no_attributes/test.rs new file mode 100644 index 0000000..bc10942 --- /dev/null +++ b/templates/code/rust/tests/event_no_attributes/test.rs @@ -0,0 +1,27 @@ +use generated_semconv::{logger, probeevent}; +use opentelemetry::logs::Severity; +use opentelemetry_sdk::logs::{InMemoryLogExporter, SdkLoggerProvider}; + +#[test] +fn events_without_attributes_export_cleanly() { + let exporter = InMemoryLogExporter::default(); + let provider = SdkLoggerProvider::builder() + .with_simple_exporter(exporter.clone()) + .build(); + let logger = logger::Logger::new(&provider, "synthetic-clock"); + probeevent::emit_tick( + &opentelemetry::Context::new(), + &logger, + [probeevent::TickOption::Severity(Severity::Debug)], + ); + provider.force_flush().unwrap(); + let records = exporter.get_emitted_logs().unwrap(); + assert_eq!(records.len(), 1); + assert_eq!(records[0].record.event_name(), Some("probe.tick")); + assert_eq!(records[0].record.severity_number(), Some(Severity::Debug)); + assert_eq!(records[0].record.attributes_iter().count(), 0); + assert_eq!( + records[0].instrumentation.schema_url(), + Some(generated_semconv::SCHEMA_URL) + ); +} diff --git a/templates/code/rust/tests/events/expected/logger.rs b/templates/code/rust/tests/events/expected/logger.rs index 175c830..179c64c 100644 --- a/templates/code/rust/tests/events/expected/logger.rs +++ b/templates/code/rust/tests/events/expected/logger.rs @@ -5,7 +5,7 @@ use opentelemetry::{Array, Value}; pub struct Logger::Logger>(L); impl Logger { pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.logger_with_scope(registry_scope(scope))) @@ -33,6 +33,7 @@ pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::Any } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/events/expected/myappattr.rs b/templates/code/rust/tests/events/expected/myappattr.rs index 594e302..94f38f0 100644 --- a/templates/code/rust/tests/events/expected/myappattr.rs +++ b/templates/code/rust/tests/events/expected/myappattr.rs @@ -10,13 +10,37 @@ impl BoolValuesAttr { #[allow(deprecated)] impl From> for BoolValuesAttr { + #[inline] fn from(value: Vec) -> Self { Self(value) } } +#[allow(deprecated)] +impl AsRef<[bool]> for BoolValuesAttr { + #[inline] + fn as_ref(&self) -> &[bool] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for BoolValuesAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + ::std::fmt::Display::fmt(value, formatter)?; + } + formatter.write_str("]") + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: BoolValuesAttr) -> Self { ::opentelemetry::KeyValue::new(BoolValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(value.0))) } @@ -32,13 +56,37 @@ impl DoubleValuesAttr { #[allow(deprecated)] impl From> for DoubleValuesAttr { + #[inline] fn from(value: Vec) -> Self { Self(value) } } +#[allow(deprecated)] +impl AsRef<[f64]> for DoubleValuesAttr { + #[inline] + fn as_ref(&self) -> &[f64] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for DoubleValuesAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + ::std::fmt::Display::fmt(value, formatter)?; + } + formatter.write_str("]") + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: DoubleValuesAttr) -> Self { ::opentelemetry::KeyValue::new(DoubleValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(value.0))) } @@ -54,41 +102,95 @@ impl IntValuesAttr { #[allow(deprecated)] impl From> for IntValuesAttr { + #[inline] fn from(value: Vec) -> Self { Self(value) } } +#[allow(deprecated)] +impl AsRef<[i64]> for IntValuesAttr { + #[inline] + fn as_ref(&self) -> &[i64] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for IntValuesAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + ::std::fmt::Display::fmt(value, formatter)?; + } + formatter.write_str("]") + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: IntValuesAttr) -> Self { ::opentelemetry::KeyValue::new(IntValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) } } /// Synthetic string values. #[derive(Debug, Clone, PartialEq)] -pub struct StringValuesAttr(Vec); +pub struct StringValuesAttr(Vec<::opentelemetry::StringValue>); #[allow(deprecated)] impl StringValuesAttr { pub const KEY: &'static str = "myapp.string.values"; } +#[allow(deprecated)] +impl From> for StringValuesAttr { + #[inline] + fn from(value: Vec<::opentelemetry::StringValue>) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From> for StringValuesAttr { fn from(value: Vec) -> Self { - Self(value) + Self(value.into_iter().map(Into::into).collect()) + } +} + +#[allow(deprecated)] +impl AsRef<[::opentelemetry::StringValue]> for StringValuesAttr { + #[inline] + fn as_ref(&self) -> &[::opentelemetry::StringValue] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for StringValuesAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + write!(formatter, "\"{value}\"")?; + } + formatter.write_str("]") } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: StringValuesAttr) -> Self { - ::opentelemetry::KeyValue::new(StringValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0.into_iter().map(Into::into).collect()))) + ::opentelemetry::KeyValue::new(StringValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0))) } } /// Number of the attempt, starting at 1. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskAttemptAttr(i64); #[allow(deprecated)] @@ -98,13 +200,23 @@ impl TaskAttemptAttr { #[allow(deprecated)] impl From for TaskAttemptAttr { + #[inline] fn from(value: i64) -> Self { Self(value) } } +#[allow(deprecated)] +impl ::std::fmt::Display for TaskAttemptAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskAttemptAttr) -> Self { ::opentelemetry::KeyValue::new(TaskAttemptAttr::KEY, value.0) } @@ -123,12 +235,32 @@ impl TaskStateAttr { pub const KEY: &'static str = "myapp.task.state"; } +#[allow(deprecated)] +impl AsRef for TaskStateAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + TaskStateAttr::Done => "done", + TaskStateAttr::Failed => "failed", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskStateAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskStateAttr) -> Self { - let value: String = match value { - TaskStateAttr::Done => "done".into(), - TaskStateAttr::Failed => "failed".into(), + let value: &'static str = match value { + TaskStateAttr::Done => "done", + TaskStateAttr::Failed => "failed", }; ::opentelemetry::KeyValue::new(TaskStateAttr::KEY, value) } diff --git a/templates/code/rust/tests/events/expected/myappevent.rs b/templates/code/rust/tests/events/expected/myappevent.rs index 0d2cb22..1d23167 100644 --- a/templates/code/rust/tests/events/expected/myappevent.rs +++ b/templates/code/rust/tests/events/expected/myappevent.rs @@ -19,23 +19,18 @@ pub enum TaskFinishedOption { /// /// Emitted once per task, after its last attempt. pub fn r#emit_task_finished(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) { - let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let mut attributes: Vec<::opentelemetry::KeyValue> = vec![::opentelemetry::KeyValue::from(r#myapp_task_state)]; + let mut attributes = ::smallvec::SmallVec::<[TaskFinishedOption; 6]>::new(); for option in options { match option { TaskFinishedOption::Severity(value) => severity = value, TaskFinishedOption::Timestamp(value) => timestamp = Some(value), - TaskFinishedOption::BoolValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), - TaskFinishedOption::DoubleValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), - TaskFinishedOption::IntValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), - TaskFinishedOption::StringValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), - TaskFinishedOption::TaskAttempt(value) => attributes.push(::opentelemetry::KeyValue::from(value)), - TaskFinishedOption::HostName(value) => attributes.push(::opentelemetry::KeyValue::from(value)), + attribute => attributes.push(attribute), } } if !logger.inner().event_enabled(severity, "", Some("myapp.task.finished")) { return; } + let _context_guard = context.clone().attach(); let mut record = logger.inner().create_log_record(); record.set_event_name("myapp.task.finished"); record.set_severity_number(severity); @@ -44,7 +39,20 @@ pub fn r#emit_task_finished(context: &::opente let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + let attribute = ::opentelemetry::KeyValue::from(r#myapp_task_state); + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + for option in attributes { + let attribute = match option { + TaskFinishedOption::BoolValues(value) => ::opentelemetry::KeyValue::from(value), + TaskFinishedOption::DoubleValues(value) => ::opentelemetry::KeyValue::from(value), + TaskFinishedOption::IntValues(value) => ::opentelemetry::KeyValue::from(value), + TaskFinishedOption::StringValues(value) => ::opentelemetry::KeyValue::from(value), + TaskFinishedOption::TaskAttempt(value) => ::opentelemetry::KeyValue::from(value), + TaskFinishedOption::HostName(value) => ::opentelemetry::KeyValue::from(value), + TaskFinishedOption::Severity(_) | TaskFinishedOption::Timestamp(_) => continue, + }; + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } logger.inner().emit(record); } #[derive(Clone, Debug)] @@ -56,10 +64,8 @@ pub enum TaskRetriedOption { /// Opt-in: record only when the user requests it. #[deprecated(note = "Read the attempt from `myapp.task.finished` instead.")] pub fn r#emit_task_retried(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#myapp_task_attempt: super::myappattr::TaskAttemptAttr, options: impl IntoIterator) { - let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let attributes: Vec<::opentelemetry::KeyValue> = vec![::opentelemetry::KeyValue::from(r#myapp_task_attempt)]; for option in options { match option { TaskRetriedOption::Severity(value) => severity = value, @@ -67,6 +73,7 @@ pub fn r#emit_task_retried(context: &::opentel } } if !logger.inner().event_enabled(severity, "", Some("myapp.task.retried")) { return; } + let _context_guard = context.clone().attach(); let mut record = logger.inner().create_log_record(); record.set_event_name("myapp.task.retried"); record.set_severity_number(severity); @@ -75,6 +82,7 @@ pub fn r#emit_task_retried(context: &::opentel let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + let attribute = ::opentelemetry::KeyValue::from(r#myapp_task_attempt); + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); logger.inner().emit(record); } diff --git a/templates/code/rust/tests/events/expected/workerattr.rs b/templates/code/rust/tests/events/expected/workerattr.rs index a3521b2..99f1d8c 100644 --- a/templates/code/rust/tests/events/expected/workerattr.rs +++ b/templates/code/rust/tests/events/expected/workerattr.rs @@ -1,28 +1,55 @@ // Generated by OpenTelemetry Weaver. /// Name of the worker host. #[derive(Debug, Clone, PartialEq)] -pub struct HostNameAttr(String); +pub struct HostNameAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl HostNameAttr { pub const KEY: &'static str = "worker.host.name"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for HostNameAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for HostNameAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for HostNameAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for HostNameAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for HostNameAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for HostNameAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: HostNameAttr) -> Self { ::opentelemetry::KeyValue::new(HostNameAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/events/expected/workerevent.rs b/templates/code/rust/tests/events/expected/workerevent.rs index b926f0f..7a6a0aa 100644 --- a/templates/code/rust/tests/events/expected/workerevent.rs +++ b/templates/code/rust/tests/events/expected/workerevent.rs @@ -9,10 +9,8 @@ pub enum HostStartedOption { } /// A worker host started taking tasks. pub fn r#emit_host_started(context: &::opentelemetry::Context, logger: &super::logger::Logger, options: impl IntoIterator) { - let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let attributes: Vec<::opentelemetry::KeyValue> = vec![]; for option in options { match option { HostStartedOption::Severity(value) => severity = value, @@ -20,6 +18,7 @@ pub fn r#emit_host_started(context: &::opentel } } if !logger.inner().event_enabled(severity, "", Some("worker.host.started")) { return; } + let _context_guard = context.clone().attach(); let mut record = logger.inner().create_log_record(); record.set_event_name("worker.host.started"); record.set_severity_number(severity); @@ -28,7 +27,6 @@ pub fn r#emit_host_started(context: &::opentel let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } logger.inner().emit(record); } #[derive(Clone, Debug)] @@ -46,22 +44,18 @@ pub enum TaskFinishedOption { /// /// Emitted once per task, after its last attempt. pub fn r#emit_task_finished(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#myapp_task_state: super::myappattr::TaskStateAttr, r#worker_host_name: super::workerattr::HostNameAttr, options: impl IntoIterator) { - let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let mut attributes: Vec<::opentelemetry::KeyValue> = vec![::opentelemetry::KeyValue::from(r#myapp_task_state), ::opentelemetry::KeyValue::from(r#worker_host_name)]; + let mut attributes = ::smallvec::SmallVec::<[TaskFinishedOption; 5]>::new(); for option in options { match option { TaskFinishedOption::Severity(value) => severity = value, TaskFinishedOption::Timestamp(value) => timestamp = Some(value), - TaskFinishedOption::BoolValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), - TaskFinishedOption::DoubleValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), - TaskFinishedOption::IntValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), - TaskFinishedOption::StringValues(value) => attributes.push(::opentelemetry::KeyValue::from(value)), - TaskFinishedOption::TaskAttempt(value) => attributes.push(::opentelemetry::KeyValue::from(value)), + attribute => attributes.push(attribute), } } if !logger.inner().event_enabled(severity, "", Some("worker.task.finished")) { return; } + let _context_guard = context.clone().attach(); let mut record = logger.inner().create_log_record(); record.set_event_name("worker.task.finished"); record.set_severity_number(severity); @@ -70,6 +64,20 @@ pub fn r#emit_task_finished(context: &::opente let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + let attribute = ::opentelemetry::KeyValue::from(r#myapp_task_state); + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + let attribute = ::opentelemetry::KeyValue::from(r#worker_host_name); + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + for option in attributes { + let attribute = match option { + TaskFinishedOption::BoolValues(value) => ::opentelemetry::KeyValue::from(value), + TaskFinishedOption::DoubleValues(value) => ::opentelemetry::KeyValue::from(value), + TaskFinishedOption::IntValues(value) => ::opentelemetry::KeyValue::from(value), + TaskFinishedOption::StringValues(value) => ::opentelemetry::KeyValue::from(value), + TaskFinishedOption::TaskAttempt(value) => ::opentelemetry::KeyValue::from(value), + TaskFinishedOption::Severity(_) | TaskFinishedOption::Timestamp(_) => continue, + }; + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } logger.inner().emit(record); } diff --git a/templates/code/rust/tests/events/test.rs b/templates/code/rust/tests/events/test.rs index d68062a..edf2c8e 100644 --- a/templates/code/rust/tests/events/test.rs +++ b/templates/code/rust/tests/events/test.rs @@ -41,7 +41,7 @@ fn typed_events_have_schema_timestamps_severity_attributes_and_trace_context() { 1.5, ])), myappevent::TaskFinishedOption::StringValues(myappattr::StringValuesAttr::from(vec![ - "fetch".into(), + opentelemetry::StringValue::from("fetch"), ])), ], ); diff --git a/templates/code/rust/tests/filtering/expected/authattr.rs b/templates/code/rust/tests/filtering/expected/authattr.rs index 4c02410..5f7a4c3 100644 --- a/templates/code/rust/tests/filtering/expected/authattr.rs +++ b/templates/code/rust/tests/filtering/expected/authattr.rs @@ -13,40 +13,87 @@ impl MethodAttr { pub const KEY: &'static str = "auth.method"; } +#[allow(deprecated)] +impl AsRef for MethodAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + MethodAttr::Password => "password", + MethodAttr::Token => "token", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for MethodAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: MethodAttr) -> Self { - let value: String = match value { - MethodAttr::Password => "password".into(), - MethodAttr::Token => "token".into(), + let value: &'static str = match value { + MethodAttr::Password => "password", + MethodAttr::Token => "token", }; ::opentelemetry::KeyValue::new(MethodAttr::KEY, value) } } /// Identifier of the authenticated user. #[derive(Debug, Clone, PartialEq)] -pub struct UserIdAttr(String); +pub struct UserIdAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl UserIdAttr { pub const KEY: &'static str = "auth.user.id"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for UserIdAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for UserIdAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for UserIdAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for UserIdAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for UserIdAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for UserIdAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: UserIdAttr) -> Self { ::opentelemetry::KeyValue::new(UserIdAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/filtering/expected/taskattr.rs b/templates/code/rust/tests/filtering/expected/taskattr.rs index 39f6f5d..30317f9 100644 --- a/templates/code/rust/tests/filtering/expected/taskattr.rs +++ b/templates/code/rust/tests/filtering/expected/taskattr.rs @@ -3,34 +3,61 @@ /// /// The scheduler sets it on every task it passes along to `myapp.task.state`. Workers never set it themselves. #[derive(Debug, Clone, PartialEq)] -pub struct AssignedByAttr(String); +pub struct AssignedByAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl AssignedByAttr { pub const KEY: &'static str = "myapp.task.assigned_by"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for AssignedByAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for AssignedByAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) } } + #[allow(deprecated)] -impl From<&str> for AssignedByAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl From<&'static str> for AssignedByAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl AsRef for AssignedByAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for AssignedByAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: AssignedByAttr) -> Self { ::opentelemetry::KeyValue::new(AssignedByAttr::KEY, value.0) } } /// Whether the task was cancelled. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct CancelledAttr(bool); #[allow(deprecated)] @@ -40,13 +67,23 @@ impl CancelledAttr { #[allow(deprecated)] impl From for CancelledAttr { + #[inline] fn from(value: bool) -> Self { Self(value) } } +#[allow(deprecated)] +impl ::std::fmt::Display for CancelledAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: CancelledAttr) -> Self { ::opentelemetry::KeyValue::new(CancelledAttr::KEY, value.0) } @@ -55,28 +92,55 @@ impl From for ::opentelemetry::KeyValue { /// /// The identifier is assigned by the scheduler and stays stable across retries. #[derive(Debug, Clone, PartialEq)] -pub struct IdAttr(String); +pub struct IdAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl IdAttr { pub const KEY: &'static str = "myapp.task.id"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for IdAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for IdAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) } } + #[allow(deprecated)] -impl From<&str> for IdAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl From<&'static str> for IdAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl AsRef for IdAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for IdAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: IdAttr) -> Self { ::opentelemetry::KeyValue::new(IdAttr::KEY, value.0) } @@ -95,8 +159,21 @@ impl PreemptibleAttr { pub const KEY: &'static str = "myapp.task.preemptible"; } +#[allow(deprecated)] +impl ::std::fmt::Display for PreemptibleAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + let value: bool = match self { + PreemptibleAttr::Allowed => true, + PreemptibleAttr::Forbidden => false, + }; + ::std::fmt::Display::fmt(&value, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: PreemptibleAttr) -> Self { let value: bool = match value { PreemptibleAttr::Allowed => true, @@ -106,7 +183,7 @@ impl From for ::opentelemetry::KeyValue { } } /// Number of times the task was retried. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct RetriesAttr(i64); #[allow(deprecated)] @@ -116,13 +193,23 @@ impl RetriesAttr { #[allow(deprecated)] impl From for RetriesAttr { + #[inline] fn from(value: i64) -> Self { Self(value) } } +#[allow(deprecated)] +impl ::std::fmt::Display for RetriesAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: RetriesAttr) -> Self { ::opentelemetry::KeyValue::new(RetriesAttr::KEY, value.0) } @@ -141,8 +228,21 @@ impl SampleRateAttr { pub const KEY: &'static str = "myapp.task.sample_rate"; } +#[allow(deprecated)] +impl ::std::fmt::Display for SampleRateAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + let value: f64 = match self { + SampleRateAttr::Tenth => 0.1_f64, + SampleRateAttr::All => 1_f64, + }; + ::std::fmt::Display::fmt(&value, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: SampleRateAttr) -> Self { let value: f64 = match value { SampleRateAttr::Tenth => 0.1_f64, @@ -162,13 +262,37 @@ impl ShardIdsAttr { #[allow(deprecated)] impl From> for ShardIdsAttr { + #[inline] fn from(value: Vec) -> Self { Self(value) } } +#[allow(deprecated)] +impl AsRef<[i64]> for ShardIdsAttr { + #[inline] + fn as_ref(&self) -> &[i64] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for ShardIdsAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + ::std::fmt::Display::fmt(value, formatter)?; + } + formatter.write_str("]") + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: ShardIdsAttr) -> Self { ::opentelemetry::KeyValue::new(ShardIdsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) } @@ -189,35 +313,85 @@ impl StateAttr { pub const KEY: &'static str = "myapp.task.state"; } +#[allow(deprecated)] +impl AsRef for StateAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + StateAttr::Queued => "queued", + StateAttr::Running => "running", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for StateAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: StateAttr) -> Self { - let value: String = match value { - StateAttr::Queued => "queued".into(), - StateAttr::Running => "running".into(), + let value: &'static str = match value { + StateAttr::Queued => "queued", + StateAttr::Running => "running", }; ::opentelemetry::KeyValue::new(StateAttr::KEY, value) } } /// Tags attached to the task. #[derive(Debug, Clone, PartialEq)] -pub struct TagsAttr(Vec); +pub struct TagsAttr(Vec<::opentelemetry::StringValue>); #[allow(deprecated)] impl TagsAttr { pub const KEY: &'static str = "myapp.task.tags"; } +#[allow(deprecated)] +impl From> for TagsAttr { + #[inline] + fn from(value: Vec<::opentelemetry::StringValue>) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From> for TagsAttr { fn from(value: Vec) -> Self { - Self(value) + Self(value.into_iter().map(Into::into).collect()) + } +} + +#[allow(deprecated)] +impl AsRef<[::opentelemetry::StringValue]> for TagsAttr { + #[inline] + fn as_ref(&self) -> &[::opentelemetry::StringValue] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TagsAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + write!(formatter, "\"{value}\"")?; + } + formatter.write_str("]") } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TagsAttr) -> Self { - ::opentelemetry::KeyValue::new(TagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0.into_iter().map(Into::into).collect()))) + ::opentelemetry::KeyValue::new(TagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0))) } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs index 176d064..2607994 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs @@ -2,7 +2,7 @@ pub struct Meter(opentelemetry::metrics::Meter); impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.meter_with_scope(registry_scope(scope))) @@ -14,6 +14,7 @@ impl Default for Meter { } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs index 3b1f7f5..4987524 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs @@ -1,28 +1,55 @@ // Generated by OpenTelemetry Weaver. /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] -pub struct TaskIdAttr(String); +pub struct TaskIdAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for TaskIdAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for TaskIdAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for TaskIdAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for TaskIdAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for TaskIdAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for TaskIdAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskIdAttr) -> Self { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs index 2f8d42e..bef1184 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs @@ -4,14 +4,15 @@ pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } impl TaskDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_histogram("myapp.task.duration") + let instrument = meter.inner().f64_histogram("myapp.task.duration") .with_description("Time a task took from start to finish.") .with_unit("s") .with_boundaries(vec![0.005_f64, 0.01_f64, 0.025_f64, 0.05_f64, 0.075_f64, 0.1_f64, 0.25_f64, 0.5_f64, 0.75_f64, 1_f64, 2.5_f64, 5_f64, 7.5_f64, 10_f64]) - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; + let attributes = [::opentelemetry::KeyValue::from(r#myapp_task_id)]; self.instrument.record(value, &attributes); } } @@ -23,14 +24,15 @@ impl Default for TaskDurationHistogram { pub struct TaskLatencyHistogram { instrument: ::opentelemetry::metrics::Histogram } impl TaskLatencyHistogram { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_histogram("myapp.task.latency") + let instrument = meter.inner().f64_histogram("myapp.task.latency") .with_description("Time between a task being queued and started.") .with_unit("s") .with_boundaries(vec![1_f64, 10_f64, 100_f64]) - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; + let attributes = [::opentelemetry::KeyValue::from(r#myapp_task_id)]; self.instrument.record(value, &attributes); } } @@ -42,14 +44,15 @@ impl Default for TaskLatencyHistogram { pub struct TaskRetryDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } impl TaskRetryDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_histogram("myapp.task.duration") + let instrument = meter.inner().f64_histogram("myapp.task.duration") .with_description("Time a task took from start to finish.") .with_unit("s") .with_boundaries(vec![0.005_f64, 0.01_f64, 0.025_f64, 0.05_f64, 0.075_f64, 0.1_f64, 0.25_f64, 0.5_f64, 0.75_f64, 1_f64, 2.5_f64, 5_f64, 7.5_f64, 10_f64]) - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; + let attributes = [::opentelemetry::KeyValue::from(r#myapp_task_id)]; self.instrument.record(value, &attributes); } } @@ -61,13 +64,14 @@ impl Default for TaskRetryDurationHistogram { pub struct TaskSizeHistogram { instrument: ::opentelemetry::metrics::Histogram } impl TaskSizeHistogram { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_histogram("myapp.task.size") + let instrument = meter.inner().f64_histogram("myapp.task.size") .with_description("Size of a task\u{0027}s payload.") .with_unit("By") - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; + let attributes = [::opentelemetry::KeyValue::from(r#myapp_task_id)]; self.instrument.record(value, &attributes); } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs index 176d064..2607994 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs @@ -2,7 +2,7 @@ pub struct Meter(opentelemetry::metrics::Meter); impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.meter_with_scope(registry_scope(scope))) @@ -14,6 +14,7 @@ impl Default for Meter { } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs index 3b1f7f5..4987524 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs @@ -1,28 +1,55 @@ // Generated by OpenTelemetry Weaver. /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] -pub struct TaskIdAttr(String); +pub struct TaskIdAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for TaskIdAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for TaskIdAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for TaskIdAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for TaskIdAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for TaskIdAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for TaskIdAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskIdAttr) -> Self { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs index be6b988..291169d 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs @@ -4,13 +4,14 @@ pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } impl TaskDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_histogram("myapp.task.duration") + let instrument = meter.inner().f64_histogram("myapp.task.duration") .with_description("Time a task took from start to finish.") .with_unit("s") - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; + let attributes = [::opentelemetry::KeyValue::from(r#myapp_task_id)]; self.instrument.record(value, &attributes); } } @@ -22,14 +23,15 @@ impl Default for TaskDurationHistogram { pub struct TaskQueueWaitHistogram { instrument: ::opentelemetry::metrics::Histogram } impl TaskQueueWaitHistogram { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_histogram("myapp.task.queue_wait") + let instrument = meter.inner().f64_histogram("myapp.task.queue_wait") .with_description("Time a task waited in the queue, in minutes.") .with_unit("min") .with_boundaries(vec![1_f64, 5_f64, 10_f64, 30_f64, 60_f64]) - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; + let attributes = [::opentelemetry::KeyValue::from(r#myapp_task_id)]; self.instrument.record(value, &attributes); } } diff --git a/templates/code/rust/tests/imported/expected/edgeevent.rs b/templates/code/rust/tests/imported/expected/edgeevent.rs index 11549dc..0d6e7e3 100644 --- a/templates/code/rust/tests/imported/expected/edgeevent.rs +++ b/templates/code/rust/tests/imported/expected/edgeevent.rs @@ -6,22 +6,22 @@ use ::opentelemetry::trace::TraceContextExt; pub enum UpstreamFailedOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), - ServerAddress(String), + ServerAddress(::opentelemetry::StringValue), } /// A request to an upstream server failed. -pub fn r#emit_upstream_failed(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#error_type: String, options: impl IntoIterator) { - let _context_guard = context.clone().attach(); +pub fn r#emit_upstream_failed(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#error_type: ::opentelemetry::StringValue, options: impl IntoIterator) { let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let mut attributes: Vec<::opentelemetry::KeyValue> = vec![::opentelemetry::KeyValue::new("error.type", r#error_type)]; + let mut attributes = ::smallvec::SmallVec::<[UpstreamFailedOption; 1]>::new(); for option in options { match option { UpstreamFailedOption::Severity(value) => severity = value, UpstreamFailedOption::Timestamp(value) => timestamp = Some(value), - UpstreamFailedOption::ServerAddress(value) => attributes.push(::opentelemetry::KeyValue::new("server.address", value)), + attribute => attributes.push(attribute), } } if !logger.inner().event_enabled(severity, "", Some("edge.upstream.failed")) { return; } + let _context_guard = context.clone().attach(); let mut record = logger.inner().create_log_record(); record.set_event_name("edge.upstream.failed"); record.set_severity_number(severity); @@ -30,6 +30,14 @@ pub fn r#emit_upstream_failed(context: &::open let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + let attribute = ::opentelemetry::KeyValue::new("error.type", r#error_type); + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + for option in attributes { + let attribute = match option { + UpstreamFailedOption::ServerAddress(value) => ::opentelemetry::KeyValue::new("server.address", value), + UpstreamFailedOption::Severity(_) | UpstreamFailedOption::Timestamp(_) => continue, + }; + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } logger.inner().emit(record); } diff --git a/templates/code/rust/tests/imported/expected/edgemetric.rs b/templates/code/rust/tests/imported/expected/edgemetric.rs index 1bb88d0..5373426 100644 --- a/templates/code/rust/tests/imported/expected/edgemetric.rs +++ b/templates/code/rust/tests/imported/expected/edgemetric.rs @@ -15,14 +15,16 @@ impl From for ::opentelemetry::KeyValue { pub struct UpstreamDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } impl UpstreamDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_histogram("edge.upstream.duration") + let instrument = meter.inner().f64_histogram("edge.upstream.duration") .with_description("Time spent waiting on an upstream server.") .with_unit("s") .with_boundaries(vec![0.005_f64, 0.01_f64, 0.025_f64, 0.05_f64, 0.075_f64, 0.1_f64, 0.25_f64, 0.5_f64, 0.75_f64, 1_f64, 2.5_f64, 5_f64, 7.5_f64, 10_f64]) - .build() } + .build(); + Self { instrument } } - pub fn record(&self, value: f64, r#server_address: String, options: impl IntoIterator) { - let mut attributes = vec![::opentelemetry::KeyValue::new("server.address", r#server_address)]; + pub fn record(&self, value: f64, r#server_address: ::opentelemetry::StringValue, options: impl IntoIterator) { + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 2]>::new(); + attributes.extend([::opentelemetry::KeyValue::new("server.address", r#server_address)]); attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.record(value, &attributes); } diff --git a/templates/code/rust/tests/imported/expected/edgespan.rs b/templates/code/rust/tests/imported/expected/edgespan.rs index 6149379..55b1330 100644 --- a/templates/code/rust/tests/imported/expected/edgespan.rs +++ b/templates/code/rust/tests/imported/expected/edgespan.rs @@ -1,23 +1,59 @@ #![allow(deprecated)] use ::opentelemetry::trace::{TraceContextExt, Tracer}; +use ::std::fmt::Write; +/// A request named from attempted methods. +pub struct UpstreamMethodsSpan { span: S } +impl UpstreamMethodsSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut S { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } +} +impl Default for UpstreamMethodsSpan { + fn default() -> Self { + Self { span: super::tracer::Tracer::default().inner().start("edge.upstream.methods") } + } +} + +pub fn r#start_upstream_methods(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#http_request_method_list: Vec<::opentelemetry::StringValue>) -> UpstreamMethodsSpan { + let mut name = String::with_capacity(r#http_request_method_list.iter().map(|value| value.as_str().len() + 3).sum::() + 2); + name.push('['); + for (index, value) in r#http_request_method_list.iter().enumerate() { + if index > 0 { name.push(','); } + write!(&mut name, "\"{}\"", value).expect("writing a span name to String cannot fail"); + } + name.push(']'); + let attributes: [::opentelemetry::KeyValue; 1] = [::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(r#http_request_method_list)))]; + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Client) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + UpstreamMethodsSpan { span } +} #[derive(Clone, Debug)] pub enum UpstreamRequestStartAttr { /// Conditionally required: If the request failed. - ErrorType(String), - HttpRequestMethodList(Vec), + ErrorType(::opentelemetry::StringValue), + HttpRequestMethodList(Vec<::opentelemetry::StringValue>), } impl From for ::opentelemetry::KeyValue { fn from(value: UpstreamRequestStartAttr) -> Self { match value { UpstreamRequestStartAttr::ErrorType(value) => ::opentelemetry::KeyValue::new("error.type", value), - UpstreamRequestStartAttr::HttpRequestMethodList(value) => ::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.into_iter().map(Into::into).collect()))), + UpstreamRequestStartAttr::HttpRequestMethodList(value) => ::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(value))), } } } #[derive(Clone, Debug)] pub enum UpstreamRequestAttr { - HttpRequestMethodList(Vec), + HttpRequestMethodList(Vec<::opentelemetry::StringValue>), } impl From for UpstreamRequestStartAttr { fn from(value: UpstreamRequestAttr) -> Self { @@ -27,12 +63,14 @@ impl From for UpstreamRequestStartAttr { } } /// A request to an upstream server. -pub struct UpstreamRequestSpan { span: ::opentelemetry::global::BoxedSpan } -impl UpstreamRequestSpan { - pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { +pub struct UpstreamRequestSpan { span: S } +impl UpstreamRequestSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { parent.with_span(self.span) } - pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn span(&mut self) -> &mut S { &mut self.span } pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } @@ -47,16 +85,15 @@ impl Default for UpstreamRequestSpan { } } -pub fn r#start_upstream_request(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#server_address: String, r#server_port: i64, options: impl IntoIterator) -> UpstreamRequestSpan { - let mut name = String::new(); - name.push_str(&::opentelemetry::KeyValue::new("server.address", r#server_address.clone()).value.to_string()); +pub fn r#start_upstream_request(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#server_address: ::opentelemetry::StringValue, r#server_port: i64, options: impl IntoIterator) -> UpstreamRequestSpan { + let mut name = String::with_capacity(r#server_address.as_str().len() + ":".len() + 20); + write!(&mut name, "{}", r#server_address).expect("writing a span name to String cannot fail"); name.push(':'); - name.push_str(&::opentelemetry::KeyValue::new("server.port", r#server_port).value.to_string()); - let mut attributes = vec![::opentelemetry::KeyValue::new("server.address", r#server_address), ::opentelemetry::KeyValue::new("server.port", r#server_port)]; - attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); + write!(&mut name, "{}", r#server_port).expect("writing a span name to String cannot fail"); + let attributes: [::opentelemetry::KeyValue; 2] = [::opentelemetry::KeyValue::new("server.address", r#server_address), ::opentelemetry::KeyValue::new("server.port", r#server_port)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Client) - .with_attributes(attributes) + .with_attributes(attributes.into_iter().chain(options.into_iter().map(::opentelemetry::KeyValue::from))) .start_with_context(tracer.inner(), context); UpstreamRequestSpan { span } } diff --git a/templates/code/rust/tests/imported/expected/logger.rs b/templates/code/rust/tests/imported/expected/logger.rs index 175c830..179c64c 100644 --- a/templates/code/rust/tests/imported/expected/logger.rs +++ b/templates/code/rust/tests/imported/expected/logger.rs @@ -5,7 +5,7 @@ use opentelemetry::{Array, Value}; pub struct Logger::Logger>(L); impl Logger { pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.logger_with_scope(registry_scope(scope))) @@ -33,6 +33,7 @@ pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::Any } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/imported/expected/meter.rs b/templates/code/rust/tests/imported/expected/meter.rs index 176d064..2607994 100644 --- a/templates/code/rust/tests/imported/expected/meter.rs +++ b/templates/code/rust/tests/imported/expected/meter.rs @@ -2,7 +2,7 @@ pub struct Meter(opentelemetry::metrics::Meter); impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.meter_with_scope(registry_scope(scope))) @@ -14,6 +14,7 @@ impl Default for Meter { } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/imported/expected/myappattr.rs b/templates/code/rust/tests/imported/expected/myappattr.rs index 3b1f7f5..4987524 100644 --- a/templates/code/rust/tests/imported/expected/myappattr.rs +++ b/templates/code/rust/tests/imported/expected/myappattr.rs @@ -1,28 +1,55 @@ // Generated by OpenTelemetry Weaver. /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] -pub struct TaskIdAttr(String); +pub struct TaskIdAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for TaskIdAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for TaskIdAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for TaskIdAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for TaskIdAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for TaskIdAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for TaskIdAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskIdAttr) -> Self { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/imported/expected/myappmetric.rs b/templates/code/rust/tests/imported/expected/myappmetric.rs index 47a7e48..1fed95f 100644 --- a/templates/code/rust/tests/imported/expected/myappmetric.rs +++ b/templates/code/rust/tests/imported/expected/myappmetric.rs @@ -1,12 +1,12 @@ #![allow(deprecated)] #[derive(Clone, Debug)] pub enum TaskFailedCounterAttr { - HttpRequestMethodList(Vec), + HttpRequestMethodList(Vec<::opentelemetry::StringValue>), } impl From for ::opentelemetry::KeyValue { fn from(value: TaskFailedCounterAttr) -> Self { match value { - TaskFailedCounterAttr::HttpRequestMethodList(value) => ::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.into_iter().map(Into::into).collect()))), + TaskFailedCounterAttr::HttpRequestMethodList(value) => ::opentelemetry::KeyValue::new("http.request.method_list", ::opentelemetry::Value::Array(::opentelemetry::Array::String(value))), } } } @@ -15,13 +15,15 @@ impl From for ::opentelemetry::KeyValue { pub struct TaskFailedCounter { instrument: ::opentelemetry::metrics::Counter } impl TaskFailedCounter { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().u64_counter("myapp.task.failed") + let instrument = meter.inner().u64_counter("myapp.task.failed") .with_description("Number of tasks that failed.") .with_unit("{task}") - .build() } + .build(); + Self { instrument } } - pub fn add(&self, value: u64, r#error_type: String, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { - let mut attributes = vec![::opentelemetry::KeyValue::new("error.type", r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]; + pub fn add(&self, value: u64, r#error_type: ::opentelemetry::StringValue, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 3]>::new(); + attributes.extend([::opentelemetry::KeyValue::new("error.type", r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]); attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.add(value, &attributes); } @@ -31,8 +33,9 @@ impl Default for TaskFailedCounter { } pub struct TaskFailedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskFailedCounterObserver<'_> { - pub fn observe(&self, value: u64, r#error_type: String, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { - let mut attributes = vec![::opentelemetry::KeyValue::new("error.type", r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]; + pub fn observe(&self, value: u64, r#error_type: ::opentelemetry::StringValue, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 3]>::new(); + attributes.extend([::opentelemetry::KeyValue::new("error.type", r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]); attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.observer.observe(value, &attributes); } @@ -42,11 +45,12 @@ impl TaskFailedCounterObserver<'_> { pub struct TaskFailedObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } impl TaskFailedObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFailedCounterObserver<'_>) + Send + Sync + 'static) -> Self { - Self { _instrument: meter.inner().u64_observable_counter("myapp.task.failed") + let instrument = meter.inner().u64_observable_counter("myapp.task.failed") .with_description("Number of tasks that failed.") .with_unit("{task}") .with_callback(move |observer| callback(TaskFailedCounterObserver { observer })) - .build() } + .build(); + Self { _instrument: instrument } } } impl Default for TaskFailedObservableCounter { diff --git a/templates/code/rust/tests/imported/expected/tracer.rs b/templates/code/rust/tests/imported/expected/tracer.rs index 6580bf3..e6865f2 100644 --- a/templates/code/rust/tests/imported/expected/tracer.rs +++ b/templates/code/rust/tests/imported/expected/tracer.rs @@ -1,26 +1,20 @@ -pub struct Tracer(opentelemetry::global::BoxedTracer); -impl Tracer { - pub fn new(provider: &P, scope: impl Into>) -> Self - where - P::Tracer: Send + Sync + 'static, - ::Span: Send + Sync + 'static, - { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) +pub struct Tracer(T); +impl Tracer { + pub fn new>(provider: &P, scope: impl Into>) -> Self { + Self(provider.tracer_with_scope(opentelemetry::InstrumentationScope::builder(scope) + .with_schema_url(super::SCHEMA_URL).build())) } - pub fn new_with_scope(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self - where - P::Tracer: Send + Sync + 'static, - ::Span: Send + Sync + 'static, - { - Self(opentelemetry::global::BoxedTracer::new(Box::new(provider.tracer_with_scope(registry_scope(scope))))) + pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.tracer_with_scope(registry_scope(scope))) } - pub fn inner(&self) -> &opentelemetry::global::BoxedTracer { &self.0 } + pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/imported/registry/model.yaml b/templates/code/rust/tests/imported/registry/model.yaml index dac6860..c51ba44 100644 --- a/templates/code/rust/tests/imported/registry/model.yaml +++ b/templates/code/rust/tests/imported/registry/model.yaml @@ -53,6 +53,16 @@ spans: sampling_relevant: true - ref: http.request.method_list requirement_level: recommended + - type: edge.upstream.methods + kind: client + requirement_level: recommended + stability: stable + brief: A request named from attempted methods. + name: + note: "`{http.request.method_list}`" + attributes: + - ref: http.request.method_list + requirement_level: required events: - name: edge.upstream.failed requirement_level: recommended diff --git a/templates/code/rust/tests/imported/test.rs b/templates/code/rust/tests/imported/test.rs new file mode 100644 index 0000000..fb7e0bf --- /dev/null +++ b/templates/code/rust/tests/imported/test.rs @@ -0,0 +1,64 @@ +use generated_semconv::{edgeevent, edgespan, logger, myappattr, myappmetric, tracer}; +use opentelemetry::{Array, KeyValue, StringValue, Value}; + +#[test] +fn imported_native_strings_and_arrays_keep_their_sdk_storage() { + let methods = vec![StringValue::from("GET"), StringValue::from("POST")]; + let pointer = methods.as_ptr(); + let attribute = KeyValue::from(myappmetric::TaskFailedCounterAttr::HttpRequestMethodList( + methods, + )); + assert_eq!(attribute.key.as_str(), "http.request.method_list"); + let Value::Array(Array::String(methods)) = attribute.value else { + panic!("imported string arrays must keep native SDK storage"); + }; + assert_eq!(methods.as_ptr(), pointer); + assert_eq!( + methods.iter().map(StringValue::as_str).collect::>(), + ["GET", "POST"] + ); + myappmetric::TaskFailedCounter::default().add( + 1, + StringValue::from("timeout"), + myappattr::TaskIdAttr::from("task-1"), + [myappmetric::TaskFailedCounterAttr::HttpRequestMethodList( + methods, + )], + ); + let context = opentelemetry::Context::new(); + edgeevent::emit_upstream_failed( + &context, + &logger::Logger::default(), + StringValue::from("timeout"), + [edgeevent::UpstreamFailedOption::ServerAddress( + StringValue::from("example.com"), + )], + ); + let mut span = edgespan::start_upstream_request( + &context, + &tracer::Tracer::default(), + StringValue::from("example.com"), + 443, + [], + ); + span.end(); +} + +#[test] +fn imported_native_string_arrays_format_derived_span_names() { + let exporter = opentelemetry_sdk::trace::InMemorySpanExporter::default(); + let provider = opentelemetry_sdk::trace::SdkTracerProvider::builder() + .with_simple_exporter(exporter.clone()) + .build(); + let tracer = tracer::Tracer::new(&provider, "synthetic-upstream"); + let mut span = edgespan::start_upstream_methods( + &opentelemetry::Context::new(), + &tracer, + vec![StringValue::from("GET"), StringValue::from("POST")], + ); + span.end(); + provider.force_flush().unwrap(); + let spans = exporter.get_finished_spans().unwrap(); + assert_eq!(spans.len(), 1); + assert_eq!(spans[0].name, "[\"GET\",\"POST\"]"); +} diff --git a/templates/code/rust/tests/imported_typed/expected/logger.rs b/templates/code/rust/tests/imported_typed/expected/logger.rs index 175c830..179c64c 100644 --- a/templates/code/rust/tests/imported_typed/expected/logger.rs +++ b/templates/code/rust/tests/imported_typed/expected/logger.rs @@ -5,7 +5,7 @@ use opentelemetry::{Array, Value}; pub struct Logger::Logger>(L); impl Logger { pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.logger_with_scope(registry_scope(scope))) @@ -33,6 +33,7 @@ pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::Any } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/imported_typed/expected/meter.rs b/templates/code/rust/tests/imported_typed/expected/meter.rs index 176d064..2607994 100644 --- a/templates/code/rust/tests/imported_typed/expected/meter.rs +++ b/templates/code/rust/tests/imported_typed/expected/meter.rs @@ -2,7 +2,7 @@ pub struct Meter(opentelemetry::metrics::Meter); impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.meter_with_scope(registry_scope(scope))) @@ -14,6 +14,7 @@ impl Default for Meter { } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/imported_typed/expected/myappattr.rs b/templates/code/rust/tests/imported_typed/expected/myappattr.rs index 3b1f7f5..4987524 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappattr.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappattr.rs @@ -1,28 +1,55 @@ // Generated by OpenTelemetry Weaver. /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] -pub struct TaskIdAttr(String); +pub struct TaskIdAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for TaskIdAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for TaskIdAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for TaskIdAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for TaskIdAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for TaskIdAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for TaskIdAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskIdAttr) -> Self { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/imported_typed/expected/myappevent.rs b/templates/code/rust/tests/imported_typed/expected/myappevent.rs index a170dc4..02542b2 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappevent.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappevent.rs @@ -10,18 +10,18 @@ pub enum TaskErroredOption { } /// A task failed with an error. pub fn r#emit_task_errored(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#error_type: upstream::errorattr::TypeAttr, options: impl IntoIterator) { - let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let mut attributes: Vec<::opentelemetry::KeyValue> = vec![::opentelemetry::KeyValue::from(r#error_type)]; + let mut attributes = ::smallvec::SmallVec::<[TaskErroredOption; 1]>::new(); for option in options { match option { TaskErroredOption::Severity(value) => severity = value, TaskErroredOption::Timestamp(value) => timestamp = Some(value), - TaskErroredOption::ServerPort(value) => attributes.push(::opentelemetry::KeyValue::new("server.port", value)), + attribute => attributes.push(attribute), } } if !logger.inner().event_enabled(severity, "", Some("myapp.task.errored")) { return; } + let _context_guard = context.clone().attach(); let mut record = logger.inner().create_log_record(); record.set_event_name("myapp.task.errored"); record.set_severity_number(severity); @@ -30,6 +30,14 @@ pub fn r#emit_task_errored(context: &::opentel let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + let attribute = ::opentelemetry::KeyValue::from(r#error_type); + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + for option in attributes { + let attribute = match option { + TaskErroredOption::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), + TaskErroredOption::Severity(_) | TaskErroredOption::Timestamp(_) => continue, + }; + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } logger.inner().emit(record); } diff --git a/templates/code/rust/tests/imported_typed/expected/myappmetric.rs b/templates/code/rust/tests/imported_typed/expected/myappmetric.rs index 2694242..2305ffa 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappmetric.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappmetric.rs @@ -15,13 +15,15 @@ impl From for ::opentelemetry::KeyValue { pub struct TaskFailedCounter { instrument: ::opentelemetry::metrics::Counter } impl TaskFailedCounter { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().u64_counter("myapp.task.failed") + let instrument = meter.inner().u64_counter("myapp.task.failed") .with_description("Number of tasks that failed.") .with_unit("{task}") - .build() } + .build(); + Self { instrument } } pub fn add(&self, value: u64, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { - let mut attributes = vec![::opentelemetry::KeyValue::from(r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]; + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 3]>::new(); + attributes.extend([::opentelemetry::KeyValue::from(r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]); attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.add(value, &attributes); } @@ -32,7 +34,8 @@ impl Default for TaskFailedCounter { pub struct TaskFailedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskFailedCounterObserver<'_> { pub fn observe(&self, value: u64, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { - let mut attributes = vec![::opentelemetry::KeyValue::from(r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]; + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 3]>::new(); + attributes.extend([::opentelemetry::KeyValue::from(r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]); attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.observer.observe(value, &attributes); } @@ -42,11 +45,12 @@ impl TaskFailedCounterObserver<'_> { pub struct TaskFailedObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } impl TaskFailedObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFailedCounterObserver<'_>) + Send + Sync + 'static) -> Self { - Self { _instrument: meter.inner().u64_observable_counter("myapp.task.failed") + let instrument = meter.inner().u64_observable_counter("myapp.task.failed") .with_description("Number of tasks that failed.") .with_unit("{task}") .with_callback(move |observer| callback(TaskFailedCounterObserver { observer })) - .build() } + .build(); + Self { _instrument: instrument } } } impl Default for TaskFailedObservableCounter { diff --git a/templates/code/rust/tests/imported_typed/expected/myappspan.rs b/templates/code/rust/tests/imported_typed/expected/myappspan.rs index 2aeceed..c6c0856 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappspan.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappspan.rs @@ -1,5 +1,6 @@ #![allow(deprecated)] use ::opentelemetry::trace::{TraceContextExt, Tracer}; +use ::std::fmt::Write; #[derive(Clone, Debug)] pub enum TaskDispatchStartAttr { @@ -24,12 +25,14 @@ impl From for TaskDispatchStartAttr { } } /// Dispatch of a task. -pub struct TaskDispatchSpan { span: ::opentelemetry::global::BoxedSpan } -impl TaskDispatchSpan { - pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { +pub struct TaskDispatchSpan { span: S } +impl TaskDispatchSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { parent.with_span(self.span) } - pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn span(&mut self) -> &mut S { &mut self.span } pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } @@ -44,17 +47,16 @@ impl Default for TaskDispatchSpan { } } -pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) -> TaskDispatchSpan { - let mut name = String::new(); +pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) -> TaskDispatchSpan { + let mut name = String::with_capacity("task ".len() + ::std::convert::AsRef::::as_ref(&r#myapp_task_id).len() + " failed with ".len() + ::std::convert::AsRef::::as_ref(&r#error_type).len()); name.push_str("task "); - name.push_str(&::opentelemetry::KeyValue::from(r#myapp_task_id.clone()).value.to_string()); + write!(&mut name, "{}", r#myapp_task_id).expect("writing a span name to String cannot fail"); name.push_str(" failed with "); - name.push_str(&::opentelemetry::KeyValue::from(r#error_type).value.to_string()); - let mut attributes = vec![::opentelemetry::KeyValue::from(r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]; - attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); + write!(&mut name, "{}", r#error_type).expect("writing a span name to String cannot fail"); + let attributes: [::opentelemetry::KeyValue; 2] = [::opentelemetry::KeyValue::from(r#error_type), ::opentelemetry::KeyValue::from(r#myapp_task_id)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) - .with_attributes(attributes) + .with_attributes(attributes.into_iter().chain(options.into_iter().map(::opentelemetry::KeyValue::from))) .start_with_context(tracer.inner(), context); TaskDispatchSpan { span } } diff --git a/templates/code/rust/tests/imported_typed/expected/tracer.rs b/templates/code/rust/tests/imported_typed/expected/tracer.rs index 6580bf3..e6865f2 100644 --- a/templates/code/rust/tests/imported_typed/expected/tracer.rs +++ b/templates/code/rust/tests/imported_typed/expected/tracer.rs @@ -1,26 +1,20 @@ -pub struct Tracer(opentelemetry::global::BoxedTracer); -impl Tracer { - pub fn new(provider: &P, scope: impl Into>) -> Self - where - P::Tracer: Send + Sync + 'static, - ::Span: Send + Sync + 'static, - { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) +pub struct Tracer(T); +impl Tracer { + pub fn new>(provider: &P, scope: impl Into>) -> Self { + Self(provider.tracer_with_scope(opentelemetry::InstrumentationScope::builder(scope) + .with_schema_url(super::SCHEMA_URL).build())) } - pub fn new_with_scope(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self - where - P::Tracer: Send + Sync + 'static, - ::Span: Send + Sync + 'static, - { - Self(opentelemetry::global::BoxedTracer::new(Box::new(provider.tracer_with_scope(registry_scope(scope))))) + pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.tracer_with_scope(registry_scope(scope))) } - pub fn inner(&self) -> &opentelemetry::global::BoxedTracer { &self.0 } + pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/imported_typed/test.rs b/templates/code/rust/tests/imported_typed/test.rs new file mode 100644 index 0000000..54a62ed --- /dev/null +++ b/templates/code/rust/tests/imported_typed/test.rs @@ -0,0 +1,32 @@ +use generated_semconv::{logger, myappattr, myappevent, myappmetric, myappspan, tracer}; +use opentelemetry::KeyValue; + +#[test] +fn typed_dependencies_and_plain_imported_values_work_together() { + let error = upstream::errorattr::TypeAttr::Timeout; + assert_eq!( + KeyValue::from(error), + KeyValue::new("error.type", "timeout") + ); + myappmetric::TaskFailedCounter::default().add( + 1, + error, + myappattr::TaskIdAttr::from("task-1"), + [myappmetric::TaskFailedCounterAttr::ServerPort(443)], + ); + let context = opentelemetry::Context::new(); + myappevent::emit_task_errored( + &context, + &logger::Logger::default(), + error, + [myappevent::TaskErroredOption::ServerPort(443)], + ); + let mut span = myappspan::start_task_dispatch( + &context, + &tracer::Tracer::default(), + error, + myappattr::TaskIdAttr::from("task-1"), + [myappspan::TaskDispatchStartAttr::ServerPort(443)], + ); + span.end(); +} diff --git a/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs b/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs index 28efa9c..6a3b7f9 100644 --- a/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs +++ b/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs @@ -13,8 +13,21 @@ impl BoundaryAttr { pub const KEY: &'static str = "demo.boundary"; } +#[allow(deprecated)] +impl ::std::fmt::Display for BoundaryAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + let value: i64 = match self { + BoundaryAttr::Minimum => -9223372036854775808, + BoundaryAttr::Maximum => 9223372036854775807, + }; + ::std::fmt::Display::fmt(&value, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: BoundaryAttr) -> Self { let value: i64 = match value { BoundaryAttr::Minimum => -9223372036854775808, diff --git a/templates/code/rust/tests/literal_escaping/expected/demoattr.rs b/templates/code/rust/tests/literal_escaping/expected/demoattr.rs index a07ed4d..ab4c9a1 100644 --- a/templates/code/rust/tests/literal_escaping/expected/demoattr.rs +++ b/templates/code/rust/tests/literal_escaping/expected/demoattr.rs @@ -13,12 +13,32 @@ impl LiteralAttr { pub const KEY: &'static str = "demo.literal"; } +#[allow(deprecated)] +impl AsRef for LiteralAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + LiteralAttr::Literal => "backspace\\b formfeed\\f unicode\\u1234 doubled\\\\b tripled\\\\\\u0000", + LiteralAttr::Controls => "backspace\u{0008} formfeed\u{000c} unicode\u{0001} slash\\b", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for LiteralAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: LiteralAttr) -> Self { - let value: String = match value { - LiteralAttr::Literal => "backspace\\b formfeed\\f unicode\\u1234 doubled\\\\b tripled\\\\\\u0000".into(), - LiteralAttr::Controls => "backspace\u{0008} formfeed\u{000c} unicode\u{0001} slash\\b".into(), + let value: &'static str = match value { + LiteralAttr::Literal => "backspace\\b formfeed\\f unicode\\u1234 doubled\\\\b tripled\\\\\\u0000", + LiteralAttr::Controls => "backspace\u{0008} formfeed\u{000c} unicode\u{0001} slash\\b", }; ::opentelemetry::KeyValue::new(LiteralAttr::KEY, value) } diff --git a/templates/code/rust/tests/literal_escaping/expected/demometric.rs b/templates/code/rust/tests/literal_escaping/expected/demometric.rs index e84fc8c..e66f6e1 100644 --- a/templates/code/rust/tests/literal_escaping/expected/demometric.rs +++ b/templates/code/rust/tests/literal_escaping/expected/demometric.rs @@ -4,13 +4,14 @@ pub struct LiteralCountCounter { instrument: ::opentelemetry::metrics::Counter } impl LiteralCountCounter { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().u64_counter("demo.literal.count") + let instrument = meter.inner().u64_counter("demo.literal.count") .with_description("literal \\b \\f \\u1234") .with_unit("literal\\b\\u1234") - .build() } + .build(); + Self { instrument } } pub fn add(&self, value: u64, r#demo_literal: super::demoattr::LiteralAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#demo_literal)]; + let attributes = [::opentelemetry::KeyValue::from(r#demo_literal)]; self.instrument.add(value, &attributes); } } @@ -20,7 +21,7 @@ impl Default for LiteralCountCounter { pub struct LiteralCountCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl LiteralCountCounterObserver<'_> { pub fn observe(&self, value: u64, r#demo_literal: super::demoattr::LiteralAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#demo_literal)]; + let attributes = [::opentelemetry::KeyValue::from(r#demo_literal)]; self.observer.observe(value, &attributes); } } @@ -29,11 +30,12 @@ impl LiteralCountCounterObserver<'_> { pub struct LiteralCountObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } impl LiteralCountObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(LiteralCountCounterObserver<'_>) + Send + Sync + 'static) -> Self { - Self { _instrument: meter.inner().u64_observable_counter("demo.literal.count") + let instrument = meter.inner().u64_observable_counter("demo.literal.count") .with_description("literal \\b \\f \\u1234") .with_unit("literal\\b\\u1234") .with_callback(move |observer| callback(LiteralCountCounterObserver { observer })) - .build() } + .build(); + Self { _instrument: instrument } } } impl Default for LiteralCountObservableCounter { diff --git a/templates/code/rust/tests/literal_escaping/expected/meter.rs b/templates/code/rust/tests/literal_escaping/expected/meter.rs index 176d064..2607994 100644 --- a/templates/code/rust/tests/literal_escaping/expected/meter.rs +++ b/templates/code/rust/tests/literal_escaping/expected/meter.rs @@ -2,7 +2,7 @@ pub struct Meter(opentelemetry::metrics::Meter); impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.meter_with_scope(registry_scope(scope))) @@ -14,6 +14,7 @@ impl Default for Meter { } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/metrics/expected/authattr.rs b/templates/code/rust/tests/metrics/expected/authattr.rs index acbcc1a..563c8d2 100644 --- a/templates/code/rust/tests/metrics/expected/authattr.rs +++ b/templates/code/rust/tests/metrics/expected/authattr.rs @@ -13,18 +13,38 @@ impl MethodAttr { pub const KEY: &'static str = "auth.method"; } +#[allow(deprecated)] +impl AsRef for MethodAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + MethodAttr::Password => "password", + MethodAttr::Token => "token", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for MethodAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: MethodAttr) -> Self { - let value: String = match value { - MethodAttr::Password => "password".into(), - MethodAttr::Token => "token".into(), + let value: &'static str = match value { + MethodAttr::Password => "password", + MethodAttr::Token => "token", }; ::opentelemetry::KeyValue::new(MethodAttr::KEY, value) } } /// Whether the attempt succeeded. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct SuccessAttr(bool); #[allow(deprecated)] @@ -34,13 +54,23 @@ impl SuccessAttr { #[allow(deprecated)] impl From for SuccessAttr { + #[inline] fn from(value: bool) -> Self { Self(value) } } +#[allow(deprecated)] +impl ::std::fmt::Display for SuccessAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: SuccessAttr) -> Self { ::opentelemetry::KeyValue::new(SuccessAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/metrics/expected/authmetric.rs b/templates/code/rust/tests/metrics/expected/authmetric.rs index 3bd980d..11d5a53 100644 --- a/templates/code/rust/tests/metrics/expected/authmetric.rs +++ b/templates/code/rust/tests/metrics/expected/authmetric.rs @@ -4,13 +4,14 @@ pub struct AttemptsCounter { instrument: ::opentelemetry::metrics::Counter } impl AttemptsCounter { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().u64_counter("auth.attempts") + let instrument = meter.inner().u64_counter("auth.attempts") .with_description("Number of authentication attempts.") .with_unit("{attempt}") - .build() } + .build(); + Self { instrument } } pub fn add(&self, value: u64, r#auth_method: super::authattr::MethodAttr, r#auth_success: super::authattr::SuccessAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#auth_method), ::opentelemetry::KeyValue::from(r#auth_success)]; + let attributes = [::opentelemetry::KeyValue::from(r#auth_method), ::opentelemetry::KeyValue::from(r#auth_success)]; self.instrument.add(value, &attributes); } } @@ -20,7 +21,7 @@ impl Default for AttemptsCounter { pub struct AttemptsCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl AttemptsCounterObserver<'_> { pub fn observe(&self, value: u64, r#auth_method: super::authattr::MethodAttr, r#auth_success: super::authattr::SuccessAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#auth_method), ::opentelemetry::KeyValue::from(r#auth_success)]; + let attributes = [::opentelemetry::KeyValue::from(r#auth_method), ::opentelemetry::KeyValue::from(r#auth_success)]; self.observer.observe(value, &attributes); } } @@ -29,11 +30,12 @@ impl AttemptsCounterObserver<'_> { pub struct AttemptsObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } impl AttemptsObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(AttemptsCounterObserver<'_>) + Send + Sync + 'static) -> Self { - Self { _instrument: meter.inner().u64_observable_counter("auth.attempts") + let instrument = meter.inner().u64_observable_counter("auth.attempts") .with_description("Number of authentication attempts.") .with_unit("{attempt}") .with_callback(move |observer| callback(AttemptsCounterObserver { observer })) - .build() } + .build(); + Self { _instrument: instrument } } } impl Default for AttemptsObservableCounter { diff --git a/templates/code/rust/tests/metrics/expected/meter.rs b/templates/code/rust/tests/metrics/expected/meter.rs index 176d064..2607994 100644 --- a/templates/code/rust/tests/metrics/expected/meter.rs +++ b/templates/code/rust/tests/metrics/expected/meter.rs @@ -2,7 +2,7 @@ pub struct Meter(opentelemetry::metrics::Meter); impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.meter_with_scope(registry_scope(scope))) @@ -14,6 +14,7 @@ impl Default for Meter { } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/metrics/expected/myappattr.rs b/templates/code/rust/tests/metrics/expected/myappattr.rs index b327b3b..c41ad67 100644 --- a/templates/code/rust/tests/metrics/expected/myappattr.rs +++ b/templates/code/rust/tests/metrics/expected/myappattr.rs @@ -1,28 +1,55 @@ // Generated by OpenTelemetry Weaver. /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] -pub struct TaskIdAttr(String); +pub struct TaskIdAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for TaskIdAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for TaskIdAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for TaskIdAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl AsRef for TaskIdAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() } } + #[allow(deprecated)] -impl From<&str> for TaskIdAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for TaskIdAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskIdAttr) -> Self { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } @@ -41,12 +68,32 @@ impl TaskStateAttr { pub const KEY: &'static str = "myapp.task.state"; } +#[allow(deprecated)] +impl AsRef for TaskStateAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + TaskStateAttr::Queued => "queued", + TaskStateAttr::Done => "done", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskStateAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskStateAttr) -> Self { - let value: String = match value { - TaskStateAttr::Queued => "queued".into(), - TaskStateAttr::Done => "done".into(), + let value: &'static str = match value { + TaskStateAttr::Queued => "queued", + TaskStateAttr::Done => "done", }; ::opentelemetry::KeyValue::new(TaskStateAttr::KEY, value) } diff --git a/templates/code/rust/tests/metrics/expected/myappmetric.rs b/templates/code/rust/tests/metrics/expected/myappmetric.rs index 008c8fe..d5ea051 100644 --- a/templates/code/rust/tests/metrics/expected/myappmetric.rs +++ b/templates/code/rust/tests/metrics/expected/myappmetric.rs @@ -5,13 +5,14 @@ pub struct QueueDepthGauge { instrument: ::opentelemetry::metrics::Gauge } impl QueueDepthGauge { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().i64_gauge("myapp.queue.depth") + let instrument = meter.inner().i64_gauge("myapp.queue.depth") .with_description("Number of tasks waiting in the queue.") .with_unit("{task}") - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: i64) { - let attributes = vec![]; + let attributes = []; self.instrument.record(value, &attributes); } } @@ -21,7 +22,7 @@ impl Default for QueueDepthGauge { pub struct QueueDepthGaugeObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl QueueDepthGaugeObserver<'_> { pub fn observe(&self, value: i64) { - let attributes = vec![]; + let attributes = []; self.observer.observe(value, &attributes); } } @@ -30,11 +31,12 @@ impl QueueDepthGaugeObserver<'_> { pub struct QueueDepthObservableGauge { _instrument: ::opentelemetry::metrics::ObservableGauge } impl QueueDepthObservableGauge { pub fn new(meter: &super::meter::Meter, callback: impl Fn(QueueDepthGaugeObserver<'_>) + Send + Sync + 'static) -> Self { - Self { _instrument: meter.inner().i64_observable_gauge("myapp.queue.depth") + let instrument = meter.inner().i64_observable_gauge("myapp.queue.depth") .with_description("Number of tasks waiting in the queue.") .with_unit("{task}") .with_callback(move |observer| callback(QueueDepthGaugeObserver { observer })) - .build() } + .build(); + Self { _instrument: instrument } } } impl Default for QueueDepthObservableGauge { @@ -45,13 +47,14 @@ impl Default for QueueDepthObservableGauge { pub struct TaskActiveUpDownCounter { instrument: ::opentelemetry::metrics::UpDownCounter } impl TaskActiveUpDownCounter { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().i64_up_down_counter("myapp.task.active") + let instrument = meter.inner().i64_up_down_counter("myapp.task.active") .with_description("Number of tasks currently running.") .with_unit("{task}") - .build() } + .build(); + Self { instrument } } pub fn add(&self, value: i64, r#myapp_task_state: super::myappattr::TaskStateAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_state)]; + let attributes = [::opentelemetry::KeyValue::from(r#myapp_task_state)]; self.instrument.add(value, &attributes); } } @@ -61,7 +64,7 @@ impl Default for TaskActiveUpDownCounter { pub struct TaskActiveUpDownCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskActiveUpDownCounterObserver<'_> { pub fn observe(&self, value: i64, r#myapp_task_state: super::myappattr::TaskStateAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_state)]; + let attributes = [::opentelemetry::KeyValue::from(r#myapp_task_state)]; self.observer.observe(value, &attributes); } } @@ -70,11 +73,12 @@ impl TaskActiveUpDownCounterObserver<'_> { pub struct TaskActiveObservableUpDownCounter { _instrument: ::opentelemetry::metrics::ObservableUpDownCounter } impl TaskActiveObservableUpDownCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskActiveUpDownCounterObserver<'_>) + Send + Sync + 'static) -> Self { - Self { _instrument: meter.inner().i64_observable_up_down_counter("myapp.task.active") + let instrument = meter.inner().i64_observable_up_down_counter("myapp.task.active") .with_description("Number of tasks currently running.") .with_unit("{task}") .with_callback(move |observer| callback(TaskActiveUpDownCounterObserver { observer })) - .build() } + .build(); + Self { _instrument: instrument } } } impl Default for TaskActiveObservableUpDownCounter { @@ -102,14 +106,16 @@ impl From for ::opentelemetry::KeyValue { pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } impl TaskDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_histogram("myapp.task.duration") + let instrument = meter.inner().f64_histogram("myapp.task.duration") .with_description("Time a task took from start to finish.") .with_unit("s") .with_boundaries(vec![0_f64, 0.005_f64, 0.01_f64, 0.1_f64, 1_f64, 10_f64]) - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { - let mut attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 3]>::new(); + attributes.extend([::opentelemetry::KeyValue::from(r#myapp_task_id)]); attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.record(value, &attributes); } @@ -122,13 +128,14 @@ impl Default for TaskDurationHistogram { pub struct TaskFloatActiveUpDownCounter { instrument: ::opentelemetry::metrics::UpDownCounter } impl TaskFloatActiveUpDownCounter { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_up_down_counter("myapp.task.float.active") + let instrument = meter.inner().f64_up_down_counter("myapp.task.float.active") .with_description("Fractional active task adjustment.") .with_unit("{task}") - .build() } + .build(); + Self { instrument } } pub fn add(&self, value: f64) { - let attributes = vec![]; + let attributes = []; self.instrument.add(value, &attributes); } } @@ -138,7 +145,7 @@ impl Default for TaskFloatActiveUpDownCounter { pub struct TaskFloatActiveUpDownCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskFloatActiveUpDownCounterObserver<'_> { pub fn observe(&self, value: f64) { - let attributes = vec![]; + let attributes = []; self.observer.observe(value, &attributes); } } @@ -147,11 +154,12 @@ impl TaskFloatActiveUpDownCounterObserver<'_> { pub struct TaskFloatActiveObservableUpDownCounter { _instrument: ::opentelemetry::metrics::ObservableUpDownCounter } impl TaskFloatActiveObservableUpDownCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFloatActiveUpDownCounterObserver<'_>) + Send + Sync + 'static) -> Self { - Self { _instrument: meter.inner().f64_observable_up_down_counter("myapp.task.float.active") + let instrument = meter.inner().f64_observable_up_down_counter("myapp.task.float.active") .with_description("Fractional active task adjustment.") .with_unit("{task}") .with_callback(move |observer| callback(TaskFloatActiveUpDownCounterObserver { observer })) - .build() } + .build(); + Self { _instrument: instrument } } } impl Default for TaskFloatActiveObservableUpDownCounter { @@ -162,13 +170,14 @@ impl Default for TaskFloatActiveObservableUpDownCounter { pub struct TaskFloatDepthGauge { instrument: ::opentelemetry::metrics::Gauge } impl TaskFloatDepthGauge { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_gauge("myapp.task.float.depth") + let instrument = meter.inner().f64_gauge("myapp.task.float.depth") .with_description("Fractional queue depth.") .with_unit("{task}") - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: f64) { - let attributes = vec![]; + let attributes = []; self.instrument.record(value, &attributes); } } @@ -178,7 +187,7 @@ impl Default for TaskFloatDepthGauge { pub struct TaskFloatDepthGaugeObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskFloatDepthGaugeObserver<'_> { pub fn observe(&self, value: f64) { - let attributes = vec![]; + let attributes = []; self.observer.observe(value, &attributes); } } @@ -187,11 +196,12 @@ impl TaskFloatDepthGaugeObserver<'_> { pub struct TaskFloatDepthObservableGauge { _instrument: ::opentelemetry::metrics::ObservableGauge } impl TaskFloatDepthObservableGauge { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFloatDepthGaugeObserver<'_>) + Send + Sync + 'static) -> Self { - Self { _instrument: meter.inner().f64_observable_gauge("myapp.task.float.depth") + let instrument = meter.inner().f64_observable_gauge("myapp.task.float.depth") .with_description("Fractional queue depth.") .with_unit("{task}") .with_callback(move |observer| callback(TaskFloatDepthGaugeObserver { observer })) - .build() } + .build(); + Self { _instrument: instrument } } } impl Default for TaskFloatDepthObservableGauge { @@ -202,13 +212,14 @@ impl Default for TaskFloatDepthObservableGauge { pub struct TaskFloatStartedCounter { instrument: ::opentelemetry::metrics::Counter } impl TaskFloatStartedCounter { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_counter("myapp.task.float.started") + let instrument = meter.inner().f64_counter("myapp.task.float.started") .with_description("Fractional tasks started.") .with_unit("{task}") - .build() } + .build(); + Self { instrument } } pub fn add(&self, value: f64) { - let attributes = vec![]; + let attributes = []; self.instrument.add(value, &attributes); } } @@ -218,7 +229,7 @@ impl Default for TaskFloatStartedCounter { pub struct TaskFloatStartedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskFloatStartedCounterObserver<'_> { pub fn observe(&self, value: f64) { - let attributes = vec![]; + let attributes = []; self.observer.observe(value, &attributes); } } @@ -227,11 +238,12 @@ impl TaskFloatStartedCounterObserver<'_> { pub struct TaskFloatStartedObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } impl TaskFloatStartedObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFloatStartedCounterObserver<'_>) + Send + Sync + 'static) -> Self { - Self { _instrument: meter.inner().f64_observable_counter("myapp.task.float.started") + let instrument = meter.inner().f64_observable_counter("myapp.task.float.started") .with_description("Fractional tasks started.") .with_unit("{task}") .with_callback(move |observer| callback(TaskFloatStartedCounterObserver { observer })) - .build() } + .build(); + Self { _instrument: instrument } } } impl Default for TaskFloatStartedObservableCounter { @@ -242,14 +254,15 @@ impl Default for TaskFloatStartedObservableCounter { pub struct TaskPayloadHistogram { instrument: ::opentelemetry::metrics::Histogram } impl TaskPayloadHistogram { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().u64_histogram("myapp.task.payload") + let instrument = meter.inner().u64_histogram("myapp.task.payload") .with_description("Task payload size.") .with_unit("By") .with_boundaries(vec![128_f64, 256_f64, 1024_f64]) - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: u64) { - let attributes = vec![]; + let attributes = []; self.instrument.record(value, &attributes); } } @@ -275,14 +288,16 @@ impl From for ::opentelemetry::KeyValue { pub struct TaskRetryDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } impl TaskRetryDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_histogram("myapp.task.duration") + let instrument = meter.inner().f64_histogram("myapp.task.duration") .with_description("Time a task took from start to finish.") .with_unit("s") .with_boundaries(vec![0_f64, 0.005_f64, 0.01_f64, 0.1_f64, 1_f64, 10_f64]) - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) { - let mut attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id), ::opentelemetry::KeyValue::from(r#myapp_task_state)]; + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 3]>::new(); + attributes.extend([::opentelemetry::KeyValue::from(r#myapp_task_id), ::opentelemetry::KeyValue::from(r#myapp_task_state)]); attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.record(value, &attributes); } @@ -308,13 +323,14 @@ impl From for ::opentelemetry::KeyValue { pub struct TaskStartedCounter { instrument: ::opentelemetry::metrics::Counter } impl TaskStartedCounter { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().u64_counter("myapp.task.started") + let instrument = meter.inner().u64_counter("myapp.task.started") .with_description("Number of tasks started.") .with_unit("{task}") - .build() } + .build(); + Self { instrument } } pub fn add(&self, value: u64, options: impl IntoIterator) { - let mut attributes = vec![]; + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 1]>::new(); attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.add(value, &attributes); } @@ -325,7 +341,7 @@ impl Default for TaskStartedCounter { pub struct TaskStartedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl TaskStartedCounterObserver<'_> { pub fn observe(&self, value: u64, options: impl IntoIterator) { - let mut attributes = vec![]; + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 1]>::new(); attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.observer.observe(value, &attributes); } @@ -335,11 +351,12 @@ impl TaskStartedCounterObserver<'_> { pub struct TaskStartedObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } impl TaskStartedObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskStartedCounterObserver<'_>) + Send + Sync + 'static) -> Self { - Self { _instrument: meter.inner().u64_observable_counter("myapp.task.started") + let instrument = meter.inner().u64_observable_counter("myapp.task.started") .with_description("Number of tasks started.") .with_unit("{task}") .with_callback(move |observer| callback(TaskStartedCounterObserver { observer })) - .build() } + .build(); + Self { _instrument: instrument } } } impl Default for TaskStartedObservableCounter { diff --git a/templates/code/rust/tests/metrics/expected/workermetric.rs b/templates/code/rust/tests/metrics/expected/workermetric.rs index 88dc405..e19e682 100644 --- a/templates/code/rust/tests/metrics/expected/workermetric.rs +++ b/templates/code/rust/tests/metrics/expected/workermetric.rs @@ -21,14 +21,16 @@ impl From for ::opentelemetry::KeyValue { pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } impl TaskDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_histogram("myapp.task.duration") + let instrument = meter.inner().f64_histogram("myapp.task.duration") .with_description("Time a task took from start to finish.") .with_unit("s") .with_boundaries(vec![0_f64, 0.005_f64, 0.01_f64, 0.1_f64, 1_f64, 10_f64]) - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: f64, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { - let mut attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_id)]; + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 3]>::new(); + attributes.extend([::opentelemetry::KeyValue::from(r#myapp_task_id)]); attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.record(value, &attributes); } diff --git a/templates/code/rust/tests/naming/expected/capsattr.rs b/templates/code/rust/tests/naming/expected/capsattr.rs index c7f265a..619b334 100644 --- a/templates/code/rust/tests/naming/expected/capsattr.rs +++ b/templates/code/rust/tests/naming/expected/capsattr.rs @@ -1,28 +1,55 @@ // Generated by OpenTelemetry Weaver. /// Synthetic identifier. #[derive(Debug, Clone, PartialEq)] -pub struct Http2STATUSApiIDAttr(String); +pub struct Http2STATUSApiIDAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl Http2STATUSApiIDAttr { pub const KEY: &'static str = "caps.http2_STATUS.api_ID"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for Http2STATUSApiIDAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for Http2STATUSApiIDAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for Http2STATUSApiIDAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl AsRef for Http2STATUSApiIDAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() } } + #[allow(deprecated)] -impl From<&str> for Http2STATUSApiIDAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for Http2STATUSApiIDAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: Http2STATUSApiIDAttr) -> Self { ::opentelemetry::KeyValue::new(Http2STATUSApiIDAttr::KEY, value.0) } @@ -39,11 +66,30 @@ impl Mode2STATEAttr { pub const KEY: &'static str = "caps.mode2_STATE"; } +#[allow(deprecated)] +impl AsRef for Mode2STATEAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + Mode2STATEAttr::HTTP2ReadySTATE => "ready", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for Mode2STATEAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: Mode2STATEAttr) -> Self { - let value: String = match value { - Mode2STATEAttr::HTTP2ReadySTATE => "ready".into(), + let value: &'static str = match value { + Mode2STATEAttr::HTTP2ReadySTATE => "ready", }; ::opentelemetry::KeyValue::new(Mode2STATEAttr::KEY, value) } diff --git a/templates/code/rust/tests/naming/expected/capsmetric.rs b/templates/code/rust/tests/naming/expected/capsmetric.rs index 11b46d0..5447fd8 100644 --- a/templates/code/rust/tests/naming/expected/capsmetric.rs +++ b/templates/code/rust/tests/naming/expected/capsmetric.rs @@ -4,13 +4,14 @@ pub struct Http2STATUSCountCounter { instrument: ::opentelemetry::metrics::Counter } impl Http2STATUSCountCounter { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().u64_counter("caps.http2_STATUS.count") + let instrument = meter.inner().u64_counter("caps.http2_STATUS.count") .with_description("Synthetic count.") .with_unit("{item}") - .build() } + .build(); + Self { instrument } } pub fn add(&self, value: u64, r#caps_http2_status_api_id: super::capsattr::Http2STATUSApiIDAttr, r#caps_mode2_state: super::capsattr::Mode2STATEAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#caps_http2_status_api_id), ::opentelemetry::KeyValue::from(r#caps_mode2_state)]; + let attributes = [::opentelemetry::KeyValue::from(r#caps_http2_status_api_id), ::opentelemetry::KeyValue::from(r#caps_mode2_state)]; self.instrument.add(value, &attributes); } } @@ -20,7 +21,7 @@ impl Default for Http2STATUSCountCounter { pub struct Http2STATUSCountCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } impl Http2STATUSCountCounterObserver<'_> { pub fn observe(&self, value: u64, r#caps_http2_status_api_id: super::capsattr::Http2STATUSApiIDAttr, r#caps_mode2_state: super::capsattr::Mode2STATEAttr) { - let attributes = vec![::opentelemetry::KeyValue::from(r#caps_http2_status_api_id), ::opentelemetry::KeyValue::from(r#caps_mode2_state)]; + let attributes = [::opentelemetry::KeyValue::from(r#caps_http2_status_api_id), ::opentelemetry::KeyValue::from(r#caps_mode2_state)]; self.observer.observe(value, &attributes); } } @@ -29,11 +30,12 @@ impl Http2STATUSCountCounterObserver<'_> { pub struct Http2STATUSCountObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } impl Http2STATUSCountObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(Http2STATUSCountCounterObserver<'_>) + Send + Sync + 'static) -> Self { - Self { _instrument: meter.inner().u64_observable_counter("caps.http2_STATUS.count") + let instrument = meter.inner().u64_observable_counter("caps.http2_STATUS.count") .with_description("Synthetic count.") .with_unit("{item}") .with_callback(move |observer| callback(Http2STATUSCountCounterObserver { observer })) - .build() } + .build(); + Self { _instrument: instrument } } } impl Default for Http2STATUSCountObservableCounter { diff --git a/templates/code/rust/tests/naming/expected/meter.rs b/templates/code/rust/tests/naming/expected/meter.rs index 176d064..2607994 100644 --- a/templates/code/rust/tests/naming/expected/meter.rs +++ b/templates/code/rust/tests/naming/expected/meter.rs @@ -2,7 +2,7 @@ pub struct Meter(opentelemetry::metrics::Meter); impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.meter_with_scope(registry_scope(scope))) @@ -14,6 +14,7 @@ impl Default for Meter { } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs index b3982cb..ac56186 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs @@ -1,56 +1,110 @@ // Generated by OpenTelemetry Weaver. /// The exception message. #[derive(Debug, Clone, PartialEq)] -pub struct MessageAttr(String); +pub struct MessageAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl MessageAttr { pub const KEY: &'static str = "exception.message"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for MessageAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for MessageAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for MessageAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for MessageAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for MessageAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for MessageAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: MessageAttr) -> Self { ::opentelemetry::KeyValue::new(MessageAttr::KEY, value.0) } } /// The type of the exception. #[derive(Debug, Clone, PartialEq)] -pub struct TypeAttr(String); +pub struct TypeAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl TypeAttr { pub const KEY: &'static str = "exception.type"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for TypeAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for TypeAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for TypeAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for TypeAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for TypeAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for TypeAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TypeAttr) -> Self { ::opentelemetry::KeyValue::new(TypeAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs index f52df3a..36af491 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs @@ -10,18 +10,18 @@ pub enum Option { } /// A noteworthy exception occurred. pub fn r#emit_(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#exception_type: super::exceptionattr::TypeAttr, options: impl IntoIterator) { - let _context_guard = context.clone().attach(); let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let mut attributes: Vec<::opentelemetry::KeyValue> = vec![::opentelemetry::KeyValue::from(r#exception_type)]; + let mut attributes = ::smallvec::SmallVec::<[Option; 1]>::new(); for option in options { match option { Option::Severity(value) => severity = value, Option::Timestamp(value) => timestamp = Some(value), - Option::Message(value) => attributes.push(::opentelemetry::KeyValue::from(value)), + attribute => attributes.push(attribute), } } if !logger.inner().event_enabled(severity, "", Some("exception")) { return; } + let _context_guard = context.clone().attach(); let mut record = logger.inner().create_log_record(); record.set_event_name("exception"); record.set_severity_number(severity); @@ -30,6 +30,14 @@ pub fn r#emit_(context: &::opentelemetry::Cont let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - for attribute in attributes { record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); } + let attribute = ::opentelemetry::KeyValue::from(r#exception_type); + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + for option in attributes { + let attribute = match option { + Option::Message(value) => ::opentelemetry::KeyValue::from(value), + Option::Severity(_) | Option::Timestamp(_) => continue, + }; + record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } logger.inner().emit(record); } diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs index 7f6e0da..ad0d10d 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs @@ -1,6 +1,6 @@ // Generated by OpenTelemetry Weaver. /// Sequence number of the heartbeat. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct SequenceAttr(i64); #[allow(deprecated)] @@ -10,41 +10,78 @@ impl SequenceAttr { #[allow(deprecated)] impl From for SequenceAttr { + #[inline] fn from(value: i64) -> Self { Self(value) } } +#[allow(deprecated)] +impl ::std::fmt::Display for SequenceAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: SequenceAttr) -> Self { ::opentelemetry::KeyValue::new(SequenceAttr::KEY, value.0) } } /// Name of the component that sent the heartbeat. #[derive(Debug, Clone, PartialEq)] -pub struct SourceAttr(String); +pub struct SourceAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl SourceAttr { pub const KEY: &'static str = "heartbeat.source"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for SourceAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for SourceAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) } } + +#[allow(deprecated)] +impl From<&'static str> for SourceAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl AsRef for SourceAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for SourceAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for SourceAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: SourceAttr) -> Self { ::opentelemetry::KeyValue::new(SourceAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs index cb99671..f72c617 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs @@ -24,17 +24,25 @@ impl From for StartAttr { } } #[derive(Clone, Debug, Default)] -pub struct Name(String); -impl Name { - pub fn new(value: impl Into) -> Self { Self(value.into()) } +pub struct Name(::std::borrow::Cow<'static, str>); +impl From<&'static str> for Name { + fn from(value: &'static str) -> Self { Self(::std::borrow::Cow::Borrowed(value)) } +} +impl From for Name { + fn from(value: String) -> Self { Self(::std::borrow::Cow::Owned(value)) } +} +impl From<::std::borrow::Cow<'static, str>> for Name { + fn from(value: ::std::borrow::Cow<'static, str>) -> Self { Self(value) } } /// A periodic liveness signal. -pub struct Span { span: ::opentelemetry::global::BoxedSpan } -impl Span { - pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { +pub struct Span { span: S } +impl Span { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { parent.with_span(self.span) } - pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn span(&mut self) -> &mut S { &mut self.span } pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } @@ -49,13 +57,12 @@ impl Default for Span { } } -pub fn r#start_(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: Name, r#heartbeat_sequence: super::heartbeatattr::SequenceAttr, options: impl IntoIterator) -> Span { - let name = if name.0.is_empty() { "heartbeat".to_owned() } else { name.0 }; - let mut attributes = vec![::opentelemetry::KeyValue::from(r#heartbeat_sequence)]; - attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); +pub fn r#start_(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: Name, r#heartbeat_sequence: super::heartbeatattr::SequenceAttr, options: impl IntoIterator) -> Span { + let name = if name.0.is_empty() { ::std::borrow::Cow::Borrowed("heartbeat") } else { name.0 }; + let attributes: [::opentelemetry::KeyValue; 1] = [::opentelemetry::KeyValue::from(r#heartbeat_sequence)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) - .with_attributes(attributes) + .with_attributes(attributes.into_iter().chain(options.into_iter().map(::opentelemetry::KeyValue::from))) .start_with_context(tracer.inner(), context); Span { span } } diff --git a/templates/code/rust/tests/no_namespace/expected/hostattr.rs b/templates/code/rust/tests/no_namespace/expected/hostattr.rs index 7489472..456ceb2 100644 --- a/templates/code/rust/tests/no_namespace/expected/hostattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/hostattr.rs @@ -1,56 +1,110 @@ // Generated by OpenTelemetry Weaver. /// Unique identifier of the host. #[derive(Debug, Clone, PartialEq)] -pub struct IdAttr(String); +pub struct IdAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl IdAttr { pub const KEY: &'static str = "host.id"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for IdAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for IdAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for IdAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for IdAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for IdAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for IdAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: IdAttr) -> Self { ::opentelemetry::KeyValue::new(IdAttr::KEY, value.0) } } /// Name of the host. #[derive(Debug, Clone, PartialEq)] -pub struct NameAttr(String); +pub struct NameAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl NameAttr { pub const KEY: &'static str = "host.name"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for NameAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for NameAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for NameAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for NameAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for NameAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for NameAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: NameAttr) -> Self { ::opentelemetry::KeyValue::new(NameAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/no_namespace/expected/hostentity.rs b/templates/code/rust/tests/no_namespace/expected/hostentity.rs index 62ae58e..49100c6 100644 --- a/templates/code/rust/tests/no_namespace/expected/hostentity.rs +++ b/templates/code/rust/tests/no_namespace/expected/hostentity.rs @@ -15,27 +15,34 @@ impl From for ::opentelemetry::KeyValue { /// A physical or virtual machine. /// Identifies the entity: `host.id`. /// Describes the entity: `host.name`. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct Entity { - attributes: Vec<::opentelemetry::KeyValue>, + r#host_id: super::hostattr::IdAttr, + options: ::smallvec::SmallVec<[EntityAttr; 1]>, } impl Entity { pub fn new(r#host_id: super::hostattr::IdAttr, options: impl IntoIterator) -> Self { - let mut attributes = vec![ - ::opentelemetry::KeyValue::from(r#host_id), - ]; - attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); - Self { attributes } + Self { + r#host_id, + options: options.into_iter().collect(), + } } - pub fn attributes(&self) -> Vec<::opentelemetry::KeyValue> { - self.attributes.clone() + pub fn attributes(&self) -> impl Iterator + '_ { + ::std::iter::empty() + .chain(::std::iter::once_with(move || ::opentelemetry::KeyValue::from(self.r#host_id.clone()))) + .chain(self.options.iter().cloned().map(::opentelemetry::KeyValue::from)) } +} - pub fn resource(&self) -> ::opentelemetry_sdk::Resource { +impl From for ::opentelemetry_sdk::Resource { + fn from(value: Entity) -> Self { + let attributes = [ + ::opentelemetry::KeyValue::from(value.r#host_id), + ].into_iter().chain(value.options.into_iter().map(::opentelemetry::KeyValue::from)); ::opentelemetry_sdk::Resource::builder_empty() - .with_schema_url(self.attributes(), super::SCHEMA_URL) + .with_schema_url(attributes, super::SCHEMA_URL) .build() } } diff --git a/templates/code/rust/tests/no_namespace/expected/logger.rs b/templates/code/rust/tests/no_namespace/expected/logger.rs index 175c830..179c64c 100644 --- a/templates/code/rust/tests/no_namespace/expected/logger.rs +++ b/templates/code/rust/tests/no_namespace/expected/logger.rs @@ -5,7 +5,7 @@ use opentelemetry::{Array, Value}; pub struct Logger::Logger>(L); impl Logger { pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.logger_with_scope(registry_scope(scope))) @@ -33,6 +33,7 @@ pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::Any } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/no_namespace/expected/tracer.rs b/templates/code/rust/tests/no_namespace/expected/tracer.rs index 6580bf3..e6865f2 100644 --- a/templates/code/rust/tests/no_namespace/expected/tracer.rs +++ b/templates/code/rust/tests/no_namespace/expected/tracer.rs @@ -1,26 +1,20 @@ -pub struct Tracer(opentelemetry::global::BoxedTracer); -impl Tracer { - pub fn new(provider: &P, scope: impl Into>) -> Self - where - P::Tracer: Send + Sync + 'static, - ::Span: Send + Sync + 'static, - { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) +pub struct Tracer(T); +impl Tracer { + pub fn new>(provider: &P, scope: impl Into>) -> Self { + Self(provider.tracer_with_scope(opentelemetry::InstrumentationScope::builder(scope) + .with_schema_url(super::SCHEMA_URL).build())) } - pub fn new_with_scope(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self - where - P::Tracer: Send + Sync + 'static, - ::Span: Send + Sync + 'static, - { - Self(opentelemetry::global::BoxedTracer::new(Box::new(provider.tracer_with_scope(registry_scope(scope))))) + pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.tracer_with_scope(registry_scope(scope))) } - pub fn inner(&self) -> &opentelemetry::global::BoxedTracer { &self.0 } + pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/params/expected/billingattr.rs b/templates/code/rust/tests/params/expected/billingattr.rs index ca483cf..1649776 100644 --- a/templates/code/rust/tests/params/expected/billingattr.rs +++ b/templates/code/rust/tests/params/expected/billingattr.rs @@ -1,56 +1,110 @@ // Generated by OpenTelemetry Weaver. /// Identifier of the invoice. #[derive(Debug, Clone, PartialEq)] -pub struct InvoiceIdAttr(String); +pub struct InvoiceIdAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl InvoiceIdAttr { pub const KEY: &'static str = "acme.billing.invoice.id"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for InvoiceIdAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for InvoiceIdAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for InvoiceIdAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for InvoiceIdAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for InvoiceIdAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for InvoiceIdAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: InvoiceIdAttr) -> Self { ::opentelemetry::KeyValue::new(InvoiceIdAttr::KEY, value.0) } } /// ISO 4217 currency code of the amount. #[derive(Debug, Clone, PartialEq)] -pub struct CurrencyAttr(String); +pub struct CurrencyAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl CurrencyAttr { pub const KEY: &'static str = "billing.currency"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for CurrencyAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for CurrencyAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for CurrencyAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for CurrencyAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for CurrencyAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for CurrencyAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: CurrencyAttr) -> Self { ::opentelemetry::KeyValue::new(CurrencyAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/params/expected/billingmetric.rs b/templates/code/rust/tests/params/expected/billingmetric.rs index d2bf001..bbdc365 100644 --- a/templates/code/rust/tests/params/expected/billingmetric.rs +++ b/templates/code/rust/tests/params/expected/billingmetric.rs @@ -17,13 +17,15 @@ impl From for ::opentelemetry::KeyValue { pub struct InvoiceAmountHistogram { instrument: ::opentelemetry::metrics::Histogram } impl InvoiceAmountHistogram { pub fn new(meter: &super::meter::Meter) -> Self { - Self { instrument: meter.inner().f64_histogram("acme.billing.invoice.amount") + let instrument = meter.inner().f64_histogram("acme.billing.invoice.amount") .with_description("Amount of each issued invoice.") .with_unit("{currency_unit}") - .build() } + .build(); + Self { instrument } } pub fn record(&self, value: f64, r#billing_invoice_id: super::billingattr::InvoiceIdAttr, options: impl IntoIterator) { - let mut attributes = vec![::opentelemetry::KeyValue::from(r#billing_invoice_id)]; + let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 3]>::new(); + attributes.extend([::opentelemetry::KeyValue::from(r#billing_invoice_id)]); attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); self.instrument.record(value, &attributes); } diff --git a/templates/code/rust/tests/params/expected/meter.rs b/templates/code/rust/tests/params/expected/meter.rs index 176d064..2607994 100644 --- a/templates/code/rust/tests/params/expected/meter.rs +++ b/templates/code/rust/tests/params/expected/meter.rs @@ -2,7 +2,7 @@ pub struct Meter(opentelemetry::metrics::Meter); impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) + Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) } pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { Self(provider.meter_with_scope(registry_scope(scope))) @@ -14,6 +14,7 @@ impl Default for Meter { } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/params/expected/myappattr.rs b/templates/code/rust/tests/params/expected/myappattr.rs index a4d03d2..15e3f47 100644 --- a/templates/code/rust/tests/params/expected/myappattr.rs +++ b/templates/code/rust/tests/params/expected/myappattr.rs @@ -1,28 +1,55 @@ // Generated by OpenTelemetry Weaver. /// URL the request was sent to. #[derive(Debug, Clone, PartialEq)] -pub struct RequestUrlAttr(String); +pub struct RequestUrlAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl RequestUrlAttr { pub const KEY: &'static str = "myapp.request.url"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for RequestUrlAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for RequestUrlAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for RequestUrlAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) } } + +#[allow(deprecated)] +impl AsRef for RequestUrlAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + #[allow(deprecated)] -impl From<&str> for RequestUrlAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for RequestUrlAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: RequestUrlAttr) -> Self { ::opentelemetry::KeyValue::new(RequestUrlAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/spans/expected/myappattr.rs b/templates/code/rust/tests/spans/expected/myappattr.rs index ff00b86..6861a8b 100644 --- a/templates/code/rust/tests/spans/expected/myappattr.rs +++ b/templates/code/rust/tests/spans/expected/myappattr.rs @@ -1,34 +1,283 @@ // Generated by OpenTelemetry Weaver. +/// Synthetic naming value. +#[derive(Debug, Clone, PartialEq)] +pub struct ArrayFlagsAttr(Vec); + +#[allow(deprecated)] +impl ArrayFlagsAttr { + pub const KEY: &'static str = "myapp.array.flags"; +} + +#[allow(deprecated)] +impl From> for ArrayFlagsAttr { + #[inline] + fn from(value: Vec) -> Self { + Self(value) + } +} + +#[allow(deprecated)] +impl AsRef<[bool]> for ArrayFlagsAttr { + #[inline] + fn as_ref(&self) -> &[bool] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for ArrayFlagsAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + ::std::fmt::Display::fmt(value, formatter)?; + } + formatter.write_str("]") + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + #[inline] + fn from(value: ArrayFlagsAttr) -> Self { + ::opentelemetry::KeyValue::new(ArrayFlagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(value.0))) + } +} +/// Synthetic naming value. +#[derive(Debug, Clone, PartialEq)] +pub struct ArrayIndicesAttr(Vec); + +#[allow(deprecated)] +impl ArrayIndicesAttr { + pub const KEY: &'static str = "myapp.array.indices"; +} + +#[allow(deprecated)] +impl From> for ArrayIndicesAttr { + #[inline] + fn from(value: Vec) -> Self { + Self(value) + } +} + +#[allow(deprecated)] +impl AsRef<[i64]> for ArrayIndicesAttr { + #[inline] + fn as_ref(&self) -> &[i64] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for ArrayIndicesAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + ::std::fmt::Display::fmt(value, formatter)?; + } + formatter.write_str("]") + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + #[inline] + fn from(value: ArrayIndicesAttr) -> Self { + ::opentelemetry::KeyValue::new(ArrayIndicesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) + } +} +/// Synthetic naming value. +#[derive(Debug, Clone, PartialEq)] +pub struct ArraySamplesAttr(Vec); + +#[allow(deprecated)] +impl ArraySamplesAttr { + pub const KEY: &'static str = "myapp.array.samples"; +} + +#[allow(deprecated)] +impl From> for ArraySamplesAttr { + #[inline] + fn from(value: Vec) -> Self { + Self(value) + } +} + +#[allow(deprecated)] +impl AsRef<[f64]> for ArraySamplesAttr { + #[inline] + fn as_ref(&self) -> &[f64] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for ArraySamplesAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + ::std::fmt::Display::fmt(value, formatter)?; + } + formatter.write_str("]") + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + #[inline] + fn from(value: ArraySamplesAttr) -> Self { + ::opentelemetry::KeyValue::new(ArraySamplesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(value.0))) + } +} +/// Synthetic naming value. +#[derive(Debug, Clone, PartialEq)] +pub struct ArrayTagsAttr(Vec<::opentelemetry::StringValue>); + +#[allow(deprecated)] +impl ArrayTagsAttr { + pub const KEY: &'static str = "myapp.array.tags"; +} + +#[allow(deprecated)] +impl From> for ArrayTagsAttr { + #[inline] + fn from(value: Vec<::opentelemetry::StringValue>) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From> for ArrayTagsAttr { + fn from(value: Vec) -> Self { + Self(value.into_iter().map(Into::into).collect()) + } +} + +#[allow(deprecated)] +impl AsRef<[::opentelemetry::StringValue]> for ArrayTagsAttr { + #[inline] + fn as_ref(&self) -> &[::opentelemetry::StringValue] { + &self.0 + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for ArrayTagsAttr { + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str("[")?; + for (index, value) in self.0.iter().enumerate() { + if index != 0 { + formatter.write_str(",")?; + } + write!(formatter, "\"{value}\"")?; + } + formatter.write_str("]") + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + #[inline] + fn from(value: ArrayTagsAttr) -> Self { + ::opentelemetry::KeyValue::new(ArrayTagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0))) + } +} +/// Synthetic naming value. +#[derive(Debug, Clone, PartialEq, Copy)] +pub struct NumberValueAttr(f64); + +#[allow(deprecated)] +impl NumberValueAttr { + pub const KEY: &'static str = "myapp.number.value"; +} + +#[allow(deprecated)] +impl From for NumberValueAttr { + #[inline] + fn from(value: f64) -> Self { + Self(value) + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for NumberValueAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + #[inline] + fn from(value: NumberValueAttr) -> Self { + ::opentelemetry::KeyValue::new(NumberValueAttr::KEY, value.0) + } +} /// Name of the queue the task came from. #[derive(Debug, Clone, PartialEq)] -pub struct QueueNameAttr(String); +pub struct QueueNameAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl QueueNameAttr { pub const KEY: &'static str = "myapp.queue.name"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for QueueNameAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for QueueNameAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) } } + #[allow(deprecated)] -impl From<&str> for QueueNameAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl From<&'static str> for QueueNameAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl AsRef for QueueNameAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for QueueNameAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: QueueNameAttr) -> Self { ::opentelemetry::KeyValue::new(QueueNameAttr::KEY, value.0) } } /// Number of the attempt, starting at one. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskAttemptAttr(i64); #[allow(deprecated)] @@ -38,41 +287,78 @@ impl TaskAttemptAttr { #[allow(deprecated)] impl From for TaskAttemptAttr { + #[inline] fn from(value: i64) -> Self { Self(value) } } +#[allow(deprecated)] +impl ::std::fmt::Display for TaskAttemptAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskAttemptAttr) -> Self { ::opentelemetry::KeyValue::new(TaskAttemptAttr::KEY, value.0) } } /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] -pub struct TaskIdAttr(String); +pub struct TaskIdAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl TaskIdAttr { pub const KEY: &'static str = "myapp.task.id"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for TaskIdAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for TaskIdAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for TaskIdAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl AsRef for TaskIdAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() } } + #[allow(deprecated)] -impl From<&str> for TaskIdAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl ::std::fmt::Display for TaskIdAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskIdAttr) -> Self { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } @@ -91,12 +377,32 @@ impl TaskStateAttr { pub const KEY: &'static str = "myapp.task.state"; } +#[allow(deprecated)] +impl AsRef for TaskStateAttr { + #[inline] + fn as_ref(&self) -> &str { + match self { + TaskStateAttr::Queued => "queued", + TaskStateAttr::Done => "done", + } + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for TaskStateAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: TaskStateAttr) -> Self { - let value: String = match value { - TaskStateAttr::Queued => "queued".into(), - TaskStateAttr::Done => "done".into(), + let value: &'static str = match value { + TaskStateAttr::Queued => "queued", + TaskStateAttr::Done => "done", }; ::opentelemetry::KeyValue::new(TaskStateAttr::KEY, value) } diff --git a/templates/code/rust/tests/spans/expected/myappspan.rs b/templates/code/rust/tests/spans/expected/myappspan.rs index 00ef698..e8a5666 100644 --- a/templates/code/rust/tests/spans/expected/myappspan.rs +++ b/templates/code/rust/tests/spans/expected/myappspan.rs @@ -1,13 +1,16 @@ #![allow(deprecated)] use ::opentelemetry::trace::{TraceContextExt, Tracer}; +use ::std::fmt::Write; /// Synthetic escaped name. -pub struct NameApostropheSpan { span: ::opentelemetry::global::BoxedSpan } -impl NameApostropheSpan { - pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { +pub struct NameApostropheSpan { span: S } +impl NameApostropheSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { parent.with_span(self.span) } - pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn span(&mut self) -> &mut S { &mut self.span } pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } @@ -19,24 +22,62 @@ impl Default for NameApostropheSpan { } } -pub fn r#start_name_apostrophe(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameApostropheSpan { - let mut name = String::new(); +pub fn r#start_name_apostrophe(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameApostropheSpan { + let mut name = String::with_capacity("\u{0027}".len() + 20); name.push('\u{0027}'); - name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); - let attributes = vec![::opentelemetry::KeyValue::from(r#worker_host_port)]; + write!(&mut name, "{}", r#worker_host_port).expect("writing a span name to String cannot fail"); + let attributes: [::opentelemetry::KeyValue; 1] = [::opentelemetry::KeyValue::from(r#worker_host_port)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) .start_with_context(tracer.inner(), context); NameApostropheSpan { span } } +/// A span named from array values. +pub struct NameArraysSpan { span: S } +impl NameArraysSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut S { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } +} +impl Default for NameArraysSpan { + fn default() -> Self { + Self { span: super::tracer::Tracer::default().inner().start("myapp.name.arrays") } + } +} + +pub fn r#start_name_arrays(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#myapp_array_flags: super::myappattr::ArrayFlagsAttr, r#myapp_array_indices: super::myappattr::ArrayIndicesAttr, r#myapp_array_samples: super::myappattr::ArraySamplesAttr, r#myapp_array_tags: super::myappattr::ArrayTagsAttr) -> NameArraysSpan { + let mut name = String::with_capacity(::std::convert::AsRef::<[::opentelemetry::StringValue]>::as_ref(&r#myapp_array_tags).iter().map(|value| value.as_str().len() + 3).sum::() + 2 + ":".len() + ::std::convert::AsRef::<[i64]>::as_ref(&r#myapp_array_indices).len() * 21 + 2 + ":".len() + ::std::convert::AsRef::<[f64]>::as_ref(&r#myapp_array_samples).len() * 328 + 2 + ":".len() + ::std::convert::AsRef::<[bool]>::as_ref(&r#myapp_array_flags).len() * 6 + 2); + write!(&mut name, "{}", r#myapp_array_tags).expect("writing a span name to String cannot fail"); + name.push(':'); + write!(&mut name, "{}", r#myapp_array_indices).expect("writing a span name to String cannot fail"); + name.push(':'); + write!(&mut name, "{}", r#myapp_array_samples).expect("writing a span name to String cannot fail"); + name.push(':'); + write!(&mut name, "{}", r#myapp_array_flags).expect("writing a span name to String cannot fail"); + let attributes: [::opentelemetry::KeyValue; 4] = [::opentelemetry::KeyValue::from(r#myapp_array_flags), ::opentelemetry::KeyValue::from(r#myapp_array_indices), ::opentelemetry::KeyValue::from(r#myapp_array_samples), ::opentelemetry::KeyValue::from(r#myapp_array_tags)]; + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Internal) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + NameArraysSpan { span } +} /// Synthetic escaped name. -pub struct NameBackslashSpan { span: ::opentelemetry::global::BoxedSpan } -impl NameBackslashSpan { - pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { +pub struct NameBackslashSpan { span: S } +impl NameBackslashSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { parent.with_span(self.span) } - pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn span(&mut self) -> &mut S { &mut self.span } pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } @@ -48,11 +89,11 @@ impl Default for NameBackslashSpan { } } -pub fn r#start_name_backslash(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameBackslashSpan { - let mut name = String::new(); +pub fn r#start_name_backslash(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameBackslashSpan { + let mut name = String::with_capacity("\\".len() + 20); name.push('\\'); - name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); - let attributes = vec![::opentelemetry::KeyValue::from(r#worker_host_port)]; + write!(&mut name, "{}", r#worker_host_port).expect("writing a span name to String cannot fail"); + let attributes: [::opentelemetry::KeyValue; 1] = [::opentelemetry::KeyValue::from(r#worker_host_port)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) @@ -60,12 +101,14 @@ pub fn r#start_name_backslash(context: &::opentelemetry::Context, tracer: &super NameBackslashSpan { span } } /// Synthetic escaped name. -pub struct NameControlSpan { span: ::opentelemetry::global::BoxedSpan } -impl NameControlSpan { - pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { +pub struct NameControlSpan { span: S } +impl NameControlSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { parent.with_span(self.span) } - pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn span(&mut self) -> &mut S { &mut self.span } pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } @@ -77,24 +120,96 @@ impl Default for NameControlSpan { } } -pub fn r#start_name_control(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameControlSpan { - let mut name = String::new(); +pub fn r#start_name_control(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameControlSpan { + let mut name = String::with_capacity("\u{0008}".len() + 20); name.push('\u{0008}'); - name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); - let attributes = vec![::opentelemetry::KeyValue::from(r#worker_host_port)]; + write!(&mut name, "{}", r#worker_host_port).expect("writing a span name to String cannot fail"); + let attributes: [::opentelemetry::KeyValue; 1] = [::opentelemetry::KeyValue::from(r#worker_host_port)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) .start_with_context(tracer.inner(), context); NameControlSpan { span } } +/// A span named from a floating point value. +pub struct NameFloatSpan { span: S } +impl NameFloatSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut S { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } +} +impl Default for NameFloatSpan { + fn default() -> Self { + Self { span: super::tracer::Tracer::default().inner().start("myapp.name.float") } + } +} + +pub fn r#start_name_float(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#myapp_number_value: super::myappattr::NumberValueAttr) -> NameFloatSpan { + let mut name = String::with_capacity(328); + write!(&mut name, "{}", r#myapp_number_value).expect("writing a span name to String cannot fail"); + let attributes: [::opentelemetry::KeyValue; 1] = [::opentelemetry::KeyValue::from(r#myapp_number_value)]; + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Internal) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + NameFloatSpan { span } +} +#[derive(Clone, Debug, Default)] +pub struct NameStaticName(::std::borrow::Cow<'static, str>); +impl From<&'static str> for NameStaticName { + fn from(value: &'static str) -> Self { Self(::std::borrow::Cow::Borrowed(value)) } +} +impl From for NameStaticName { + fn from(value: String) -> Self { Self(::std::borrow::Cow::Owned(value)) } +} +impl From<::std::borrow::Cow<'static, str>> for NameStaticName { + fn from(value: ::std::borrow::Cow<'static, str>) -> Self { Self(value) } +} +/// A span with an unconstrained caller supplied name. +pub struct NameStaticSpan { span: S } +impl NameStaticSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut S { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } +} +impl Default for NameStaticSpan { + fn default() -> Self { + Self { span: super::tracer::Tracer::default().inner().start("myapp.name.static") } + } +} + +pub fn r#start_name_static(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: NameStaticName) -> NameStaticSpan { + let name = if name.0.is_empty() { ::std::borrow::Cow::Borrowed("myapp.name.static") } else { name.0 }; + let attributes: [::opentelemetry::KeyValue; 0] = []; + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Internal) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + NameStaticSpan { span } +} /// Synthetic escaped name. -pub struct NameUnicodeSpan { span: ::opentelemetry::global::BoxedSpan } -impl NameUnicodeSpan { - pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { +pub struct NameUnicodeSpan { span: S } +impl NameUnicodeSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { parent.with_span(self.span) } - pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn span(&mut self) -> &mut S { &mut self.span } pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } @@ -106,11 +221,11 @@ impl Default for NameUnicodeSpan { } } -pub fn r#start_name_unicode(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameUnicodeSpan { - let mut name = String::new(); +pub fn r#start_name_unicode(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_port: super::workerattr::HostPortAttr) -> NameUnicodeSpan { + let mut name = String::with_capacity("é".len() + 20); name.push('é'); - name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); - let attributes = vec![::opentelemetry::KeyValue::from(r#worker_host_port)]; + write!(&mut name, "{}", r#worker_host_port).expect("writing a span name to String cannot fail"); + let attributes: [::opentelemetry::KeyValue; 1] = [::opentelemetry::KeyValue::from(r#worker_host_port)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) .with_attributes(attributes) @@ -118,19 +233,27 @@ pub fn r#start_name_unicode(context: &::opentelemetry::Context, tracer: &super:: NameUnicodeSpan { span } } #[derive(Clone, Debug, Default)] -pub struct QueueDrainName(String); -impl QueueDrainName { - pub fn new(value: impl Into) -> Self { Self(value.into()) } +pub struct QueueDrainName(::std::borrow::Cow<'static, str>); +impl From<&'static str> for QueueDrainName { + fn from(value: &'static str) -> Self { Self(::std::borrow::Cow::Borrowed(value)) } +} +impl From for QueueDrainName { + fn from(value: String) -> Self { Self(::std::borrow::Cow::Owned(value)) } +} +impl From<::std::borrow::Cow<'static, str>> for QueueDrainName { + fn from(value: ::std::borrow::Cow<'static, str>) -> Self { Self(value) } } /// Removing every task from a queue. /// Opt-in: record only when the user requests it. #[deprecated(note = "Drain queues by dispatching their tasks instead.")] -pub struct QueueDrainSpan { span: ::opentelemetry::global::BoxedSpan } -impl QueueDrainSpan { - pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { +pub struct QueueDrainSpan { span: S } +impl QueueDrainSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { parent.with_span(self.span) } - pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn span(&mut self) -> &mut S { &mut self.span } pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } @@ -142,9 +265,9 @@ impl Default for QueueDrainSpan { } } #[deprecated(note = "Drain queues by dispatching their tasks instead.")] -pub fn r#start_queue_drain(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: QueueDrainName) -> QueueDrainSpan { - let name = if name.0.is_empty() { "myapp.queue.drain".to_owned() } else { name.0 }; - let attributes = vec![]; +pub fn r#start_queue_drain(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: QueueDrainName) -> QueueDrainSpan { + let name = if name.0.is_empty() { ::std::borrow::Cow::Borrowed("myapp.queue.drain") } else { name.0 }; + let attributes: [::opentelemetry::KeyValue; 0] = []; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Consumer) .with_attributes(attributes) @@ -184,12 +307,14 @@ impl From for TaskDispatchStartAttr { /// The scheduler handing a task to a worker. /// /// Ends when the worker accepts the task. -pub struct TaskDispatchSpan { span: ::opentelemetry::global::BoxedSpan } -impl TaskDispatchSpan { - pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { +pub struct TaskDispatchSpan { span: S } +impl TaskDispatchSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { parent.with_span(self.span) } - pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn span(&mut self) -> &mut S { &mut self.span } pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } @@ -204,17 +329,16 @@ impl Default for TaskDispatchSpan { } } -pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_name: super::workerattr::HostNameAttr, r#worker_host_port: super::workerattr::HostPortAttr, options: impl IntoIterator) -> TaskDispatchSpan { - let mut name = String::new(); +pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#worker_host_name: super::workerattr::HostNameAttr, r#worker_host_port: super::workerattr::HostPortAttr, options: impl IntoIterator) -> TaskDispatchSpan { + let mut name = String::with_capacity("dispatch ".len() + ::std::convert::AsRef::::as_ref(&r#worker_host_name).len() + ":".len() + 20); name.push_str("dispatch "); - name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_name.clone()).value.to_string()); + write!(&mut name, "{}", r#worker_host_name).expect("writing a span name to String cannot fail"); name.push(':'); - name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); - let mut attributes = vec![::opentelemetry::KeyValue::from(r#worker_host_name), ::opentelemetry::KeyValue::from(r#worker_host_port)]; - attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); + write!(&mut name, "{}", r#worker_host_port).expect("writing a span name to String cannot fail"); + let attributes: [::opentelemetry::KeyValue; 2] = [::opentelemetry::KeyValue::from(r#worker_host_name), ::opentelemetry::KeyValue::from(r#worker_host_port)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Client) - .with_attributes(attributes) + .with_attributes(attributes.into_iter().chain(options.into_iter().map(::opentelemetry::KeyValue::from))) .start_with_context(tracer.inner(), context); TaskDispatchSpan { span } } @@ -241,17 +365,25 @@ impl From for TaskRunStartAttr { } } #[derive(Clone, Debug, Default)] -pub struct TaskRunName(String); -impl TaskRunName { - pub fn new(value: impl Into) -> Self { Self(value.into()) } +pub struct TaskRunName(::std::borrow::Cow<'static, str>); +impl From<&'static str> for TaskRunName { + fn from(value: &'static str) -> Self { Self(::std::borrow::Cow::Borrowed(value)) } +} +impl From for TaskRunName { + fn from(value: String) -> Self { Self(::std::borrow::Cow::Owned(value)) } +} +impl From<::std::borrow::Cow<'static, str>> for TaskRunName { + fn from(value: ::std::borrow::Cow<'static, str>) -> Self { Self(value) } } /// One run of a task. -pub struct TaskRunSpan { span: ::opentelemetry::global::BoxedSpan } -impl TaskRunSpan { - pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { +pub struct TaskRunSpan { span: S } +impl TaskRunSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { parent.with_span(self.span) } - pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn span(&mut self) -> &mut S { &mut self.span } pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } @@ -266,13 +398,12 @@ impl Default for TaskRunSpan { } } -pub fn r#start_task_run(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: TaskRunName, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) -> TaskRunSpan { - let name = if name.0.is_empty() { "myapp.task.run".to_owned() } else { name.0 }; - let mut attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_state)]; - attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); +pub fn r#start_task_run(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: TaskRunName, r#myapp_task_state: super::myappattr::TaskStateAttr, options: impl IntoIterator) -> TaskRunSpan { + let name = if name.0.is_empty() { ::std::borrow::Cow::Borrowed("myapp.task.run") } else { name.0 }; + let attributes: [::opentelemetry::KeyValue; 1] = [::opentelemetry::KeyValue::from(r#myapp_task_state)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Internal) - .with_attributes(attributes) + .with_attributes(attributes.into_iter().chain(options.into_iter().map(::opentelemetry::KeyValue::from))) .start_with_context(tracer.inner(), context); TaskRunSpan { span } } diff --git a/templates/code/rust/tests/spans/expected/tracer.rs b/templates/code/rust/tests/spans/expected/tracer.rs index 6580bf3..e6865f2 100644 --- a/templates/code/rust/tests/spans/expected/tracer.rs +++ b/templates/code/rust/tests/spans/expected/tracer.rs @@ -1,26 +1,20 @@ -pub struct Tracer(opentelemetry::global::BoxedTracer); -impl Tracer { - pub fn new(provider: &P, scope: impl Into>) -> Self - where - P::Tracer: Send + Sync + 'static, - ::Span: Send + Sync + 'static, - { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) +pub struct Tracer(T); +impl Tracer { + pub fn new>(provider: &P, scope: impl Into>) -> Self { + Self(provider.tracer_with_scope(opentelemetry::InstrumentationScope::builder(scope) + .with_schema_url(super::SCHEMA_URL).build())) } - pub fn new_with_scope(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self - where - P::Tracer: Send + Sync + 'static, - ::Span: Send + Sync + 'static, - { - Self(opentelemetry::global::BoxedTracer::new(Box::new(provider.tracer_with_scope(registry_scope(scope))))) + pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.tracer_with_scope(registry_scope(scope))) } - pub fn inner(&self) -> &opentelemetry::global::BoxedTracer { &self.0 } + pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/tests/spans/expected/workerattr.rs b/templates/code/rust/tests/spans/expected/workerattr.rs index 64d7cdc..03463aa 100644 --- a/templates/code/rust/tests/spans/expected/workerattr.rs +++ b/templates/code/rust/tests/spans/expected/workerattr.rs @@ -1,34 +1,61 @@ // Generated by OpenTelemetry Weaver. /// Host name of the worker. #[derive(Debug, Clone, PartialEq)] -pub struct HostNameAttr(String); +pub struct HostNameAttr(::opentelemetry::StringValue); #[allow(deprecated)] impl HostNameAttr { pub const KEY: &'static str = "worker.host.name"; } +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for HostNameAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} #[allow(deprecated)] impl From for HostNameAttr { + #[inline] fn from(value: String) -> Self { - Self(value) + Self(value.into()) } } + +#[allow(deprecated)] +impl From<&'static str> for HostNameAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + #[allow(deprecated)] -impl From<&str> for HostNameAttr { - fn from(value: &str) -> Self { - Self(value.to_owned()) +impl AsRef for HostNameAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for HostNameAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) } } #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: HostNameAttr) -> Self { ::opentelemetry::KeyValue::new(HostNameAttr::KEY, value.0) } } /// Port the worker listens on. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Copy)] pub struct HostPortAttr(i64); #[allow(deprecated)] @@ -38,13 +65,23 @@ impl HostPortAttr { #[allow(deprecated)] impl From for HostPortAttr { + #[inline] fn from(value: i64) -> Self { Self(value) } } +#[allow(deprecated)] +impl ::std::fmt::Display for HostPortAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + #[allow(deprecated)] impl From for ::opentelemetry::KeyValue { + #[inline] fn from(value: HostPortAttr) -> Self { ::opentelemetry::KeyValue::new(HostPortAttr::KEY, value.0) } diff --git a/templates/code/rust/tests/spans/expected/workerspan.rs b/templates/code/rust/tests/spans/expected/workerspan.rs index c8de1e9..708fbe6 100644 --- a/templates/code/rust/tests/spans/expected/workerspan.rs +++ b/templates/code/rust/tests/spans/expected/workerspan.rs @@ -1,5 +1,6 @@ #![allow(deprecated)] use ::opentelemetry::trace::{TraceContextExt, Tracer}; +use ::std::fmt::Write; #[derive(Clone, Debug)] pub enum TaskDispatchStartAttr { @@ -29,12 +30,14 @@ impl From for TaskDispatchStartAttr { /// The scheduler handing a task to a worker. /// /// Ends when the worker accepts the task. -pub struct TaskDispatchSpan { span: ::opentelemetry::global::BoxedSpan } -impl TaskDispatchSpan { - pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context { +pub struct TaskDispatchSpan { span: S } +impl TaskDispatchSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { parent.with_span(self.span) } - pub fn span(&mut self) -> &mut ::opentelemetry::global::BoxedSpan { &mut self.span } + pub fn span(&mut self) -> &mut S { &mut self.span } pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } @@ -49,17 +52,16 @@ impl Default for TaskDispatchSpan { } } -pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#myapp_task_attempt: super::myappattr::TaskAttemptAttr, r#worker_host_name: super::workerattr::HostNameAttr, r#worker_host_port: super::workerattr::HostPortAttr, options: impl IntoIterator) -> TaskDispatchSpan { - let mut name = String::new(); +pub fn r#start_task_dispatch(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#myapp_task_attempt: super::myappattr::TaskAttemptAttr, r#worker_host_name: super::workerattr::HostNameAttr, r#worker_host_port: super::workerattr::HostPortAttr, options: impl IntoIterator) -> TaskDispatchSpan { + let mut name = String::with_capacity("dispatch ".len() + ::std::convert::AsRef::::as_ref(&r#worker_host_name).len() + ":".len() + 20); name.push_str("dispatch "); - name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_name.clone()).value.to_string()); + write!(&mut name, "{}", r#worker_host_name).expect("writing a span name to String cannot fail"); name.push(':'); - name.push_str(&::opentelemetry::KeyValue::from(r#worker_host_port.clone()).value.to_string()); - let mut attributes = vec![::opentelemetry::KeyValue::from(r#myapp_task_attempt), ::opentelemetry::KeyValue::from(r#worker_host_name), ::opentelemetry::KeyValue::from(r#worker_host_port)]; - attributes.extend(options.into_iter().map(::opentelemetry::KeyValue::from)); + write!(&mut name, "{}", r#worker_host_port).expect("writing a span name to String cannot fail"); + let attributes: [::opentelemetry::KeyValue; 3] = [::opentelemetry::KeyValue::from(r#myapp_task_attempt), ::opentelemetry::KeyValue::from(r#worker_host_name), ::opentelemetry::KeyValue::from(r#worker_host_port)]; let span = tracer.inner().span_builder(name) .with_kind(::opentelemetry::trace::SpanKind::Client) - .with_attributes(attributes) + .with_attributes(attributes.into_iter().chain(options.into_iter().map(::opentelemetry::KeyValue::from))) .start_with_context(tracer.inner(), context); TaskDispatchSpan { span } } diff --git a/templates/code/rust/tests/spans/registry/model.yaml b/templates/code/rust/tests/spans/registry/model.yaml index 71cba23..d84d1f5 100644 --- a/templates/code/rust/tests/spans/registry/model.yaml +++ b/templates/code/rust/tests/spans/registry/model.yaml @@ -38,6 +38,31 @@ attributes: stability: stable brief: Port the worker listens on. examples: 8080 + - key: myapp.number.value + type: double + stability: stable + brief: Synthetic naming value. + examples: [1.5] + - key: myapp.array.flags + type: boolean[] + stability: stable + brief: Synthetic naming value. + examples: [[true]] + - key: myapp.array.indices + type: int[] + stability: stable + brief: Synthetic naming value. + examples: [[1]] + - key: myapp.array.samples + type: double[] + stability: stable + brief: Synthetic naming value. + examples: [[1.5]] + - key: myapp.array.tags + type: string[] + stability: stable + brief: Synthetic naming value. + examples: [["a"]] spans: - type: myapp.task.dispatch kind: client @@ -122,6 +147,39 @@ spans: attributes: - ref: worker.host.port requirement_level: required + - type: myapp.name.float + kind: internal + requirement_level: recommended + stability: stable + brief: A span named from a floating point value. + name: + note: "`{myapp.number.value}`" + attributes: + - ref: myapp.number.value + requirement_level: required + - type: myapp.name.arrays + kind: internal + requirement_level: recommended + stability: stable + brief: A span named from array values. + name: + note: "`{myapp.array.tags}:{myapp.array.indices}:{myapp.array.samples}:{myapp.array.flags}`" + attributes: + - ref: myapp.array.tags + requirement_level: required + - ref: myapp.array.indices + requirement_level: required + - ref: myapp.array.samples + requirement_level: required + - ref: myapp.array.flags + requirement_level: required + - type: myapp.name.static + kind: internal + requirement_level: recommended + stability: stable + brief: A span with an unconstrained caller supplied name. + name: + note: "`static`" span_refinements: - id: worker.task.dispatch ref: myapp.task.dispatch diff --git a/templates/code/rust/tests/spans/test.rs b/templates/code/rust/tests/spans/test.rs index 07a80cc..811db2a 100644 --- a/templates/code/rust/tests/spans/test.rs +++ b/templates/code/rust/tests/spans/test.rs @@ -16,7 +16,8 @@ fn derived_names_refinements_parent_context_and_late_attributes() { .with_attributes([opentelemetry::KeyValue::new("scope.kind", "test")]) .build(), ); - let parent = myappspan::start_task_dispatch( + let _: &opentelemetry_sdk::trace::SdkTracer = tracer.inner(); + let mut parent = myappspan::start_task_dispatch( &opentelemetry::Context::new(), &tracer, workerattr::HostNameAttr::from("worker-1"), @@ -25,11 +26,12 @@ fn derived_names_refinements_parent_context_and_late_attributes() { myappattr::TaskIdAttr::from("task-1"), )], ); + let _: &mut opentelemetry_sdk::trace::Span = parent.span(); let context = parent.into_context(&opentelemetry::Context::new()); let mut child = myappspan::start_task_run( &context, &tracer, - myappspan::TaskRunName::new("run task-1"), + myappspan::TaskRunName::from("run task-1"), myappattr::TaskStateAttr::Done, [], ); @@ -80,9 +82,36 @@ fn derived_names_refinements_parent_context_and_late_attributes() { workerattr::HostPortAttr::from(1), ) .end(); + for value in [f64::MAX, -f64::from_bits(1)] { + myappspan::start_name_float( + &opentelemetry::Context::new(), + &tracer, + myappattr::NumberValueAttr::from(value), + ) + .end(); + } + myappspan::start_name_arrays( + &opentelemetry::Context::new(), + &tracer, + myappattr::ArrayFlagsAttr::from(vec![true, false]), + myappattr::ArrayIndicesAttr::from(vec![-1, 2]), + myappattr::ArraySamplesAttr::from(vec![1.5, 2.5]), + myappattr::ArrayTagsAttr::from(vec![ + opentelemetry::StringValue::from("a"), + opentelemetry::StringValue::from("b"), + ]), + ) + .end(); + for name in [ + myappspan::NameStaticName::default(), + myappspan::NameStaticName::from("explicit static"), + myappspan::NameStaticName::from(String::from("owned dynamic")), + ] { + myappspan::start_name_static(&opentelemetry::Context::new(), &tracer, name).end(); + } provider.force_flush().unwrap(); let spans = exporter.get_finished_spans().unwrap(); - assert_eq!(spans.len(), 8); + assert_eq!(spans.len(), 14); let child = spans.iter().find(|span| span.name == "run task-1").unwrap(); let parent = spans .iter() @@ -115,6 +144,16 @@ fn derived_names_refinements_parent_context_and_late_attributes() { for name in ["'1", "\\1", "é1", "\u{0008}1"] { assert!(spans.iter().any(|span| span.name == name)); } + for value in [f64::MAX, -f64::from_bits(1)] { + assert!(value.to_string().len() <= 328); + assert!(spans.iter().any(|span| span.name == value.to_string())); + } + assert!(spans + .iter() + .any(|span| span.name == "[\"a\",\"b\"]:[-1,2]:[1.5,2.5]:[true,false]")); + for name in ["myapp.name.static", "explicit static", "owned dynamic"] { + assert!(spans.iter().any(|span| span.name == name)); + } let mut noop = myappspan::TaskRunSpan::default(); assert!(!noop.span().is_recording()); noop.end(); diff --git a/templates/code/rust/tests/spans/tests/allocations.rs b/templates/code/rust/tests/spans/tests/allocations.rs new file mode 100644 index 0000000..88a9d91 --- /dev/null +++ b/templates/code/rust/tests/spans/tests/allocations.rs @@ -0,0 +1,115 @@ +use generated_semconv::{myappattr, myappspan, tracer, workerattr}; +use opentelemetry::trace::noop::NoopTracerProvider; +use std::alloc::{GlobalAlloc, Layout, System}; +use std::cell::Cell; + +struct CountingAllocator; +thread_local! { + static ALLOCATIONS: Cell> = const { Cell::new(None) }; +} +fn record_allocation() { + let _ = ALLOCATIONS.try_with(|count| { + if let Some(value) = count.get() { + count.set(Some(value + 1)); + } + }); +} +unsafe impl GlobalAlloc for CountingAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + record_allocation(); + unsafe { System.alloc(layout) } + } + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + unsafe { System.dealloc(ptr, layout) } + } + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, size: usize) -> *mut u8 { + record_allocation(); + unsafe { System.realloc(ptr, layout, size) } + } +} +#[global_allocator] +static ALLOCATOR: CountingAllocator = CountingAllocator; +fn allocations(operation: impl FnOnce() -> T) -> (T, usize) { + ALLOCATIONS.with(|count| count.set(Some(0))); + let value = operation(); + let count = ALLOCATIONS.with(|count| count.replace(None).unwrap()); + (value, count) +} +#[test] +fn static_scope_constructor_has_no_generated_heap_allocations() { + let (_, count) = allocations(|| tracer::Tracer::new(&NoopTracerProvider::new(), "worker")); + assert_eq!(count, 0); +} +#[test] +fn derived_name_only_allocates_output_and_attribute_vector() { + let tracer = tracer::Tracer::default(); + let context = opentelemetry::Context::new(); + let host = workerattr::HostNameAttr::from("worker-1"); + let port = workerattr::HostPortAttr::from(8080); + let (_, count) = + allocations(|| myappspan::start_task_dispatch(&context, &tracer, host, port, [])); + assert_eq!(count, 2); +} + +#[test] +fn extreme_float_names_do_not_reallocate_the_output() { + let tracer = tracer::Tracer::default(); + let context = opentelemetry::Context::new(); + for value in [f64::MAX, -f64::from_bits(1)] { + let attribute = myappattr::NumberValueAttr::from(value); + let (_, count) = allocations(|| myappspan::start_name_float(&context, &tracer, attribute)); + assert_eq!(count, 2); + } +} +#[test] +fn long_owned_string_names_do_not_clone_or_reallocate() { + let tracer = tracer::Tracer::default(); + let context = opentelemetry::Context::new(); + let host = workerattr::HostNameAttr::from("worker".repeat(1000)); + let port = workerattr::HostPortAttr::from(8080); + let (_, count) = + allocations(|| myappspan::start_task_dispatch(&context, &tracer, host, port, [])); + assert_eq!(count, 2); +} +#[test] +fn array_names_only_allocate_output_and_builder_attributes() { + let tracer = tracer::Tracer::default(); + let context = opentelemetry::Context::new(); + let flags = myappattr::ArrayFlagsAttr::from(vec![true, false]); + let indices = myappattr::ArrayIndicesAttr::from(vec![-1, 2]); + let samples = myappattr::ArraySamplesAttr::from(vec![f64::MAX, -f64::from_bits(1)]); + let tags = myappattr::ArrayTagsAttr::from(vec![ + opentelemetry::StringValue::from("a"), + opentelemetry::StringValue::from("b"), + ]); + let (_, count) = allocations(|| { + myappspan::start_name_arrays(&context, &tracer, flags, indices, samples, tags) + }); + assert_eq!(count, 2); +} + +#[test] +fn untemplated_names_move_or_borrow_without_heap_allocations() { + let tracer = tracer::Tracer::default(); + let context = opentelemetry::Context::new(); + for name in [ + myappspan::NameStaticName::default(), + myappspan::NameStaticName::from("explicit static"), + myappspan::NameStaticName::from(String::from("owned dynamic")), + ] { + let (_, count) = allocations(|| myappspan::start_name_static(&context, &tracer, name)); + assert_eq!(count, 0); + } +} + +#[test] +fn matching_scope_schema_moves_existing_metadata_without_cloning() { + let scope = opentelemetry::InstrumentationScope::builder("worker") + .with_schema_url(generated_semconv::SCHEMA_URL) + .with_version("1.0.0") + .with_attributes([opentelemetry::KeyValue::new("scope.kind", "worker")]) + .build(); + let (_, count) = + allocations(|| tracer::Tracer::new_with_scope(&NoopTracerProvider::new(), scope)); + assert_eq!(count, 0); +} diff --git a/templates/code/rust/tracer.rs.j2 b/templates/code/rust/tracer.rs.j2 index 5d1b247..eb03b66 100644 --- a/templates/code/rust/tracer.rs.j2 +++ b/templates/code/rust/tracer.rs.j2 @@ -1,27 +1,21 @@ {%- filter trim %} -pub struct Tracer(opentelemetry::global::BoxedTracer); -impl Tracer { - pub fn new(provider: &P, scope: impl Into>) -> Self - where - P::Tracer: Send + Sync + 'static, - ::Span: Send + Sync + 'static, - { - Self::new_with_scope(provider, opentelemetry::InstrumentationScope::builder(scope).build()) +pub struct Tracer(T); +impl Tracer { + pub fn new>(provider: &P, scope: impl Into>) -> Self { + Self(provider.tracer_with_scope(opentelemetry::InstrumentationScope::builder(scope) + .with_schema_url(super::SCHEMA_URL).build())) } - pub fn new_with_scope(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self - where - P::Tracer: Send + Sync + 'static, - ::Span: Send + Sync + 'static, - { - Self(opentelemetry::global::BoxedTracer::new(Box::new(provider.tracer_with_scope(registry_scope(scope))))) + pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { + Self(provider.tracer_with_scope(registry_scope(scope))) } - pub fn inner(&self) -> &opentelemetry::global::BoxedTracer { &self.0 } + pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } } fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { + if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) .with_schema_url(super::SCHEMA_URL) .with_attributes(scope.attributes().cloned()); diff --git a/templates/code/rust/weaver.yaml b/templates/code/rust/weaver.yaml index e50ea24..f1eca4d 100644 --- a/templates/code/rust/weaver.yaml +++ b/templates/code/rust/weaver.yaml @@ -599,8 +599,14 @@ templates: file_name: tracer.rs - template: logger.rs.j2 filter: |- + def kept($o): + stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) + | map(.attributes = ((.attributes // []) | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o))); {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $o - | if ((.registry.events // []) + (.refinements.events // []) | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) | length) > 0 then [{}] else [] end + | [.registry.events // [] | .[].name] as $bases + | ((.registry.events // [] | kept($o)) + + (.refinements.events // [] | map(select(.id as $id | $bases | any(. == $id) | not)) | kept($o))) + | if length > 0 then [{has_attributes: any((.attributes | length) > 0)}] else [] end application_mode: each file_name: logger.rs From dc4a6e37204de4706f470fa547f6faa45de0eba0 Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Mon, 5 Oct 2026 11:32:27 -0400 Subject: [PATCH 09/14] refactor: keep telemetry setup unambiguous Signed-off-by: Yordis Prieto --- templates/code/rust/README.md | 39 +++++++---- templates/code/rust/logger.rs.j2 | 21 ++---- templates/code/rust/meter.rs.j2 | 21 ++---- templates/code/rust/mod.rs.j2 | 3 + templates/code/rust/scope.rs.j2 | 29 +++++++++ .../rust/tests/allocations/expected/logger.rs | 22 ++----- .../rust/tests/allocations/expected/meter.rs | 22 ++----- .../rust/tests/allocations/expected/mod.rs | 1 + .../rust/tests/allocations/expected/scope.rs | 27 ++++++++ templates/code/rust/tests/allocations/test.rs | 65 +++++++++++++++---- .../event_no_attributes/expected/logger.rs | 22 ++----- .../tests/event_no_attributes/expected/mod.rs | 1 + .../event_no_attributes/expected/scope.rs | 27 ++++++++ .../code/rust/tests/events/expected/logger.rs | 22 ++----- .../code/rust/tests/events/expected/mod.rs | 1 + .../code/rust/tests/events/expected/scope.rs | 27 ++++++++ templates/code/rust/tests/events/test.rs | 18 ++--- .../expected/meter.rs | 22 ++----- .../expected/mod.rs | 1 + .../expected/scope.rs | 27 ++++++++ .../expected/meter.rs | 22 ++----- .../expected/mod.rs | 1 + .../expected/scope.rs | 27 ++++++++ .../rust/tests/imported/expected/logger.rs | 22 ++----- .../rust/tests/imported/expected/meter.rs | 22 ++----- .../code/rust/tests/imported/expected/mod.rs | 1 + .../rust/tests/imported/expected/scope.rs | 27 ++++++++ .../rust/tests/imported/expected/tracer.rs | 23 ++----- .../tests/imported_typed/expected/logger.rs | 22 ++----- .../tests/imported_typed/expected/meter.rs | 22 ++----- .../rust/tests/imported_typed/expected/mod.rs | 1 + .../tests/imported_typed/expected/scope.rs | 27 ++++++++ .../tests/imported_typed/expected/tracer.rs | 23 ++----- .../tests/literal_escaping/expected/meter.rs | 22 ++----- .../tests/literal_escaping/expected/mod.rs | 1 + .../tests/literal_escaping/expected/scope.rs | 27 ++++++++ .../code/rust/tests/metrics/expected/meter.rs | 22 ++----- .../code/rust/tests/metrics/expected/mod.rs | 1 + .../code/rust/tests/metrics/expected/scope.rs | 27 ++++++++ templates/code/rust/tests/metrics/test.rs | 14 ++-- .../code/rust/tests/naming/expected/meter.rs | 22 ++----- .../code/rust/tests/naming/expected/mod.rs | 1 + .../code/rust/tests/naming/expected/scope.rs | 27 ++++++++ .../tests/no_namespace/expected/logger.rs | 22 ++----- .../rust/tests/no_namespace/expected/mod.rs | 1 + .../rust/tests/no_namespace/expected/scope.rs | 27 ++++++++ .../tests/no_namespace/expected/tracer.rs | 23 ++----- .../code/rust/tests/params/expected/meter.rs | 22 ++----- .../code/rust/tests/params/expected/mod.rs | 1 + .../code/rust/tests/params/expected/scope.rs | 27 ++++++++ .../code/rust/tests/spans/expected/mod.rs | 1 + .../code/rust/tests/spans/expected/scope.rs | 27 ++++++++ .../code/rust/tests/spans/expected/tracer.rs | 23 ++----- templates/code/rust/tests/spans/test.rs | 12 ++-- .../rust/tests/spans/tests/allocations.rs | 15 ++--- templates/code/rust/tracer.rs.j2 | 22 ++----- templates/code/rust/weaver.yaml | 10 +++ 57 files changed, 667 insertions(+), 388 deletions(-) create mode 100644 templates/code/rust/scope.rs.j2 create mode 100644 templates/code/rust/tests/allocations/expected/scope.rs create mode 100644 templates/code/rust/tests/event_no_attributes/expected/scope.rs create mode 100644 templates/code/rust/tests/events/expected/scope.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs create mode 100644 templates/code/rust/tests/imported/expected/scope.rs create mode 100644 templates/code/rust/tests/imported_typed/expected/scope.rs create mode 100644 templates/code/rust/tests/literal_escaping/expected/scope.rs create mode 100644 templates/code/rust/tests/metrics/expected/scope.rs create mode 100644 templates/code/rust/tests/naming/expected/scope.rs create mode 100644 templates/code/rust/tests/no_namespace/expected/scope.rs create mode 100644 templates/code/rust/tests/params/expected/scope.rs create mode 100644 templates/code/rust/tests/spans/expected/scope.rs diff --git a/templates/code/rust/README.md b/templates/code/rust/README.md index c8d76ea..9801f9a 100644 --- a/templates/code/rust/README.md +++ b/templates/code/rust/README.md @@ -42,21 +42,34 @@ the signal modules. Names use the first dotted segment as their namespace; `vendor_prefixes` removes a leading vendor segment before choosing that namespace. -| Module | API | -| ------------------- | -------------------------------------------------------------------------------------------- | -| `attr` | Attribute newtypes and enum variants, `KEY` and conversion into `KeyValue`. | -| `meter` | Schema-aware `Meter`, with `new`, `new_with_scope`, `inner`, and a no-op `Default`. | -| `tracer` | Schema-aware `Tracer`, with `new`, `new_with_scope`, `inner`, and a no-op `Default`. | -| `logger` | Schema-aware generic `Logger`, with `new`, `new_with_scope`, `inner`, and a no-op `Default`. | -| `metric` | Synchronous instruments and observable counters, up-down counters, and gauges. | -| `span` | Span starters, typed names, start attributes, and attributes allowed after starting. | -| `event` | Typed log event emitters and options for attributes, severity, and timestamp. | -| `entity` | Typed entity values, attribute iterators, and resources carrying the registry schema URL. | +| Module | API | +| ------------------- | ----------------------------------------------------------------------------------------- | +| `attr` | Attribute newtypes and enum variants, `KEY` and conversion into `KeyValue`. | +| `scope` | Shared scope name, version, and attributes configuration. | +| `meter` | Schema-aware `Meter`, with `new`, `inner`, and a no-op `Default`. | +| `tracer` | Schema-aware `Tracer`, with `new`, `inner`, and a no-op `Default`. | +| `logger` | Schema-aware generic `Logger`, with `new`, `inner`, and a no-op `Default`. | +| `metric` | Synchronous instruments and observable counters, up-down counters, and gauges. | +| `span` | Span starters, typed names, start attributes, and attributes allowed after starting. | +| `event` | Typed log event emitters and options for attributes, severity, and timestamp. | +| `entity` | Typed entity values, attribute iterators, and resources carrying the registry schema URL. | Handle modules are emitted when the registry includes their corresponding -signals. They set the registry schema URL on their instrumentation scope. -Use `new_with_scope` to preserve a supplied scope's name, version, and -attributes; its schema URL is replaced by the registry's schema URL. +signals. Their `new(provider, scope)` constructor accepts a static string, owned +`String`, `Cow<'static, str>`, or the shared `scope::Scope` configuration: + +```rust +let scope = semconv::scope::Scope { + name: "worker".into(), + version: Some("1.0.0".into()), + attributes: vec![opentelemetry::KeyValue::new("scope.kind", "worker")], +}; +let tracer = semconv::tracer::Tracer::new(&provider, scope); +``` + +Scope values move into OpenTelemetry without rebuilding their metadata. The +registry schema URL is always applied; it is not a configuration field. The +shared scope module is emitted when a handle is needed. Attribute keys, metric names, and event names retain their full registry names. ### Typed attributes diff --git a/templates/code/rust/logger.rs.j2 b/templates/code/rust/logger.rs.j2 index b2a7260..a299488 100644 --- a/templates/code/rust/logger.rs.j2 +++ b/templates/code/rust/logger.rs.j2 @@ -1,5 +1,7 @@ {%- filter trim %} +use super::scope::Scope; {% if ctx.has_attributes %} + use opentelemetry::logs::AnyValue; use opentelemetry::{Array, Value}; {% endif %} @@ -7,16 +9,15 @@ use opentelemetry::{Array, Value}; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.logger_with_scope(registry_scope(scope))) + pub fn new>(provider: &P, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let logger = provider.logger_with_scope(scope.into()); + Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } } {% if ctx.has_attributes %} pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { @@ -37,12 +38,4 @@ pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::Any } {% endif %} -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() -} {% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/meter.rs.j2 b/templates/code/rust/meter.rs.j2 index 97a3f58..b56001f 100644 --- a/templates/code/rust/meter.rs.j2 +++ b/templates/code/rust/meter.rs.j2 @@ -1,25 +1,18 @@ {%- filter trim %} +use super::scope::Scope; + #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.meter_with_scope(registry_scope(scope))) + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let meter = provider.meter_with_scope(scope.into()); + Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } } -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() -} {% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/mod.rs.j2 b/templates/code/rust/mod.rs.j2 index 7c6d64b..19b3242 100644 --- a/templates/code/rust/mod.rs.j2 +++ b/templates/code/rust/mod.rs.j2 @@ -12,6 +12,9 @@ pub const SCHEMA_URL: &str = {{ ctx.schema_literal }}; pub mod {{ namespace }}; {% endfor %} +{% if ctx.has_metrics or ctx.has_spans or ctx.has_events %} +pub mod scope; +{% endif %} {% if ctx.has_metrics %} pub mod meter; {% endif %} diff --git a/templates/code/rust/scope.rs.j2 b/templates/code/rust/scope.rs.j2 new file mode 100644 index 0000000..00d502b --- /dev/null +++ b/templates/code/rust/scope.rs.j2 @@ -0,0 +1,29 @@ +{%- filter trim %} +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} +{% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/tests/allocations/expected/logger.rs b/templates/code/rust/tests/allocations/expected/logger.rs index 179c64c..9455600 100644 --- a/templates/code/rust/tests/allocations/expected/logger.rs +++ b/templates/code/rust/tests/allocations/expected/logger.rs @@ -1,19 +1,20 @@ +use super::scope::Scope; + use opentelemetry::logs::AnyValue; use opentelemetry::{Array, Value}; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.logger_with_scope(registry_scope(scope))) + pub fn new>(provider: &P, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let logger = provider.logger_with_scope(scope.into()); + Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { match value { @@ -31,12 +32,3 @@ pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::Any _ => AnyValue::String(value.to_string().into()), } } - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() -} diff --git a/templates/code/rust/tests/allocations/expected/meter.rs b/templates/code/rust/tests/allocations/expected/meter.rs index 2607994..98512f3 100644 --- a/templates/code/rust/tests/allocations/expected/meter.rs +++ b/templates/code/rust/tests/allocations/expected/meter.rs @@ -1,23 +1,15 @@ +use super::scope::Scope; + #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.meter_with_scope(registry_scope(scope))) + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let meter = provider.meter_with_scope(scope.into()); + Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/allocations/expected/mod.rs b/templates/code/rust/tests/allocations/expected/mod.rs index 6a65324..7db7281 100644 --- a/templates/code/rust/tests/allocations/expected/mod.rs +++ b/templates/code/rust/tests/allocations/expected/mod.rs @@ -2,6 +2,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/allocations/1.0.0"; pub mod probeattr; +pub mod scope; pub mod meter; pub mod logger; pub mod probeevent; diff --git a/templates/code/rust/tests/allocations/expected/scope.rs b/templates/code/rust/tests/allocations/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/allocations/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/allocations/test.rs b/templates/code/rust/tests/allocations/test.rs index 96fcca7..208130a 100644 --- a/templates/code/rust/tests/allocations/test.rs +++ b/templates/code/rust/tests/allocations/test.rs @@ -1,4 +1,4 @@ -use generated_semconv::{logger, meter, probeattr, probeevent, probemetric}; +use generated_semconv::{logger, meter, probeattr, probeevent, probemetric, scope}; use opentelemetry::logs::{AnyValue, LogRecord, Logger, LoggerProvider, Severity}; use opentelemetry::metrics::{ AsyncInstrument, AsyncInstrumentBuilder, Callback, Counter, InstrumentBuilder, @@ -312,7 +312,7 @@ fn static_meter_and_logger_scope_names_remain_borrowed() { } #[test] -fn matching_scopes_move_metadata_without_rebuilding_storage() { +fn configured_scopes_move_metadata_without_rebuilding_storage() { let metric_provider = BorrowedMeterProvider { meter: Meter::new(Arc::new(MetricProvider(Arc::new(MetricState::default())))), scope: Mutex::new(None), @@ -320,37 +320,74 @@ fn matching_scopes_move_metadata_without_rebuilding_storage() { let log_provider = LogProvider(Arc::new(LogState::default())); drop(metric_provider.scope.lock().unwrap()); drop(log_provider.0.scope.lock().unwrap()); - let scope = || { - InstrumentationScope::builder("allocation-test") - .with_version("1.2.3") - .with_schema_url(generated_semconv::SCHEMA_URL) - .with_attributes([KeyValue::new("scope.identity", 7_i64)]) - .build() + let scope = || scope::Scope { + name: String::from("allocation-test").into(), + version: Some(String::from("1.2.3").into()), + attributes: vec![KeyValue::new("scope.identity", 7_i64)], }; let metric_scope = scope(); let log_scope = scope(); + let original = |scope: &scope::Scope| { + ( + scope.name.as_ptr(), + scope.version.as_ref().unwrap().as_ptr(), + scope.attributes.as_ptr(), + ) + }; + let original_metric = original(&metric_scope); + let original_log = original(&log_scope); let metric_count = allocations(|| { - black_box(meter::Meter::new_with_scope(&metric_provider, metric_scope)); + black_box(meter::Meter::new(&metric_provider, metric_scope)); }); let log_count = allocations(|| { - black_box(logger::Logger::new_with_scope(&log_provider, log_scope)); + black_box(logger::Logger::new(&log_provider, log_scope)); }); assert_eq!(metric_count, 0); assert_eq!(log_count, 0); - for stored in [ - metric_provider.scope.lock().unwrap(), - log_provider.0.scope.lock().unwrap(), + for (stored, original) in [ + (metric_provider.scope.lock().unwrap(), original_metric), + (log_provider.0.scope.lock().unwrap(), original_log), ] { let scope = stored.as_ref().unwrap(); assert_eq!(scope.name(), "allocation-test"); assert_eq!(scope.version(), Some("1.2.3")); assert_eq!(scope.schema_url(), Some(generated_semconv::SCHEMA_URL)); + assert_eq!(scope.name().as_ptr(), original.0); + assert_eq!(scope.version().unwrap().as_ptr(), original.1); + assert_eq!( + scope.attributes().next().unwrap() as *const KeyValue, + original.2 + ); assert_eq!( scope.attributes().collect::>(), [&KeyValue::new("scope.identity", 7_i64)] ); } - println!("generated matching scope allocations: meter={metric_count}, logger={log_count}"); + println!("generated configured scope allocations: meter={metric_count}, logger={log_count}"); +} + +#[test] +fn scope_convenience_inputs_share_one_constructor() { + let metric_provider = BorrowedMeterProvider { + meter: Meter::new(Arc::new(MetricProvider(Arc::new(MetricState::default())))), + scope: Mutex::new(None), + }; + for configuration in [ + scope::Scope::from("static"), + scope::Scope::from(String::from("owned")), + scope::Scope::from(Cow::Borrowed("cow-borrowed")), + scope::Scope::from(Cow::Owned(String::from("cow-owned"))), + scope::Scope::default(), + ] { + let name = configuration.name.clone(); + let _meter = meter::Meter::new(&metric_provider, configuration); + let stored = metric_provider.scope.lock().unwrap(); + let stored = stored.as_ref().unwrap(); + assert_eq!(stored.name(), name); + assert_eq!(stored.version(), None); + assert_eq!(stored.attributes().count(), 0); + assert_eq!(stored.schema_url(), Some(generated_semconv::SCHEMA_URL)); + } } #[test] diff --git a/templates/code/rust/tests/event_no_attributes/expected/logger.rs b/templates/code/rust/tests/event_no_attributes/expected/logger.rs index 9468744..4c31cfc 100644 --- a/templates/code/rust/tests/event_no_attributes/expected/logger.rs +++ b/templates/code/rust/tests/event_no_attributes/expected/logger.rs @@ -1,23 +1,15 @@ +use super::scope::Scope; + #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.logger_with_scope(registry_scope(scope))) + pub fn new>(provider: &P, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let logger = provider.logger_with_scope(scope.into()); + Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/event_no_attributes/expected/mod.rs b/templates/code/rust/tests/event_no_attributes/expected/mod.rs index 4a3f109..b79824f 100644 --- a/templates/code/rust/tests/event_no_attributes/expected/mod.rs +++ b/templates/code/rust/tests/event_no_attributes/expected/mod.rs @@ -1,5 +1,6 @@ // Generated by OpenTelemetry Weaver. pub const SCHEMA_URL: &str = "https://example.com/schemas/event-no-attributes/1.0.0"; +pub mod scope; pub mod logger; pub mod probeevent; diff --git a/templates/code/rust/tests/event_no_attributes/expected/scope.rs b/templates/code/rust/tests/event_no_attributes/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/event_no_attributes/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/events/expected/logger.rs b/templates/code/rust/tests/events/expected/logger.rs index 179c64c..9455600 100644 --- a/templates/code/rust/tests/events/expected/logger.rs +++ b/templates/code/rust/tests/events/expected/logger.rs @@ -1,19 +1,20 @@ +use super::scope::Scope; + use opentelemetry::logs::AnyValue; use opentelemetry::{Array, Value}; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.logger_with_scope(registry_scope(scope))) + pub fn new>(provider: &P, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let logger = provider.logger_with_scope(scope.into()); + Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { match value { @@ -31,12 +32,3 @@ pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::Any _ => AnyValue::String(value.to_string().into()), } } - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() -} diff --git a/templates/code/rust/tests/events/expected/mod.rs b/templates/code/rust/tests/events/expected/mod.rs index 924b2ab..f8259d0 100644 --- a/templates/code/rust/tests/events/expected/mod.rs +++ b/templates/code/rust/tests/events/expected/mod.rs @@ -3,6 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/events/1.0.0"; pub mod myappattr; pub mod workerattr; +pub mod scope; pub mod logger; pub mod myappevent; pub mod workerevent; diff --git a/templates/code/rust/tests/events/expected/scope.rs b/templates/code/rust/tests/events/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/events/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/events/test.rs b/templates/code/rust/tests/events/test.rs index edf2c8e..65c273d 100644 --- a/templates/code/rust/tests/events/test.rs +++ b/templates/code/rust/tests/events/test.rs @@ -1,4 +1,6 @@ -use generated_semconv::{logger, myappattr, myappevent, workerattr, workerevent, SCHEMA_URL}; +use generated_semconv::{ + logger, myappattr, myappevent, scope, workerattr, workerevent, SCHEMA_URL, +}; use opentelemetry::logs::{AnyValue, Severity}; use opentelemetry::trace::{SpanContext, SpanId, TraceContextExt, TraceFlags, TraceId, TraceState}; use opentelemetry_sdk::logs::{InMemoryLogExporter, SdkLoggerProvider}; @@ -9,13 +11,13 @@ fn typed_events_have_schema_timestamps_severity_attributes_and_trace_context() { let provider = SdkLoggerProvider::builder() .with_simple_exporter(exporter.clone()) .build(); - let logger = logger::Logger::new_with_scope( + let logger = logger::Logger::new( &provider, - opentelemetry::InstrumentationScope::builder("worker") - .with_version("1.2.3") - .with_schema_url("https://example.com/ignored/1.0.0") - .with_attributes([opentelemetry::KeyValue::new("scope.kind", "test")]) - .build(), + scope::Scope { + name: "worker".into(), + version: Some("1.2.3".into()), + attributes: vec![opentelemetry::KeyValue::new("scope.kind", "test")], + }, ); let span = SpanContext::new( TraceId::from(7), @@ -67,7 +69,7 @@ fn typed_events_have_schema_timestamps_severity_attributes_and_trace_context() { assert!(log .instrumentation .attributes() - .any(|kv| kv.key.as_str() == "scope.kind")); + .any(|kv| kv == &opentelemetry::KeyValue::new("scope.kind", "test"))); assert_eq!( log.record.trace_context().unwrap().trace_id, span.trace_id() diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs index 2607994..98512f3 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs @@ -1,23 +1,15 @@ +use super::scope::Scope; + #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.meter_with_scope(registry_scope(scope))) + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let meter = provider.meter_with_scope(scope.into()); + Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs index ae1eaf7..c3bb3d4 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs @@ -2,5 +2,6 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/histogram_boundaries_by_unit/1.0.0"; pub mod myappattr; +pub mod scope; pub mod meter; pub mod myappmetric; diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs index 2607994..98512f3 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs @@ -1,23 +1,15 @@ +use super::scope::Scope; + #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.meter_with_scope(registry_scope(scope))) + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let meter = provider.meter_with_scope(scope.into()); + Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs index d5166c8..7ce7635 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs @@ -2,5 +2,6 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/histogram_boundaries_by_unit_params/1.0.0"; pub mod myappattr; +pub mod scope; pub mod meter; pub mod myappmetric; diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/imported/expected/logger.rs b/templates/code/rust/tests/imported/expected/logger.rs index 179c64c..9455600 100644 --- a/templates/code/rust/tests/imported/expected/logger.rs +++ b/templates/code/rust/tests/imported/expected/logger.rs @@ -1,19 +1,20 @@ +use super::scope::Scope; + use opentelemetry::logs::AnyValue; use opentelemetry::{Array, Value}; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.logger_with_scope(registry_scope(scope))) + pub fn new>(provider: &P, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let logger = provider.logger_with_scope(scope.into()); + Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { match value { @@ -31,12 +32,3 @@ pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::Any _ => AnyValue::String(value.to_string().into()), } } - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() -} diff --git a/templates/code/rust/tests/imported/expected/meter.rs b/templates/code/rust/tests/imported/expected/meter.rs index 2607994..98512f3 100644 --- a/templates/code/rust/tests/imported/expected/meter.rs +++ b/templates/code/rust/tests/imported/expected/meter.rs @@ -1,23 +1,15 @@ +use super::scope::Scope; + #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.meter_with_scope(registry_scope(scope))) + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let meter = provider.meter_with_scope(scope.into()); + Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/imported/expected/mod.rs b/templates/code/rust/tests/imported/expected/mod.rs index 2690858..1010f0d 100644 --- a/templates/code/rust/tests/imported/expected/mod.rs +++ b/templates/code/rust/tests/imported/expected/mod.rs @@ -2,6 +2,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/myapp/1.0.0"; pub mod myappattr; +pub mod scope; pub mod meter; pub mod tracer; pub mod logger; diff --git a/templates/code/rust/tests/imported/expected/scope.rs b/templates/code/rust/tests/imported/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/imported/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/imported/expected/tracer.rs b/templates/code/rust/tests/imported/expected/tracer.rs index e6865f2..802f1e8 100644 --- a/templates/code/rust/tests/imported/expected/tracer.rs +++ b/templates/code/rust/tests/imported/expected/tracer.rs @@ -1,23 +1,14 @@ +use super::scope::Scope; + pub struct Tracer(T); impl Tracer { - pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self(provider.tracer_with_scope(opentelemetry::InstrumentationScope::builder(scope) - .with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.tracer_with_scope(registry_scope(scope))) + pub fn new>(provider: &P, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let tracer = provider.tracer_with_scope(scope.into()); + Self(tracer) } pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { - fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/imported_typed/expected/logger.rs b/templates/code/rust/tests/imported_typed/expected/logger.rs index 179c64c..9455600 100644 --- a/templates/code/rust/tests/imported_typed/expected/logger.rs +++ b/templates/code/rust/tests/imported_typed/expected/logger.rs @@ -1,19 +1,20 @@ +use super::scope::Scope; + use opentelemetry::logs::AnyValue; use opentelemetry::{Array, Value}; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.logger_with_scope(registry_scope(scope))) + pub fn new>(provider: &P, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let logger = provider.logger_with_scope(scope.into()); + Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { match value { @@ -31,12 +32,3 @@ pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::Any _ => AnyValue::String(value.to_string().into()), } } - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() -} diff --git a/templates/code/rust/tests/imported_typed/expected/meter.rs b/templates/code/rust/tests/imported_typed/expected/meter.rs index 2607994..98512f3 100644 --- a/templates/code/rust/tests/imported_typed/expected/meter.rs +++ b/templates/code/rust/tests/imported_typed/expected/meter.rs @@ -1,23 +1,15 @@ +use super::scope::Scope; + #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.meter_with_scope(registry_scope(scope))) + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let meter = provider.meter_with_scope(scope.into()); + Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/imported_typed/expected/mod.rs b/templates/code/rust/tests/imported_typed/expected/mod.rs index da9ba6d..3110e3c 100644 --- a/templates/code/rust/tests/imported_typed/expected/mod.rs +++ b/templates/code/rust/tests/imported_typed/expected/mod.rs @@ -2,6 +2,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/myapp/1.0.0"; pub mod myappattr; +pub mod scope; pub mod meter; pub mod tracer; pub mod logger; diff --git a/templates/code/rust/tests/imported_typed/expected/scope.rs b/templates/code/rust/tests/imported_typed/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/imported_typed/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/imported_typed/expected/tracer.rs b/templates/code/rust/tests/imported_typed/expected/tracer.rs index e6865f2..802f1e8 100644 --- a/templates/code/rust/tests/imported_typed/expected/tracer.rs +++ b/templates/code/rust/tests/imported_typed/expected/tracer.rs @@ -1,23 +1,14 @@ +use super::scope::Scope; + pub struct Tracer(T); impl Tracer { - pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self(provider.tracer_with_scope(opentelemetry::InstrumentationScope::builder(scope) - .with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.tracer_with_scope(registry_scope(scope))) + pub fn new>(provider: &P, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let tracer = provider.tracer_with_scope(scope.into()); + Self(tracer) } pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { - fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/literal_escaping/expected/meter.rs b/templates/code/rust/tests/literal_escaping/expected/meter.rs index 2607994..98512f3 100644 --- a/templates/code/rust/tests/literal_escaping/expected/meter.rs +++ b/templates/code/rust/tests/literal_escaping/expected/meter.rs @@ -1,23 +1,15 @@ +use super::scope::Scope; + #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.meter_with_scope(registry_scope(scope))) + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let meter = provider.meter_with_scope(scope.into()); + Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/literal_escaping/expected/mod.rs b/templates/code/rust/tests/literal_escaping/expected/mod.rs index 43f1e41..4c95d9f 100644 --- a/templates/code/rust/tests/literal_escaping/expected/mod.rs +++ b/templates/code/rust/tests/literal_escaping/expected/mod.rs @@ -2,5 +2,6 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/escaping/1.0.0"; pub mod demoattr; +pub mod scope; pub mod meter; pub mod demometric; diff --git a/templates/code/rust/tests/literal_escaping/expected/scope.rs b/templates/code/rust/tests/literal_escaping/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/literal_escaping/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/metrics/expected/meter.rs b/templates/code/rust/tests/metrics/expected/meter.rs index 2607994..98512f3 100644 --- a/templates/code/rust/tests/metrics/expected/meter.rs +++ b/templates/code/rust/tests/metrics/expected/meter.rs @@ -1,23 +1,15 @@ +use super::scope::Scope; + #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.meter_with_scope(registry_scope(scope))) + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let meter = provider.meter_with_scope(scope.into()); + Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/metrics/expected/mod.rs b/templates/code/rust/tests/metrics/expected/mod.rs index 57229fc..24c9a92 100644 --- a/templates/code/rust/tests/metrics/expected/mod.rs +++ b/templates/code/rust/tests/metrics/expected/mod.rs @@ -3,6 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/metrics/1.0.0"; pub mod authattr; pub mod myappattr; +pub mod scope; pub mod meter; pub mod authmetric; pub mod myappmetric; diff --git a/templates/code/rust/tests/metrics/expected/scope.rs b/templates/code/rust/tests/metrics/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/metrics/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/metrics/test.rs b/templates/code/rust/tests/metrics/test.rs index 46fc832..ad2140e 100644 --- a/templates/code/rust/tests/metrics/test.rs +++ b/templates/code/rust/tests/metrics/test.rs @@ -1,4 +1,4 @@ -use generated_semconv::{authattr, authmetric, meter, myappattr, myappmetric, workermetric}; +use generated_semconv::{authattr, authmetric, meter, myappattr, myappmetric, scope, workermetric}; use opentelemetry::KeyValue; use opentelemetry_sdk::metrics::data::{AggregatedMetrics, MetricData}; use opentelemetry_sdk::metrics::{InMemoryMetricExporter, PeriodicReader, SdkMeterProvider}; @@ -20,13 +20,13 @@ fn provider() -> (SdkMeterProvider, InMemoryMetricExporter) { #[allow(deprecated)] fn synchronous_metrics_export_types_values_attributes_and_refinements() { let (provider, exporter) = provider(); - let meter = meter::Meter::new_with_scope( + let meter = meter::Meter::new( &provider, - opentelemetry::InstrumentationScope::builder("synthetic-worker") - .with_version("1.2.3") - .with_schema_url("https://example.com/other/1.0.0") - .with_attributes([opentelemetry::KeyValue::new("scope.kind", "worker")]) - .build(), + scope::Scope { + name: "synthetic-worker".into(), + version: Some("1.2.3".into()), + attributes: vec![KeyValue::new("scope.kind", "worker")], + }, ); myappmetric::TaskDurationHistogram::new(&meter).record( 0.1, diff --git a/templates/code/rust/tests/naming/expected/meter.rs b/templates/code/rust/tests/naming/expected/meter.rs index 2607994..98512f3 100644 --- a/templates/code/rust/tests/naming/expected/meter.rs +++ b/templates/code/rust/tests/naming/expected/meter.rs @@ -1,23 +1,15 @@ +use super::scope::Scope; + #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.meter_with_scope(registry_scope(scope))) + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let meter = provider.meter_with_scope(scope.into()); + Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/naming/expected/mod.rs b/templates/code/rust/tests/naming/expected/mod.rs index 5062b2c..cdd6422 100644 --- a/templates/code/rust/tests/naming/expected/mod.rs +++ b/templates/code/rust/tests/naming/expected/mod.rs @@ -2,5 +2,6 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/naming/1.0.0"; pub mod capsattr; +pub mod scope; pub mod meter; pub mod capsmetric; diff --git a/templates/code/rust/tests/naming/expected/scope.rs b/templates/code/rust/tests/naming/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/naming/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/no_namespace/expected/logger.rs b/templates/code/rust/tests/no_namespace/expected/logger.rs index 179c64c..9455600 100644 --- a/templates/code/rust/tests/no_namespace/expected/logger.rs +++ b/templates/code/rust/tests/no_namespace/expected/logger.rs @@ -1,19 +1,20 @@ +use super::scope::Scope; + use opentelemetry::logs::AnyValue; use opentelemetry::{Array, Value}; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self(provider.logger_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.logger_with_scope(registry_scope(scope))) + pub fn new>(provider: &P, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let logger = provider.logger_with_scope(scope.into()); + Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), "") } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { match value { @@ -31,12 +32,3 @@ pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::Any _ => AnyValue::String(value.to_string().into()), } } - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() -} diff --git a/templates/code/rust/tests/no_namespace/expected/mod.rs b/templates/code/rust/tests/no_namespace/expected/mod.rs index 5f85d2b..224f6b3 100644 --- a/templates/code/rust/tests/no_namespace/expected/mod.rs +++ b/templates/code/rust/tests/no_namespace/expected/mod.rs @@ -4,6 +4,7 @@ pub mod exceptionattr; pub mod heartbeatattr; pub mod hostattr; +pub mod scope; pub mod tracer; pub mod logger; pub mod exceptionevent; diff --git a/templates/code/rust/tests/no_namespace/expected/scope.rs b/templates/code/rust/tests/no_namespace/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/no_namespace/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/no_namespace/expected/tracer.rs b/templates/code/rust/tests/no_namespace/expected/tracer.rs index e6865f2..802f1e8 100644 --- a/templates/code/rust/tests/no_namespace/expected/tracer.rs +++ b/templates/code/rust/tests/no_namespace/expected/tracer.rs @@ -1,23 +1,14 @@ +use super::scope::Scope; + pub struct Tracer(T); impl Tracer { - pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self(provider.tracer_with_scope(opentelemetry::InstrumentationScope::builder(scope) - .with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.tracer_with_scope(registry_scope(scope))) + pub fn new>(provider: &P, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let tracer = provider.tracer_with_scope(scope.into()); + Self(tracer) } pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { - fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/params/expected/meter.rs b/templates/code/rust/tests/params/expected/meter.rs index 2607994..98512f3 100644 --- a/templates/code/rust/tests/params/expected/meter.rs +++ b/templates/code/rust/tests/params/expected/meter.rs @@ -1,23 +1,15 @@ +use super::scope::Scope; + #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into>) -> Self { - Self(provider.meter_with_scope(opentelemetry::InstrumentationScope::builder(scope).with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope(provider: &impl opentelemetry::metrics::MeterProvider, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.meter_with_scope(registry_scope(scope))) + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let meter = provider.meter_with_scope(scope.into()); + Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/params/expected/mod.rs b/templates/code/rust/tests/params/expected/mod.rs index 421154e..42d537f 100644 --- a/templates/code/rust/tests/params/expected/mod.rs +++ b/templates/code/rust/tests/params/expected/mod.rs @@ -6,5 +6,6 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/params/1.0.0"; pub mod billingattr; pub mod myappattr; +pub mod scope; pub mod meter; pub mod billingmetric; diff --git a/templates/code/rust/tests/params/expected/scope.rs b/templates/code/rust/tests/params/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/params/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/spans/expected/mod.rs b/templates/code/rust/tests/spans/expected/mod.rs index 6149b46..0ae3799 100644 --- a/templates/code/rust/tests/spans/expected/mod.rs +++ b/templates/code/rust/tests/spans/expected/mod.rs @@ -3,6 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/spans/1.0.0"; pub mod myappattr; pub mod workerattr; +pub mod scope; pub mod tracer; pub mod myappspan; pub mod workerspan; diff --git a/templates/code/rust/tests/spans/expected/scope.rs b/templates/code/rust/tests/spans/expected/scope.rs new file mode 100644 index 0000000..d73be75 --- /dev/null +++ b/templates/code/rust/tests/spans/expected/scope.rs @@ -0,0 +1,27 @@ +use ::std::borrow::Cow; + +#[derive(Clone, Debug, Default)] +pub struct Scope { + pub name: Cow<'static, str>, + pub version: Option>, + pub attributes: Vec<::opentelemetry::KeyValue>, +} +impl From<&'static str> for Scope { + fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } +} +impl From for Scope { + fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } +} +impl From> for Scope { + fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } +} +impl From for ::opentelemetry::InstrumentationScope { + fn from(value: Scope) -> Self { + let Scope { name, version, attributes } = value; + let mut builder = Self::builder(name) + .with_schema_url(super::SCHEMA_URL) + .with_attributes(attributes); + if let Some(version) = version { builder = builder.with_version(version); } + builder.build() + } +} diff --git a/templates/code/rust/tests/spans/expected/tracer.rs b/templates/code/rust/tests/spans/expected/tracer.rs index e6865f2..802f1e8 100644 --- a/templates/code/rust/tests/spans/expected/tracer.rs +++ b/templates/code/rust/tests/spans/expected/tracer.rs @@ -1,23 +1,14 @@ +use super::scope::Scope; + pub struct Tracer(T); impl Tracer { - pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self(provider.tracer_with_scope(opentelemetry::InstrumentationScope::builder(scope) - .with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.tracer_with_scope(registry_scope(scope))) + pub fn new>(provider: &P, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let tracer = provider.tracer_with_scope(scope.into()); + Self(tracer) } pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { - fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } -} - -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), Scope::default()) } } diff --git a/templates/code/rust/tests/spans/test.rs b/templates/code/rust/tests/spans/test.rs index 811db2a..d682f66 100644 --- a/templates/code/rust/tests/spans/test.rs +++ b/templates/code/rust/tests/spans/test.rs @@ -8,13 +8,13 @@ fn derived_names_refinements_parent_context_and_late_attributes() { let provider = SdkTracerProvider::builder() .with_simple_exporter(exporter.clone()) .build(); - let tracer = tracer::Tracer::new_with_scope( + let tracer = tracer::Tracer::new( &provider, - opentelemetry::InstrumentationScope::builder("worker") - .with_version("1.2.3") - .with_schema_url("https://example.com/ignored/1.0.0") - .with_attributes([opentelemetry::KeyValue::new("scope.kind", "test")]) - .build(), + generated_semconv::scope::Scope { + name: "worker".into(), + version: Some("1.2.3".into()), + attributes: vec![opentelemetry::KeyValue::new("scope.kind", "test")], + }, ); let _: &opentelemetry_sdk::trace::SdkTracer = tracer.inner(); let mut parent = myappspan::start_task_dispatch( diff --git a/templates/code/rust/tests/spans/tests/allocations.rs b/templates/code/rust/tests/spans/tests/allocations.rs index 88a9d91..5577886 100644 --- a/templates/code/rust/tests/spans/tests/allocations.rs +++ b/templates/code/rust/tests/spans/tests/allocations.rs @@ -103,13 +103,12 @@ fn untemplated_names_move_or_borrow_without_heap_allocations() { } #[test] -fn matching_scope_schema_moves_existing_metadata_without_cloning() { - let scope = opentelemetry::InstrumentationScope::builder("worker") - .with_schema_url(generated_semconv::SCHEMA_URL) - .with_version("1.0.0") - .with_attributes([opentelemetry::KeyValue::new("scope.kind", "worker")]) - .build(); - let (_, count) = - allocations(|| tracer::Tracer::new_with_scope(&NoopTracerProvider::new(), scope)); +fn configured_scope_moves_existing_metadata_without_cloning() { + let scope = generated_semconv::scope::Scope { + name: "worker".into(), + version: Some("1.0.0".into()), + attributes: vec![opentelemetry::KeyValue::new("scope.kind", "worker")], + }; + let (_, count) = allocations(|| tracer::Tracer::new(&NoopTracerProvider::new(), scope)); assert_eq!(count, 0); } diff --git a/templates/code/rust/tracer.rs.j2 b/templates/code/rust/tracer.rs.j2 index eb03b66..c684168 100644 --- a/templates/code/rust/tracer.rs.j2 +++ b/templates/code/rust/tracer.rs.j2 @@ -1,25 +1,17 @@ {%- filter trim %} +use super::scope::Scope; + pub struct Tracer(T); impl Tracer { - pub fn new>(provider: &P, scope: impl Into>) -> Self { - Self(provider.tracer_with_scope(opentelemetry::InstrumentationScope::builder(scope) - .with_schema_url(super::SCHEMA_URL).build())) - } - pub fn new_with_scope>(provider: &P, scope: opentelemetry::InstrumentationScope) -> Self { - Self(provider.tracer_with_scope(registry_scope(scope))) + pub fn new>(provider: &P, scope: impl Into) -> Self { + let scope: Scope = scope.into(); + let tracer = provider.tracer_with_scope(scope.into()); + Self(tracer) } pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { - fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), "") } + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), Scope::default()) } } -fn registry_scope(scope: opentelemetry::InstrumentationScope) -> opentelemetry::InstrumentationScope { - if scope.schema_url() == Some(super::SCHEMA_URL) { return scope; } - let mut builder = opentelemetry::InstrumentationScope::builder(scope.name().to_owned()) - .with_schema_url(super::SCHEMA_URL) - .with_attributes(scope.attributes().cloned()); - if let Some(version) = scope.version() { builder = builder.with_version(version.to_owned()); } - builder.build() -} {% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/weaver.yaml b/templates/code/rust/weaver.yaml index f1eca4d..240f8f9 100644 --- a/templates/code/rust/weaver.yaml +++ b/templates/code/rust/weaver.yaml @@ -585,6 +585,16 @@ templates: application_mode: each file_name: "{{ ctx.namespace }}entity.rs" + - template: scope.rs.j2 + filter: |- + {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $o + | if ((semconv_grouped_metrics($o) | map(.metrics) | add // [] | length) > 0 + or (.registry.spans // [] | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) | length) > 0 + or ((.registry.events // []) + (.refinements.events // []) | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) | length) > 0) + then [{}] else [] end + application_mode: each + file_name: scope.rs + - template: meter.rs.j2 filter: |- {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $o From ae1bc636b3c3e1f0ef15e9b05e19a13c17fd852e Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Mon, 5 Oct 2026 12:43:18 -0400 Subject: [PATCH 10/14] refactor: make instrumentation configuration explicit Signed-off-by: Yordis Prieto --- templates/code/rust/README.md | 25 ++++--- templates/code/rust/logger.rs.j2 | 9 ++- templates/code/rust/meter.rs.j2 | 9 ++- templates/code/rust/mod.rs.j2 | 1 + templates/code/rust/options.rs.j2 | 8 +++ .../rust/tests/allocations/expected/logger.rs | 9 ++- .../rust/tests/allocations/expected/meter.rs | 9 ++- .../rust/tests/allocations/expected/mod.rs | 1 + .../tests/allocations/expected/options.rs | 6 ++ templates/code/rust/tests/allocations/test.rs | 70 +++++++++++++++---- .../event_no_attributes/expected/logger.rs | 9 ++- .../tests/event_no_attributes/expected/mod.rs | 1 + .../event_no_attributes/expected/options.rs | 6 ++ .../rust/tests/event_no_attributes/test.rs | 8 ++- .../code/rust/tests/events/expected/logger.rs | 9 ++- .../code/rust/tests/events/expected/mod.rs | 1 + .../rust/tests/events/expected/options.rs | 6 ++ templates/code/rust/tests/events/test.rs | 18 +++-- .../expected/meter.rs | 9 ++- .../expected/mod.rs | 1 + .../expected/options.rs | 6 ++ .../expected/meter.rs | 9 ++- .../expected/mod.rs | 1 + .../expected/options.rs | 6 ++ .../rust/tests/imported/expected/logger.rs | 9 ++- .../rust/tests/imported/expected/meter.rs | 9 ++- .../code/rust/tests/imported/expected/mod.rs | 1 + .../rust/tests/imported/expected/options.rs | 6 ++ .../rust/tests/imported/expected/tracer.rs | 9 ++- templates/code/rust/tests/imported/test.rs | 8 ++- .../tests/imported_typed/expected/logger.rs | 9 ++- .../tests/imported_typed/expected/meter.rs | 9 ++- .../rust/tests/imported_typed/expected/mod.rs | 1 + .../tests/imported_typed/expected/options.rs | 6 ++ .../tests/imported_typed/expected/tracer.rs | 9 ++- .../tests/literal_escaping/expected/meter.rs | 9 ++- .../tests/literal_escaping/expected/mod.rs | 1 + .../literal_escaping/expected/options.rs | 6 ++ .../code/rust/tests/literal_escaping/test.rs | 9 ++- .../code/rust/tests/metrics/expected/meter.rs | 9 ++- .../code/rust/tests/metrics/expected/mod.rs | 1 + .../rust/tests/metrics/expected/options.rs | 6 ++ templates/code/rust/tests/metrics/test.rs | 32 +++++++-- .../code/rust/tests/naming/expected/meter.rs | 9 ++- .../code/rust/tests/naming/expected/mod.rs | 1 + .../rust/tests/naming/expected/options.rs | 6 ++ .../tests/no_namespace/expected/logger.rs | 9 ++- .../rust/tests/no_namespace/expected/mod.rs | 1 + .../tests/no_namespace/expected/options.rs | 6 ++ .../tests/no_namespace/expected/tracer.rs | 9 ++- .../code/rust/tests/params/expected/meter.rs | 9 ++- .../code/rust/tests/params/expected/mod.rs | 1 + .../rust/tests/params/expected/options.rs | 6 ++ .../code/rust/tests/spans/expected/mod.rs | 1 + .../code/rust/tests/spans/expected/options.rs | 6 ++ .../code/rust/tests/spans/expected/tracer.rs | 9 ++- templates/code/rust/tests/spans/test.rs | 10 +-- .../rust/tests/spans/tests/allocations.rs | 16 ++++- templates/code/rust/tracer.rs.j2 | 9 ++- templates/code/rust/weaver.yaml | 7 +- 60 files changed, 345 insertions(+), 156 deletions(-) create mode 100644 templates/code/rust/options.rs.j2 create mode 100644 templates/code/rust/tests/allocations/expected/options.rs create mode 100644 templates/code/rust/tests/event_no_attributes/expected/options.rs create mode 100644 templates/code/rust/tests/events/expected/options.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit/expected/options.rs create mode 100644 templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/options.rs create mode 100644 templates/code/rust/tests/imported/expected/options.rs create mode 100644 templates/code/rust/tests/imported_typed/expected/options.rs create mode 100644 templates/code/rust/tests/literal_escaping/expected/options.rs create mode 100644 templates/code/rust/tests/metrics/expected/options.rs create mode 100644 templates/code/rust/tests/naming/expected/options.rs create mode 100644 templates/code/rust/tests/no_namespace/expected/options.rs create mode 100644 templates/code/rust/tests/params/expected/options.rs create mode 100644 templates/code/rust/tests/spans/expected/options.rs diff --git a/templates/code/rust/README.md b/templates/code/rust/README.md index 9801f9a..ddbbd8b 100644 --- a/templates/code/rust/README.md +++ b/templates/code/rust/README.md @@ -45,6 +45,7 @@ before choosing that namespace. | Module | API | | ------------------- | ----------------------------------------------------------------------------------------- | | `attr` | Attribute newtypes and enum variants, `KEY` and conversion into `KeyValue`. | +| `options` | Typed instrumentation options containing scope configuration. | | `scope` | Shared scope name, version, and attributes configuration. | | `meter` | Schema-aware `Meter`, with `new`, `inner`, and a no-op `Default`. | | `tracer` | Schema-aware `Tracer`, with `new`, `inner`, and a no-op `Default`. | @@ -55,21 +56,25 @@ before choosing that namespace. | `entity` | Typed entity values, attribute iterators, and resources carrying the registry schema URL. | Handle modules are emitted when the registry includes their corresponding -signals. Their `new(provider, scope)` constructor accepts a static string, owned -`String`, `Cow<'static, str>`, or the shared `scope::Scope` configuration: +signals. Their `new(provider, options)` constructor takes the exact +`options::InstrumentationOptions` type, with metadata nested under `scope`: ```rust -let scope = semconv::scope::Scope { - name: "worker".into(), - version: Some("1.0.0".into()), - attributes: vec![opentelemetry::KeyValue::new("scope.kind", "worker")], +let options = semconv::options::InstrumentationOptions { + scope: semconv::scope::Scope { + name: "worker".into(), + version: Some("1.0.0".into()), + attributes: vec![opentelemetry::KeyValue::new("scope.kind", "worker")], + }, }; -let tracer = semconv::tracer::Tracer::new(&provider, scope); +let tracer = semconv::tracer::Tracer::new(&provider, options); ``` -Scope values move into OpenTelemetry without rebuilding their metadata. The -registry schema URL is always applied; it is not a configuration field. The -shared scope module is emitted when a handle is needed. +Use `InstrumentationOptions::default()` for default metadata. `Scope` accepts +static strings, owned `String`, or `Cow<'static, str>` through `From` when only a +name is needed. Scope values move into OpenTelemetry without rebuilding their +metadata. The registry schema URL is always applied; it is not a configuration +field. The shared scope and options modules are emitted when a handle is needed. Attribute keys, metric names, and event names retain their full registry names. ### Typed attributes diff --git a/templates/code/rust/logger.rs.j2 b/templates/code/rust/logger.rs.j2 index a299488..55ad48a 100644 --- a/templates/code/rust/logger.rs.j2 +++ b/templates/code/rust/logger.rs.j2 @@ -1,5 +1,5 @@ {%- filter trim %} -use super::scope::Scope; +use super::options::InstrumentationOptions; {% if ctx.has_attributes %} use opentelemetry::logs::AnyValue; @@ -9,15 +9,14 @@ use opentelemetry::{Array, Value}; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let logger = provider.logger_with_scope(scope.into()); + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let logger = provider.logger_with_scope(options.scope.into()); Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } {% if ctx.has_attributes %} pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { diff --git a/templates/code/rust/meter.rs.j2 b/templates/code/rust/meter.rs.j2 index b56001f..ca74571 100644 --- a/templates/code/rust/meter.rs.j2 +++ b/templates/code/rust/meter.rs.j2 @@ -1,18 +1,17 @@ {%- filter trim %} -use super::scope::Scope; +use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let meter = provider.meter_with_scope(scope.into()); + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { + let meter = provider.meter_with_scope(options.scope.into()); Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } {% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/mod.rs.j2 b/templates/code/rust/mod.rs.j2 index 19b3242..229f253 100644 --- a/templates/code/rust/mod.rs.j2 +++ b/templates/code/rust/mod.rs.j2 @@ -14,6 +14,7 @@ pub mod {{ namespace }}; {% if ctx.has_metrics or ctx.has_spans or ctx.has_events %} pub mod scope; +pub mod options; {% endif %} {% if ctx.has_metrics %} pub mod meter; diff --git a/templates/code/rust/options.rs.j2 b/templates/code/rust/options.rs.j2 new file mode 100644 index 0000000..b0e6496 --- /dev/null +++ b/templates/code/rust/options.rs.j2 @@ -0,0 +1,8 @@ +{%- filter trim %} +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} +{% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/tests/allocations/expected/logger.rs b/templates/code/rust/tests/allocations/expected/logger.rs index 9455600..8235fca 100644 --- a/templates/code/rust/tests/allocations/expected/logger.rs +++ b/templates/code/rust/tests/allocations/expected/logger.rs @@ -1,4 +1,4 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; use opentelemetry::logs::AnyValue; use opentelemetry::{Array, Value}; @@ -6,15 +6,14 @@ use opentelemetry::{Array, Value}; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let logger = provider.logger_with_scope(scope.into()); + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let logger = provider.logger_with_scope(options.scope.into()); Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { match value { diff --git a/templates/code/rust/tests/allocations/expected/meter.rs b/templates/code/rust/tests/allocations/expected/meter.rs index 98512f3..3e2e018 100644 --- a/templates/code/rust/tests/allocations/expected/meter.rs +++ b/templates/code/rust/tests/allocations/expected/meter.rs @@ -1,15 +1,14 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let meter = provider.meter_with_scope(scope.into()); + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { + let meter = provider.meter_with_scope(options.scope.into()); Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/allocations/expected/mod.rs b/templates/code/rust/tests/allocations/expected/mod.rs index 7db7281..afe3186 100644 --- a/templates/code/rust/tests/allocations/expected/mod.rs +++ b/templates/code/rust/tests/allocations/expected/mod.rs @@ -3,6 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/allocations/1.0.0"; pub mod probeattr; pub mod scope; +pub mod options; pub mod meter; pub mod logger; pub mod probeevent; diff --git a/templates/code/rust/tests/allocations/expected/options.rs b/templates/code/rust/tests/allocations/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/allocations/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/allocations/test.rs b/templates/code/rust/tests/allocations/test.rs index 208130a..0399e3c 100644 --- a/templates/code/rust/tests/allocations/test.rs +++ b/templates/code/rust/tests/allocations/test.rs @@ -1,3 +1,4 @@ +use generated_semconv::options::InstrumentationOptions; use generated_semconv::{logger, meter, probeattr, probeevent, probemetric, scope}; use opentelemetry::logs::{AnyValue, LogRecord, Logger, LoggerProvider, Severity}; use opentelemetry::metrics::{ @@ -221,7 +222,12 @@ impl Logger for FakeLogger { #[test] fn metrics_use_no_generated_heap_for_required_or_typical_optional_attributes() { let state = Arc::new(MetricState::default()); - let meter = meter::Meter::new(&MetricProvider(state.clone()), "allocation-test"); + let meter = meter::Meter::new( + &MetricProvider(state.clone()), + InstrumentationOptions { + scope: "allocation-test".into(), + }, + ); let required = probemetric::RequiredCounter::new(&meter); let optional = probemetric::OptionalCounter::new(&meter); let required_count = allocations(|| required.add(1, probeattr::RequiredAttr::from(3))); @@ -266,7 +272,12 @@ fn metrics_use_no_generated_heap_for_required_or_typical_optional_attributes() { fn observable_measurements_use_stack_attribute_storage() { let state = Arc::new(MetricState::default()); let provider = MetricProvider(state.clone()); - let meter = meter::Meter::new(&provider, "allocation-test"); + let meter = meter::Meter::new( + &provider, + InstrumentationOptions { + scope: "allocation-test".into(), + }, + ); let _required = probemetric::RequiredObservableCounter::new(&meter, |observer| { observer.observe(1, probeattr::RequiredAttr::from(3)); }); @@ -299,12 +310,22 @@ fn static_meter_and_logger_scope_names_remain_borrowed() { }; drop(metric_provider.scope.lock().unwrap()); let metric_count = allocations(|| { - black_box(meter::Meter::new(&metric_provider, "allocation-test")); + black_box(meter::Meter::new( + &metric_provider, + InstrumentationOptions { + scope: "allocation-test".into(), + }, + )); }); let log_provider = LogProvider(Arc::new(LogState::default())); drop(log_provider.0.scope.lock().unwrap()); let log_count = allocations(|| { - black_box(logger::Logger::new(&log_provider, "allocation-test")); + black_box(logger::Logger::new( + &log_provider, + InstrumentationOptions { + scope: "allocation-test".into(), + }, + )); }); assert_eq!(metric_count, 0); assert_eq!(log_count, 0); @@ -337,10 +358,18 @@ fn configured_scopes_move_metadata_without_rebuilding_storage() { let original_metric = original(&metric_scope); let original_log = original(&log_scope); let metric_count = allocations(|| { - black_box(meter::Meter::new(&metric_provider, metric_scope)); + black_box(meter::Meter::new( + &metric_provider, + InstrumentationOptions { + scope: metric_scope, + }, + )); }); let log_count = allocations(|| { - black_box(logger::Logger::new(&log_provider, log_scope)); + black_box(logger::Logger::new( + &log_provider, + InstrumentationOptions { scope: log_scope }, + )); }); assert_eq!(metric_count, 0); assert_eq!(log_count, 0); @@ -367,20 +396,23 @@ fn configured_scopes_move_metadata_without_rebuilding_storage() { } #[test] -fn scope_convenience_inputs_share_one_constructor() { +fn scope_convenience_inputs_are_nested_in_instrumentation_options() { let metric_provider = BorrowedMeterProvider { meter: Meter::new(Arc::new(MetricProvider(Arc::new(MetricState::default())))), scope: Mutex::new(None), }; - for configuration in [ + for options in [ scope::Scope::from("static"), scope::Scope::from(String::from("owned")), scope::Scope::from(Cow::Borrowed("cow-borrowed")), scope::Scope::from(Cow::Owned(String::from("cow-owned"))), - scope::Scope::default(), - ] { - let name = configuration.name.clone(); - let _meter = meter::Meter::new(&metric_provider, configuration); + ] + .into_iter() + .map(|scope| InstrumentationOptions { scope }) + .chain(std::iter::once(InstrumentationOptions::default())) + { + let name = options.scope.name.clone(); + let _meter = meter::Meter::new(&metric_provider, options); let stored = metric_provider.scope.lock().unwrap(); let stored = stored.as_ref().unwrap(); assert_eq!(stored.name(), name); @@ -394,7 +426,12 @@ fn scope_convenience_inputs_share_one_constructor() { fn enabled_events_use_no_generated_heap_and_preserve_duplicate_attributes() { let state = Arc::new(LogState::default()); state.enabled.store(true, Ordering::Relaxed); - let logger = logger::Logger::new(&LogProvider(state.clone()), "allocation-test"); + let logger = logger::Logger::new( + &LogProvider(state.clone()), + InstrumentationOptions { + scope: "allocation-test".into(), + }, + ); let context = Context::new(); probeevent::emit_recorded(&context, &logger, probeattr::RequiredAttr::from(3), []); let count = allocations(|| { @@ -451,7 +488,12 @@ fn enabled_events_use_no_generated_heap_and_preserve_duplicate_attributes() { #[test] fn disabled_events_defer_context_attachment_and_attribute_conversion() { let state = Arc::new(LogState::default()); - let logger = logger::Logger::new(&LogProvider(state.clone()), "allocation-test"); + let logger = logger::Logger::new( + &LogProvider(state.clone()), + InstrumentationOptions { + scope: "allocation-test".into(), + }, + ); let context = Context::new().with_value(ExplicitContext); let values = probeattr::ValuesAttr::from(vec![1, 2, 3]); probeevent::emit_recorded( diff --git a/templates/code/rust/tests/event_no_attributes/expected/logger.rs b/templates/code/rust/tests/event_no_attributes/expected/logger.rs index 4c31cfc..137ef4c 100644 --- a/templates/code/rust/tests/event_no_attributes/expected/logger.rs +++ b/templates/code/rust/tests/event_no_attributes/expected/logger.rs @@ -1,15 +1,14 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let logger = provider.logger_with_scope(scope.into()); + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let logger = provider.logger_with_scope(options.scope.into()); Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/event_no_attributes/expected/mod.rs b/templates/code/rust/tests/event_no_attributes/expected/mod.rs index b79824f..86001b2 100644 --- a/templates/code/rust/tests/event_no_attributes/expected/mod.rs +++ b/templates/code/rust/tests/event_no_attributes/expected/mod.rs @@ -2,5 +2,6 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/event-no-attributes/1.0.0"; pub mod scope; +pub mod options; pub mod logger; pub mod probeevent; diff --git a/templates/code/rust/tests/event_no_attributes/expected/options.rs b/templates/code/rust/tests/event_no_attributes/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/event_no_attributes/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/event_no_attributes/test.rs b/templates/code/rust/tests/event_no_attributes/test.rs index bc10942..3e5255f 100644 --- a/templates/code/rust/tests/event_no_attributes/test.rs +++ b/templates/code/rust/tests/event_no_attributes/test.rs @@ -1,3 +1,4 @@ +use generated_semconv::options::InstrumentationOptions; use generated_semconv::{logger, probeevent}; use opentelemetry::logs::Severity; use opentelemetry_sdk::logs::{InMemoryLogExporter, SdkLoggerProvider}; @@ -8,7 +9,12 @@ fn events_without_attributes_export_cleanly() { let provider = SdkLoggerProvider::builder() .with_simple_exporter(exporter.clone()) .build(); - let logger = logger::Logger::new(&provider, "synthetic-clock"); + let logger = logger::Logger::new( + &provider, + InstrumentationOptions { + scope: "synthetic-clock".into(), + }, + ); probeevent::emit_tick( &opentelemetry::Context::new(), &logger, diff --git a/templates/code/rust/tests/events/expected/logger.rs b/templates/code/rust/tests/events/expected/logger.rs index 9455600..8235fca 100644 --- a/templates/code/rust/tests/events/expected/logger.rs +++ b/templates/code/rust/tests/events/expected/logger.rs @@ -1,4 +1,4 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; use opentelemetry::logs::AnyValue; use opentelemetry::{Array, Value}; @@ -6,15 +6,14 @@ use opentelemetry::{Array, Value}; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let logger = provider.logger_with_scope(scope.into()); + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let logger = provider.logger_with_scope(options.scope.into()); Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { match value { diff --git a/templates/code/rust/tests/events/expected/mod.rs b/templates/code/rust/tests/events/expected/mod.rs index f8259d0..2f1689e 100644 --- a/templates/code/rust/tests/events/expected/mod.rs +++ b/templates/code/rust/tests/events/expected/mod.rs @@ -4,6 +4,7 @@ pub mod myappattr; pub mod workerattr; pub mod scope; +pub mod options; pub mod logger; pub mod myappevent; pub mod workerevent; diff --git a/templates/code/rust/tests/events/expected/options.rs b/templates/code/rust/tests/events/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/events/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/events/test.rs b/templates/code/rust/tests/events/test.rs index 65c273d..02a3fa0 100644 --- a/templates/code/rust/tests/events/test.rs +++ b/templates/code/rust/tests/events/test.rs @@ -1,3 +1,4 @@ +use generated_semconv::options::InstrumentationOptions; use generated_semconv::{ logger, myappattr, myappevent, scope, workerattr, workerevent, SCHEMA_URL, }; @@ -13,10 +14,12 @@ fn typed_events_have_schema_timestamps_severity_attributes_and_trace_context() { .build(); let logger = logger::Logger::new( &provider, - scope::Scope { - name: "worker".into(), - version: Some("1.2.3".into()), - attributes: vec![opentelemetry::KeyValue::new("scope.kind", "test")], + InstrumentationOptions { + scope: scope::Scope { + name: "worker".into(), + version: Some("1.2.3".into()), + attributes: vec![opentelemetry::KeyValue::new("scope.kind", "test")], + }, }, ); let span = SpanContext::new( @@ -129,7 +132,12 @@ impl opentelemetry::logs::Logger for DisabledLogger { fn disabled_events_are_checked_before_record_creation() { myappevent::emit_task_finished( &opentelemetry::Context::new(), - &logger::Logger::new(&DisabledProvider, "test"), + &logger::Logger::new( + &DisabledProvider, + InstrumentationOptions { + scope: "test".into(), + }, + ), myappattr::TaskStateAttr::Done, [myappevent::TaskFinishedOption::Severity(Severity::Error)], ); diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs index 98512f3..3e2e018 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs @@ -1,15 +1,14 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let meter = provider.meter_with_scope(scope.into()); + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { + let meter = provider.meter_with_scope(options.scope.into()); Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs index c3bb3d4..834ced1 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/mod.rs @@ -3,5 +3,6 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/histogram_boundaries_b pub mod myappattr; pub mod scope; +pub mod options; pub mod meter; pub mod myappmetric; diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/options.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs index 98512f3..3e2e018 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs @@ -1,15 +1,14 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let meter = provider.meter_with_scope(scope.into()); + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { + let meter = provider.meter_with_scope(options.scope.into()); Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs index 7ce7635..bf2567f 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/mod.rs @@ -3,5 +3,6 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/histogram_boundaries_b pub mod myappattr; pub mod scope; +pub mod options; pub mod meter; pub mod myappmetric; diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/options.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/imported/expected/logger.rs b/templates/code/rust/tests/imported/expected/logger.rs index 9455600..8235fca 100644 --- a/templates/code/rust/tests/imported/expected/logger.rs +++ b/templates/code/rust/tests/imported/expected/logger.rs @@ -1,4 +1,4 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; use opentelemetry::logs::AnyValue; use opentelemetry::{Array, Value}; @@ -6,15 +6,14 @@ use opentelemetry::{Array, Value}; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let logger = provider.logger_with_scope(scope.into()); + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let logger = provider.logger_with_scope(options.scope.into()); Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { match value { diff --git a/templates/code/rust/tests/imported/expected/meter.rs b/templates/code/rust/tests/imported/expected/meter.rs index 98512f3..3e2e018 100644 --- a/templates/code/rust/tests/imported/expected/meter.rs +++ b/templates/code/rust/tests/imported/expected/meter.rs @@ -1,15 +1,14 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let meter = provider.meter_with_scope(scope.into()); + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { + let meter = provider.meter_with_scope(options.scope.into()); Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/imported/expected/mod.rs b/templates/code/rust/tests/imported/expected/mod.rs index 1010f0d..c1aaad3 100644 --- a/templates/code/rust/tests/imported/expected/mod.rs +++ b/templates/code/rust/tests/imported/expected/mod.rs @@ -3,6 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/myapp/1.0.0"; pub mod myappattr; pub mod scope; +pub mod options; pub mod meter; pub mod tracer; pub mod logger; diff --git a/templates/code/rust/tests/imported/expected/options.rs b/templates/code/rust/tests/imported/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/imported/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/imported/expected/tracer.rs b/templates/code/rust/tests/imported/expected/tracer.rs index 802f1e8..bde566c 100644 --- a/templates/code/rust/tests/imported/expected/tracer.rs +++ b/templates/code/rust/tests/imported/expected/tracer.rs @@ -1,14 +1,13 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; pub struct Tracer(T); impl Tracer { - pub fn new>(provider: &P, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let tracer = provider.tracer_with_scope(scope.into()); + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let tracer = provider.tracer_with_scope(options.scope.into()); Self(tracer) } pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { - fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/imported/test.rs b/templates/code/rust/tests/imported/test.rs index fb7e0bf..7844080 100644 --- a/templates/code/rust/tests/imported/test.rs +++ b/templates/code/rust/tests/imported/test.rs @@ -1,3 +1,4 @@ +use generated_semconv::options::InstrumentationOptions; use generated_semconv::{edgeevent, edgespan, logger, myappattr, myappmetric, tracer}; use opentelemetry::{Array, KeyValue, StringValue, Value}; @@ -50,7 +51,12 @@ fn imported_native_string_arrays_format_derived_span_names() { let provider = opentelemetry_sdk::trace::SdkTracerProvider::builder() .with_simple_exporter(exporter.clone()) .build(); - let tracer = tracer::Tracer::new(&provider, "synthetic-upstream"); + let tracer = tracer::Tracer::new( + &provider, + InstrumentationOptions { + scope: "synthetic-upstream".into(), + }, + ); let mut span = edgespan::start_upstream_methods( &opentelemetry::Context::new(), &tracer, diff --git a/templates/code/rust/tests/imported_typed/expected/logger.rs b/templates/code/rust/tests/imported_typed/expected/logger.rs index 9455600..8235fca 100644 --- a/templates/code/rust/tests/imported_typed/expected/logger.rs +++ b/templates/code/rust/tests/imported_typed/expected/logger.rs @@ -1,4 +1,4 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; use opentelemetry::logs::AnyValue; use opentelemetry::{Array, Value}; @@ -6,15 +6,14 @@ use opentelemetry::{Array, Value}; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let logger = provider.logger_with_scope(scope.into()); + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let logger = provider.logger_with_scope(options.scope.into()); Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { match value { diff --git a/templates/code/rust/tests/imported_typed/expected/meter.rs b/templates/code/rust/tests/imported_typed/expected/meter.rs index 98512f3..3e2e018 100644 --- a/templates/code/rust/tests/imported_typed/expected/meter.rs +++ b/templates/code/rust/tests/imported_typed/expected/meter.rs @@ -1,15 +1,14 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let meter = provider.meter_with_scope(scope.into()); + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { + let meter = provider.meter_with_scope(options.scope.into()); Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/imported_typed/expected/mod.rs b/templates/code/rust/tests/imported_typed/expected/mod.rs index 3110e3c..11c3f63 100644 --- a/templates/code/rust/tests/imported_typed/expected/mod.rs +++ b/templates/code/rust/tests/imported_typed/expected/mod.rs @@ -3,6 +3,7 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/myapp/1.0.0"; pub mod myappattr; pub mod scope; +pub mod options; pub mod meter; pub mod tracer; pub mod logger; diff --git a/templates/code/rust/tests/imported_typed/expected/options.rs b/templates/code/rust/tests/imported_typed/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/imported_typed/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/imported_typed/expected/tracer.rs b/templates/code/rust/tests/imported_typed/expected/tracer.rs index 802f1e8..bde566c 100644 --- a/templates/code/rust/tests/imported_typed/expected/tracer.rs +++ b/templates/code/rust/tests/imported_typed/expected/tracer.rs @@ -1,14 +1,13 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; pub struct Tracer(T); impl Tracer { - pub fn new>(provider: &P, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let tracer = provider.tracer_with_scope(scope.into()); + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let tracer = provider.tracer_with_scope(options.scope.into()); Self(tracer) } pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { - fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/literal_escaping/expected/meter.rs b/templates/code/rust/tests/literal_escaping/expected/meter.rs index 98512f3..3e2e018 100644 --- a/templates/code/rust/tests/literal_escaping/expected/meter.rs +++ b/templates/code/rust/tests/literal_escaping/expected/meter.rs @@ -1,15 +1,14 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let meter = provider.meter_with_scope(scope.into()); + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { + let meter = provider.meter_with_scope(options.scope.into()); Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/literal_escaping/expected/mod.rs b/templates/code/rust/tests/literal_escaping/expected/mod.rs index 4c95d9f..86079ee 100644 --- a/templates/code/rust/tests/literal_escaping/expected/mod.rs +++ b/templates/code/rust/tests/literal_escaping/expected/mod.rs @@ -3,5 +3,6 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/escaping/1.0.0"; pub mod demoattr; pub mod scope; +pub mod options; pub mod meter; pub mod demometric; diff --git a/templates/code/rust/tests/literal_escaping/expected/options.rs b/templates/code/rust/tests/literal_escaping/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/literal_escaping/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/literal_escaping/test.rs b/templates/code/rust/tests/literal_escaping/test.rs index b400c34..11e8c0a 100644 --- a/templates/code/rust/tests/literal_escaping/test.rs +++ b/templates/code/rust/tests/literal_escaping/test.rs @@ -1,4 +1,5 @@ use generated_semconv::demoattr::LiteralAttr; +use generated_semconv::options::InstrumentationOptions; use generated_semconv::{demometric::LiteralCountCounter, meter::Meter}; use opentelemetry::Value; use opentelemetry_sdk::metrics::{InMemoryMetricExporter, PeriodicReader, SdkMeterProvider}; @@ -20,7 +21,13 @@ fn signal_metadata_preserves_literal_backslash_sequences() { let provider = SdkMeterProvider::builder() .with_reader(PeriodicReader::builder(exporter.clone()).build()) .build(); - LiteralCountCounter::new(&Meter::new(&provider, "escaping")).add(1, LiteralAttr::Literal); + LiteralCountCounter::new(&Meter::new( + &provider, + InstrumentationOptions { + scope: "escaping".into(), + }, + )) + .add(1, LiteralAttr::Literal); provider.force_flush().unwrap(); let exported = exporter.get_finished_metrics().unwrap(); let scope = exported[0].scope_metrics().next().unwrap(); diff --git a/templates/code/rust/tests/metrics/expected/meter.rs b/templates/code/rust/tests/metrics/expected/meter.rs index 98512f3..3e2e018 100644 --- a/templates/code/rust/tests/metrics/expected/meter.rs +++ b/templates/code/rust/tests/metrics/expected/meter.rs @@ -1,15 +1,14 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let meter = provider.meter_with_scope(scope.into()); + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { + let meter = provider.meter_with_scope(options.scope.into()); Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/metrics/expected/mod.rs b/templates/code/rust/tests/metrics/expected/mod.rs index 24c9a92..f85e525 100644 --- a/templates/code/rust/tests/metrics/expected/mod.rs +++ b/templates/code/rust/tests/metrics/expected/mod.rs @@ -4,6 +4,7 @@ pub mod authattr; pub mod myappattr; pub mod scope; +pub mod options; pub mod meter; pub mod authmetric; pub mod myappmetric; diff --git a/templates/code/rust/tests/metrics/expected/options.rs b/templates/code/rust/tests/metrics/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/metrics/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/metrics/test.rs b/templates/code/rust/tests/metrics/test.rs index ad2140e..28c12ef 100644 --- a/templates/code/rust/tests/metrics/test.rs +++ b/templates/code/rust/tests/metrics/test.rs @@ -1,3 +1,4 @@ +use generated_semconv::options::InstrumentationOptions; use generated_semconv::{authattr, authmetric, meter, myappattr, myappmetric, scope, workermetric}; use opentelemetry::KeyValue; use opentelemetry_sdk::metrics::data::{AggregatedMetrics, MetricData}; @@ -22,10 +23,12 @@ fn synchronous_metrics_export_types_values_attributes_and_refinements() { let (provider, exporter) = provider(); let meter = meter::Meter::new( &provider, - scope::Scope { - name: "synthetic-worker".into(), - version: Some("1.2.3".into()), - attributes: vec![KeyValue::new("scope.kind", "worker")], + InstrumentationOptions { + scope: scope::Scope { + name: "synthetic-worker".into(), + version: Some("1.2.3".into()), + attributes: vec![KeyValue::new("scope.kind", "worker")], + }, }, ); myappmetric::TaskDurationHistogram::new(&meter).record( @@ -188,7 +191,12 @@ fn synchronous_metrics_export_types_values_attributes_and_refinements() { #[allow(deprecated)] fn observable_callbacks_export_values_and_typed_attributes() { let (provider, exporter) = provider(); - let meter = meter::Meter::new(&provider, "synthetic-observer"); + let meter = meter::Meter::new( + &provider, + InstrumentationOptions { + scope: "synthetic-observer".into(), + }, + ); let _started = myappmetric::TaskStartedObservableCounter::new(&meter, |observer| { observer.observe( 11, @@ -256,12 +264,22 @@ fn observable_callbacks_export_values_and_typed_attributes() { #[test] fn alternate_numeric_types_export_sync_and_observable_measurements() { let (provider, exporter) = provider(); - let sync_meter = meter::Meter::new(&provider, "synthetic-float-sync"); + let sync_meter = meter::Meter::new( + &provider, + InstrumentationOptions { + scope: "synthetic-float-sync".into(), + }, + ); myappmetric::TaskFloatStartedCounter::new(&sync_meter).add(0.5); myappmetric::TaskFloatActiveUpDownCounter::new(&sync_meter).add(-1.25); myappmetric::TaskFloatDepthGauge::new(&sync_meter).record(2.5); myappmetric::TaskPayloadHistogram::new(&sync_meter).record(512); - let async_meter = meter::Meter::new(&provider, "synthetic-float-async"); + let async_meter = meter::Meter::new( + &provider, + InstrumentationOptions { + scope: "synthetic-float-async".into(), + }, + ); let _started = myappmetric::TaskFloatStartedObservableCounter::new(&async_meter, |observer| { observer.observe(0.75); }); diff --git a/templates/code/rust/tests/naming/expected/meter.rs b/templates/code/rust/tests/naming/expected/meter.rs index 98512f3..3e2e018 100644 --- a/templates/code/rust/tests/naming/expected/meter.rs +++ b/templates/code/rust/tests/naming/expected/meter.rs @@ -1,15 +1,14 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let meter = provider.meter_with_scope(scope.into()); + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { + let meter = provider.meter_with_scope(options.scope.into()); Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/naming/expected/mod.rs b/templates/code/rust/tests/naming/expected/mod.rs index cdd6422..dc64fde 100644 --- a/templates/code/rust/tests/naming/expected/mod.rs +++ b/templates/code/rust/tests/naming/expected/mod.rs @@ -3,5 +3,6 @@ pub const SCHEMA_URL: &str = "https://example.com/schemas/naming/1.0.0"; pub mod capsattr; pub mod scope; +pub mod options; pub mod meter; pub mod capsmetric; diff --git a/templates/code/rust/tests/naming/expected/options.rs b/templates/code/rust/tests/naming/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/naming/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/no_namespace/expected/logger.rs b/templates/code/rust/tests/no_namespace/expected/logger.rs index 9455600..8235fca 100644 --- a/templates/code/rust/tests/no_namespace/expected/logger.rs +++ b/templates/code/rust/tests/no_namespace/expected/logger.rs @@ -1,4 +1,4 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; use opentelemetry::logs::AnyValue; use opentelemetry::{Array, Value}; @@ -6,15 +6,14 @@ use opentelemetry::{Array, Value}; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { - pub fn new>(provider: &P, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let logger = provider.logger_with_scope(scope.into()); + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let logger = provider.logger_with_scope(options.scope.into()); Self(logger) } pub fn inner(&self) -> &L { &self.0 } } impl Default for Logger { - fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { match value { diff --git a/templates/code/rust/tests/no_namespace/expected/mod.rs b/templates/code/rust/tests/no_namespace/expected/mod.rs index 224f6b3..fc6773d 100644 --- a/templates/code/rust/tests/no_namespace/expected/mod.rs +++ b/templates/code/rust/tests/no_namespace/expected/mod.rs @@ -5,6 +5,7 @@ pub mod heartbeatattr; pub mod hostattr; pub mod scope; +pub mod options; pub mod tracer; pub mod logger; pub mod exceptionevent; diff --git a/templates/code/rust/tests/no_namespace/expected/options.rs b/templates/code/rust/tests/no_namespace/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/no_namespace/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/no_namespace/expected/tracer.rs b/templates/code/rust/tests/no_namespace/expected/tracer.rs index 802f1e8..bde566c 100644 --- a/templates/code/rust/tests/no_namespace/expected/tracer.rs +++ b/templates/code/rust/tests/no_namespace/expected/tracer.rs @@ -1,14 +1,13 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; pub struct Tracer(T); impl Tracer { - pub fn new>(provider: &P, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let tracer = provider.tracer_with_scope(scope.into()); + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let tracer = provider.tracer_with_scope(options.scope.into()); Self(tracer) } pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { - fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/params/expected/meter.rs b/templates/code/rust/tests/params/expected/meter.rs index 98512f3..3e2e018 100644 --- a/templates/code/rust/tests/params/expected/meter.rs +++ b/templates/code/rust/tests/params/expected/meter.rs @@ -1,15 +1,14 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); impl Meter { - pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let meter = provider.meter_with_scope(scope.into()); + pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { + let meter = provider.meter_with_scope(options.scope.into()); Self(meter) } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } impl Default for Meter { - fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/params/expected/mod.rs b/templates/code/rust/tests/params/expected/mod.rs index 42d537f..c36f547 100644 --- a/templates/code/rust/tests/params/expected/mod.rs +++ b/templates/code/rust/tests/params/expected/mod.rs @@ -7,5 +7,6 @@ pub mod billingattr; pub mod myappattr; pub mod scope; +pub mod options; pub mod meter; pub mod billingmetric; diff --git a/templates/code/rust/tests/params/expected/options.rs b/templates/code/rust/tests/params/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/params/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/spans/expected/mod.rs b/templates/code/rust/tests/spans/expected/mod.rs index 0ae3799..2a8aae8 100644 --- a/templates/code/rust/tests/spans/expected/mod.rs +++ b/templates/code/rust/tests/spans/expected/mod.rs @@ -4,6 +4,7 @@ pub mod myappattr; pub mod workerattr; pub mod scope; +pub mod options; pub mod tracer; pub mod myappspan; pub mod workerspan; diff --git a/templates/code/rust/tests/spans/expected/options.rs b/templates/code/rust/tests/spans/expected/options.rs new file mode 100644 index 0000000..69a821a --- /dev/null +++ b/templates/code/rust/tests/spans/expected/options.rs @@ -0,0 +1,6 @@ +use super::scope::Scope; + +#[derive(Clone, Debug, Default)] +pub struct InstrumentationOptions { + pub scope: Scope, +} diff --git a/templates/code/rust/tests/spans/expected/tracer.rs b/templates/code/rust/tests/spans/expected/tracer.rs index 802f1e8..bde566c 100644 --- a/templates/code/rust/tests/spans/expected/tracer.rs +++ b/templates/code/rust/tests/spans/expected/tracer.rs @@ -1,14 +1,13 @@ -use super::scope::Scope; +use super::options::InstrumentationOptions; pub struct Tracer(T); impl Tracer { - pub fn new>(provider: &P, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let tracer = provider.tracer_with_scope(scope.into()); + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let tracer = provider.tracer_with_scope(options.scope.into()); Self(tracer) } pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { - fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/spans/test.rs b/templates/code/rust/tests/spans/test.rs index d682f66..52248de 100644 --- a/templates/code/rust/tests/spans/test.rs +++ b/templates/code/rust/tests/spans/test.rs @@ -10,10 +10,12 @@ fn derived_names_refinements_parent_context_and_late_attributes() { .build(); let tracer = tracer::Tracer::new( &provider, - generated_semconv::scope::Scope { - name: "worker".into(), - version: Some("1.2.3".into()), - attributes: vec![opentelemetry::KeyValue::new("scope.kind", "test")], + generated_semconv::options::InstrumentationOptions { + scope: generated_semconv::scope::Scope { + name: "worker".into(), + version: Some("1.2.3".into()), + attributes: vec![opentelemetry::KeyValue::new("scope.kind", "test")], + }, }, ); let _: &opentelemetry_sdk::trace::SdkTracer = tracer.inner(); diff --git a/templates/code/rust/tests/spans/tests/allocations.rs b/templates/code/rust/tests/spans/tests/allocations.rs index 5577886..5382537 100644 --- a/templates/code/rust/tests/spans/tests/allocations.rs +++ b/templates/code/rust/tests/spans/tests/allocations.rs @@ -37,7 +37,14 @@ fn allocations(operation: impl FnOnce() -> T) -> (T, usize) { } #[test] fn static_scope_constructor_has_no_generated_heap_allocations() { - let (_, count) = allocations(|| tracer::Tracer::new(&NoopTracerProvider::new(), "worker")); + let (_, count) = allocations(|| { + tracer::Tracer::new( + &NoopTracerProvider::new(), + generated_semconv::options::InstrumentationOptions { + scope: "worker".into(), + }, + ) + }); assert_eq!(count, 0); } #[test] @@ -109,6 +116,11 @@ fn configured_scope_moves_existing_metadata_without_cloning() { version: Some("1.0.0".into()), attributes: vec![opentelemetry::KeyValue::new("scope.kind", "worker")], }; - let (_, count) = allocations(|| tracer::Tracer::new(&NoopTracerProvider::new(), scope)); + let (_, count) = allocations(|| { + tracer::Tracer::new( + &NoopTracerProvider::new(), + generated_semconv::options::InstrumentationOptions { scope }, + ) + }); assert_eq!(count, 0); } diff --git a/templates/code/rust/tracer.rs.j2 b/templates/code/rust/tracer.rs.j2 index c684168..9062a76 100644 --- a/templates/code/rust/tracer.rs.j2 +++ b/templates/code/rust/tracer.rs.j2 @@ -1,17 +1,16 @@ {%- filter trim %} -use super::scope::Scope; +use super::options::InstrumentationOptions; pub struct Tracer(T); impl Tracer { - pub fn new>(provider: &P, scope: impl Into) -> Self { - let scope: Scope = scope.into(); - let tracer = provider.tracer_with_scope(scope.into()); + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let tracer = provider.tracer_with_scope(options.scope.into()); Self(tracer) } pub fn inner(&self) -> &T { &self.0 } } impl Default for Tracer { - fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), Scope::default()) } + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), InstrumentationOptions::default()) } } {% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/weaver.yaml b/templates/code/rust/weaver.yaml index 240f8f9..20d461f 100644 --- a/templates/code/rust/weaver.yaml +++ b/templates/code/rust/weaver.yaml @@ -586,7 +586,7 @@ templates: file_name: "{{ ctx.namespace }}entity.rs" - template: scope.rs.j2 - filter: |- + filter: &instrumentation_filter |- {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $o | if ((semconv_grouped_metrics($o) | map(.metrics) | add // [] | length) > 0 or (.registry.spans // [] | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) | length) > 0 @@ -595,6 +595,11 @@ templates: application_mode: each file_name: scope.rs + - template: options.rs.j2 + filter: *instrumentation_filter + application_mode: each + file_name: options.rs + - template: meter.rs.j2 filter: |- {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $o From 7eb29fe10adb7158ad7f7efcdc22638c8f7a6f84 Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Mon, 5 Oct 2026 14:21:51 -0400 Subject: [PATCH 11/14] fix: prevent instrumentation identity drift Signed-off-by: Yordis Prieto --- templates/code/rust/README.md | 19 +++-- templates/code/rust/scope.rs.j2 | 22 +---- .../scope_name.expected-error.txt | 1 + .../allocations/compile-fail/scope_name.rs | 10 +++ .../scope_schema.expected-error.txt | 1 + .../allocations/compile-fail/scope_schema.rs | 10 +++ .../scope_version.expected-error.txt | 1 + .../allocations/compile-fail/scope_version.rs | 10 +++ .../compile-fail/sdk_scope.expected-error.txt | 1 + .../allocations/compile-fail/sdk_scope.rs | 9 +++ .../rust/tests/allocations/expected/scope.rs | 22 +---- templates/code/rust/tests/allocations/test.rs | 80 +++++-------------- .../event_no_attributes/expected/scope.rs | 22 +---- .../rust/tests/event_no_attributes/test.rs | 9 +-- .../code/rust/tests/events/expected/scope.rs | 22 +---- templates/code/rust/tests/events/test.rs | 13 +-- .../expected/scope.rs | 22 +---- .../expected/scope.rs | 22 +---- .../rust/tests/imported/expected/scope.rs | 22 +---- templates/code/rust/tests/imported/test.rs | 13 +-- .../tests/imported_typed/expected/scope.rs | 22 +---- .../tests/literal_escaping/expected/scope.rs | 22 +---- .../code/rust/tests/literal_escaping/test.rs | 15 ++-- .../code/rust/tests/metrics/expected/scope.rs | 22 +---- templates/code/rust/tests/metrics/test.rs | 41 +++++----- .../code/rust/tests/naming/expected/scope.rs | 22 +---- .../rust/tests/no_namespace/expected/scope.rs | 22 +---- .../code/rust/tests/params/expected/scope.rs | 22 +---- .../code/rust/tests/spans/expected/scope.rs | 22 +---- templates/code/rust/tests/spans/test.rs | 6 +- .../rust/tests/spans/tests/allocations.rs | 10 +-- 31 files changed, 180 insertions(+), 377 deletions(-) create mode 100644 templates/code/rust/tests/allocations/compile-fail/scope_name.expected-error.txt create mode 100644 templates/code/rust/tests/allocations/compile-fail/scope_name.rs create mode 100644 templates/code/rust/tests/allocations/compile-fail/scope_schema.expected-error.txt create mode 100644 templates/code/rust/tests/allocations/compile-fail/scope_schema.rs create mode 100644 templates/code/rust/tests/allocations/compile-fail/scope_version.expected-error.txt create mode 100644 templates/code/rust/tests/allocations/compile-fail/scope_version.rs create mode 100644 templates/code/rust/tests/allocations/compile-fail/sdk_scope.expected-error.txt create mode 100644 templates/code/rust/tests/allocations/compile-fail/sdk_scope.rs diff --git a/templates/code/rust/README.md b/templates/code/rust/README.md index ddbbd8b..47dd9fd 100644 --- a/templates/code/rust/README.md +++ b/templates/code/rust/README.md @@ -46,7 +46,7 @@ before choosing that namespace. | ------------------- | ----------------------------------------------------------------------------------------- | | `attr` | Attribute newtypes and enum variants, `KEY` and conversion into `KeyValue`. | | `options` | Typed instrumentation options containing scope configuration. | -| `scope` | Shared scope name, version, and attributes configuration. | +| `scope` | Scope attributes configuration; package identity is fixed. | | `meter` | Schema-aware `Meter`, with `new`, `inner`, and a no-op `Default`. | | `tracer` | Schema-aware `Tracer`, with `new`, `inner`, and a no-op `Default`. | | `logger` | Schema-aware generic `Logger`, with `new`, `inner`, and a no-op `Default`. | @@ -62,19 +62,22 @@ signals. Their `new(provider, options)` constructor takes the exact ```rust let options = semconv::options::InstrumentationOptions { scope: semconv::scope::Scope { - name: "worker".into(), - version: Some("1.0.0".into()), attributes: vec![opentelemetry::KeyValue::new("scope.kind", "worker")], }, }; let tracer = semconv::tracer::Tracer::new(&provider, options); ``` -Use `InstrumentationOptions::default()` for default metadata. `Scope` accepts -static strings, owned `String`, or `Cow<'static, str>` through `From` when only a -name is needed. Scope values move into OpenTelemetry without rebuilding their -metadata. The registry schema URL is always applied; it is not a configuration -field. The shared scope and options modules are emitted when a handle is needed. +Use `InstrumentationOptions::default()` when no scope attributes are needed. +The instrumentation name and version come from the containing Cargo package's +`CARGO_PKG_NAME` and `CARGO_PKG_VERSION` at compile time. If generated code lives +in a library crate, that library supplies the identity; if it lives in the +application crate, the application supplies it. The registry schema URL is also +fixed. These values are not configuration fields. + +Configured scope attributes move into OpenTelemetry without rebuilding their +storage. The shared scope and options modules are emitted when a handle is +needed. Attribute keys, metric names, and event names retain their full registry names. ### Typed attributes diff --git a/templates/code/rust/scope.rs.j2 b/templates/code/rust/scope.rs.j2 index 00d502b..c00189f 100644 --- a/templates/code/rust/scope.rs.j2 +++ b/templates/code/rust/scope.rs.j2 @@ -1,29 +1,15 @@ {%- filter trim %} -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } {% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/tests/allocations/compile-fail/scope_name.expected-error.txt b/templates/code/rust/tests/allocations/compile-fail/scope_name.expected-error.txt new file mode 100644 index 0000000..9108842 --- /dev/null +++ b/templates/code/rust/tests/allocations/compile-fail/scope_name.expected-error.txt @@ -0,0 +1 @@ +has no field named `name` diff --git a/templates/code/rust/tests/allocations/compile-fail/scope_name.rs b/templates/code/rust/tests/allocations/compile-fail/scope_name.rs new file mode 100644 index 0000000..7179456 --- /dev/null +++ b/templates/code/rust/tests/allocations/compile-fail/scope_name.rs @@ -0,0 +1,10 @@ +use generated_semconv::{options::InstrumentationOptions, scope::Scope}; + +fn main() { + let _ = InstrumentationOptions { + scope: Scope { + name: "caller-identity".into(), + ..Scope::default() + }, + }; +} diff --git a/templates/code/rust/tests/allocations/compile-fail/scope_schema.expected-error.txt b/templates/code/rust/tests/allocations/compile-fail/scope_schema.expected-error.txt new file mode 100644 index 0000000..fd96262 --- /dev/null +++ b/templates/code/rust/tests/allocations/compile-fail/scope_schema.expected-error.txt @@ -0,0 +1 @@ +has no field named `schema_url` diff --git a/templates/code/rust/tests/allocations/compile-fail/scope_schema.rs b/templates/code/rust/tests/allocations/compile-fail/scope_schema.rs new file mode 100644 index 0000000..0bc8d56 --- /dev/null +++ b/templates/code/rust/tests/allocations/compile-fail/scope_schema.rs @@ -0,0 +1,10 @@ +use generated_semconv::{options::InstrumentationOptions, scope::Scope}; + +fn main() { + let _ = InstrumentationOptions { + scope: Scope { + schema_url: Some("https://example.com/caller/1.0.0".into()), + ..Scope::default() + }, + }; +} diff --git a/templates/code/rust/tests/allocations/compile-fail/scope_version.expected-error.txt b/templates/code/rust/tests/allocations/compile-fail/scope_version.expected-error.txt new file mode 100644 index 0000000..d66263f --- /dev/null +++ b/templates/code/rust/tests/allocations/compile-fail/scope_version.expected-error.txt @@ -0,0 +1 @@ +has no field named `version` diff --git a/templates/code/rust/tests/allocations/compile-fail/scope_version.rs b/templates/code/rust/tests/allocations/compile-fail/scope_version.rs new file mode 100644 index 0000000..379b683 --- /dev/null +++ b/templates/code/rust/tests/allocations/compile-fail/scope_version.rs @@ -0,0 +1,10 @@ +use generated_semconv::{options::InstrumentationOptions, scope::Scope}; + +fn main() { + let _ = InstrumentationOptions { + scope: Scope { + version: Some("1.2.3".into()), + ..Scope::default() + }, + }; +} diff --git a/templates/code/rust/tests/allocations/compile-fail/sdk_scope.expected-error.txt b/templates/code/rust/tests/allocations/compile-fail/sdk_scope.expected-error.txt new file mode 100644 index 0000000..545f57b --- /dev/null +++ b/templates/code/rust/tests/allocations/compile-fail/sdk_scope.expected-error.txt @@ -0,0 +1 @@ +expected `Scope`, found `InstrumentationScope` diff --git a/templates/code/rust/tests/allocations/compile-fail/sdk_scope.rs b/templates/code/rust/tests/allocations/compile-fail/sdk_scope.rs new file mode 100644 index 0000000..925bfe1 --- /dev/null +++ b/templates/code/rust/tests/allocations/compile-fail/sdk_scope.rs @@ -0,0 +1,9 @@ +use generated_semconv::options::InstrumentationOptions; + +fn main() { + let _ = InstrumentationOptions { + scope: opentelemetry::InstrumentationScope::builder("caller-identity") + .with_version("1.2.3") + .build(), + }; +} diff --git a/templates/code/rust/tests/allocations/expected/scope.rs b/templates/code/rust/tests/allocations/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/allocations/expected/scope.rs +++ b/templates/code/rust/tests/allocations/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/allocations/test.rs b/templates/code/rust/tests/allocations/test.rs index 0399e3c..7470f16 100644 --- a/templates/code/rust/tests/allocations/test.rs +++ b/templates/code/rust/tests/allocations/test.rs @@ -224,9 +224,7 @@ fn metrics_use_no_generated_heap_for_required_or_typical_optional_attributes() { let state = Arc::new(MetricState::default()); let meter = meter::Meter::new( &MetricProvider(state.clone()), - InstrumentationOptions { - scope: "allocation-test".into(), - }, + InstrumentationOptions::default(), ); let required = probemetric::RequiredCounter::new(&meter); let optional = probemetric::OptionalCounter::new(&meter); @@ -272,12 +270,7 @@ fn metrics_use_no_generated_heap_for_required_or_typical_optional_attributes() { fn observable_measurements_use_stack_attribute_storage() { let state = Arc::new(MetricState::default()); let provider = MetricProvider(state.clone()); - let meter = meter::Meter::new( - &provider, - InstrumentationOptions { - scope: "allocation-test".into(), - }, - ); + let meter = meter::Meter::new(&provider, InstrumentationOptions::default()); let _required = probemetric::RequiredObservableCounter::new(&meter, |observer| { observer.observe(1, probeattr::RequiredAttr::from(3)); }); @@ -303,7 +296,7 @@ fn observable_measurements_use_stack_attribute_storage() { } #[test] -fn static_meter_and_logger_scope_names_remain_borrowed() { +fn fixed_scope_identity_uses_no_generated_heap() { let metric_provider = BorrowedMeterProvider { meter: Meter::new(Arc::new(MetricProvider(Arc::new(MetricState::default())))), scope: Mutex::new(None), @@ -312,9 +305,7 @@ fn static_meter_and_logger_scope_names_remain_borrowed() { let metric_count = allocations(|| { black_box(meter::Meter::new( &metric_provider, - InstrumentationOptions { - scope: "allocation-test".into(), - }, + InstrumentationOptions::default(), )); }); let log_provider = LogProvider(Arc::new(LogState::default())); @@ -322,9 +313,7 @@ fn static_meter_and_logger_scope_names_remain_borrowed() { let log_count = allocations(|| { black_box(logger::Logger::new( &log_provider, - InstrumentationOptions { - scope: "allocation-test".into(), - }, + InstrumentationOptions::default(), )); }); assert_eq!(metric_count, 0); @@ -333,7 +322,7 @@ fn static_meter_and_logger_scope_names_remain_borrowed() { } #[test] -fn configured_scopes_move_metadata_without_rebuilding_storage() { +fn scope_attributes_move_without_rebuilding_storage() { let metric_provider = BorrowedMeterProvider { meter: Meter::new(Arc::new(MetricProvider(Arc::new(MetricState::default())))), scope: Mutex::new(None), @@ -342,21 +331,12 @@ fn configured_scopes_move_metadata_without_rebuilding_storage() { drop(metric_provider.scope.lock().unwrap()); drop(log_provider.0.scope.lock().unwrap()); let scope = || scope::Scope { - name: String::from("allocation-test").into(), - version: Some(String::from("1.2.3").into()), attributes: vec![KeyValue::new("scope.identity", 7_i64)], }; let metric_scope = scope(); let log_scope = scope(); - let original = |scope: &scope::Scope| { - ( - scope.name.as_ptr(), - scope.version.as_ref().unwrap().as_ptr(), - scope.attributes.as_ptr(), - ) - }; - let original_metric = original(&metric_scope); - let original_log = original(&log_scope); + let original_metric = metric_scope.attributes.as_ptr(); + let original_log = log_scope.attributes.as_ptr(); let metric_count = allocations(|| { black_box(meter::Meter::new( &metric_provider, @@ -378,14 +358,12 @@ fn configured_scopes_move_metadata_without_rebuilding_storage() { (log_provider.0.scope.lock().unwrap(), original_log), ] { let scope = stored.as_ref().unwrap(); - assert_eq!(scope.name(), "allocation-test"); - assert_eq!(scope.version(), Some("1.2.3")); + assert_eq!(scope.name(), "generated_semconv"); + assert_eq!(scope.version(), Some("0.0.0")); assert_eq!(scope.schema_url(), Some(generated_semconv::SCHEMA_URL)); - assert_eq!(scope.name().as_ptr(), original.0); - assert_eq!(scope.version().unwrap().as_ptr(), original.1); assert_eq!( scope.attributes().next().unwrap() as *const KeyValue, - original.2 + original ); assert_eq!( scope.attributes().collect::>(), @@ -396,30 +374,18 @@ fn configured_scopes_move_metadata_without_rebuilding_storage() { } #[test] -fn scope_convenience_inputs_are_nested_in_instrumentation_options() { +fn default_options_apply_fixed_package_identity() { let metric_provider = BorrowedMeterProvider { meter: Meter::new(Arc::new(MetricProvider(Arc::new(MetricState::default())))), scope: Mutex::new(None), }; - for options in [ - scope::Scope::from("static"), - scope::Scope::from(String::from("owned")), - scope::Scope::from(Cow::Borrowed("cow-borrowed")), - scope::Scope::from(Cow::Owned(String::from("cow-owned"))), - ] - .into_iter() - .map(|scope| InstrumentationOptions { scope }) - .chain(std::iter::once(InstrumentationOptions::default())) - { - let name = options.scope.name.clone(); - let _meter = meter::Meter::new(&metric_provider, options); - let stored = metric_provider.scope.lock().unwrap(); - let stored = stored.as_ref().unwrap(); - assert_eq!(stored.name(), name); - assert_eq!(stored.version(), None); - assert_eq!(stored.attributes().count(), 0); - assert_eq!(stored.schema_url(), Some(generated_semconv::SCHEMA_URL)); - } + let _meter = meter::Meter::new(&metric_provider, InstrumentationOptions::default()); + let stored = metric_provider.scope.lock().unwrap(); + let stored = stored.as_ref().unwrap(); + assert_eq!(stored.name(), "generated_semconv"); + assert_eq!(stored.version(), Some("0.0.0")); + assert_eq!(stored.attributes().count(), 0); + assert_eq!(stored.schema_url(), Some(generated_semconv::SCHEMA_URL)); } #[test] @@ -428,9 +394,7 @@ fn enabled_events_use_no_generated_heap_and_preserve_duplicate_attributes() { state.enabled.store(true, Ordering::Relaxed); let logger = logger::Logger::new( &LogProvider(state.clone()), - InstrumentationOptions { - scope: "allocation-test".into(), - }, + InstrumentationOptions::default(), ); let context = Context::new(); probeevent::emit_recorded(&context, &logger, probeattr::RequiredAttr::from(3), []); @@ -490,9 +454,7 @@ fn disabled_events_defer_context_attachment_and_attribute_conversion() { let state = Arc::new(LogState::default()); let logger = logger::Logger::new( &LogProvider(state.clone()), - InstrumentationOptions { - scope: "allocation-test".into(), - }, + InstrumentationOptions::default(), ); let context = Context::new().with_value(ExplicitContext); let values = probeattr::ValuesAttr::from(vec![1, 2, 3]); diff --git a/templates/code/rust/tests/event_no_attributes/expected/scope.rs b/templates/code/rust/tests/event_no_attributes/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/event_no_attributes/expected/scope.rs +++ b/templates/code/rust/tests/event_no_attributes/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/event_no_attributes/test.rs b/templates/code/rust/tests/event_no_attributes/test.rs index 3e5255f..16ecfcf 100644 --- a/templates/code/rust/tests/event_no_attributes/test.rs +++ b/templates/code/rust/tests/event_no_attributes/test.rs @@ -9,12 +9,7 @@ fn events_without_attributes_export_cleanly() { let provider = SdkLoggerProvider::builder() .with_simple_exporter(exporter.clone()) .build(); - let logger = logger::Logger::new( - &provider, - InstrumentationOptions { - scope: "synthetic-clock".into(), - }, - ); + let logger = logger::Logger::new(&provider, InstrumentationOptions::default()); probeevent::emit_tick( &opentelemetry::Context::new(), &logger, @@ -23,6 +18,8 @@ fn events_without_attributes_export_cleanly() { provider.force_flush().unwrap(); let records = exporter.get_emitted_logs().unwrap(); assert_eq!(records.len(), 1); + assert_eq!(records[0].instrumentation.name(), "generated_semconv"); + assert_eq!(records[0].instrumentation.version(), Some("0.0.0")); assert_eq!(records[0].record.event_name(), Some("probe.tick")); assert_eq!(records[0].record.severity_number(), Some(Severity::Debug)); assert_eq!(records[0].record.attributes_iter().count(), 0); diff --git a/templates/code/rust/tests/events/expected/scope.rs b/templates/code/rust/tests/events/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/events/expected/scope.rs +++ b/templates/code/rust/tests/events/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/events/test.rs b/templates/code/rust/tests/events/test.rs index 02a3fa0..a7f7f72 100644 --- a/templates/code/rust/tests/events/test.rs +++ b/templates/code/rust/tests/events/test.rs @@ -16,8 +16,6 @@ fn typed_events_have_schema_timestamps_severity_attributes_and_trace_context() { &provider, InstrumentationOptions { scope: scope::Scope { - name: "worker".into(), - version: Some("1.2.3".into()), attributes: vec![opentelemetry::KeyValue::new("scope.kind", "test")], }, }, @@ -67,8 +65,8 @@ fn typed_events_have_schema_timestamps_severity_attributes_and_trace_context() { assert!(log.record.observed_timestamp().is_some()); assert!(log.record.body().is_none()); assert_eq!(log.instrumentation.schema_url(), Some(SCHEMA_URL)); - assert_eq!(log.instrumentation.name(), "worker"); - assert_eq!(log.instrumentation.version(), Some("1.2.3")); + assert_eq!(log.instrumentation.name(), "generated_semconv"); + assert_eq!(log.instrumentation.version(), Some("0.0.0")); assert!(log .instrumentation .attributes() @@ -132,12 +130,7 @@ impl opentelemetry::logs::Logger for DisabledLogger { fn disabled_events_are_checked_before_record_creation() { myappevent::emit_task_finished( &opentelemetry::Context::new(), - &logger::Logger::new( - &DisabledProvider, - InstrumentationOptions { - scope: "test".into(), - }, - ), + &logger::Logger::new(&DisabledProvider, InstrumentationOptions::default()), myappattr::TaskStateAttr::Done, [myappevent::TaskFinishedOption::Severity(Severity::Error)], ); diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/imported/expected/scope.rs b/templates/code/rust/tests/imported/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/imported/expected/scope.rs +++ b/templates/code/rust/tests/imported/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/imported/test.rs b/templates/code/rust/tests/imported/test.rs index 7844080..61e7fb8 100644 --- a/templates/code/rust/tests/imported/test.rs +++ b/templates/code/rust/tests/imported/test.rs @@ -51,12 +51,7 @@ fn imported_native_string_arrays_format_derived_span_names() { let provider = opentelemetry_sdk::trace::SdkTracerProvider::builder() .with_simple_exporter(exporter.clone()) .build(); - let tracer = tracer::Tracer::new( - &provider, - InstrumentationOptions { - scope: "synthetic-upstream".into(), - }, - ); + let tracer = tracer::Tracer::new(&provider, InstrumentationOptions::default()); let mut span = edgespan::start_upstream_methods( &opentelemetry::Context::new(), &tracer, @@ -66,5 +61,11 @@ fn imported_native_string_arrays_format_derived_span_names() { provider.force_flush().unwrap(); let spans = exporter.get_finished_spans().unwrap(); assert_eq!(spans.len(), 1); + assert_eq!(spans[0].instrumentation_scope.name(), "generated_semconv"); + assert_eq!(spans[0].instrumentation_scope.version(), Some("0.0.0")); + assert_eq!( + spans[0].instrumentation_scope.schema_url(), + Some(generated_semconv::SCHEMA_URL) + ); assert_eq!(spans[0].name, "[\"GET\",\"POST\"]"); } diff --git a/templates/code/rust/tests/imported_typed/expected/scope.rs b/templates/code/rust/tests/imported_typed/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/imported_typed/expected/scope.rs +++ b/templates/code/rust/tests/imported_typed/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/literal_escaping/expected/scope.rs b/templates/code/rust/tests/literal_escaping/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/literal_escaping/expected/scope.rs +++ b/templates/code/rust/tests/literal_escaping/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/literal_escaping/test.rs b/templates/code/rust/tests/literal_escaping/test.rs index 11e8c0a..478b469 100644 --- a/templates/code/rust/tests/literal_escaping/test.rs +++ b/templates/code/rust/tests/literal_escaping/test.rs @@ -21,16 +21,17 @@ fn signal_metadata_preserves_literal_backslash_sequences() { let provider = SdkMeterProvider::builder() .with_reader(PeriodicReader::builder(exporter.clone()).build()) .build(); - LiteralCountCounter::new(&Meter::new( - &provider, - InstrumentationOptions { - scope: "escaping".into(), - }, - )) - .add(1, LiteralAttr::Literal); + LiteralCountCounter::new(&Meter::new(&provider, InstrumentationOptions::default())) + .add(1, LiteralAttr::Literal); provider.force_flush().unwrap(); let exported = exporter.get_finished_metrics().unwrap(); let scope = exported[0].scope_metrics().next().unwrap(); + assert_eq!(scope.scope().name(), "generated_semconv"); + assert_eq!(scope.scope().version(), Some("0.0.0")); + assert_eq!( + scope.scope().schema_url(), + Some(generated_semconv::SCHEMA_URL) + ); let metric = scope.metrics().next().unwrap(); assert_eq!(metric.description(), r"literal \b \f \u1234"); assert_eq!(metric.unit(), r"literal\b\u1234"); diff --git a/templates/code/rust/tests/metrics/expected/scope.rs b/templates/code/rust/tests/metrics/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/metrics/expected/scope.rs +++ b/templates/code/rust/tests/metrics/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/metrics/test.rs b/templates/code/rust/tests/metrics/test.rs index 28c12ef..440770d 100644 --- a/templates/code/rust/tests/metrics/test.rs +++ b/templates/code/rust/tests/metrics/test.rs @@ -25,8 +25,6 @@ fn synchronous_metrics_export_types_values_attributes_and_refinements() { &provider, InstrumentationOptions { scope: scope::Scope { - name: "synthetic-worker".into(), - version: Some("1.2.3".into()), attributes: vec![KeyValue::new("scope.kind", "worker")], }, }, @@ -69,13 +67,13 @@ fn synchronous_metrics_export_types_values_attributes_and_refinements() { provider.force_flush().unwrap(); let exported = exporter.get_finished_metrics().unwrap(); let scope = exported[0].scope_metrics().next().unwrap(); - assert_eq!(scope.scope().version(), Some("1.2.3")); + assert_eq!(scope.scope().version(), Some("0.0.0")); assert!(scope .scope() .attributes() .any(|attribute| attribute.key.as_str() == "scope.kind" && attribute.value.as_str() == "worker")); - assert_eq!(scope.scope().name(), "synthetic-worker"); + assert_eq!(scope.scope().name(), "generated_semconv"); assert_eq!( scope.scope().schema_url(), Some(generated_semconv::SCHEMA_URL) @@ -191,12 +189,7 @@ fn synchronous_metrics_export_types_values_attributes_and_refinements() { #[allow(deprecated)] fn observable_callbacks_export_values_and_typed_attributes() { let (provider, exporter) = provider(); - let meter = meter::Meter::new( - &provider, - InstrumentationOptions { - scope: "synthetic-observer".into(), - }, - ); + let meter = meter::Meter::new(&provider, InstrumentationOptions::default()); let _started = myappmetric::TaskStartedObservableCounter::new(&meter, |observer| { observer.observe( 11, @@ -221,6 +214,8 @@ fn observable_callbacks_export_values_and_typed_attributes() { provider.force_flush().unwrap(); let exported = exporter.get_finished_metrics().unwrap(); let scope = exported[0].scope_metrics().next().unwrap(); + assert_eq!(scope.scope().name(), "generated_semconv"); + assert_eq!(scope.scope().version(), Some("0.0.0")); assert_eq!( scope.scope().schema_url(), Some(generated_semconv::SCHEMA_URL) @@ -267,7 +262,9 @@ fn alternate_numeric_types_export_sync_and_observable_measurements() { let sync_meter = meter::Meter::new( &provider, InstrumentationOptions { - scope: "synthetic-float-sync".into(), + scope: scope::Scope { + attributes: vec![KeyValue::new("measurement.mode", "sync")], + }, }, ); myappmetric::TaskFloatStartedCounter::new(&sync_meter).add(0.5); @@ -277,7 +274,9 @@ fn alternate_numeric_types_export_sync_and_observable_measurements() { let async_meter = meter::Meter::new( &provider, InstrumentationOptions { - scope: "synthetic-float-async".into(), + scope: scope::Scope { + attributes: vec![KeyValue::new("measurement.mode", "async")], + }, }, ); let _started = myappmetric::TaskFloatStartedObservableCounter::new(&async_meter, |observer| { @@ -292,14 +291,20 @@ fn alternate_numeric_types_export_sync_and_observable_measurements() { }); provider.force_flush().unwrap(); let exported = exporter.get_finished_metrics().unwrap(); - for (name, started_value, active_value, depth_value) in [ - ("synthetic-float-sync", 0.5, -1.25, 2.5), - ("synthetic-float-async", 0.75, -2.5, 3.75), - ] { + for (mode, started_value, active_value, depth_value) in + [("sync", 0.5, -1.25, 2.5), ("async", 0.75, -2.5, 3.75)] + { let scope = exported[0] .scope_metrics() - .find(|scope| scope.scope().name() == name) + .find(|scope| { + scope + .scope() + .attributes() + .any(|attribute| attribute == &KeyValue::new("measurement.mode", mode)) + }) .unwrap(); + assert_eq!(scope.scope().name(), "generated_semconv"); + assert_eq!(scope.scope().version(), Some("0.0.0")); assert_eq!( scope.scope().schema_url(), Some(generated_semconv::SCHEMA_URL) @@ -328,7 +333,7 @@ fn alternate_numeric_types_export_sync_and_observable_measurements() { panic!("double gauge must export a floating gauge"); }; assert_eq!(depth.data_points().next().unwrap().value(), depth_value); - if name == "synthetic-float-sync" { + if mode == "sync" { let payload = find("myapp.task.payload"); assert_eq!(payload.unit(), "By"); let AggregatedMetrics::U64(MetricData::Histogram(histogram)) = payload.data() else { diff --git a/templates/code/rust/tests/naming/expected/scope.rs b/templates/code/rust/tests/naming/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/naming/expected/scope.rs +++ b/templates/code/rust/tests/naming/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/no_namespace/expected/scope.rs b/templates/code/rust/tests/no_namespace/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/no_namespace/expected/scope.rs +++ b/templates/code/rust/tests/no_namespace/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/params/expected/scope.rs b/templates/code/rust/tests/params/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/params/expected/scope.rs +++ b/templates/code/rust/tests/params/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/spans/expected/scope.rs b/templates/code/rust/tests/spans/expected/scope.rs index d73be75..9ed8538 100644 --- a/templates/code/rust/tests/spans/expected/scope.rs +++ b/templates/code/rust/tests/spans/expected/scope.rs @@ -1,27 +1,13 @@ -use ::std::borrow::Cow; - #[derive(Clone, Debug, Default)] pub struct Scope { - pub name: Cow<'static, str>, - pub version: Option>, pub attributes: Vec<::opentelemetry::KeyValue>, } -impl From<&'static str> for Scope { - fn from(name: &'static str) -> Self { Self { name: Cow::Borrowed(name), ..Self::default() } } -} -impl From for Scope { - fn from(name: String) -> Self { Self { name: Cow::Owned(name), ..Self::default() } } -} -impl From> for Scope { - fn from(name: Cow<'static, str>) -> Self { Self { name, ..Self::default() } } -} impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - let Scope { name, version, attributes } = value; - let mut builder = Self::builder(name) + Self::builder(env!("CARGO_PKG_NAME")) + .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(super::SCHEMA_URL) - .with_attributes(attributes); - if let Some(version) = version { builder = builder.with_version(version); } - builder.build() + .with_attributes(value.attributes) + .build() } } diff --git a/templates/code/rust/tests/spans/test.rs b/templates/code/rust/tests/spans/test.rs index 52248de..4f9f491 100644 --- a/templates/code/rust/tests/spans/test.rs +++ b/templates/code/rust/tests/spans/test.rs @@ -12,8 +12,6 @@ fn derived_names_refinements_parent_context_and_late_attributes() { &provider, generated_semconv::options::InstrumentationOptions { scope: generated_semconv::scope::Scope { - name: "worker".into(), - version: Some("1.2.3".into()), attributes: vec![opentelemetry::KeyValue::new("scope.kind", "test")], }, }, @@ -127,8 +125,8 @@ fn derived_names_refinements_parent_context_and_late_attributes() { .iter() .any(|kv| kv.key.as_str() == "myapp.task.id" && kv.value.as_str() == "task-1")); assert_eq!(parent.instrumentation_scope.schema_url(), Some(SCHEMA_URL)); - assert_eq!(parent.instrumentation_scope.name(), "worker"); - assert_eq!(parent.instrumentation_scope.version(), Some("1.2.3")); + assert_eq!(parent.instrumentation_scope.name(), "generated_semconv"); + assert_eq!(parent.instrumentation_scope.version(), Some("0.0.0")); assert!(parent .instrumentation_scope .attributes() diff --git a/templates/code/rust/tests/spans/tests/allocations.rs b/templates/code/rust/tests/spans/tests/allocations.rs index 5382537..6c3b775 100644 --- a/templates/code/rust/tests/spans/tests/allocations.rs +++ b/templates/code/rust/tests/spans/tests/allocations.rs @@ -36,13 +36,11 @@ fn allocations(operation: impl FnOnce() -> T) -> (T, usize) { (value, count) } #[test] -fn static_scope_constructor_has_no_generated_heap_allocations() { +fn fixed_scope_identity_has_no_generated_heap_allocations() { let (_, count) = allocations(|| { tracer::Tracer::new( &NoopTracerProvider::new(), - generated_semconv::options::InstrumentationOptions { - scope: "worker".into(), - }, + generated_semconv::options::InstrumentationOptions::default(), ) }); assert_eq!(count, 0); @@ -110,10 +108,8 @@ fn untemplated_names_move_or_borrow_without_heap_allocations() { } #[test] -fn configured_scope_moves_existing_metadata_without_cloning() { +fn scope_attributes_move_without_cloning() { let scope = generated_semconv::scope::Scope { - name: "worker".into(), - version: Some("1.0.0".into()), attributes: vec![opentelemetry::KeyValue::new("scope.kind", "worker")], }; let (_, count) = allocations(|| { From ad75aaf48985afc0e0615e78f08b96639d76927c Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Mon, 5 Oct 2026 14:55:05 -0400 Subject: [PATCH 12/14] refactor: keep generated telemetry contracts explicit Signed-off-by: Yordis Prieto --- templates/code/rust/README.md | 40 +++-- templates/code/rust/attributes.rs.j2 | 21 +++ templates/code/rust/events.rs.j2 | 10 +- templates/code/rust/logger.rs.j2 | 24 --- templates/code/rust/scope.rs.j2 | 7 +- templates/code/rust/signal_helpers.j2 | 3 + .../rust/tests/allocations/expected/logger.rs | 19 -- .../tests/allocations/expected/probeattr.rs | 167 ++++++++++++++++++ .../tests/allocations/expected/probeevent.rs | 12 +- .../rust/tests/allocations/expected/scope.rs | 3 +- .../tests/allocations/registry/model.yaml | 15 ++ templates/code/rust/tests/allocations/test.rs | 24 ++- .../tests/attributes/expected/authattr.rs | 32 ++++ .../tests/attributes/expected/myappattr.rs | 140 +++++++++++++++ .../rust/tests/attributes/tests/log_values.rs | 88 +++++++++ .../codegen_exclusion/expected/demoattr.rs | 19 ++ .../rust/tests/entities/expected/myappattr.rs | 52 ++++++ .../expected-error.txt | 1 + .../params.yaml | 2 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 5 + .../expected-error.txt | 1 + .../params.yaml | 2 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 5 + .../expected-error.txt | 1 + .../params.yaml | 2 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 5 + .../event_no_attributes/expected/scope.rs | 3 +- .../rust/tests/event_no_attributes/test.rs | 4 +- .../code/rust/tests/events/expected/logger.rs | 19 -- .../rust/tests/events/expected/myappattr.rs | 52 ++++++ .../rust/tests/events/expected/myappevent.rs | 23 ++- .../code/rust/tests/events/expected/scope.rs | 3 +- .../rust/tests/events/expected/workerattr.rs | 8 + .../rust/tests/events/expected/workerevent.rs | 21 +-- templates/code/rust/tests/events/test.rs | 4 +- .../rust/tests/filtering/expected/authattr.rs | 20 +++ .../rust/tests/filtering/expected/taskattr.rs | 84 +++++++++ .../expected/myappattr.rs | 8 + .../expected/scope.rs | 3 +- .../expected/myappattr.rs | 8 + .../expected/scope.rs | 3 +- .../rust/tests/imported/expected/edgeevent.rs | 14 +- .../rust/tests/imported/expected/logger.rs | 19 -- .../rust/tests/imported/expected/myappattr.rs | 8 + .../rust/tests/imported/expected/scope.rs | 3 +- .../rust/tests/imported/registry/model.yaml | 2 + templates/code/rust/tests/imported/test.rs | 40 ++++- .../tests/imported_typed/expected/logger.rs | 19 -- .../imported_typed/expected/myappattr.rs | 8 + .../imported_typed/expected/myappevent.rs | 10 +- .../tests/imported_typed/expected/scope.rs | 3 +- .../integer_boundaries/expected/demoattr.rs | 12 ++ .../literal_escaping/expected/demoattr.rs | 12 ++ .../tests/literal_escaping/expected/scope.rs | 4 +- .../rust/tests/literal_escaping/params.yaml | 3 + .../code/rust/tests/literal_escaping/test.rs | 10 +- .../rust/tests/metrics/expected/authattr.rs | 20 +++ .../rust/tests/metrics/expected/myappattr.rs | 20 +++ .../code/rust/tests/metrics/expected/scope.rs | 3 +- templates/code/rust/tests/metrics/test.rs | 12 +- .../rust/tests/naming/expected/capsattr.rs | 19 ++ .../code/rust/tests/naming/expected/scope.rs | 3 +- .../no_namespace/expected/exceptionattr.rs | 16 ++ .../no_namespace/expected/exceptionevent.rs | 10 +- .../no_namespace/expected/heartbeatattr.rs | 16 ++ .../tests/no_namespace/expected/hostattr.rs | 16 ++ .../tests/no_namespace/expected/logger.rs | 19 -- .../rust/tests/no_namespace/expected/scope.rs | 3 +- .../rust/tests/params/expected/billingattr.rs | 16 ++ .../tests/params/expected/billingevent.rs | 32 ++++ .../rust/tests/params/expected/billingspan.rs | 35 ++++ .../code/rust/tests/params/expected/logger.rs | 14 ++ .../code/rust/tests/params/expected/mod.rs | 4 + .../rust/tests/params/expected/myappattr.rs | 8 + .../code/rust/tests/params/expected/scope.rs | 4 +- .../code/rust/tests/params/expected/tracer.rs | 13 ++ templates/code/rust/tests/params/params.yaml | 2 + .../rust/tests/params/registry/model.yaml | 19 ++ templates/code/rust/tests/params/test.rs | 79 +++++++++ .../rust/tests/spans/expected/myappattr.rs | 76 ++++++++ .../code/rust/tests/spans/expected/scope.rs | 3 +- .../rust/tests/spans/expected/workerattr.rs | 16 ++ templates/code/rust/tests/spans/test.rs | 4 +- templates/code/rust/weaver.yaml | 13 +- 87 files changed, 1385 insertions(+), 246 deletions(-) create mode 100644 templates/code/rust/tests/attributes/tests/log_values.rs create mode 100644 templates/code/rust/tests/error_instrumentation_name_empty/expected-error.txt create mode 100644 templates/code/rust/tests/error_instrumentation_name_empty/params.yaml create mode 100644 templates/code/rust/tests/error_instrumentation_name_empty/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_instrumentation_name_empty/registry/model.yaml create mode 100644 templates/code/rust/tests/error_instrumentation_name_type/expected-error.txt create mode 100644 templates/code/rust/tests/error_instrumentation_name_type/params.yaml create mode 100644 templates/code/rust/tests/error_instrumentation_name_type/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_instrumentation_name_type/registry/model.yaml create mode 100644 templates/code/rust/tests/error_instrumentation_version_type/expected-error.txt create mode 100644 templates/code/rust/tests/error_instrumentation_version_type/params.yaml create mode 100644 templates/code/rust/tests/error_instrumentation_version_type/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_instrumentation_version_type/registry/model.yaml create mode 100644 templates/code/rust/tests/literal_escaping/params.yaml create mode 100644 templates/code/rust/tests/params/expected/billingevent.rs create mode 100644 templates/code/rust/tests/params/expected/billingspan.rs create mode 100644 templates/code/rust/tests/params/expected/logger.rs create mode 100644 templates/code/rust/tests/params/expected/tracer.rs create mode 100644 templates/code/rust/tests/params/test.rs diff --git a/templates/code/rust/README.md b/templates/code/rust/README.md index 47dd9fd..f39ff89 100644 --- a/templates/code/rust/README.md +++ b/templates/code/rust/README.md @@ -42,18 +42,18 @@ the signal modules. Names use the first dotted segment as their namespace; `vendor_prefixes` removes a leading vendor segment before choosing that namespace. -| Module | API | -| ------------------- | ----------------------------------------------------------------------------------------- | -| `attr` | Attribute newtypes and enum variants, `KEY` and conversion into `KeyValue`. | -| `options` | Typed instrumentation options containing scope configuration. | -| `scope` | Scope attributes configuration; package identity is fixed. | -| `meter` | Schema-aware `Meter`, with `new`, `inner`, and a no-op `Default`. | -| `tracer` | Schema-aware `Tracer`, with `new`, `inner`, and a no-op `Default`. | -| `logger` | Schema-aware generic `Logger`, with `new`, `inner`, and a no-op `Default`. | -| `metric` | Synchronous instruments and observable counters, up-down counters, and gauges. | -| `span` | Span starters, typed names, start attributes, and attributes allowed after starting. | -| `event` | Typed log event emitters and options for attributes, severity, and timestamp. | -| `entity` | Typed entity values, attribute iterators, and resources carrying the registry schema URL. | +| Module | API | +| ------------------- | ---------------------------------------------------------------------------------------------- | +| `attr` | Attribute newtypes and enum variants, `KEY` and conversions into `KeyValue` or log `AnyValue`. | +| `options` | Typed instrumentation options containing scope configuration. | +| `scope` | Scope attributes configuration; package identity is fixed. | +| `meter` | Schema-aware `Meter`, with `new`, `inner`, and a no-op `Default`. | +| `tracer` | Schema-aware `Tracer`, with `new`, `inner`, and a no-op `Default`. | +| `logger` | Schema-aware generic `Logger`, with `new`, `inner`, and a no-op `Default`. | +| `metric` | Synchronous instruments and observable counters, up-down counters, and gauges. | +| `span` | Span starters, typed names, start attributes, and attributes allowed after starting. | +| `event` | Typed log event emitters and options for attributes, severity, and timestamp. | +| `entity` | Typed entity values, attribute iterators, and resources carrying the registry schema URL. | Handle modules are emitted when the registry includes their corresponding signals. Their `new(provider, options)` constructor takes the exact @@ -69,11 +69,11 @@ let tracer = semconv::tracer::Tracer::new(&provider, options); ``` Use `InstrumentationOptions::default()` when no scope attributes are needed. -The instrumentation name and version come from the containing Cargo package's -`CARGO_PKG_NAME` and `CARGO_PKG_VERSION` at compile time. If generated code lives -in a library crate, that library supplies the identity; if it lives in the -application crate, the application supplies it. The registry schema URL is also -fixed. These values are not configuration fields. +The instrumentation identity is fixed during generation. Set +`instrumentation_name` and `instrumentation_version` in the Weaver params to +choose its name and version. The name defaults to `generated-semconv`; an empty +version omits SDK version metadata. The registry supplies the schema URL. +Runtime options cannot override these values. Configured scope attributes move into OpenTelemetry without rebuilding their storage. The shared scope and options modules are emitted when a handle is @@ -102,6 +102,10 @@ without building a temporary `KeyValue`; arrays follow OpenTelemetry's array formatting. Boolean, integer, floating-point and enum attributes are `Copy`. Deprecation metadata becomes Rust deprecation annotations. +Attributes also convert directly into `opentelemetry::logs::AnyValue` through +`From`. Generated event emitters pass `Attr::KEY` and the typed attribute to +the SDK log record. + ### Metrics Each metric becomes a typed instrument with a `new(&meter)` constructor and @@ -209,6 +213,8 @@ string with `.into()` or `StringValue::from` at the call site. | Parameter | Default | Purpose | | ------------------------------ | --------------------------- | ------------------------------------------------------------------------- | +| `instrumentation_name` | `generated-semconv` | Name baked into every generated instrumentation scope. | +| `instrumentation_version` | `""` | Version baked into generated scopes; empty omits SDK version metadata. | | `vendor_prefixes` | `[]` | Leading vendor segments removed when deriving namespaces and identifiers. | | `exclude_deprecated` | `false` | Exclude deprecated conventions and enum members. | | `stable_only` | `false` | Include only stable conventions and enum members. | diff --git a/templates/code/rust/attributes.rs.j2 b/templates/code/rust/attributes.rs.j2 index 7227dd8..7e8cf4f 100644 --- a/templates/code/rust/attributes.rs.j2 +++ b/templates/code/rust/attributes.rs.j2 @@ -139,5 +139,26 @@ impl From<{{ attr.name }}> for ::opentelemetry::KeyValue { {% endif %} } } + +#[allow(deprecated)] +impl From<{{ attr.name }}> for ::opentelemetry::logs::AnyValue { +{% if attr.type is not mapping or attr.type.members | length <= 8 %} + #[inline] +{% endif %} + fn from(value: {{ attr.name }}) -> Self { +{% if attr.type is mapping %} + let value: {{ "&'static str" if attr.value_type == "string" else attr.value_type | map_text("rust_type") }} = match value { +{% for member in attr.type.members %} + {{ attr.name }}::{{ member.name }} => {{ member.literal }}{% if attr.value_type == "double" %}_f64{% endif %}, +{% endfor %} + }; + value.into() +{% elif "[]" in attr.value_type %} + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() +{% else %} + value.0.into() +{% endif %} + } +} {% endfor %} {% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/events.rs.j2 b/templates/code/rust/events.rs.j2 index db50914..555017b 100644 --- a/templates/code/rust/events.rs.j2 +++ b/templates/code/rust/events.rs.j2 @@ -44,18 +44,16 @@ pub fn {{ h.ident('emit.' ~ def.short_name) }} let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } {% for req in def.required %} - let attribute = {{ h.attr_kv(req, h.ident(req.attr_param)) }}; - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + {{ h.attr_log("record", req, h.ident(req.attr_param)) }}; {% endfor %} {% if def.optional %} for option in attributes { - let attribute = match option { + match option { {% for opt in def.optional %} - {{ name }}Option::{{ h.exported(opt.attr_short_name) }}(value) => {{ h.attr_kv(opt, 'value') }}, + {{ name }}Option::{{ h.exported(opt.attr_short_name) }}(value) => {{ h.attr_log('record', opt, 'value') }}, {% endfor %} {{ name }}Option::Severity(_) | {{ name }}Option::Timestamp(_) => continue, - }; - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } } {% endif %} logger.inner().emit(record); diff --git a/templates/code/rust/logger.rs.j2 b/templates/code/rust/logger.rs.j2 index 55ad48a..f03691b 100644 --- a/templates/code/rust/logger.rs.j2 +++ b/templates/code/rust/logger.rs.j2 @@ -1,10 +1,5 @@ {%- filter trim %} use super::options::InstrumentationOptions; -{% if ctx.has_attributes %} - -use opentelemetry::logs::AnyValue; -use opentelemetry::{Array, Value}; -{% endif %} #[derive(Clone, Debug)] pub struct Logger::Logger>(L); @@ -18,23 +13,4 @@ impl Logger { impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } -{% if ctx.has_attributes %} -pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { - match value { - Value::Bool(value) => value.into(), - Value::I64(value) => value.into(), - Value::F64(value) => value.into(), - Value::String(value) => value.into(), - Value::Array(array) => match array { - Array::Bool(values) => values.into_iter().collect::(), - Array::I64(values) => values.into_iter().collect::(), - Array::F64(values) => values.into_iter().collect::(), - Array::String(values) => values.into_iter().collect::(), - _ => AnyValue::String(array.to_string().into()), - }, - _ => AnyValue::String(value.to_string().into()), - } -} -{% endif %} - {% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/scope.rs.j2 b/templates/code/rust/scope.rs.j2 index c00189f..08ccf3c 100644 --- a/templates/code/rust/scope.rs.j2 +++ b/templates/code/rust/scope.rs.j2 @@ -1,12 +1,15 @@ {%- filter trim %} +{% import "signal_helpers.j2" as h %} #[derive(Clone, Debug, Default)] pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder({{ h.literal(params.instrumentation_name) }}) +{% if params.instrumentation_version %} + .with_version({{ h.literal(params.instrumentation_version) }}) +{% endif %} .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/signal_helpers.j2 b/templates/code/rust/signal_helpers.j2 index a01c3f1..56f520c 100644 --- a/templates/code/rust/signal_helpers.j2 +++ b/templates/code/rust/signal_helpers.j2 @@ -13,6 +13,9 @@ {%- else -%}::opentelemetry::KeyValue::from({{ value }}) {%- endif -%} {%- endmacro %} +{% macro attr_log(record, a, value) -%} +{{ record }}.add_attribute({% if a.imported %}{{ literal(a.key) }}{% else %}{{ attr_type(a) }}::KEY{% endif %}, {% if a.imported and '[]' in a.attr_type %}{{ value }}.into_iter().collect::<::opentelemetry::logs::AnyValue>(){% else %}{{ value }}{% endif %}) +{%- endmacro %} {% macro deprecated(def) -%} {%- if def.deprecated -%}#[deprecated(note = {{ literal((def.deprecated.note if def.deprecated.note else 'Deprecated by the semantic convention registry')) }})] {%- endif -%} diff --git a/templates/code/rust/tests/allocations/expected/logger.rs b/templates/code/rust/tests/allocations/expected/logger.rs index 8235fca..137ef4c 100644 --- a/templates/code/rust/tests/allocations/expected/logger.rs +++ b/templates/code/rust/tests/allocations/expected/logger.rs @@ -1,8 +1,5 @@ use super::options::InstrumentationOptions; -use opentelemetry::logs::AnyValue; -use opentelemetry::{Array, Value}; - #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { @@ -15,19 +12,3 @@ impl Logger { impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } -pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { - match value { - Value::Bool(value) => value.into(), - Value::I64(value) => value.into(), - Value::F64(value) => value.into(), - Value::String(value) => value.into(), - Value::Array(array) => match array { - Array::Bool(values) => values.into_iter().collect::(), - Array::I64(values) => values.into_iter().collect::(), - Array::F64(values) => values.into_iter().collect::(), - Array::String(values) => values.into_iter().collect::(), - _ => AnyValue::String(array.to_string().into()), - }, - _ => AnyValue::String(value.to_string().into()), - } -} diff --git a/templates/code/rust/tests/allocations/expected/probeattr.rs b/templates/code/rust/tests/allocations/expected/probeattr.rs index 9c7a207..0d34500 100644 --- a/templates/code/rust/tests/allocations/expected/probeattr.rs +++ b/templates/code/rust/tests/allocations/expected/probeattr.rs @@ -1,4 +1,147 @@ // Generated by OpenTelemetry Weaver. +/// A synthetic boolean value. +#[derive(Debug, Clone, PartialEq, Copy)] +pub struct FlagAttr(bool); + +#[allow(deprecated)] +impl FlagAttr { + pub const KEY: &'static str = "probe.flag"; +} + +#[allow(deprecated)] +impl From for FlagAttr { + #[inline] + fn from(value: bool) -> Self { + Self(value) + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for FlagAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + #[inline] + fn from(value: FlagAttr) -> Self { + ::opentelemetry::KeyValue::new(FlagAttr::KEY, value.0) + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: FlagAttr) -> Self { + value.0.into() + } +} +/// A synthetic fractional value. +#[derive(Debug, Clone, PartialEq, Copy)] +pub struct FractionAttr(f64); + +#[allow(deprecated)] +impl FractionAttr { + pub const KEY: &'static str = "probe.fraction"; +} + +#[allow(deprecated)] +impl From for FractionAttr { + #[inline] + fn from(value: f64) -> Self { + Self(value) + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for FractionAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::std::fmt::Display::fmt(&self.0, formatter) + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + #[inline] + fn from(value: FractionAttr) -> Self { + ::opentelemetry::KeyValue::new(FractionAttr::KEY, value.0) + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: FractionAttr) -> Self { + value.0.into() + } +} +/// A synthetic text value. +#[derive(Debug, Clone, PartialEq)] +pub struct LabelAttr(::opentelemetry::StringValue); + +#[allow(deprecated)] +impl LabelAttr { + pub const KEY: &'static str = "probe.label"; +} + +#[allow(deprecated)] +impl From<::opentelemetry::StringValue> for LabelAttr { + #[inline] + fn from(value: ::opentelemetry::StringValue) -> Self { + Self(value) + } +} +#[allow(deprecated)] +impl From for LabelAttr { + #[inline] + fn from(value: String) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl From<&'static str> for LabelAttr { + #[inline] + fn from(value: &'static str) -> Self { + Self(value.into()) + } +} + +#[allow(deprecated)] +impl AsRef for LabelAttr { + #[inline] + fn as_ref(&self) -> &str { + self.0.as_str() + } +} + +#[allow(deprecated)] +impl ::std::fmt::Display for LabelAttr { + #[inline] + fn fmt(&self, formatter: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + formatter.write_str(self.as_ref()) + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::KeyValue { + #[inline] + fn from(value: LabelAttr) -> Self { + ::opentelemetry::KeyValue::new(LabelAttr::KEY, value.0) + } +} + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: LabelAttr) -> Self { + value.0.into() + } +} /// Optional numeric measurement identity. #[derive(Debug, Clone, PartialEq, Copy)] pub struct OptionalAttr(i64); @@ -31,6 +174,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(OptionalAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: OptionalAttr) -> Self { + value.0.into() + } +} /// Required numeric measurement identity. #[derive(Debug, Clone, PartialEq, Copy)] pub struct RequiredAttr(i64); @@ -63,6 +214,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(RequiredAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: RequiredAttr) -> Self { + value.0.into() + } +} /// Numeric values attached to an event. #[derive(Debug, Clone, PartialEq)] pub struct ValuesAttr(Vec); @@ -109,3 +268,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(ValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: ValuesAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} diff --git a/templates/code/rust/tests/allocations/expected/probeevent.rs b/templates/code/rust/tests/allocations/expected/probeevent.rs index be2ebfc..5db4b38 100644 --- a/templates/code/rust/tests/allocations/expected/probeevent.rs +++ b/templates/code/rust/tests/allocations/expected/probeevent.rs @@ -31,15 +31,13 @@ pub fn r#emit_recorded(context: &::opentelemet let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - let attribute = ::opentelemetry::KeyValue::from(r#probe_required); - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + record.add_attribute(super::probeattr::RequiredAttr::KEY, r#probe_required); for option in attributes { - let attribute = match option { - RecordedOption::Optional(value) => ::opentelemetry::KeyValue::from(value), - RecordedOption::Values(value) => ::opentelemetry::KeyValue::from(value), + match option { + RecordedOption::Optional(value) => record.add_attribute(super::probeattr::OptionalAttr::KEY, value), + RecordedOption::Values(value) => record.add_attribute(super::probeattr::ValuesAttr::KEY, value), RecordedOption::Severity(_) | RecordedOption::Timestamp(_) => continue, - }; - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } } logger.inner().emit(record); } diff --git a/templates/code/rust/tests/allocations/expected/scope.rs b/templates/code/rust/tests/allocations/expected/scope.rs index 9ed8538..920a74d 100644 --- a/templates/code/rust/tests/allocations/expected/scope.rs +++ b/templates/code/rust/tests/allocations/expected/scope.rs @@ -4,8 +4,7 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("generated-semconv") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/allocations/registry/model.yaml b/templates/code/rust/tests/allocations/registry/model.yaml index 7ef9979..abb4ceb 100644 --- a/templates/code/rust/tests/allocations/registry/model.yaml +++ b/templates/code/rust/tests/allocations/registry/model.yaml @@ -1,5 +1,20 @@ file_format: definition/2 attributes: + - key: probe.flag + type: boolean + stability: stable + brief: A synthetic boolean value. + examples: true + - key: probe.fraction + type: double + stability: stable + brief: A synthetic fractional value. + examples: 0.5 + - key: probe.label + type: string + stability: stable + brief: A synthetic text value. + examples: ["label"] - key: probe.required type: int stability: stable diff --git a/templates/code/rust/tests/allocations/test.rs b/templates/code/rust/tests/allocations/test.rs index 7470f16..9470ec4 100644 --- a/templates/code/rust/tests/allocations/test.rs +++ b/templates/code/rust/tests/allocations/test.rs @@ -358,8 +358,8 @@ fn scope_attributes_move_without_rebuilding_storage() { (log_provider.0.scope.lock().unwrap(), original_log), ] { let scope = stored.as_ref().unwrap(); - assert_eq!(scope.name(), "generated_semconv"); - assert_eq!(scope.version(), Some("0.0.0")); + assert_eq!(scope.name(), "generated-semconv"); + assert_eq!(scope.version(), None); assert_eq!(scope.schema_url(), Some(generated_semconv::SCHEMA_URL)); assert_eq!( scope.attributes().next().unwrap() as *const KeyValue, @@ -374,7 +374,7 @@ fn scope_attributes_move_without_rebuilding_storage() { } #[test] -fn default_options_apply_fixed_package_identity() { +fn default_options_apply_generated_identity() { let metric_provider = BorrowedMeterProvider { meter: Meter::new(Arc::new(MetricProvider(Arc::new(MetricState::default())))), scope: Mutex::new(None), @@ -382,12 +382,26 @@ fn default_options_apply_fixed_package_identity() { let _meter = meter::Meter::new(&metric_provider, InstrumentationOptions::default()); let stored = metric_provider.scope.lock().unwrap(); let stored = stored.as_ref().unwrap(); - assert_eq!(stored.name(), "generated_semconv"); - assert_eq!(stored.version(), Some("0.0.0")); + assert_eq!(stored.name(), "generated-semconv"); + assert_eq!(stored.version(), None); assert_eq!(stored.attributes().count(), 0); assert_eq!(stored.schema_url(), Some(generated_semconv::SCHEMA_URL)); } +#[test] +fn direct_scalar_log_values_move_without_heap_allocations() { + let owned = probeattr::LabelAttr::from(String::from("owned text")); + let count = allocations(|| { + black_box(AnyValue::from(probeattr::RequiredAttr::from(7))); + black_box(AnyValue::from(probeattr::FlagAttr::from(true))); + black_box(AnyValue::from(probeattr::FractionAttr::from(0.5))); + black_box(AnyValue::from(probeattr::LabelAttr::from("static text"))); + black_box(AnyValue::from(owned)); + }); + assert_eq!(count, 0); + println!("generated direct scalar log conversion allocations: {count}"); +} + #[test] fn enabled_events_use_no_generated_heap_and_preserve_duplicate_attributes() { let state = Arc::new(LogState::default()); diff --git a/templates/code/rust/tests/attributes/expected/authattr.rs b/templates/code/rust/tests/attributes/expected/authattr.rs index bfc631a..27b8586 100644 --- a/templates/code/rust/tests/attributes/expected/authattr.rs +++ b/templates/code/rust/tests/attributes/expected/authattr.rs @@ -36,6 +36,18 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(LevelAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: LevelAttr) -> Self { + let value: i64 = match value { + LevelAttr::Low => 1, + LevelAttr::High => 2, + }; + value.into() + } +} /// How the user was authenticated. #[derive(Debug, Clone, PartialEq, Copy)] pub enum MethodAttr { @@ -80,6 +92,18 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(MethodAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: MethodAttr) -> Self { + let value: &'static str = match value { + MethodAttr::Password => "password", + MethodAttr::Token => "token", + }; + value.into() + } +} /// Identifier of the authenticated user. #[derive(Debug, Clone, PartialEq)] pub struct UserIdAttr(::opentelemetry::StringValue); @@ -135,3 +159,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(UserIdAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: UserIdAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/attributes/expected/myappattr.rs b/templates/code/rust/tests/attributes/expected/myappattr.rs index fe74394..9f3d8e0 100644 --- a/templates/code/rust/tests/attributes/expected/myappattr.rs +++ b/templates/code/rust/tests/attributes/expected/myappattr.rs @@ -56,6 +56,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskAssignedByAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskAssignedByAttr) -> Self { + value.0.into() + } +} /// Whether the task was cancelled. #[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskCancelledAttr(bool); @@ -88,6 +96,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskCancelledAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskCancelledAttr) -> Self { + value.0.into() + } +} /// Tests Rust string literals. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskEscapedAttr { @@ -128,6 +144,17 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskEscapedAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskEscapedAttr) -> Self { + let value: &'static str = match value { + TaskEscapedAttr::Quoted => "quote\" slash\\ newline\n tab\t backspace\u{0008} formfeed\u{000c} null\u{0000} snowman☃", + }; + value.into() + } +} /// Feature flags evaluated for the task. #[derive(Debug, Clone, PartialEq)] pub struct TaskFlagsAttr(Vec); @@ -174,6 +201,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskFlagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskFlagsAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} /// Unique identifier of the task. /// /// The identifier is assigned by the scheduler and stays stable across retries. @@ -231,6 +266,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskIdAttr) -> Self { + value.0.into() + } +} /// Lane the task was scheduled in. #[deprecated(note = "Lanes were replaced by priorities.")] #[derive(Debug, Clone, PartialEq, Copy)] @@ -278,6 +321,18 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskLaneAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskLaneAttr) -> Self { + let value: &'static str = match value { + TaskLaneAttr::Fast => "fast", + TaskLaneAttr::Slow => "slow", + }; + value.into() + } +} /// Owner of the task. #[deprecated(note = "Replaced by `auth.user.id`.")] #[derive(Debug, Clone, PartialEq)] @@ -334,6 +389,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskOwnerAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskOwnerAttr) -> Self { + value.0.into() + } +} /// Whether the scheduler may preempt the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskPreemptibleAttr { @@ -371,6 +434,18 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskPreemptibleAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskPreemptibleAttr) -> Self { + let value: bool = match value { + TaskPreemptibleAttr::Allowed => true, + TaskPreemptibleAttr::Forbidden => false, + }; + value.into() + } +} /// Fraction of the task that has completed, between 0 and 1. #[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskProgressAttr(f64); @@ -403,6 +478,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskProgressAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskProgressAttr) -> Self { + value.0.into() + } +} /// Number of times the task was retried. #[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskRetriesAttr(i64); @@ -435,6 +518,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskRetriesAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskRetriesAttr) -> Self { + value.0.into() + } +} /// Fraction of tasks whose telemetry is sampled. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskSampleRateAttr { @@ -472,6 +563,18 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskSampleRateAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskSampleRateAttr) -> Self { + let value: f64 = match value { + TaskSampleRateAttr::Tenth => 0.1_f64, + TaskSampleRateAttr::All => 1_f64, + }; + value.into() + } +} /// Shards the task touched. #[derive(Debug, Clone, PartialEq)] pub struct TaskShardIdsAttr(Vec); @@ -518,6 +621,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskShardIdsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskShardIdsAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskStateAttr { @@ -569,6 +680,19 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskStateAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskStateAttr) -> Self { + let value: &'static str = match value { + TaskStateAttr::Queued => "queued", + TaskStateAttr::Running => "running", + TaskStateAttr::Paused => "paused", + }; + value.into() + } +} /// Tags attached to the task. #[derive(Debug, Clone, PartialEq)] pub struct TaskTagsAttr(Vec<::opentelemetry::StringValue>); @@ -621,6 +745,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskTagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskTagsAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} /// Scheduling weights applied to the task. #[derive(Debug, Clone, PartialEq)] pub struct TaskWeightsAttr(Vec); @@ -667,3 +799,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskWeightsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskWeightsAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} diff --git a/templates/code/rust/tests/attributes/tests/log_values.rs b/templates/code/rust/tests/attributes/tests/log_values.rs new file mode 100644 index 0000000..e009bc3 --- /dev/null +++ b/templates/code/rust/tests/attributes/tests/log_values.rs @@ -0,0 +1,88 @@ +use generated_semconv::{authattr, myappattr}; +use opentelemetry::logs::AnyValue; + +#[test] +fn typed_attributes_convert_directly_to_log_values() { + let retries: AnyValue = myappattr::TaskRetriesAttr::from(4).into(); + assert_eq!(retries, AnyValue::Int(4)); + assert_eq!( + AnyValue::from(myappattr::TaskProgressAttr::from(0.5)), + AnyValue::Double(0.5) + ); + assert_eq!( + AnyValue::from(myappattr::TaskCancelledAttr::from(true)), + AnyValue::Boolean(true) + ); + assert_eq!( + AnyValue::from(myappattr::TaskStateAttr::Running), + AnyValue::String("running".into()) + ); + assert_eq!(AnyValue::from(authattr::LevelAttr::High), AnyValue::Int(2)); + assert_eq!( + AnyValue::from(myappattr::TaskPreemptibleAttr::Allowed), + AnyValue::Boolean(true) + ); + assert_eq!( + AnyValue::from(myappattr::TaskSampleRateAttr::Tenth), + AnyValue::Double(0.1) + ); +} + +#[test] +fn log_conversion_preserves_string_storage() { + for attribute in [ + myappattr::TaskIdAttr::from("static-task"), + myappattr::TaskIdAttr::from(String::from("owned-task")), + myappattr::TaskIdAttr::from(opentelemetry::StringValue::from( + std::sync::Arc::::from("shared-task"), + )), + ] { + let pointer = attribute.as_ref().as_ptr(); + let AnyValue::String(value) = AnyValue::from(attribute) else { + panic!("expected string log value"); + }; + assert_eq!(value.as_str().as_ptr(), pointer); + } +} + +#[test] +fn typed_arrays_export_log_lists_with_order_and_duplicates() { + assert_eq!( + AnyValue::from(myappattr::TaskShardIdsAttr::from(vec![1, 1, 2])), + AnyValue::ListAny(Box::new(vec![ + AnyValue::Int(1), + AnyValue::Int(1), + AnyValue::Int(2), + ])) + ); + assert_eq!( + AnyValue::from(myappattr::TaskWeightsAttr::from(vec![0.25, 0.75])), + AnyValue::ListAny(Box::new(vec![ + AnyValue::Double(0.25), + AnyValue::Double(0.75), + ])) + ); + assert_eq!( + AnyValue::from(myappattr::TaskFlagsAttr::from(vec![true, false])), + AnyValue::ListAny(Box::new(vec![ + AnyValue::Boolean(true), + AnyValue::Boolean(false), + ])) + ); + let tag = opentelemetry::StringValue::from(String::from("owned-tag")); + let pointer = tag.as_str().as_ptr(); + let AnyValue::ListAny(values) = AnyValue::from(myappattr::TaskTagsAttr::from(vec![tag])) else { + panic!("expected string log list"); + }; + let AnyValue::String(value) = &values[0] else { + panic!("expected string list element"); + }; + assert_eq!(value.as_str(), "owned-tag"); + assert_eq!(value.as_str().as_ptr(), pointer); + assert_eq!( + AnyValue::from(myappattr::TaskTagsAttr::from(Vec::< + opentelemetry::StringValue, + >::new())), + AnyValue::ListAny(Box::default()) + ); +} diff --git a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs index d5c49a0..835f35a 100644 --- a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs +++ b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs @@ -54,6 +54,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(KeptAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: KeptAttr) -> Self { + value.0.into() + } +} /// Synthetic mode. #[derive(Debug, Clone, PartialEq, Copy)] pub enum ModeAttr { @@ -94,3 +102,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(ModeAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: ModeAttr) -> Self { + let value: &'static str = match value { + ModeAttr::Kept => "kept", + }; + value.into() + } +} diff --git a/templates/code/rust/tests/entities/expected/myappattr.rs b/templates/code/rust/tests/entities/expected/myappattr.rs index df868b2..f385007 100644 --- a/templates/code/rust/tests/entities/expected/myappattr.rs +++ b/templates/code/rust/tests/entities/expected/myappattr.rs @@ -32,6 +32,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(HostCpuCountAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: HostCpuCountAttr) -> Self { + value.0.into() + } +} /// Name of the host. #[derive(Debug, Clone, PartialEq)] pub struct HostNameAttr(::opentelemetry::StringValue); @@ -87,6 +95,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(HostNameAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: HostNameAttr) -> Self { + value.0.into() + } +} /// Role the host plays in the cluster. #[derive(Debug, Clone, PartialEq)] pub struct HostRoleAttr(::opentelemetry::StringValue); @@ -142,6 +158,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(HostRoleAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: HostRoleAttr) -> Self { + value.0.into() + } +} /// Type of the host. #[derive(Debug, Clone, PartialEq, Copy)] pub enum HostTypeAttr { @@ -186,6 +210,18 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(HostTypeAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: HostTypeAttr) -> Self { + let value: &'static str = match value { + HostTypeAttr::Physical => "physical", + HostTypeAttr::Virtual => "virtual", + }; + value.into() + } +} /// Name of the queue. #[derive(Debug, Clone, PartialEq)] pub struct QueueNameAttr(::opentelemetry::StringValue); @@ -241,6 +277,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(QueueNameAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: QueueNameAttr) -> Self { + value.0.into() + } +} /// Number of items currently in the queue. #[derive(Debug, Clone, PartialEq, Copy)] pub struct QueueSizeAttr(i64); @@ -273,3 +317,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(QueueSizeAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: QueueSizeAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/error_instrumentation_name_empty/expected-error.txt b/templates/code/rust/tests/error_instrumentation_name_empty/expected-error.txt new file mode 100644 index 0000000..29bd62a --- /dev/null +++ b/templates/code/rust/tests/error_instrumentation_name_empty/expected-error.txt @@ -0,0 +1 @@ +instrumentation_name must be a nonempty string diff --git a/templates/code/rust/tests/error_instrumentation_name_empty/params.yaml b/templates/code/rust/tests/error_instrumentation_name_empty/params.yaml new file mode 100644 index 0000000..2e72054 --- /dev/null +++ b/templates/code/rust/tests/error_instrumentation_name_empty/params.yaml @@ -0,0 +1,2 @@ +params: + instrumentation_name: "" diff --git a/templates/code/rust/tests/error_instrumentation_name_empty/registry/manifest.yaml b/templates/code/rust/tests/error_instrumentation_name_empty/registry/manifest.yaml new file mode 100644 index 0000000..209c36a --- /dev/null +++ b/templates/code/rust/tests/error_instrumentation_name_empty/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: synthetic-empty-event-fixture +schema_url: https://example.com/schemas/event-no-attributes/1.0.0 diff --git a/templates/code/rust/tests/error_instrumentation_name_empty/registry/model.yaml b/templates/code/rust/tests/error_instrumentation_name_empty/registry/model.yaml new file mode 100644 index 0000000..b9120fb --- /dev/null +++ b/templates/code/rust/tests/error_instrumentation_name_empty/registry/model.yaml @@ -0,0 +1,5 @@ +file_format: definition/2 +events: + - name: probe.tick + stability: stable + brief: A synthetic tick occurred. diff --git a/templates/code/rust/tests/error_instrumentation_name_type/expected-error.txt b/templates/code/rust/tests/error_instrumentation_name_type/expected-error.txt new file mode 100644 index 0000000..29bd62a --- /dev/null +++ b/templates/code/rust/tests/error_instrumentation_name_type/expected-error.txt @@ -0,0 +1 @@ +instrumentation_name must be a nonempty string diff --git a/templates/code/rust/tests/error_instrumentation_name_type/params.yaml b/templates/code/rust/tests/error_instrumentation_name_type/params.yaml new file mode 100644 index 0000000..d1f6288 --- /dev/null +++ b/templates/code/rust/tests/error_instrumentation_name_type/params.yaml @@ -0,0 +1,2 @@ +params: + instrumentation_name: true diff --git a/templates/code/rust/tests/error_instrumentation_name_type/registry/manifest.yaml b/templates/code/rust/tests/error_instrumentation_name_type/registry/manifest.yaml new file mode 100644 index 0000000..209c36a --- /dev/null +++ b/templates/code/rust/tests/error_instrumentation_name_type/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: synthetic-empty-event-fixture +schema_url: https://example.com/schemas/event-no-attributes/1.0.0 diff --git a/templates/code/rust/tests/error_instrumentation_name_type/registry/model.yaml b/templates/code/rust/tests/error_instrumentation_name_type/registry/model.yaml new file mode 100644 index 0000000..b9120fb --- /dev/null +++ b/templates/code/rust/tests/error_instrumentation_name_type/registry/model.yaml @@ -0,0 +1,5 @@ +file_format: definition/2 +events: + - name: probe.tick + stability: stable + brief: A synthetic tick occurred. diff --git a/templates/code/rust/tests/error_instrumentation_version_type/expected-error.txt b/templates/code/rust/tests/error_instrumentation_version_type/expected-error.txt new file mode 100644 index 0000000..101ce01 --- /dev/null +++ b/templates/code/rust/tests/error_instrumentation_version_type/expected-error.txt @@ -0,0 +1 @@ +instrumentation_version must be a string diff --git a/templates/code/rust/tests/error_instrumentation_version_type/params.yaml b/templates/code/rust/tests/error_instrumentation_version_type/params.yaml new file mode 100644 index 0000000..e1f53ac --- /dev/null +++ b/templates/code/rust/tests/error_instrumentation_version_type/params.yaml @@ -0,0 +1,2 @@ +params: + instrumentation_version: false diff --git a/templates/code/rust/tests/error_instrumentation_version_type/registry/manifest.yaml b/templates/code/rust/tests/error_instrumentation_version_type/registry/manifest.yaml new file mode 100644 index 0000000..209c36a --- /dev/null +++ b/templates/code/rust/tests/error_instrumentation_version_type/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: synthetic-empty-event-fixture +schema_url: https://example.com/schemas/event-no-attributes/1.0.0 diff --git a/templates/code/rust/tests/error_instrumentation_version_type/registry/model.yaml b/templates/code/rust/tests/error_instrumentation_version_type/registry/model.yaml new file mode 100644 index 0000000..b9120fb --- /dev/null +++ b/templates/code/rust/tests/error_instrumentation_version_type/registry/model.yaml @@ -0,0 +1,5 @@ +file_format: definition/2 +events: + - name: probe.tick + stability: stable + brief: A synthetic tick occurred. diff --git a/templates/code/rust/tests/event_no_attributes/expected/scope.rs b/templates/code/rust/tests/event_no_attributes/expected/scope.rs index 9ed8538..920a74d 100644 --- a/templates/code/rust/tests/event_no_attributes/expected/scope.rs +++ b/templates/code/rust/tests/event_no_attributes/expected/scope.rs @@ -4,8 +4,7 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("generated-semconv") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/event_no_attributes/test.rs b/templates/code/rust/tests/event_no_attributes/test.rs index 16ecfcf..7483c37 100644 --- a/templates/code/rust/tests/event_no_attributes/test.rs +++ b/templates/code/rust/tests/event_no_attributes/test.rs @@ -18,8 +18,8 @@ fn events_without_attributes_export_cleanly() { provider.force_flush().unwrap(); let records = exporter.get_emitted_logs().unwrap(); assert_eq!(records.len(), 1); - assert_eq!(records[0].instrumentation.name(), "generated_semconv"); - assert_eq!(records[0].instrumentation.version(), Some("0.0.0")); + assert_eq!(records[0].instrumentation.name(), "generated-semconv"); + assert_eq!(records[0].instrumentation.version(), None); assert_eq!(records[0].record.event_name(), Some("probe.tick")); assert_eq!(records[0].record.severity_number(), Some(Severity::Debug)); assert_eq!(records[0].record.attributes_iter().count(), 0); diff --git a/templates/code/rust/tests/events/expected/logger.rs b/templates/code/rust/tests/events/expected/logger.rs index 8235fca..137ef4c 100644 --- a/templates/code/rust/tests/events/expected/logger.rs +++ b/templates/code/rust/tests/events/expected/logger.rs @@ -1,8 +1,5 @@ use super::options::InstrumentationOptions; -use opentelemetry::logs::AnyValue; -use opentelemetry::{Array, Value}; - #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { @@ -15,19 +12,3 @@ impl Logger { impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } -pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { - match value { - Value::Bool(value) => value.into(), - Value::I64(value) => value.into(), - Value::F64(value) => value.into(), - Value::String(value) => value.into(), - Value::Array(array) => match array { - Array::Bool(values) => values.into_iter().collect::(), - Array::I64(values) => values.into_iter().collect::(), - Array::F64(values) => values.into_iter().collect::(), - Array::String(values) => values.into_iter().collect::(), - _ => AnyValue::String(array.to_string().into()), - }, - _ => AnyValue::String(value.to_string().into()), - } -} diff --git a/templates/code/rust/tests/events/expected/myappattr.rs b/templates/code/rust/tests/events/expected/myappattr.rs index 94f38f0..63b08fb 100644 --- a/templates/code/rust/tests/events/expected/myappattr.rs +++ b/templates/code/rust/tests/events/expected/myappattr.rs @@ -45,6 +45,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(BoolValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: BoolValuesAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} /// Synthetic double values. #[derive(Debug, Clone, PartialEq)] pub struct DoubleValuesAttr(Vec); @@ -91,6 +99,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(DoubleValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: DoubleValuesAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} /// Synthetic int values. #[derive(Debug, Clone, PartialEq)] pub struct IntValuesAttr(Vec); @@ -137,6 +153,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(IntValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: IntValuesAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} /// Synthetic string values. #[derive(Debug, Clone, PartialEq)] pub struct StringValuesAttr(Vec<::opentelemetry::StringValue>); @@ -189,6 +213,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(StringValuesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: StringValuesAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} /// Number of the attempt, starting at 1. #[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskAttemptAttr(i64); @@ -221,6 +253,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskAttemptAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskAttemptAttr) -> Self { + value.0.into() + } +} /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskStateAttr { @@ -265,3 +305,15 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskStateAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskStateAttr) -> Self { + let value: &'static str = match value { + TaskStateAttr::Done => "done", + TaskStateAttr::Failed => "failed", + }; + value.into() + } +} diff --git a/templates/code/rust/tests/events/expected/myappevent.rs b/templates/code/rust/tests/events/expected/myappevent.rs index 1d23167..9138d5c 100644 --- a/templates/code/rust/tests/events/expected/myappevent.rs +++ b/templates/code/rust/tests/events/expected/myappevent.rs @@ -39,19 +39,17 @@ pub fn r#emit_task_finished(context: &::opente let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - let attribute = ::opentelemetry::KeyValue::from(r#myapp_task_state); - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + record.add_attribute(super::myappattr::TaskStateAttr::KEY, r#myapp_task_state); for option in attributes { - let attribute = match option { - TaskFinishedOption::BoolValues(value) => ::opentelemetry::KeyValue::from(value), - TaskFinishedOption::DoubleValues(value) => ::opentelemetry::KeyValue::from(value), - TaskFinishedOption::IntValues(value) => ::opentelemetry::KeyValue::from(value), - TaskFinishedOption::StringValues(value) => ::opentelemetry::KeyValue::from(value), - TaskFinishedOption::TaskAttempt(value) => ::opentelemetry::KeyValue::from(value), - TaskFinishedOption::HostName(value) => ::opentelemetry::KeyValue::from(value), + match option { + TaskFinishedOption::BoolValues(value) => record.add_attribute(super::myappattr::BoolValuesAttr::KEY, value), + TaskFinishedOption::DoubleValues(value) => record.add_attribute(super::myappattr::DoubleValuesAttr::KEY, value), + TaskFinishedOption::IntValues(value) => record.add_attribute(super::myappattr::IntValuesAttr::KEY, value), + TaskFinishedOption::StringValues(value) => record.add_attribute(super::myappattr::StringValuesAttr::KEY, value), + TaskFinishedOption::TaskAttempt(value) => record.add_attribute(super::myappattr::TaskAttemptAttr::KEY, value), + TaskFinishedOption::HostName(value) => record.add_attribute(super::workerattr::HostNameAttr::KEY, value), TaskFinishedOption::Severity(_) | TaskFinishedOption::Timestamp(_) => continue, - }; - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } } logger.inner().emit(record); } @@ -82,7 +80,6 @@ pub fn r#emit_task_retried(context: &::opentel let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - let attribute = ::opentelemetry::KeyValue::from(r#myapp_task_attempt); - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + record.add_attribute(super::myappattr::TaskAttemptAttr::KEY, r#myapp_task_attempt); logger.inner().emit(record); } diff --git a/templates/code/rust/tests/events/expected/scope.rs b/templates/code/rust/tests/events/expected/scope.rs index 9ed8538..920a74d 100644 --- a/templates/code/rust/tests/events/expected/scope.rs +++ b/templates/code/rust/tests/events/expected/scope.rs @@ -4,8 +4,7 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("generated-semconv") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/events/expected/workerattr.rs b/templates/code/rust/tests/events/expected/workerattr.rs index 99f1d8c..a62dda2 100644 --- a/templates/code/rust/tests/events/expected/workerattr.rs +++ b/templates/code/rust/tests/events/expected/workerattr.rs @@ -54,3 +54,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(HostNameAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: HostNameAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/events/expected/workerevent.rs b/templates/code/rust/tests/events/expected/workerevent.rs index 7a6a0aa..69a4c0f 100644 --- a/templates/code/rust/tests/events/expected/workerevent.rs +++ b/templates/code/rust/tests/events/expected/workerevent.rs @@ -64,20 +64,17 @@ pub fn r#emit_task_finished(context: &::opente let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - let attribute = ::opentelemetry::KeyValue::from(r#myapp_task_state); - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); - let attribute = ::opentelemetry::KeyValue::from(r#worker_host_name); - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + record.add_attribute(super::myappattr::TaskStateAttr::KEY, r#myapp_task_state); + record.add_attribute(super::workerattr::HostNameAttr::KEY, r#worker_host_name); for option in attributes { - let attribute = match option { - TaskFinishedOption::BoolValues(value) => ::opentelemetry::KeyValue::from(value), - TaskFinishedOption::DoubleValues(value) => ::opentelemetry::KeyValue::from(value), - TaskFinishedOption::IntValues(value) => ::opentelemetry::KeyValue::from(value), - TaskFinishedOption::StringValues(value) => ::opentelemetry::KeyValue::from(value), - TaskFinishedOption::TaskAttempt(value) => ::opentelemetry::KeyValue::from(value), + match option { + TaskFinishedOption::BoolValues(value) => record.add_attribute(super::myappattr::BoolValuesAttr::KEY, value), + TaskFinishedOption::DoubleValues(value) => record.add_attribute(super::myappattr::DoubleValuesAttr::KEY, value), + TaskFinishedOption::IntValues(value) => record.add_attribute(super::myappattr::IntValuesAttr::KEY, value), + TaskFinishedOption::StringValues(value) => record.add_attribute(super::myappattr::StringValuesAttr::KEY, value), + TaskFinishedOption::TaskAttempt(value) => record.add_attribute(super::myappattr::TaskAttemptAttr::KEY, value), TaskFinishedOption::Severity(_) | TaskFinishedOption::Timestamp(_) => continue, - }; - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } } logger.inner().emit(record); } diff --git a/templates/code/rust/tests/events/test.rs b/templates/code/rust/tests/events/test.rs index a7f7f72..9fc78a0 100644 --- a/templates/code/rust/tests/events/test.rs +++ b/templates/code/rust/tests/events/test.rs @@ -65,8 +65,8 @@ fn typed_events_have_schema_timestamps_severity_attributes_and_trace_context() { assert!(log.record.observed_timestamp().is_some()); assert!(log.record.body().is_none()); assert_eq!(log.instrumentation.schema_url(), Some(SCHEMA_URL)); - assert_eq!(log.instrumentation.name(), "generated_semconv"); - assert_eq!(log.instrumentation.version(), Some("0.0.0")); + assert_eq!(log.instrumentation.name(), "generated-semconv"); + assert_eq!(log.instrumentation.version(), None); assert!(log .instrumentation .attributes() diff --git a/templates/code/rust/tests/filtering/expected/authattr.rs b/templates/code/rust/tests/filtering/expected/authattr.rs index 5f7a4c3..aa01590 100644 --- a/templates/code/rust/tests/filtering/expected/authattr.rs +++ b/templates/code/rust/tests/filtering/expected/authattr.rs @@ -43,6 +43,18 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(MethodAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: MethodAttr) -> Self { + let value: &'static str = match value { + MethodAttr::Password => "password", + MethodAttr::Token => "token", + }; + value.into() + } +} /// Identifier of the authenticated user. #[derive(Debug, Clone, PartialEq)] pub struct UserIdAttr(::opentelemetry::StringValue); @@ -98,3 +110,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(UserIdAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: UserIdAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/filtering/expected/taskattr.rs b/templates/code/rust/tests/filtering/expected/taskattr.rs index 30317f9..0a3b34d 100644 --- a/templates/code/rust/tests/filtering/expected/taskattr.rs +++ b/templates/code/rust/tests/filtering/expected/taskattr.rs @@ -56,6 +56,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(AssignedByAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: AssignedByAttr) -> Self { + value.0.into() + } +} /// Whether the task was cancelled. #[derive(Debug, Clone, PartialEq, Copy)] pub struct CancelledAttr(bool); @@ -88,6 +96,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(CancelledAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: CancelledAttr) -> Self { + value.0.into() + } +} /// Unique identifier of the task. /// /// The identifier is assigned by the scheduler and stays stable across retries. @@ -145,6 +161,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(IdAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: IdAttr) -> Self { + value.0.into() + } +} /// Whether the scheduler may preempt the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum PreemptibleAttr { @@ -182,6 +206,18 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(PreemptibleAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: PreemptibleAttr) -> Self { + let value: bool = match value { + PreemptibleAttr::Allowed => true, + PreemptibleAttr::Forbidden => false, + }; + value.into() + } +} /// Number of times the task was retried. #[derive(Debug, Clone, PartialEq, Copy)] pub struct RetriesAttr(i64); @@ -214,6 +250,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(RetriesAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: RetriesAttr) -> Self { + value.0.into() + } +} /// Fraction of tasks whose telemetry is sampled. #[derive(Debug, Clone, PartialEq, Copy)] pub enum SampleRateAttr { @@ -251,6 +295,18 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(SampleRateAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: SampleRateAttr) -> Self { + let value: f64 = match value { + SampleRateAttr::Tenth => 0.1_f64, + SampleRateAttr::All => 1_f64, + }; + value.into() + } +} /// Shards the task touched. #[derive(Debug, Clone, PartialEq)] pub struct ShardIdsAttr(Vec); @@ -297,6 +353,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(ShardIdsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: ShardIdsAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum StateAttr { @@ -343,6 +407,18 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(StateAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: StateAttr) -> Self { + let value: &'static str = match value { + StateAttr::Queued => "queued", + StateAttr::Running => "running", + }; + value.into() + } +} /// Tags attached to the task. #[derive(Debug, Clone, PartialEq)] pub struct TagsAttr(Vec<::opentelemetry::StringValue>); @@ -395,3 +471,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TagsAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs index 4987524..0e5c78c 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs @@ -54,3 +54,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskIdAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs index 9ed8538..920a74d 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs @@ -4,8 +4,7 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("generated-semconv") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs index 4987524..0e5c78c 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs @@ -54,3 +54,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskIdAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs index 9ed8538..920a74d 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs @@ -4,8 +4,7 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("generated-semconv") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/imported/expected/edgeevent.rs b/templates/code/rust/tests/imported/expected/edgeevent.rs index 0d6e7e3..0bcd626 100644 --- a/templates/code/rust/tests/imported/expected/edgeevent.rs +++ b/templates/code/rust/tests/imported/expected/edgeevent.rs @@ -6,13 +6,14 @@ use ::opentelemetry::trace::TraceContextExt; pub enum UpstreamFailedOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), + HttpRequestMethodList(Vec<::opentelemetry::StringValue>), ServerAddress(::opentelemetry::StringValue), } /// A request to an upstream server failed. pub fn r#emit_upstream_failed(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#error_type: ::opentelemetry::StringValue, options: impl IntoIterator) { let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let mut attributes = ::smallvec::SmallVec::<[UpstreamFailedOption; 1]>::new(); + let mut attributes = ::smallvec::SmallVec::<[UpstreamFailedOption; 2]>::new(); for option in options { match option { UpstreamFailedOption::Severity(value) => severity = value, @@ -30,14 +31,13 @@ pub fn r#emit_upstream_failed(context: &::open let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - let attribute = ::opentelemetry::KeyValue::new("error.type", r#error_type); - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + record.add_attribute("error.type", r#error_type); for option in attributes { - let attribute = match option { - UpstreamFailedOption::ServerAddress(value) => ::opentelemetry::KeyValue::new("server.address", value), + match option { + UpstreamFailedOption::HttpRequestMethodList(value) => record.add_attribute("http.request.method_list", value.into_iter().collect::<::opentelemetry::logs::AnyValue>()), + UpstreamFailedOption::ServerAddress(value) => record.add_attribute("server.address", value), UpstreamFailedOption::Severity(_) | UpstreamFailedOption::Timestamp(_) => continue, - }; - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } } logger.inner().emit(record); } diff --git a/templates/code/rust/tests/imported/expected/logger.rs b/templates/code/rust/tests/imported/expected/logger.rs index 8235fca..137ef4c 100644 --- a/templates/code/rust/tests/imported/expected/logger.rs +++ b/templates/code/rust/tests/imported/expected/logger.rs @@ -1,8 +1,5 @@ use super::options::InstrumentationOptions; -use opentelemetry::logs::AnyValue; -use opentelemetry::{Array, Value}; - #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { @@ -15,19 +12,3 @@ impl Logger { impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } -pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { - match value { - Value::Bool(value) => value.into(), - Value::I64(value) => value.into(), - Value::F64(value) => value.into(), - Value::String(value) => value.into(), - Value::Array(array) => match array { - Array::Bool(values) => values.into_iter().collect::(), - Array::I64(values) => values.into_iter().collect::(), - Array::F64(values) => values.into_iter().collect::(), - Array::String(values) => values.into_iter().collect::(), - _ => AnyValue::String(array.to_string().into()), - }, - _ => AnyValue::String(value.to_string().into()), - } -} diff --git a/templates/code/rust/tests/imported/expected/myappattr.rs b/templates/code/rust/tests/imported/expected/myappattr.rs index 4987524..0e5c78c 100644 --- a/templates/code/rust/tests/imported/expected/myappattr.rs +++ b/templates/code/rust/tests/imported/expected/myappattr.rs @@ -54,3 +54,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskIdAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/imported/expected/scope.rs b/templates/code/rust/tests/imported/expected/scope.rs index 9ed8538..920a74d 100644 --- a/templates/code/rust/tests/imported/expected/scope.rs +++ b/templates/code/rust/tests/imported/expected/scope.rs @@ -4,8 +4,7 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("generated-semconv") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/imported/registry/model.yaml b/templates/code/rust/tests/imported/registry/model.yaml index c51ba44..3fc83d6 100644 --- a/templates/code/rust/tests/imported/registry/model.yaml +++ b/templates/code/rust/tests/imported/registry/model.yaml @@ -73,3 +73,5 @@ events: requirement_level: required - ref: server.address requirement_level: recommended + - ref: http.request.method_list + requirement_level: recommended diff --git a/templates/code/rust/tests/imported/test.rs b/templates/code/rust/tests/imported/test.rs index 61e7fb8..e1647e9 100644 --- a/templates/code/rust/tests/imported/test.rs +++ b/templates/code/rust/tests/imported/test.rs @@ -61,11 +61,47 @@ fn imported_native_string_arrays_format_derived_span_names() { provider.force_flush().unwrap(); let spans = exporter.get_finished_spans().unwrap(); assert_eq!(spans.len(), 1); - assert_eq!(spans[0].instrumentation_scope.name(), "generated_semconv"); - assert_eq!(spans[0].instrumentation_scope.version(), Some("0.0.0")); + assert_eq!(spans[0].instrumentation_scope.name(), "generated-semconv"); + assert_eq!(spans[0].instrumentation_scope.version(), None); assert_eq!( spans[0].instrumentation_scope.schema_url(), Some(generated_semconv::SCHEMA_URL) ); assert_eq!(spans[0].name, "[\"GET\",\"POST\"]"); } + +#[test] +fn imported_native_string_array_events_preserve_order_and_duplicates() { + let exporter = opentelemetry_sdk::logs::InMemoryLogExporter::default(); + let provider = opentelemetry_sdk::logs::SdkLoggerProvider::builder() + .with_simple_exporter(exporter.clone()) + .build(); + edgeevent::emit_upstream_failed( + &opentelemetry::Context::new(), + &logger::Logger::new(&provider, InstrumentationOptions::default()), + StringValue::from("timeout"), + [edgeevent::UpstreamFailedOption::HttpRequestMethodList( + vec![ + StringValue::from("GET"), + StringValue::from("GET"), + StringValue::from("POST"), + ], + )], + ); + provider.force_flush().unwrap(); + let records = exporter.get_emitted_logs().unwrap(); + let value = &records[0] + .record + .attributes_iter() + .find(|(key, _)| key.as_str() == "http.request.method_list") + .unwrap() + .1; + assert_eq!( + value, + &opentelemetry::logs::AnyValue::ListAny(Box::new(vec![ + "GET".into(), + "GET".into(), + "POST".into() + ])) + ); +} diff --git a/templates/code/rust/tests/imported_typed/expected/logger.rs b/templates/code/rust/tests/imported_typed/expected/logger.rs index 8235fca..137ef4c 100644 --- a/templates/code/rust/tests/imported_typed/expected/logger.rs +++ b/templates/code/rust/tests/imported_typed/expected/logger.rs @@ -1,8 +1,5 @@ use super::options::InstrumentationOptions; -use opentelemetry::logs::AnyValue; -use opentelemetry::{Array, Value}; - #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { @@ -15,19 +12,3 @@ impl Logger { impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } -pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { - match value { - Value::Bool(value) => value.into(), - Value::I64(value) => value.into(), - Value::F64(value) => value.into(), - Value::String(value) => value.into(), - Value::Array(array) => match array { - Array::Bool(values) => values.into_iter().collect::(), - Array::I64(values) => values.into_iter().collect::(), - Array::F64(values) => values.into_iter().collect::(), - Array::String(values) => values.into_iter().collect::(), - _ => AnyValue::String(array.to_string().into()), - }, - _ => AnyValue::String(value.to_string().into()), - } -} diff --git a/templates/code/rust/tests/imported_typed/expected/myappattr.rs b/templates/code/rust/tests/imported_typed/expected/myappattr.rs index 4987524..0e5c78c 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappattr.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappattr.rs @@ -54,3 +54,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskIdAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/imported_typed/expected/myappevent.rs b/templates/code/rust/tests/imported_typed/expected/myappevent.rs index 02542b2..832f6bd 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappevent.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappevent.rs @@ -30,14 +30,12 @@ pub fn r#emit_task_errored(context: &::opentel let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - let attribute = ::opentelemetry::KeyValue::from(r#error_type); - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + record.add_attribute(upstream::errorattr::TypeAttr::KEY, r#error_type); for option in attributes { - let attribute = match option { - TaskErroredOption::ServerPort(value) => ::opentelemetry::KeyValue::new("server.port", value), + match option { + TaskErroredOption::ServerPort(value) => record.add_attribute("server.port", value), TaskErroredOption::Severity(_) | TaskErroredOption::Timestamp(_) => continue, - }; - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } } logger.inner().emit(record); } diff --git a/templates/code/rust/tests/imported_typed/expected/scope.rs b/templates/code/rust/tests/imported_typed/expected/scope.rs index 9ed8538..920a74d 100644 --- a/templates/code/rust/tests/imported_typed/expected/scope.rs +++ b/templates/code/rust/tests/imported_typed/expected/scope.rs @@ -4,8 +4,7 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("generated-semconv") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs b/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs index 6a3b7f9..9ab9533 100644 --- a/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs +++ b/templates/code/rust/tests/integer_boundaries/expected/demoattr.rs @@ -36,3 +36,15 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(BoundaryAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: BoundaryAttr) -> Self { + let value: i64 = match value { + BoundaryAttr::Minimum => -9223372036854775808, + BoundaryAttr::Maximum => 9223372036854775807, + }; + value.into() + } +} diff --git a/templates/code/rust/tests/literal_escaping/expected/demoattr.rs b/templates/code/rust/tests/literal_escaping/expected/demoattr.rs index ab4c9a1..1a5a546 100644 --- a/templates/code/rust/tests/literal_escaping/expected/demoattr.rs +++ b/templates/code/rust/tests/literal_escaping/expected/demoattr.rs @@ -43,3 +43,15 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(LiteralAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: LiteralAttr) -> Self { + let value: &'static str = match value { + LiteralAttr::Literal => "backspace\\b formfeed\\f unicode\\u1234 doubled\\\\b tripled\\\\\\u0000", + LiteralAttr::Controls => "backspace\u{0008} formfeed\u{000c} unicode\u{0001} slash\\b", + }; + value.into() + } +} diff --git a/templates/code/rust/tests/literal_escaping/expected/scope.rs b/templates/code/rust/tests/literal_escaping/expected/scope.rs index 9ed8538..e45ba81 100644 --- a/templates/code/rust/tests/literal_escaping/expected/scope.rs +++ b/templates/code/rust/tests/literal_escaping/expected/scope.rs @@ -4,8 +4,8 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("literal \\b \\f \\u1234 quote\" double\\\\slash") + .with_version("controls \u{0008} \u{000c} \u{0001} literal\\b quote\"") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/literal_escaping/params.yaml b/templates/code/rust/tests/literal_escaping/params.yaml new file mode 100644 index 0000000..2e2ca96 --- /dev/null +++ b/templates/code/rust/tests/literal_escaping/params.yaml @@ -0,0 +1,3 @@ +params: + instrumentation_name: 'literal \b \f \u1234 quote" double\\slash' + instrumentation_version: "controls \b \f \u0001 literal\\b quote\"" diff --git a/templates/code/rust/tests/literal_escaping/test.rs b/templates/code/rust/tests/literal_escaping/test.rs index 478b469..a8cecfc 100644 --- a/templates/code/rust/tests/literal_escaping/test.rs +++ b/templates/code/rust/tests/literal_escaping/test.rs @@ -26,8 +26,14 @@ fn signal_metadata_preserves_literal_backslash_sequences() { provider.force_flush().unwrap(); let exported = exporter.get_finished_metrics().unwrap(); let scope = exported[0].scope_metrics().next().unwrap(); - assert_eq!(scope.scope().name(), "generated_semconv"); - assert_eq!(scope.scope().version(), Some("0.0.0")); + assert_eq!( + scope.scope().name(), + r#"literal \b \f \u1234 quote" double\\slash"# + ); + assert_eq!( + scope.scope().version(), + Some("controls \u{0008} \u{000c} \u{0001} literal\\b quote\"") + ); assert_eq!( scope.scope().schema_url(), Some(generated_semconv::SCHEMA_URL) diff --git a/templates/code/rust/tests/metrics/expected/authattr.rs b/templates/code/rust/tests/metrics/expected/authattr.rs index 563c8d2..03ad451 100644 --- a/templates/code/rust/tests/metrics/expected/authattr.rs +++ b/templates/code/rust/tests/metrics/expected/authattr.rs @@ -43,6 +43,18 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(MethodAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: MethodAttr) -> Self { + let value: &'static str = match value { + MethodAttr::Password => "password", + MethodAttr::Token => "token", + }; + value.into() + } +} /// Whether the attempt succeeded. #[derive(Debug, Clone, PartialEq, Copy)] pub struct SuccessAttr(bool); @@ -75,3 +87,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(SuccessAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: SuccessAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/metrics/expected/myappattr.rs b/templates/code/rust/tests/metrics/expected/myappattr.rs index c41ad67..a1b18f0 100644 --- a/templates/code/rust/tests/metrics/expected/myappattr.rs +++ b/templates/code/rust/tests/metrics/expected/myappattr.rs @@ -54,6 +54,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskIdAttr) -> Self { + value.0.into() + } +} /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskStateAttr { @@ -98,3 +106,15 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskStateAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskStateAttr) -> Self { + let value: &'static str = match value { + TaskStateAttr::Queued => "queued", + TaskStateAttr::Done => "done", + }; + value.into() + } +} diff --git a/templates/code/rust/tests/metrics/expected/scope.rs b/templates/code/rust/tests/metrics/expected/scope.rs index 9ed8538..920a74d 100644 --- a/templates/code/rust/tests/metrics/expected/scope.rs +++ b/templates/code/rust/tests/metrics/expected/scope.rs @@ -4,8 +4,7 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("generated-semconv") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/metrics/test.rs b/templates/code/rust/tests/metrics/test.rs index 440770d..35b5a17 100644 --- a/templates/code/rust/tests/metrics/test.rs +++ b/templates/code/rust/tests/metrics/test.rs @@ -67,13 +67,13 @@ fn synchronous_metrics_export_types_values_attributes_and_refinements() { provider.force_flush().unwrap(); let exported = exporter.get_finished_metrics().unwrap(); let scope = exported[0].scope_metrics().next().unwrap(); - assert_eq!(scope.scope().version(), Some("0.0.0")); + assert_eq!(scope.scope().version(), None); assert!(scope .scope() .attributes() .any(|attribute| attribute.key.as_str() == "scope.kind" && attribute.value.as_str() == "worker")); - assert_eq!(scope.scope().name(), "generated_semconv"); + assert_eq!(scope.scope().name(), "generated-semconv"); assert_eq!( scope.scope().schema_url(), Some(generated_semconv::SCHEMA_URL) @@ -214,8 +214,8 @@ fn observable_callbacks_export_values_and_typed_attributes() { provider.force_flush().unwrap(); let exported = exporter.get_finished_metrics().unwrap(); let scope = exported[0].scope_metrics().next().unwrap(); - assert_eq!(scope.scope().name(), "generated_semconv"); - assert_eq!(scope.scope().version(), Some("0.0.0")); + assert_eq!(scope.scope().name(), "generated-semconv"); + assert_eq!(scope.scope().version(), None); assert_eq!( scope.scope().schema_url(), Some(generated_semconv::SCHEMA_URL) @@ -303,8 +303,8 @@ fn alternate_numeric_types_export_sync_and_observable_measurements() { .any(|attribute| attribute == &KeyValue::new("measurement.mode", mode)) }) .unwrap(); - assert_eq!(scope.scope().name(), "generated_semconv"); - assert_eq!(scope.scope().version(), Some("0.0.0")); + assert_eq!(scope.scope().name(), "generated-semconv"); + assert_eq!(scope.scope().version(), None); assert_eq!( scope.scope().schema_url(), Some(generated_semconv::SCHEMA_URL) diff --git a/templates/code/rust/tests/naming/expected/capsattr.rs b/templates/code/rust/tests/naming/expected/capsattr.rs index 619b334..1a956da 100644 --- a/templates/code/rust/tests/naming/expected/capsattr.rs +++ b/templates/code/rust/tests/naming/expected/capsattr.rs @@ -54,6 +54,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Http2STATUSApiIDAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: Http2STATUSApiIDAttr) -> Self { + value.0.into() + } +} /// Synthetic mode. #[derive(Debug, Clone, PartialEq, Copy)] pub enum Mode2STATEAttr { @@ -94,3 +102,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(Mode2STATEAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: Mode2STATEAttr) -> Self { + let value: &'static str = match value { + Mode2STATEAttr::HTTP2ReadySTATE => "ready", + }; + value.into() + } +} diff --git a/templates/code/rust/tests/naming/expected/scope.rs b/templates/code/rust/tests/naming/expected/scope.rs index 9ed8538..920a74d 100644 --- a/templates/code/rust/tests/naming/expected/scope.rs +++ b/templates/code/rust/tests/naming/expected/scope.rs @@ -4,8 +4,7 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("generated-semconv") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs index ac56186..b2b99fc 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs @@ -54,6 +54,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(MessageAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: MessageAttr) -> Self { + value.0.into() + } +} /// The type of the exception. #[derive(Debug, Clone, PartialEq)] pub struct TypeAttr(::opentelemetry::StringValue); @@ -109,3 +117,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TypeAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TypeAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs index 36af491..fac6756 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs @@ -30,14 +30,12 @@ pub fn r#emit_(context: &::opentelemetry::Cont let span = context.span(); let span_context = span.span_context(); if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } - let attribute = ::opentelemetry::KeyValue::from(r#exception_type); - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + record.add_attribute(super::exceptionattr::TypeAttr::KEY, r#exception_type); for option in attributes { - let attribute = match option { - Option::Message(value) => ::opentelemetry::KeyValue::from(value), + match option { + Option::Message(value) => record.add_attribute(super::exceptionattr::MessageAttr::KEY, value), Option::Severity(_) | Option::Timestamp(_) => continue, - }; - record.add_attribute(attribute.key, super::logger::log_value(attribute.value)); + } } logger.inner().emit(record); } diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs index ad0d10d..c38b36f 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs @@ -31,6 +31,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(SequenceAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: SequenceAttr) -> Self { + value.0.into() + } +} /// Name of the component that sent the heartbeat. #[derive(Debug, Clone, PartialEq)] pub struct SourceAttr(::opentelemetry::StringValue); @@ -86,3 +94,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(SourceAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: SourceAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/no_namespace/expected/hostattr.rs b/templates/code/rust/tests/no_namespace/expected/hostattr.rs index 456ceb2..be04645 100644 --- a/templates/code/rust/tests/no_namespace/expected/hostattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/hostattr.rs @@ -54,6 +54,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(IdAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: IdAttr) -> Self { + value.0.into() + } +} /// Name of the host. #[derive(Debug, Clone, PartialEq)] pub struct NameAttr(::opentelemetry::StringValue); @@ -109,3 +117,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(NameAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: NameAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/no_namespace/expected/logger.rs b/templates/code/rust/tests/no_namespace/expected/logger.rs index 8235fca..137ef4c 100644 --- a/templates/code/rust/tests/no_namespace/expected/logger.rs +++ b/templates/code/rust/tests/no_namespace/expected/logger.rs @@ -1,8 +1,5 @@ use super::options::InstrumentationOptions; -use opentelemetry::logs::AnyValue; -use opentelemetry::{Array, Value}; - #[derive(Clone, Debug)] pub struct Logger::Logger>(L); impl Logger { @@ -15,19 +12,3 @@ impl Logger { impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } -pub(crate) fn log_value(value: opentelemetry::Value) -> opentelemetry::logs::AnyValue { - match value { - Value::Bool(value) => value.into(), - Value::I64(value) => value.into(), - Value::F64(value) => value.into(), - Value::String(value) => value.into(), - Value::Array(array) => match array { - Array::Bool(values) => values.into_iter().collect::(), - Array::I64(values) => values.into_iter().collect::(), - Array::F64(values) => values.into_iter().collect::(), - Array::String(values) => values.into_iter().collect::(), - _ => AnyValue::String(array.to_string().into()), - }, - _ => AnyValue::String(value.to_string().into()), - } -} diff --git a/templates/code/rust/tests/no_namespace/expected/scope.rs b/templates/code/rust/tests/no_namespace/expected/scope.rs index 9ed8538..920a74d 100644 --- a/templates/code/rust/tests/no_namespace/expected/scope.rs +++ b/templates/code/rust/tests/no_namespace/expected/scope.rs @@ -4,8 +4,7 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("generated-semconv") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/params/expected/billingattr.rs b/templates/code/rust/tests/params/expected/billingattr.rs index 1649776..b49ff5f 100644 --- a/templates/code/rust/tests/params/expected/billingattr.rs +++ b/templates/code/rust/tests/params/expected/billingattr.rs @@ -54,6 +54,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(InvoiceIdAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: InvoiceIdAttr) -> Self { + value.0.into() + } +} /// ISO 4217 currency code of the amount. #[derive(Debug, Clone, PartialEq)] pub struct CurrencyAttr(::opentelemetry::StringValue); @@ -109,3 +117,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(CurrencyAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: CurrencyAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/params/expected/billingevent.rs b/templates/code/rust/tests/params/expected/billingevent.rs new file mode 100644 index 0000000..d8ecae9 --- /dev/null +++ b/templates/code/rust/tests/params/expected/billingevent.rs @@ -0,0 +1,32 @@ +#![allow(deprecated)] +use ::opentelemetry::logs::LogRecord; +use ::opentelemetry::trace::TraceContextExt; + +#[derive(Clone, Debug)] +pub enum InvoiceIssuedOption { + Severity(::opentelemetry::logs::Severity), + Timestamp(::std::time::SystemTime), +} +/// An invoice was issued. +pub fn r#emit_invoice_issued(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#billing_invoice_id: super::billingattr::InvoiceIdAttr, options: impl IntoIterator) { + let mut severity = ::opentelemetry::logs::Severity::Info; + let mut timestamp = None; + for option in options { + match option { + InvoiceIssuedOption::Severity(value) => severity = value, + InvoiceIssuedOption::Timestamp(value) => timestamp = Some(value), + } + } + if !logger.inner().event_enabled(severity, "", Some("acme.billing.invoice.issued")) { return; } + let _context_guard = context.clone().attach(); + let mut record = logger.inner().create_log_record(); + record.set_event_name("acme.billing.invoice.issued"); + record.set_severity_number(severity); + record.set_observed_timestamp(::std::time::SystemTime::now()); + if let Some(timestamp) = timestamp { record.set_timestamp(timestamp); } + let span = context.span(); + let span_context = span.span_context(); + if span_context.is_valid() { record.set_trace_context(span_context.trace_id(), span_context.span_id(), Some(span_context.trace_flags())); } + record.add_attribute(super::billingattr::InvoiceIdAttr::KEY, r#billing_invoice_id); + logger.inner().emit(record); +} diff --git a/templates/code/rust/tests/params/expected/billingspan.rs b/templates/code/rust/tests/params/expected/billingspan.rs new file mode 100644 index 0000000..fff58fb --- /dev/null +++ b/templates/code/rust/tests/params/expected/billingspan.rs @@ -0,0 +1,35 @@ +#![allow(deprecated)] +use ::opentelemetry::trace::{TraceContextExt, Tracer}; +use ::std::fmt::Write; + +/// An invoice is being issued. +pub struct InvoiceIssueSpan { span: S } +impl InvoiceIssueSpan { + pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context + where S: Send + Sync + 'static, + { + parent.with_span(self.span) + } + pub fn span(&mut self) -> &mut S { &mut self.span } + pub fn end(&mut self) { ::opentelemetry::trace::Span::end(&mut self.span); } + pub fn end_with_timestamp(&mut self, timestamp: ::std::time::SystemTime) { ::opentelemetry::trace::Span::end_with_timestamp(&mut self.span, timestamp); } + pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } + pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } +} +impl Default for InvoiceIssueSpan { + fn default() -> Self { + Self { span: super::tracer::Tracer::default().inner().start("acme.billing.invoice.issue") } + } +} + +pub fn r#start_invoice_issue(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, r#billing_invoice_id: super::billingattr::InvoiceIdAttr) -> InvoiceIssueSpan { + let mut name = String::with_capacity("invoice ".len() + ::std::convert::AsRef::::as_ref(&r#billing_invoice_id).len()); + name.push_str("invoice "); + write!(&mut name, "{}", r#billing_invoice_id).expect("writing a span name to String cannot fail"); + let attributes: [::opentelemetry::KeyValue; 1] = [::opentelemetry::KeyValue::from(r#billing_invoice_id)]; + let span = tracer.inner().span_builder(name) + .with_kind(::opentelemetry::trace::SpanKind::Internal) + .with_attributes(attributes) + .start_with_context(tracer.inner(), context); + InvoiceIssueSpan { span } +} diff --git a/templates/code/rust/tests/params/expected/logger.rs b/templates/code/rust/tests/params/expected/logger.rs new file mode 100644 index 0000000..137ef4c --- /dev/null +++ b/templates/code/rust/tests/params/expected/logger.rs @@ -0,0 +1,14 @@ +use super::options::InstrumentationOptions; + +#[derive(Clone, Debug)] +pub struct Logger::Logger>(L); +impl Logger { + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let logger = provider.logger_with_scope(options.scope.into()); + Self(logger) + } + pub fn inner(&self) -> &L { &self.0 } +} +impl Default for Logger { + fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } +} diff --git a/templates/code/rust/tests/params/expected/mod.rs b/templates/code/rust/tests/params/expected/mod.rs index c36f547..bc8ad5f 100644 --- a/templates/code/rust/tests/params/expected/mod.rs +++ b/templates/code/rust/tests/params/expected/mod.rs @@ -9,4 +9,8 @@ pub mod myappattr; pub mod scope; pub mod options; pub mod meter; +pub mod tracer; +pub mod logger; +pub mod billingevent; pub mod billingmetric; +pub mod billingspan; diff --git a/templates/code/rust/tests/params/expected/myappattr.rs b/templates/code/rust/tests/params/expected/myappattr.rs index 15e3f47..85bebf0 100644 --- a/templates/code/rust/tests/params/expected/myappattr.rs +++ b/templates/code/rust/tests/params/expected/myappattr.rs @@ -54,3 +54,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(RequestUrlAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: RequestUrlAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/params/expected/scope.rs b/templates/code/rust/tests/params/expected/scope.rs index 9ed8538..f5c5ec7 100644 --- a/templates/code/rust/tests/params/expected/scope.rs +++ b/templates/code/rust/tests/params/expected/scope.rs @@ -4,8 +4,8 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("synthetic-billing") + .with_version("2.3.4") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/params/expected/tracer.rs b/templates/code/rust/tests/params/expected/tracer.rs new file mode 100644 index 0000000..bde566c --- /dev/null +++ b/templates/code/rust/tests/params/expected/tracer.rs @@ -0,0 +1,13 @@ +use super::options::InstrumentationOptions; + +pub struct Tracer(T); +impl Tracer { + pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { + let tracer = provider.tracer_with_scope(options.scope.into()); + Self(tracer) + } + pub fn inner(&self) -> &T { &self.0 } +} +impl Default for Tracer { + fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), InstrumentationOptions::default()) } +} diff --git a/templates/code/rust/tests/params/params.yaml b/templates/code/rust/tests/params/params.yaml index dbafdc2..7a7679d 100644 --- a/templates/code/rust/tests/params/params.yaml +++ b/templates/code/rust/tests/params/params.yaml @@ -1,4 +1,6 @@ params: + instrumentation_name: synthetic-billing + instrumentation_version: "2.3.4" module_description: Typed telemetry for a synthetic registry. header_source: model/ regenerate_command: mise run generate diff --git a/templates/code/rust/tests/params/registry/model.yaml b/templates/code/rust/tests/params/registry/model.yaml index d4b4995..889205a 100644 --- a/templates/code/rust/tests/params/registry/model.yaml +++ b/templates/code/rust/tests/params/registry/model.yaml @@ -40,3 +40,22 @@ metrics: requirement_level: recommended - ref: myapp.request.url requirement_level: recommended +spans: + - type: acme.billing.invoice.issue + kind: internal + stability: stable + requirement_level: recommended + brief: An invoice is being issued. + name: + note: "`invoice {acme.billing.invoice.id}`" + attributes: + - ref: acme.billing.invoice.id + requirement_level: required +events: + - name: acme.billing.invoice.issued + stability: stable + requirement_level: recommended + brief: An invoice was issued. + attributes: + - ref: acme.billing.invoice.id + requirement_level: required diff --git a/templates/code/rust/tests/params/test.rs b/templates/code/rust/tests/params/test.rs new file mode 100644 index 0000000..b6ada57 --- /dev/null +++ b/templates/code/rust/tests/params/test.rs @@ -0,0 +1,79 @@ +use generated_semconv::{ + billingattr, billingevent, billingmetric, billingspan, logger, meter, + options::InstrumentationOptions, scope::Scope, tracer, SCHEMA_URL, +}; +use opentelemetry::{InstrumentationScope, KeyValue}; +use opentelemetry_sdk::logs::{InMemoryLogExporter, SdkLoggerProvider}; +use opentelemetry_sdk::metrics::{InMemoryMetricExporter, PeriodicReader, SdkMeterProvider}; +use opentelemetry_sdk::trace::{InMemorySpanExporter, SdkTracerProvider}; +use std::time::Duration; + +fn options() -> InstrumentationOptions { + InstrumentationOptions { + scope: Scope { + attributes: vec![KeyValue::new("scope.kind", "configured")], + }, + } +} + +fn configured_identity(scope: &InstrumentationScope) { + assert_eq!(scope.name(), "synthetic-billing"); + assert_eq!(scope.version(), Some("2.3.4")); + assert_eq!(scope.schema_url(), Some(SCHEMA_URL)); + assert_eq!( + scope.attributes().collect::>(), + [&KeyValue::new("scope.kind", "configured")] + ); +} + +#[test] +fn configured_identity_is_shared_by_metrics_spans_and_events() { + let metric_exporter = InMemoryMetricExporter::default(); + let metric_provider = SdkMeterProvider::builder() + .with_reader( + PeriodicReader::builder(metric_exporter.clone()) + .with_interval(Duration::from_secs(3600)) + .build(), + ) + .build(); + billingmetric::InvoiceAmountHistogram::new(&meter::Meter::new(&metric_provider, options())) + .record(12.5, billingattr::InvoiceIdAttr::from("invoice-1"), []); + metric_provider.force_flush().unwrap(); + let metrics = metric_exporter.get_finished_metrics().unwrap(); + configured_identity(metrics[0].scope_metrics().next().unwrap().scope()); + + let span_exporter = InMemorySpanExporter::default(); + let span_provider = SdkTracerProvider::builder() + .with_simple_exporter(span_exporter.clone()) + .build(); + let tracer = tracer::Tracer::new(&span_provider, options()); + let context = opentelemetry::Context::new(); + let mut span = billingspan::start_invoice_issue( + &context, + &tracer, + billingattr::InvoiceIdAttr::from("invoice-1"), + ); + span.end(); + span_provider.force_flush().unwrap(); + let spans = span_exporter.get_finished_spans().unwrap(); + assert_eq!(spans[0].name, "invoice invoice-1"); + configured_identity(&spans[0].instrumentation_scope); + + let log_exporter = InMemoryLogExporter::default(); + let log_provider = SdkLoggerProvider::builder() + .with_simple_exporter(log_exporter.clone()) + .build(); + billingevent::emit_invoice_issued( + &context, + &logger::Logger::new(&log_provider, options()), + billingattr::InvoiceIdAttr::from("invoice-1"), + [], + ); + log_provider.force_flush().unwrap(); + let logs = log_exporter.get_emitted_logs().unwrap(); + assert_eq!( + logs[0].record.event_name(), + Some("acme.billing.invoice.issued") + ); + configured_identity(&logs[0].instrumentation); +} diff --git a/templates/code/rust/tests/spans/expected/myappattr.rs b/templates/code/rust/tests/spans/expected/myappattr.rs index 6861a8b..ff0f2b5 100644 --- a/templates/code/rust/tests/spans/expected/myappattr.rs +++ b/templates/code/rust/tests/spans/expected/myappattr.rs @@ -45,6 +45,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(ArrayFlagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::Bool(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: ArrayFlagsAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} /// Synthetic naming value. #[derive(Debug, Clone, PartialEq)] pub struct ArrayIndicesAttr(Vec); @@ -91,6 +99,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(ArrayIndicesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::I64(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: ArrayIndicesAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} /// Synthetic naming value. #[derive(Debug, Clone, PartialEq)] pub struct ArraySamplesAttr(Vec); @@ -137,6 +153,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(ArraySamplesAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::F64(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: ArraySamplesAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} /// Synthetic naming value. #[derive(Debug, Clone, PartialEq)] pub struct ArrayTagsAttr(Vec<::opentelemetry::StringValue>); @@ -189,6 +213,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(ArrayTagsAttr::KEY, ::opentelemetry::Value::Array(::opentelemetry::Array::String(value.0))) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: ArrayTagsAttr) -> Self { + value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() + } +} /// Synthetic naming value. #[derive(Debug, Clone, PartialEq, Copy)] pub struct NumberValueAttr(f64); @@ -221,6 +253,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(NumberValueAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: NumberValueAttr) -> Self { + value.0.into() + } +} /// Name of the queue the task came from. #[derive(Debug, Clone, PartialEq)] pub struct QueueNameAttr(::opentelemetry::StringValue); @@ -276,6 +316,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(QueueNameAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: QueueNameAttr) -> Self { + value.0.into() + } +} /// Number of the attempt, starting at one. #[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskAttemptAttr(i64); @@ -308,6 +356,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskAttemptAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskAttemptAttr) -> Self { + value.0.into() + } +} /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] pub struct TaskIdAttr(::opentelemetry::StringValue); @@ -363,6 +419,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskIdAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskIdAttr) -> Self { + value.0.into() + } +} /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskStateAttr { @@ -407,3 +471,15 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(TaskStateAttr::KEY, value) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: TaskStateAttr) -> Self { + let value: &'static str = match value { + TaskStateAttr::Queued => "queued", + TaskStateAttr::Done => "done", + }; + value.into() + } +} diff --git a/templates/code/rust/tests/spans/expected/scope.rs b/templates/code/rust/tests/spans/expected/scope.rs index 9ed8538..920a74d 100644 --- a/templates/code/rust/tests/spans/expected/scope.rs +++ b/templates/code/rust/tests/spans/expected/scope.rs @@ -4,8 +4,7 @@ pub struct Scope { } impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { - Self::builder(env!("CARGO_PKG_NAME")) - .with_version(env!("CARGO_PKG_VERSION")) + Self::builder("generated-semconv") .with_schema_url(super::SCHEMA_URL) .with_attributes(value.attributes) .build() diff --git a/templates/code/rust/tests/spans/expected/workerattr.rs b/templates/code/rust/tests/spans/expected/workerattr.rs index 03463aa..46d82cb 100644 --- a/templates/code/rust/tests/spans/expected/workerattr.rs +++ b/templates/code/rust/tests/spans/expected/workerattr.rs @@ -54,6 +54,14 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(HostNameAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: HostNameAttr) -> Self { + value.0.into() + } +} /// Port the worker listens on. #[derive(Debug, Clone, PartialEq, Copy)] pub struct HostPortAttr(i64); @@ -86,3 +94,11 @@ impl From for ::opentelemetry::KeyValue { ::opentelemetry::KeyValue::new(HostPortAttr::KEY, value.0) } } + +#[allow(deprecated)] +impl From for ::opentelemetry::logs::AnyValue { + #[inline] + fn from(value: HostPortAttr) -> Self { + value.0.into() + } +} diff --git a/templates/code/rust/tests/spans/test.rs b/templates/code/rust/tests/spans/test.rs index 4f9f491..6941404 100644 --- a/templates/code/rust/tests/spans/test.rs +++ b/templates/code/rust/tests/spans/test.rs @@ -125,8 +125,8 @@ fn derived_names_refinements_parent_context_and_late_attributes() { .iter() .any(|kv| kv.key.as_str() == "myapp.task.id" && kv.value.as_str() == "task-1")); assert_eq!(parent.instrumentation_scope.schema_url(), Some(SCHEMA_URL)); - assert_eq!(parent.instrumentation_scope.name(), "generated_semconv"); - assert_eq!(parent.instrumentation_scope.version(), Some("0.0.0")); + assert_eq!(parent.instrumentation_scope.name(), "generated-semconv"); + assert_eq!(parent.instrumentation_scope.version(), None); assert!(parent .instrumentation_scope .attributes() diff --git a/templates/code/rust/weaver.yaml b/templates/code/rust/weaver.yaml index 20d461f..49ae0ef 100644 --- a/templates/code/rust/weaver.yaml +++ b/templates/code/rust/weaver.yaml @@ -3,6 +3,8 @@ whitespace_control: lstrip_blocks: true params: + instrumentation_name: generated-semconv + instrumentation_version: "" module_description: "" histogram_boundaries_by_unit: s: [0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10] @@ -26,7 +28,11 @@ templates: def rust_literal: if type == "string" then explode | map([.] | implode | tojson | gsub("\\\\b"; "\\u{0008}") | gsub("\\\\f"; "\\u{000c}") | gsub("\\\\u(?[0-9a-fA-F]{4})"; "\\u{\(.code)}") | .[1:-1]) | join("") | "\"" + . + "\"" else tostring end; - .schema_url as $schema + if ($instrumentation_name | type) != "string" then error("instrumentation_name must be a nonempty string") + elif ($instrumentation_name | length) == 0 then error("instrumentation_name must be a nonempty string") + elif ($instrumentation_version | type) != "string" then error("instrumentation_version must be a string") + else . end + | .schema_url as $schema | if $schema == null or $schema == "https://unknown/unknown" or ($schema | test("^https?://[^/]+(/[^/]+)*/[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z.-]+)?$") | not) then error("the registry schema_url must name a schema version") else . end | {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $opts @@ -615,13 +621,12 @@ templates: - template: logger.rs.j2 filter: |- def kept($o): - stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o) - | map(.attributes = ((.attributes // []) | stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o))); + stability_filter($o) | code_generation_exclude_filter($o) | deprecated_filter($o); {v2: true, exclude_deprecated: $exclude_deprecated, stable_only: $stable_only} as $o | [.registry.events // [] | .[].name] as $bases | ((.registry.events // [] | kept($o)) + (.refinements.events // [] | map(select(.id as $id | $bases | any(. == $id) | not)) | kept($o))) - | if length > 0 then [{has_attributes: any((.attributes | length) > 0)}] else [] end + | if length > 0 then [{}] else [] end application_mode: each file_name: logger.rs From 27b8ba281bd4a673ef9720f405007e99ef863e8b Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Mon, 5 Oct 2026 15:40:32 -0400 Subject: [PATCH 13/14] fix: keep generated Rust APIs usable Signed-off-by: Yordis Prieto --- templates/code/rust/events.rs.j2 | 4 +- templates/code/rust/signal_helpers.j2 | 1 + templates/code/rust/spans.rs.j2 | 2 +- .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 10 +++ .../expected-error.txt | 1 + .../registry/manifest.yaml | 2 + .../registry/model.yaml | 15 ++++ .../dependency/manifest.yaml | 2 + .../dependency/model.yaml | 7 ++ .../expected-error.txt | 1 + .../registry/manifest.yaml | 6 ++ .../registry/model.yaml | 9 +++ .../rust/tests/imported/expected/tracer.rs | 1 + .../tests/imported_typed/expected/tracer.rs | 1 + .../no_namespace/expected/exceptionevent.rs | 14 ++-- .../no_namespace/expected/heartbeatspan.rs | 2 +- .../tests/no_namespace/expected/tracer.rs | 1 + .../code/rust/tests/no_namespace/test.rs | 60 ++++++++++++++++ .../code/rust/tests/params/expected/tracer.rs | 1 + .../code/rust/tests/spans/expected/tracer.rs | 1 + .../rust/tests/spans/tests/tracer_traits.rs | 71 +++++++++++++++++++ templates/code/rust/tracer.rs.j2 | 1 + templates/code/rust/weaver.yaml | 4 +- 25 files changed, 207 insertions(+), 13 deletions(-) create mode 100644 templates/code/rust/tests/error_event_option_collision/expected-error.txt create mode 100644 templates/code/rust/tests/error_event_option_collision/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_event_option_collision/registry/model.yaml create mode 100644 templates/code/rust/tests/error_event_span_context_shadow/expected-error.txt create mode 100644 templates/code/rust/tests/error_event_span_context_shadow/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_event_span_context_shadow/registry/model.yaml create mode 100644 templates/code/rust/tests/error_event_span_shadow/dependency/manifest.yaml create mode 100644 templates/code/rust/tests/error_event_span_shadow/dependency/model.yaml create mode 100644 templates/code/rust/tests/error_event_span_shadow/expected-error.txt create mode 100644 templates/code/rust/tests/error_event_span_shadow/registry/manifest.yaml create mode 100644 templates/code/rust/tests/error_event_span_shadow/registry/model.yaml create mode 100644 templates/code/rust/tests/no_namespace/test.rs create mode 100644 templates/code/rust/tests/spans/tests/tracer_traits.rs diff --git a/templates/code/rust/events.rs.j2 b/templates/code/rust/events.rs.j2 index 555017b..2af44aa 100644 --- a/templates/code/rust/events.rs.j2 +++ b/templates/code/rust/events.rs.j2 @@ -5,7 +5,7 @@ use ::opentelemetry::trace::TraceContextExt; {% import "signal_helpers.j2" as h %} {% for def in ctx.events %} -{% set name = h.exported(def.short_name) %} +{% set name = h.exported(def.short_name) or 'Event' %} #[derive(Clone, Debug)] pub enum {{ name }}Option { Severity(::opentelemetry::logs::Severity), @@ -18,7 +18,7 @@ pub enum {{ name }}Option { {% endfor %} } {{ (h.docs(def) ~ "\n" ~ h.deprecated(def)) | trim }} -pub fn {{ h.ident('emit.' ~ def.short_name) }}(context: &::opentelemetry::Context, logger: &super::logger::Logger{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}, options: impl IntoIterator) { +pub fn {{ h.signal_fn('emit', def.short_name) }}(context: &::opentelemetry::Context, logger: &super::logger::Logger{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}, options: impl IntoIterator) { let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; {% if def.optional %} diff --git a/templates/code/rust/signal_helpers.j2 b/templates/code/rust/signal_helpers.j2 index 56f520c..90ef6e9 100644 --- a/templates/code/rust/signal_helpers.j2 +++ b/templates/code/rust/signal_helpers.j2 @@ -3,6 +3,7 @@ {%- endmacro %} {% macro exported(value) -%}{% for dotted in value.split(".") %}{% for segment in dotted.split("_") %}{{ segment[:1] | upper }}{{ segment[1:] }}{% endfor %}{% endfor %}{%- endmacro %} {% macro ident(value) -%}r#{{ value | snake_case }}{%- endmacro %} +{% macro signal_fn(prefix, short_name) -%}{{ ident(prefix ~ ('.' ~ short_name if short_name else '')) }}{%- endmacro %} {% macro attr_type(a) -%} {%- if a.imported -%}{{ "::opentelemetry::StringValue" if a.attr_type == "string" else ("Vec<::opentelemetry::StringValue>" if a.attr_type == "string[]" else a.attr_type | map_text("rust_type")) }} {%- else -%}{{ a.attr_import_path if a.attr_import_path else 'super::' ~ a.attr_namespace ~ 'attr' }}::{{ exported(a.attr_short_name) }}Attr diff --git a/templates/code/rust/spans.rs.j2 b/templates/code/rust/spans.rs.j2 index 436ca1b..4726071 100644 --- a/templates/code/rust/spans.rs.j2 +++ b/templates/code/rust/spans.rs.j2 @@ -109,7 +109,7 @@ impl Default for {{ span }} { } } {{ h.deprecated(def) }} -pub fn {{ h.ident('start.' ~ def.short_name) }}(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer{% if not def.name_parts %}, name: {{ name }}Name{% endif %}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) -> {{ span }} { +pub fn {{ h.signal_fn('start', def.short_name) }}(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer{% if not def.name_parts %}, name: {{ name }}Name{% endif %}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) -> {{ span }} { {% if def.name_parts %} let mut name = String::with_capacity({% for part in def.name_parts %}{% if not loop.first %} + {% endif %}{% if part.attr %}{{ name_capacity(part.attr, h.ident(part.attr.attr_param)) }}{% else %}{{ h.literal(part.text) }}.len(){% endif %}{% endfor %}); {% for part in def.name_parts %} diff --git a/templates/code/rust/tests/error_event_option_collision/expected-error.txt b/templates/code/rust/tests/error_event_option_collision/expected-error.txt new file mode 100644 index 0000000..4cc16a3 --- /dev/null +++ b/templates/code/rust/tests/error_event_option_collision/expected-error.txt @@ -0,0 +1 @@ +package exceptionevent has events that render to the same Rust identifier diff --git a/templates/code/rust/tests/error_event_option_collision/registry/manifest.yaml b/templates/code/rust/tests/error_event_option_collision/registry/manifest.yaml new file mode 100644 index 0000000..9f878f4 --- /dev/null +++ b/templates/code/rust/tests/error_event_option_collision/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: event_option_collision +schema_url: https://example.com/schemas/event-option-collision/1.0.0 diff --git a/templates/code/rust/tests/error_event_option_collision/registry/model.yaml b/templates/code/rust/tests/error_event_option_collision/registry/model.yaml new file mode 100644 index 0000000..d4fb4a2 --- /dev/null +++ b/templates/code/rust/tests/error_event_option_collision/registry/model.yaml @@ -0,0 +1,10 @@ +file_format: definition/2 +events: + - name: exception + stability: stable + requirement_level: recommended + brief: A synthetic exception occurred. + - name: exception.event + stability: stable + requirement_level: recommended + brief: Another synthetic exception occurred. diff --git a/templates/code/rust/tests/error_event_span_context_shadow/expected-error.txt b/templates/code/rust/tests/error_event_span_context_shadow/expected-error.txt new file mode 100644 index 0000000..26c139c --- /dev/null +++ b/templates/code/rust/tests/error_event_span_context_shadow/expected-error.txt @@ -0,0 +1 @@ +event probe.recorded has required attributes whose Rust parameter would shadow a name its Emit function declares: span.context diff --git a/templates/code/rust/tests/error_event_span_context_shadow/registry/manifest.yaml b/templates/code/rust/tests/error_event_span_context_shadow/registry/manifest.yaml new file mode 100644 index 0000000..8fc6c74 --- /dev/null +++ b/templates/code/rust/tests/error_event_span_context_shadow/registry/manifest.yaml @@ -0,0 +1,2 @@ +name: synthetic-event-shadow +schema_url: https://example.com/schemas/event-shadow/1.0.0 diff --git a/templates/code/rust/tests/error_event_span_context_shadow/registry/model.yaml b/templates/code/rust/tests/error_event_span_context_shadow/registry/model.yaml new file mode 100644 index 0000000..abc08ac --- /dev/null +++ b/templates/code/rust/tests/error_event_span_context_shadow/registry/model.yaml @@ -0,0 +1,15 @@ +file_format: definition/2 +attributes: + - key: span.context + type: int + stability: stable + brief: A synthetic numeric span context attribute. + examples: 1 +events: + - name: probe.recorded + requirement_level: recommended + stability: stable + brief: A synthetic record event. + attributes: + - ref: span.context + requirement_level: required diff --git a/templates/code/rust/tests/error_event_span_shadow/dependency/manifest.yaml b/templates/code/rust/tests/error_event_span_shadow/dependency/manifest.yaml new file mode 100644 index 0000000..489cb50 --- /dev/null +++ b/templates/code/rust/tests/error_event_span_shadow/dependency/manifest.yaml @@ -0,0 +1,2 @@ +name: synthetic-upstream +schema_url: https://example.com/schemas/upstream/1.0.0 diff --git a/templates/code/rust/tests/error_event_span_shadow/dependency/model.yaml b/templates/code/rust/tests/error_event_span_shadow/dependency/model.yaml new file mode 100644 index 0000000..1a2c51e --- /dev/null +++ b/templates/code/rust/tests/error_event_span_shadow/dependency/model.yaml @@ -0,0 +1,7 @@ +file_format: definition/2 +attributes: + - key: span + type: int + stability: stable + brief: A synthetic numeric span attribute. + examples: 1 diff --git a/templates/code/rust/tests/error_event_span_shadow/expected-error.txt b/templates/code/rust/tests/error_event_span_shadow/expected-error.txt new file mode 100644 index 0000000..245b538 --- /dev/null +++ b/templates/code/rust/tests/error_event_span_shadow/expected-error.txt @@ -0,0 +1 @@ +event probe.recorded has required attributes whose Rust parameter would shadow a name its Emit function declares: span diff --git a/templates/code/rust/tests/error_event_span_shadow/registry/manifest.yaml b/templates/code/rust/tests/error_event_span_shadow/registry/manifest.yaml new file mode 100644 index 0000000..cd94a67 --- /dev/null +++ b/templates/code/rust/tests/error_event_span_shadow/registry/manifest.yaml @@ -0,0 +1,6 @@ +name: synthetic-event-shadow +schema_url: https://example.com/schemas/event-shadow/1.0.0 +dependencies: + - name: upstream + registry_path: dependency + schema_url: https://example.com/schemas/upstream/1.0.0 diff --git a/templates/code/rust/tests/error_event_span_shadow/registry/model.yaml b/templates/code/rust/tests/error_event_span_shadow/registry/model.yaml new file mode 100644 index 0000000..e0665ca --- /dev/null +++ b/templates/code/rust/tests/error_event_span_shadow/registry/model.yaml @@ -0,0 +1,9 @@ +file_format: definition/2 +events: + - name: probe.recorded + requirement_level: recommended + stability: stable + brief: A synthetic record event. + attributes: + - ref: span + requirement_level: required diff --git a/templates/code/rust/tests/imported/expected/tracer.rs b/templates/code/rust/tests/imported/expected/tracer.rs index bde566c..0dc2a89 100644 --- a/templates/code/rust/tests/imported/expected/tracer.rs +++ b/templates/code/rust/tests/imported/expected/tracer.rs @@ -1,5 +1,6 @@ use super::options::InstrumentationOptions; +#[derive(Clone, Debug)] pub struct Tracer(T); impl Tracer { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { diff --git a/templates/code/rust/tests/imported_typed/expected/tracer.rs b/templates/code/rust/tests/imported_typed/expected/tracer.rs index bde566c..0dc2a89 100644 --- a/templates/code/rust/tests/imported_typed/expected/tracer.rs +++ b/templates/code/rust/tests/imported_typed/expected/tracer.rs @@ -1,5 +1,6 @@ use super::options::InstrumentationOptions; +#[derive(Clone, Debug)] pub struct Tracer(T); impl Tracer { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs index fac6756..4123d2c 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionevent.rs @@ -3,20 +3,20 @@ use ::opentelemetry::logs::LogRecord; use ::opentelemetry::trace::TraceContextExt; #[derive(Clone, Debug)] -pub enum Option { +pub enum EventOption { Severity(::opentelemetry::logs::Severity), Timestamp(::std::time::SystemTime), Message(super::exceptionattr::MessageAttr), } /// A noteworthy exception occurred. -pub fn r#emit_(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#exception_type: super::exceptionattr::TypeAttr, options: impl IntoIterator) { +pub fn r#emit(context: &::opentelemetry::Context, logger: &super::logger::Logger, r#exception_type: super::exceptionattr::TypeAttr, options: impl IntoIterator) { let mut severity = ::opentelemetry::logs::Severity::Info; let mut timestamp = None; - let mut attributes = ::smallvec::SmallVec::<[Option; 1]>::new(); + let mut attributes = ::smallvec::SmallVec::<[EventOption; 1]>::new(); for option in options { match option { - Option::Severity(value) => severity = value, - Option::Timestamp(value) => timestamp = Some(value), + EventOption::Severity(value) => severity = value, + EventOption::Timestamp(value) => timestamp = Some(value), attribute => attributes.push(attribute), } } @@ -33,8 +33,8 @@ pub fn r#emit_(context: &::opentelemetry::Cont record.add_attribute(super::exceptionattr::TypeAttr::KEY, r#exception_type); for option in attributes { match option { - Option::Message(value) => record.add_attribute(super::exceptionattr::MessageAttr::KEY, value), - Option::Severity(_) | Option::Timestamp(_) => continue, + EventOption::Message(value) => record.add_attribute(super::exceptionattr::MessageAttr::KEY, value), + EventOption::Severity(_) | EventOption::Timestamp(_) => continue, } } logger.inner().emit(record); diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs index f72c617..c356b3b 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs @@ -57,7 +57,7 @@ impl Default for Span { } } -pub fn r#start_(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: Name, r#heartbeat_sequence: super::heartbeatattr::SequenceAttr, options: impl IntoIterator) -> Span { +pub fn r#start(context: &::opentelemetry::Context, tracer: &super::tracer::Tracer, name: Name, r#heartbeat_sequence: super::heartbeatattr::SequenceAttr, options: impl IntoIterator) -> Span { let name = if name.0.is_empty() { ::std::borrow::Cow::Borrowed("heartbeat") } else { name.0 }; let attributes: [::opentelemetry::KeyValue; 1] = [::opentelemetry::KeyValue::from(r#heartbeat_sequence)]; let span = tracer.inner().span_builder(name) diff --git a/templates/code/rust/tests/no_namespace/expected/tracer.rs b/templates/code/rust/tests/no_namespace/expected/tracer.rs index bde566c..0dc2a89 100644 --- a/templates/code/rust/tests/no_namespace/expected/tracer.rs +++ b/templates/code/rust/tests/no_namespace/expected/tracer.rs @@ -1,5 +1,6 @@ use super::options::InstrumentationOptions; +#[derive(Clone, Debug)] pub struct Tracer(T); impl Tracer { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { diff --git a/templates/code/rust/tests/no_namespace/test.rs b/templates/code/rust/tests/no_namespace/test.rs new file mode 100644 index 0000000..cbc0731 --- /dev/null +++ b/templates/code/rust/tests/no_namespace/test.rs @@ -0,0 +1,60 @@ +use generated_semconv::{ + exceptionattr, exceptionevent, heartbeatattr, heartbeatspan, logger, + options::InstrumentationOptions, tracer, +}; +use opentelemetry::logs::{AnyValue, Severity}; +use opentelemetry_sdk::logs::{InMemoryLogExporter, SdkLoggerProvider}; +use opentelemetry_sdk::trace::{InMemorySpanExporter, SdkTracerProvider}; + +#[test] +fn empty_short_names_expose_bare_functions_and_unambiguous_options() { + let context = opentelemetry::Context::new(); + let logs = InMemoryLogExporter::default(); + let logger_provider = SdkLoggerProvider::builder() + .with_simple_exporter(logs.clone()) + .build(); + let logger = logger::Logger::new(&logger_provider, InstrumentationOptions::default()); + exceptionevent::emit( + &context, + &logger, + exceptionattr::TypeAttr::from("ValueError"), + [ + exceptionevent::EventOption::Message(exceptionattr::MessageAttr::from("failed")), + exceptionevent::EventOption::Severity(Severity::Warn), + ], + ); + logger_provider.force_flush().unwrap(); + let records = logs.get_emitted_logs().unwrap(); + assert_eq!(records.len(), 1); + assert_eq!(records[0].record.event_name(), Some("exception")); + assert_eq!(records[0].record.severity_number(), Some(Severity::Warn)); + assert!(records[0].record.attributes_iter().any(|(key, value)| { + key.as_str() == "exception.message" && value == &AnyValue::String("failed".into()) + })); + + let spans = InMemorySpanExporter::default(); + let tracer_provider = SdkTracerProvider::builder() + .with_simple_exporter(spans.clone()) + .build(); + let tracer = tracer::Tracer::new(&tracer_provider, InstrumentationOptions::default()); + let mut span = heartbeatspan::start( + &context, + &tracer, + heartbeatspan::Name::default(), + heartbeatattr::SequenceAttr::from(7), + [heartbeatspan::StartAttr::Source( + heartbeatattr::SourceAttr::from("worker"), + )], + ); + span.end(); + tracer_provider.force_flush().unwrap(); + let spans = spans.get_finished_spans().unwrap(); + assert_eq!(spans.len(), 1); + assert_eq!(spans[0].name, "heartbeat"); + assert!(spans[0] + .attributes + .contains(&opentelemetry::KeyValue::new("heartbeat.sequence", 7))); + assert!(spans[0] + .attributes + .contains(&opentelemetry::KeyValue::new("heartbeat.source", "worker"))); +} diff --git a/templates/code/rust/tests/params/expected/tracer.rs b/templates/code/rust/tests/params/expected/tracer.rs index bde566c..0dc2a89 100644 --- a/templates/code/rust/tests/params/expected/tracer.rs +++ b/templates/code/rust/tests/params/expected/tracer.rs @@ -1,5 +1,6 @@ use super::options::InstrumentationOptions; +#[derive(Clone, Debug)] pub struct Tracer(T); impl Tracer { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { diff --git a/templates/code/rust/tests/spans/expected/tracer.rs b/templates/code/rust/tests/spans/expected/tracer.rs index bde566c..0dc2a89 100644 --- a/templates/code/rust/tests/spans/expected/tracer.rs +++ b/templates/code/rust/tests/spans/expected/tracer.rs @@ -1,5 +1,6 @@ use super::options::InstrumentationOptions; +#[derive(Clone, Debug)] pub struct Tracer(T); impl Tracer { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { diff --git a/templates/code/rust/tests/spans/tests/tracer_traits.rs b/templates/code/rust/tests/spans/tests/tracer_traits.rs new file mode 100644 index 0000000..9d688b1 --- /dev/null +++ b/templates/code/rust/tests/spans/tests/tracer_traits.rs @@ -0,0 +1,71 @@ +use generated_semconv::{options::InstrumentationOptions, scope::Scope, tracer, SCHEMA_URL}; +use opentelemetry::trace::{Span as _, Tracer as _}; +use opentelemetry::{Context, InstrumentationScope, KeyValue}; +use opentelemetry_sdk::trace::{InMemorySpanExporter, SdkTracerProvider}; +use std::fmt::Debug; + +fn require_clone_and_debug(_: &T) {} + +#[test] +fn default_tracer_supports_clone_and_debug() { + let tracer = tracer::Tracer::default(); + require_clone_and_debug(&tracer); + require_clone_and_debug(&tracer.clone()); +} + +#[test] +fn cloned_sdk_tracer_preserves_scope_and_exports_spans() { + let exporter = InMemorySpanExporter::default(); + let provider = SdkTracerProvider::builder() + .with_simple_exporter(exporter.clone()) + .build(); + let original = tracer::Tracer::new( + &provider, + InstrumentationOptions { + scope: Scope { + attributes: vec![KeyValue::new("scope.kind", "clone-test")], + }, + }, + ); + require_clone_and_debug(&original); + let cloned = original.clone(); + drop(original); + let mut span = cloned.inner().start("cloned-handle"); + span.end(); + provider.force_flush().unwrap(); + let spans = exporter.get_finished_spans().unwrap(); + assert_eq!(spans.len(), 1); + assert_eq!(spans[0].name, "cloned-handle"); + assert_eq!( + spans[0].instrumentation_scope.schema_url(), + Some(SCHEMA_URL) + ); + assert!(spans[0] + .instrumentation_scope + .attributes() + .any(|attribute| attribute == &KeyValue::new("scope.kind", "clone-test"))); + provider.shutdown().unwrap(); +} + +struct BareTracer; +impl opentelemetry::trace::Tracer for BareTracer { + type Span = opentelemetry::trace::noop::NoopSpan; + fn build_with_context(&self, _: opentelemetry::trace::SpanBuilder, _: &Context) -> Self::Span { + opentelemetry::trace::noop::NoopSpan::DEFAULT + } +} +struct BareProvider; +impl opentelemetry::trace::TracerProvider for BareProvider { + type Tracer = BareTracer; + fn tracer_with_scope(&self, _: InstrumentationScope) -> Self::Tracer { + BareTracer + } +} + +#[test] +fn custom_tracer_without_clone_or_debug_still_constructs_and_starts_spans() { + let tracer = tracer::Tracer::new(&BareProvider, InstrumentationOptions::default()); + let mut span = tracer.inner().start("bare-handle"); + assert!(!span.is_recording()); + span.end(); +} diff --git a/templates/code/rust/tracer.rs.j2 b/templates/code/rust/tracer.rs.j2 index 9062a76..ccca159 100644 --- a/templates/code/rust/tracer.rs.j2 +++ b/templates/code/rust/tracer.rs.j2 @@ -1,6 +1,7 @@ {%- filter trim %} use super::options::InstrumentationOptions; +#[derive(Clone, Debug)] pub struct Tracer(T); impl Tracer { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { diff --git a/templates/code/rust/weaver.yaml b/templates/code/rust/weaver.yaml index 49ae0ef..8ca0cd8 100644 --- a/templates/code/rust/weaver.yaml +++ b/templates/code/rust/weaver.yaml @@ -447,7 +447,7 @@ templates: | group_by(.attr_short_name | norm) | map(select(length > 1) | map(.key) | join(" and "))) as $optional_collisions | (.optional | map(select(.attr_short_name | norm | . as $p | ["severity", "timestamp"] | any(. == $p))) | map(.key)) as $reserved - | (.required | map(select(.attr_param | norm | . as $p | ["context", "logger", "options", "option", "record", "attributes", "severity", "timestamp"] | any(. == $p))) | map(.key)) as $shadowing + | (.required | map(select(.attr_param | norm | . as $p | ["context", "logger", "options", "option", "record", "attributes", "severity", "timestamp", "span", "spancontext"] | any(. == $p))) | map(.key)) as $shadowing | if ($required_collisions | length) > 0 then error("event \(.id) has required attributes that render to the same Rust parameter: \($required_collisions | join("; "))") elif ($optional_collisions | length) > 0 @@ -461,7 +461,7 @@ templates: | group_by(.namespace) | map( ([.[] | . as $def | .id as $event | (.short_name | norm) as $short - | (["P:emit" + $short, "P:" + $short + "option", + | (["P:emit" + $short, "P:" + (if $short == "" then "event" else $short end) + "option", "P:with" + $short + "severity", "P:with" + $short + "timestamp", "p:" + $short + "option", "p:" + $short + "eventseverity", "p:" + $short + "eventtimestamp"] + ($def.optional | map(.attr_short_name | norm) | map("P:with" + $short + ., "p:" + $short + "event" + .)))[] From a854ad104f35ee631747d6da9331504507621d1e Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Mon, 5 Oct 2026 15:54:41 -0400 Subject: [PATCH 14/14] style: improve generated Rust readability Signed-off-by: Yordis Prieto --- templates/code/rust/attributes.rs.j2 | 3 + templates/code/rust/logger.rs.j2 | 2 + templates/code/rust/meter.rs.j2 | 2 + templates/code/rust/metrics.rs.j2 | 18 ++- templates/code/rust/scope.rs.j2 | 1 + templates/code/rust/spans.rs.j2 | 11 +- .../rust/tests/allocations/expected/logger.rs | 2 + .../rust/tests/allocations/expected/meter.rs | 2 + .../tests/allocations/expected/probeattr.rs | 6 + .../tests/allocations/expected/probemetric.rs | 35 ++++- .../rust/tests/allocations/expected/scope.rs | 1 + .../tests/attributes/expected/authattr.rs | 3 + .../tests/attributes/expected/myappattr.rs | 18 +++ .../codegen_exclusion/expected/demoattr.rs | 2 + .../rust/tests/entities/expected/myappattr.rs | 8 ++ .../event_no_attributes/expected/logger.rs | 2 + .../event_no_attributes/expected/scope.rs | 1 + .../code/rust/tests/events/expected/logger.rs | 2 + .../rust/tests/events/expected/myappattr.rs | 6 + .../code/rust/tests/events/expected/scope.rs | 1 + .../rust/tests/events/expected/workerattr.rs | 1 + .../rust/tests/filtering/expected/authattr.rs | 2 + .../rust/tests/filtering/expected/taskattr.rs | 11 ++ .../expected/meter.rs | 2 + .../expected/myappattr.rs | 1 + .../expected/myappmetric.rs | 24 +++- .../expected/scope.rs | 1 + .../expected/meter.rs | 2 + .../expected/myappattr.rs | 1 + .../expected/myappmetric.rs | 12 +- .../expected/scope.rs | 1 + .../tests/imported/expected/edgemetric.rs | 7 +- .../rust/tests/imported/expected/edgespan.rs | 14 +- .../rust/tests/imported/expected/logger.rs | 2 + .../rust/tests/imported/expected/meter.rs | 2 + .../rust/tests/imported/expected/myappattr.rs | 1 + .../tests/imported/expected/myappmetric.rs | 18 ++- .../rust/tests/imported/expected/scope.rs | 1 + .../rust/tests/imported/expected/tracer.rs | 2 + .../tests/imported_typed/expected/logger.rs | 2 + .../tests/imported_typed/expected/meter.rs | 2 + .../imported_typed/expected/myappattr.rs | 1 + .../imported_typed/expected/myappmetric.rs | 18 ++- .../imported_typed/expected/myappspan.rs | 8 +- .../tests/imported_typed/expected/scope.rs | 1 + .../tests/imported_typed/expected/tracer.rs | 2 + .../literal_escaping/expected/demometric.rs | 17 ++- .../tests/literal_escaping/expected/meter.rs | 2 + .../tests/literal_escaping/expected/scope.rs | 1 + .../rust/tests/metrics/expected/authattr.rs | 1 + .../rust/tests/metrics/expected/authmetric.rs | 17 ++- .../code/rust/tests/metrics/expected/meter.rs | 2 + .../rust/tests/metrics/expected/myappattr.rs | 2 + .../tests/metrics/expected/myappmetric.rs | 123 +++++++++++++++--- .../code/rust/tests/metrics/expected/scope.rs | 1 + .../tests/metrics/expected/workermetric.rs | 7 +- .../rust/tests/naming/expected/capsattr.rs | 2 + .../rust/tests/naming/expected/capsmetric.rs | 17 ++- .../code/rust/tests/naming/expected/meter.rs | 2 + .../code/rust/tests/naming/expected/scope.rs | 1 + .../no_namespace/expected/exceptionattr.rs | 3 + .../no_namespace/expected/heartbeatattr.rs | 2 + .../no_namespace/expected/heartbeatspan.rs | 11 +- .../tests/no_namespace/expected/hostattr.rs | 3 + .../tests/no_namespace/expected/logger.rs | 2 + .../rust/tests/no_namespace/expected/scope.rs | 1 + .../tests/no_namespace/expected/tracer.rs | 2 + .../rust/tests/params/expected/billingattr.rs | 3 + .../tests/params/expected/billingmetric.rs | 7 +- .../rust/tests/params/expected/billingspan.rs | 6 +- .../code/rust/tests/params/expected/logger.rs | 2 + .../code/rust/tests/params/expected/meter.rs | 2 + .../rust/tests/params/expected/myappattr.rs | 1 + .../code/rust/tests/params/expected/scope.rs | 1 + .../code/rust/tests/params/expected/tracer.rs | 2 + .../rust/tests/spans/expected/myappattr.rs | 11 ++ .../rust/tests/spans/expected/myappspan.rs | 73 +++++++++-- .../code/rust/tests/spans/expected/scope.rs | 1 + .../code/rust/tests/spans/expected/tracer.rs | 2 + .../rust/tests/spans/expected/workerattr.rs | 2 + .../rust/tests/spans/expected/workerspan.rs | 8 +- templates/code/rust/tracer.rs.j2 | 2 + 82 files changed, 536 insertions(+), 71 deletions(-) diff --git a/templates/code/rust/attributes.rs.j2 b/templates/code/rust/attributes.rs.j2 index 7e8cf4f..7ae0192 100644 --- a/templates/code/rust/attributes.rs.j2 +++ b/templates/code/rust/attributes.rs.j2 @@ -32,6 +32,7 @@ impl From<{{ rust_type }}> for {{ attr.name }} { } } {% if attr.value_type == "string" %} + #[allow(deprecated)] impl From for {{ attr.name }} { #[inline] @@ -48,6 +49,7 @@ impl From<&'static str> for {{ attr.name }} { } } {% elif attr.value_type == "string[]" %} + #[allow(deprecated)] impl From> for {{ attr.name }} { fn from(value: Vec) -> Self { @@ -160,5 +162,6 @@ impl From<{{ attr.name }}> for ::opentelemetry::logs::AnyValue { {% endif %} } } + {% endfor %} {% endfilter -%}{{ "\n" -}} diff --git a/templates/code/rust/logger.rs.j2 b/templates/code/rust/logger.rs.j2 index f03691b..03e53a2 100644 --- a/templates/code/rust/logger.rs.j2 +++ b/templates/code/rust/logger.rs.j2 @@ -3,6 +3,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); + impl Logger { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let logger = provider.logger_with_scope(options.scope.into()); @@ -10,6 +11,7 @@ impl Logger { } pub fn inner(&self) -> &L { &self.0 } } + impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/meter.rs.j2 b/templates/code/rust/meter.rs.j2 index ca74571..4b4c5fa 100644 --- a/templates/code/rust/meter.rs.j2 +++ b/templates/code/rust/meter.rs.j2 @@ -3,6 +3,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); + impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { let meter = provider.meter_with_scope(options.scope.into()); @@ -10,6 +11,7 @@ impl Meter { } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } + impl Default for Meter { fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/metrics.rs.j2 b/templates/code/rust/metrics.rs.j2 index dad2bf1..42535b9 100644 --- a/templates/code/rust/metrics.rs.j2 +++ b/templates/code/rust/metrics.rs.j2 @@ -17,6 +17,7 @@ pub enum {{ name }}Attr { {{ h.exported(opt.attr_short_name) }}({{ h.attr_type(opt) }}), {% endfor %} } + impl From<{{ name }}Attr> for ::opentelemetry::KeyValue { fn from(value: {{ name }}Attr) -> Self { match value { @@ -29,7 +30,10 @@ impl From<{{ name }}Attr> for ::opentelemetry::KeyValue { {% endif %} {{ (h.docs(def) ~ "\n" ~ h.deprecated(def)) | trim }} #[derive(Clone)] -pub struct {{ name }} { instrument: ::opentelemetry::metrics::{{ suffix }}<{{ value_type }}> } +pub struct {{ name }} { + instrument: ::opentelemetry::metrics::{{ suffix }}<{{ value_type }}>, +} + impl {{ name }} { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().{{ builder }}({{ h.literal(def.instrument_name) }}) @@ -54,12 +58,16 @@ impl {{ name }} { self.instrument.{{ method }}(value, &attributes); } } + impl Default for {{ name }} { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } {% if def.instrument != 'histogram' %} {% set observable = h.exported(def.short_name) ~ 'Observable' ~ suffix %} -pub struct {{ name }}Observer<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument<{{ value_type }}> } +pub struct {{ name }}Observer<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument<{{ value_type }}>, +} + impl {{ name }}Observer<'_> { pub fn observe(&self, value: {{ value_type }}{% for req in def.required %}, {{ h.ident(req.attr_param) }}: {{ h.attr_type(req) }}{% endfor %}{% if def.optional %}, options: impl IntoIterator{% endif %}) { {% if def.optional %} @@ -76,7 +84,10 @@ impl {{ name }}Observer<'_> { } {{ h.deprecated(def) }} #[derive(Clone)] -pub struct {{ observable }} { _instrument: ::opentelemetry::metrics::Observable{{ suffix }}<{{ value_type }}> } +pub struct {{ observable }} { + _instrument: ::opentelemetry::metrics::Observable{{ suffix }}<{{ value_type }}>, +} + impl {{ observable }} { pub fn new(meter: &super::meter::Meter, callback: impl Fn({{ name }}Observer<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().{{ value_type }}_observable_{{ 'up_down_counter' if def.instrument == 'updowncounter' else def.instrument }}({{ h.literal(def.instrument_name) }}) @@ -87,6 +98,7 @@ impl {{ observable }} { Self { _instrument: instrument } } } + impl Default for {{ observable }} { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } diff --git a/templates/code/rust/scope.rs.j2 b/templates/code/rust/scope.rs.j2 index 08ccf3c..3979c4a 100644 --- a/templates/code/rust/scope.rs.j2 +++ b/templates/code/rust/scope.rs.j2 @@ -4,6 +4,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder({{ h.literal(params.instrumentation_name) }}) diff --git a/templates/code/rust/spans.rs.j2 b/templates/code/rust/spans.rs.j2 index 4726071..9a11638 100644 --- a/templates/code/rust/spans.rs.j2 +++ b/templates/code/rust/spans.rs.j2 @@ -44,6 +44,7 @@ pub enum {{ name }}StartAttr { {{ h.exported(opt.attr_short_name) }}({{ h.attr_type(opt) }}), {% endfor %} } + impl From<{{ name }}StartAttr> for ::opentelemetry::KeyValue { fn from(value: {{ name }}StartAttr) -> Self { match value { @@ -61,6 +62,7 @@ pub enum {{ name }}Attr { {{ h.exported(opt.attr_short_name) }}({{ h.attr_type(opt) }}), {% endfor %} } + impl From<{{ name }}Attr> for {{ name }}StartAttr { fn from(value: {{ name }}Attr) -> Self { match value { @@ -74,18 +76,24 @@ impl From<{{ name }}Attr> for {{ name }}StartAttr { {% if not def.name_parts %} #[derive(Clone, Debug, Default)] pub struct {{ name }}Name(::std::borrow::Cow<'static, str>); + impl From<&'static str> for {{ name }}Name { fn from(value: &'static str) -> Self { Self(::std::borrow::Cow::Borrowed(value)) } } + impl From for {{ name }}Name { fn from(value: String) -> Self { Self(::std::borrow::Cow::Owned(value)) } } + impl From<::std::borrow::Cow<'static, str>> for {{ name }}Name { fn from(value: ::std::borrow::Cow<'static, str>) -> Self { Self(value) } } {% endif %} {{ (h.docs(def) ~ "\n" ~ h.deprecated(def)) | trim }} -pub struct {{ span }} { span: S } +pub struct {{ span }} { + span: S, +} + impl {{ span }} { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -103,6 +111,7 @@ impl {{ span }} { } {% endif %} } + impl Default for {{ span }} { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start({{ h.literal(def.type) }}) } diff --git a/templates/code/rust/tests/allocations/expected/logger.rs b/templates/code/rust/tests/allocations/expected/logger.rs index 137ef4c..78bcc02 100644 --- a/templates/code/rust/tests/allocations/expected/logger.rs +++ b/templates/code/rust/tests/allocations/expected/logger.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); + impl Logger { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let logger = provider.logger_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Logger { } pub fn inner(&self) -> &L { &self.0 } } + impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/allocations/expected/meter.rs b/templates/code/rust/tests/allocations/expected/meter.rs index 3e2e018..a330bd2 100644 --- a/templates/code/rust/tests/allocations/expected/meter.rs +++ b/templates/code/rust/tests/allocations/expected/meter.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); + impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { let meter = provider.meter_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Meter { } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } + impl Default for Meter { fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/allocations/expected/probeattr.rs b/templates/code/rust/tests/allocations/expected/probeattr.rs index 0d34500..7028f94 100644 --- a/templates/code/rust/tests/allocations/expected/probeattr.rs +++ b/templates/code/rust/tests/allocations/expected/probeattr.rs @@ -39,6 +39,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// A synthetic fractional value. #[derive(Debug, Clone, PartialEq, Copy)] pub struct FractionAttr(f64); @@ -79,6 +80,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// A synthetic text value. #[derive(Debug, Clone, PartialEq)] pub struct LabelAttr(::opentelemetry::StringValue); @@ -95,6 +97,7 @@ impl From<::opentelemetry::StringValue> for LabelAttr { Self(value) } } + #[allow(deprecated)] impl From for LabelAttr { #[inline] @@ -142,6 +145,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Optional numeric measurement identity. #[derive(Debug, Clone, PartialEq, Copy)] pub struct OptionalAttr(i64); @@ -182,6 +186,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Required numeric measurement identity. #[derive(Debug, Clone, PartialEq, Copy)] pub struct RequiredAttr(i64); @@ -222,6 +227,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Numeric values attached to an event. #[derive(Debug, Clone, PartialEq)] pub struct ValuesAttr(Vec); diff --git a/templates/code/rust/tests/allocations/expected/probemetric.rs b/templates/code/rust/tests/allocations/expected/probemetric.rs index f047133..843bb72 100644 --- a/templates/code/rust/tests/allocations/expected/probemetric.rs +++ b/templates/code/rust/tests/allocations/expected/probemetric.rs @@ -3,6 +3,7 @@ pub enum OptionalCounterAttr { Optional(super::probeattr::OptionalAttr), } + impl From for ::opentelemetry::KeyValue { fn from(value: OptionalCounterAttr) -> Self { match value { @@ -12,7 +13,10 @@ impl From for ::opentelemetry::KeyValue { } /// Measurements with optional numeric attributes. #[derive(Clone)] -pub struct OptionalCounter { instrument: ::opentelemetry::metrics::Counter } +pub struct OptionalCounter { + instrument: ::opentelemetry::metrics::Counter, +} + impl OptionalCounter { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().u64_counter("probe.optional") @@ -28,10 +32,14 @@ impl OptionalCounter { self.instrument.add(value, &attributes); } } + impl Default for OptionalCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct OptionalCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct OptionalCounterObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl OptionalCounterObserver<'_> { pub fn observe(&self, value: u64, r#probe_required: super::probeattr::RequiredAttr, options: impl IntoIterator) { let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 2]>::new(); @@ -42,7 +50,10 @@ impl OptionalCounterObserver<'_> { } #[derive(Clone)] -pub struct OptionalObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +pub struct OptionalObservableCounter { + _instrument: ::opentelemetry::metrics::ObservableCounter, +} + impl OptionalObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(OptionalCounterObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().u64_observable_counter("probe.optional") @@ -53,12 +64,16 @@ impl OptionalObservableCounter { Self { _instrument: instrument } } } + impl Default for OptionalObservableCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } /// Measurements with a required numeric attribute. #[derive(Clone)] -pub struct RequiredCounter { instrument: ::opentelemetry::metrics::Counter } +pub struct RequiredCounter { + instrument: ::opentelemetry::metrics::Counter, +} + impl RequiredCounter { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().u64_counter("probe.required") @@ -72,10 +87,14 @@ impl RequiredCounter { self.instrument.add(value, &attributes); } } + impl Default for RequiredCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct RequiredCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct RequiredCounterObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl RequiredCounterObserver<'_> { pub fn observe(&self, value: u64, r#probe_required: super::probeattr::RequiredAttr) { let attributes = [::opentelemetry::KeyValue::from(r#probe_required)]; @@ -84,7 +103,10 @@ impl RequiredCounterObserver<'_> { } #[derive(Clone)] -pub struct RequiredObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +pub struct RequiredObservableCounter { + _instrument: ::opentelemetry::metrics::ObservableCounter, +} + impl RequiredObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(RequiredCounterObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().u64_observable_counter("probe.required") @@ -95,6 +117,7 @@ impl RequiredObservableCounter { Self { _instrument: instrument } } } + impl Default for RequiredObservableCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } diff --git a/templates/code/rust/tests/allocations/expected/scope.rs b/templates/code/rust/tests/allocations/expected/scope.rs index 920a74d..6f66e86 100644 --- a/templates/code/rust/tests/allocations/expected/scope.rs +++ b/templates/code/rust/tests/allocations/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("generated-semconv") diff --git a/templates/code/rust/tests/attributes/expected/authattr.rs b/templates/code/rust/tests/attributes/expected/authattr.rs index 27b8586..5fba6c7 100644 --- a/templates/code/rust/tests/attributes/expected/authattr.rs +++ b/templates/code/rust/tests/attributes/expected/authattr.rs @@ -48,6 +48,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// How the user was authenticated. #[derive(Debug, Clone, PartialEq, Copy)] pub enum MethodAttr { @@ -104,6 +105,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// Identifier of the authenticated user. #[derive(Debug, Clone, PartialEq)] pub struct UserIdAttr(::opentelemetry::StringValue); @@ -120,6 +122,7 @@ impl From<::opentelemetry::StringValue> for UserIdAttr { Self(value) } } + #[allow(deprecated)] impl From for UserIdAttr { #[inline] diff --git a/templates/code/rust/tests/attributes/expected/myappattr.rs b/templates/code/rust/tests/attributes/expected/myappattr.rs index 9f3d8e0..bd3bcf5 100644 --- a/templates/code/rust/tests/attributes/expected/myappattr.rs +++ b/templates/code/rust/tests/attributes/expected/myappattr.rs @@ -17,6 +17,7 @@ impl From<::opentelemetry::StringValue> for TaskAssignedByAttr { Self(value) } } + #[allow(deprecated)] impl From for TaskAssignedByAttr { #[inline] @@ -64,6 +65,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Whether the task was cancelled. #[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskCancelledAttr(bool); @@ -104,6 +106,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Tests Rust string literals. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskEscapedAttr { @@ -155,6 +158,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// Feature flags evaluated for the task. #[derive(Debug, Clone, PartialEq)] pub struct TaskFlagsAttr(Vec); @@ -209,6 +213,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() } } + /// Unique identifier of the task. /// /// The identifier is assigned by the scheduler and stays stable across retries. @@ -227,6 +232,7 @@ impl From<::opentelemetry::StringValue> for TaskIdAttr { Self(value) } } + #[allow(deprecated)] impl From for TaskIdAttr { #[inline] @@ -274,6 +280,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Lane the task was scheduled in. #[deprecated(note = "Lanes were replaced by priorities.")] #[derive(Debug, Clone, PartialEq, Copy)] @@ -333,6 +340,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// Owner of the task. #[deprecated(note = "Replaced by `auth.user.id`.")] #[derive(Debug, Clone, PartialEq)] @@ -350,6 +358,7 @@ impl From<::opentelemetry::StringValue> for TaskOwnerAttr { Self(value) } } + #[allow(deprecated)] impl From for TaskOwnerAttr { #[inline] @@ -397,6 +406,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Whether the scheduler may preempt the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskPreemptibleAttr { @@ -446,6 +456,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// Fraction of the task that has completed, between 0 and 1. #[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskProgressAttr(f64); @@ -486,6 +497,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Number of times the task was retried. #[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskRetriesAttr(i64); @@ -526,6 +538,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Fraction of tasks whose telemetry is sampled. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskSampleRateAttr { @@ -575,6 +588,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// Shards the task touched. #[derive(Debug, Clone, PartialEq)] pub struct TaskShardIdsAttr(Vec); @@ -629,6 +643,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() } } + /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskStateAttr { @@ -693,6 +708,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// Tags attached to the task. #[derive(Debug, Clone, PartialEq)] pub struct TaskTagsAttr(Vec<::opentelemetry::StringValue>); @@ -709,6 +725,7 @@ impl From> for TaskTagsAttr { Self(value) } } + #[allow(deprecated)] impl From> for TaskTagsAttr { fn from(value: Vec) -> Self { @@ -753,6 +770,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() } } + /// Scheduling weights applied to the task. #[derive(Debug, Clone, PartialEq)] pub struct TaskWeightsAttr(Vec); diff --git a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs index 835f35a..cfd8c00 100644 --- a/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs +++ b/templates/code/rust/tests/codegen_exclusion/expected/demoattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for KeptAttr { Self(value) } } + #[allow(deprecated)] impl From for KeptAttr { #[inline] @@ -62,6 +63,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Synthetic mode. #[derive(Debug, Clone, PartialEq, Copy)] pub enum ModeAttr { diff --git a/templates/code/rust/tests/entities/expected/myappattr.rs b/templates/code/rust/tests/entities/expected/myappattr.rs index f385007..67e72ed 100644 --- a/templates/code/rust/tests/entities/expected/myappattr.rs +++ b/templates/code/rust/tests/entities/expected/myappattr.rs @@ -40,6 +40,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Name of the host. #[derive(Debug, Clone, PartialEq)] pub struct HostNameAttr(::opentelemetry::StringValue); @@ -56,6 +57,7 @@ impl From<::opentelemetry::StringValue> for HostNameAttr { Self(value) } } + #[allow(deprecated)] impl From for HostNameAttr { #[inline] @@ -103,6 +105,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Role the host plays in the cluster. #[derive(Debug, Clone, PartialEq)] pub struct HostRoleAttr(::opentelemetry::StringValue); @@ -119,6 +122,7 @@ impl From<::opentelemetry::StringValue> for HostRoleAttr { Self(value) } } + #[allow(deprecated)] impl From for HostRoleAttr { #[inline] @@ -166,6 +170,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Type of the host. #[derive(Debug, Clone, PartialEq, Copy)] pub enum HostTypeAttr { @@ -222,6 +227,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// Name of the queue. #[derive(Debug, Clone, PartialEq)] pub struct QueueNameAttr(::opentelemetry::StringValue); @@ -238,6 +244,7 @@ impl From<::opentelemetry::StringValue> for QueueNameAttr { Self(value) } } + #[allow(deprecated)] impl From for QueueNameAttr { #[inline] @@ -285,6 +292,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Number of items currently in the queue. #[derive(Debug, Clone, PartialEq, Copy)] pub struct QueueSizeAttr(i64); diff --git a/templates/code/rust/tests/event_no_attributes/expected/logger.rs b/templates/code/rust/tests/event_no_attributes/expected/logger.rs index 137ef4c..78bcc02 100644 --- a/templates/code/rust/tests/event_no_attributes/expected/logger.rs +++ b/templates/code/rust/tests/event_no_attributes/expected/logger.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); + impl Logger { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let logger = provider.logger_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Logger { } pub fn inner(&self) -> &L { &self.0 } } + impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/event_no_attributes/expected/scope.rs b/templates/code/rust/tests/event_no_attributes/expected/scope.rs index 920a74d..6f66e86 100644 --- a/templates/code/rust/tests/event_no_attributes/expected/scope.rs +++ b/templates/code/rust/tests/event_no_attributes/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("generated-semconv") diff --git a/templates/code/rust/tests/events/expected/logger.rs b/templates/code/rust/tests/events/expected/logger.rs index 137ef4c..78bcc02 100644 --- a/templates/code/rust/tests/events/expected/logger.rs +++ b/templates/code/rust/tests/events/expected/logger.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); + impl Logger { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let logger = provider.logger_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Logger { } pub fn inner(&self) -> &L { &self.0 } } + impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/events/expected/myappattr.rs b/templates/code/rust/tests/events/expected/myappattr.rs index 63b08fb..697c2d0 100644 --- a/templates/code/rust/tests/events/expected/myappattr.rs +++ b/templates/code/rust/tests/events/expected/myappattr.rs @@ -53,6 +53,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() } } + /// Synthetic double values. #[derive(Debug, Clone, PartialEq)] pub struct DoubleValuesAttr(Vec); @@ -107,6 +108,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() } } + /// Synthetic int values. #[derive(Debug, Clone, PartialEq)] pub struct IntValuesAttr(Vec); @@ -161,6 +163,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() } } + /// Synthetic string values. #[derive(Debug, Clone, PartialEq)] pub struct StringValuesAttr(Vec<::opentelemetry::StringValue>); @@ -177,6 +180,7 @@ impl From> for StringValuesAttr { Self(value) } } + #[allow(deprecated)] impl From> for StringValuesAttr { fn from(value: Vec) -> Self { @@ -221,6 +225,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() } } + /// Number of the attempt, starting at 1. #[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskAttemptAttr(i64); @@ -261,6 +266,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskStateAttr { diff --git a/templates/code/rust/tests/events/expected/scope.rs b/templates/code/rust/tests/events/expected/scope.rs index 920a74d..6f66e86 100644 --- a/templates/code/rust/tests/events/expected/scope.rs +++ b/templates/code/rust/tests/events/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("generated-semconv") diff --git a/templates/code/rust/tests/events/expected/workerattr.rs b/templates/code/rust/tests/events/expected/workerattr.rs index a62dda2..50da699 100644 --- a/templates/code/rust/tests/events/expected/workerattr.rs +++ b/templates/code/rust/tests/events/expected/workerattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for HostNameAttr { Self(value) } } + #[allow(deprecated)] impl From for HostNameAttr { #[inline] diff --git a/templates/code/rust/tests/filtering/expected/authattr.rs b/templates/code/rust/tests/filtering/expected/authattr.rs index aa01590..c2c1df1 100644 --- a/templates/code/rust/tests/filtering/expected/authattr.rs +++ b/templates/code/rust/tests/filtering/expected/authattr.rs @@ -55,6 +55,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// Identifier of the authenticated user. #[derive(Debug, Clone, PartialEq)] pub struct UserIdAttr(::opentelemetry::StringValue); @@ -71,6 +72,7 @@ impl From<::opentelemetry::StringValue> for UserIdAttr { Self(value) } } + #[allow(deprecated)] impl From for UserIdAttr { #[inline] diff --git a/templates/code/rust/tests/filtering/expected/taskattr.rs b/templates/code/rust/tests/filtering/expected/taskattr.rs index 0a3b34d..2d388b5 100644 --- a/templates/code/rust/tests/filtering/expected/taskattr.rs +++ b/templates/code/rust/tests/filtering/expected/taskattr.rs @@ -17,6 +17,7 @@ impl From<::opentelemetry::StringValue> for AssignedByAttr { Self(value) } } + #[allow(deprecated)] impl From for AssignedByAttr { #[inline] @@ -64,6 +65,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Whether the task was cancelled. #[derive(Debug, Clone, PartialEq, Copy)] pub struct CancelledAttr(bool); @@ -104,6 +106,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Unique identifier of the task. /// /// The identifier is assigned by the scheduler and stays stable across retries. @@ -122,6 +125,7 @@ impl From<::opentelemetry::StringValue> for IdAttr { Self(value) } } + #[allow(deprecated)] impl From for IdAttr { #[inline] @@ -169,6 +173,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Whether the scheduler may preempt the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum PreemptibleAttr { @@ -218,6 +223,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// Number of times the task was retried. #[derive(Debug, Clone, PartialEq, Copy)] pub struct RetriesAttr(i64); @@ -258,6 +264,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Fraction of tasks whose telemetry is sampled. #[derive(Debug, Clone, PartialEq, Copy)] pub enum SampleRateAttr { @@ -307,6 +314,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// Shards the task touched. #[derive(Debug, Clone, PartialEq)] pub struct ShardIdsAttr(Vec); @@ -361,6 +369,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() } } + /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum StateAttr { @@ -419,6 +428,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// Tags attached to the task. #[derive(Debug, Clone, PartialEq)] pub struct TagsAttr(Vec<::opentelemetry::StringValue>); @@ -435,6 +445,7 @@ impl From> for TagsAttr { Self(value) } } + #[allow(deprecated)] impl From> for TagsAttr { fn from(value: Vec) -> Self { diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs index 3e2e018..a330bd2 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/meter.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); + impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { let meter = provider.meter_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Meter { } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } + impl Default for Meter { fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs index 0e5c78c..c2a50dd 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for TaskIdAttr { Self(value) } } + #[allow(deprecated)] impl From for TaskIdAttr { #[inline] diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs index bef1184..8d23184 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/myappmetric.rs @@ -1,7 +1,10 @@ #![allow(deprecated)] /// Time a task took from start to finish. #[derive(Clone)] -pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +pub struct TaskDurationHistogram { + instrument: ::opentelemetry::metrics::Histogram, +} + impl TaskDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_histogram("myapp.task.duration") @@ -16,12 +19,16 @@ impl TaskDurationHistogram { self.instrument.record(value, &attributes); } } + impl Default for TaskDurationHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } /// Time between a task being queued and started. #[derive(Clone)] -pub struct TaskLatencyHistogram { instrument: ::opentelemetry::metrics::Histogram } +pub struct TaskLatencyHistogram { + instrument: ::opentelemetry::metrics::Histogram, +} + impl TaskLatencyHistogram { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_histogram("myapp.task.latency") @@ -36,12 +43,16 @@ impl TaskLatencyHistogram { self.instrument.record(value, &attributes); } } + impl Default for TaskLatencyHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } /// Time a retried task took from start to finish. #[derive(Clone)] -pub struct TaskRetryDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +pub struct TaskRetryDurationHistogram { + instrument: ::opentelemetry::metrics::Histogram, +} + impl TaskRetryDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_histogram("myapp.task.duration") @@ -56,12 +67,16 @@ impl TaskRetryDurationHistogram { self.instrument.record(value, &attributes); } } + impl Default for TaskRetryDurationHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } /// Size of a task's payload. #[derive(Clone)] -pub struct TaskSizeHistogram { instrument: ::opentelemetry::metrics::Histogram } +pub struct TaskSizeHistogram { + instrument: ::opentelemetry::metrics::Histogram, +} + impl TaskSizeHistogram { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_histogram("myapp.task.size") @@ -75,6 +90,7 @@ impl TaskSizeHistogram { self.instrument.record(value, &attributes); } } + impl Default for TaskSizeHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs index 920a74d..6f66e86 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("generated-semconv") diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs index 3e2e018..a330bd2 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/meter.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); + impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { let meter = provider.meter_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Meter { } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } + impl Default for Meter { fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs index 0e5c78c..c2a50dd 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for TaskIdAttr { Self(value) } } + #[allow(deprecated)] impl From for TaskIdAttr { #[inline] diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs index 291169d..bd6280a 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/myappmetric.rs @@ -1,7 +1,10 @@ #![allow(deprecated)] /// Time a task took from start to finish. #[derive(Clone)] -pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +pub struct TaskDurationHistogram { + instrument: ::opentelemetry::metrics::Histogram, +} + impl TaskDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_histogram("myapp.task.duration") @@ -15,12 +18,16 @@ impl TaskDurationHistogram { self.instrument.record(value, &attributes); } } + impl Default for TaskDurationHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } /// Time a task waited in the queue, in minutes. #[derive(Clone)] -pub struct TaskQueueWaitHistogram { instrument: ::opentelemetry::metrics::Histogram } +pub struct TaskQueueWaitHistogram { + instrument: ::opentelemetry::metrics::Histogram, +} + impl TaskQueueWaitHistogram { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_histogram("myapp.task.queue_wait") @@ -35,6 +42,7 @@ impl TaskQueueWaitHistogram { self.instrument.record(value, &attributes); } } + impl Default for TaskQueueWaitHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } diff --git a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs index 920a74d..6f66e86 100644 --- a/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs +++ b/templates/code/rust/tests/histogram_boundaries_by_unit_params/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("generated-semconv") diff --git a/templates/code/rust/tests/imported/expected/edgemetric.rs b/templates/code/rust/tests/imported/expected/edgemetric.rs index 5373426..0df00c7 100644 --- a/templates/code/rust/tests/imported/expected/edgemetric.rs +++ b/templates/code/rust/tests/imported/expected/edgemetric.rs @@ -3,6 +3,7 @@ pub enum UpstreamDurationHistogramAttr { ServerPort(i64), } + impl From for ::opentelemetry::KeyValue { fn from(value: UpstreamDurationHistogramAttr) -> Self { match value { @@ -12,7 +13,10 @@ impl From for ::opentelemetry::KeyValue { } /// Time spent waiting on an upstream server. #[derive(Clone)] -pub struct UpstreamDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +pub struct UpstreamDurationHistogram { + instrument: ::opentelemetry::metrics::Histogram, +} + impl UpstreamDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_histogram("edge.upstream.duration") @@ -29,6 +33,7 @@ impl UpstreamDurationHistogram { self.instrument.record(value, &attributes); } } + impl Default for UpstreamDurationHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } diff --git a/templates/code/rust/tests/imported/expected/edgespan.rs b/templates/code/rust/tests/imported/expected/edgespan.rs index 55b1330..a7ba98f 100644 --- a/templates/code/rust/tests/imported/expected/edgespan.rs +++ b/templates/code/rust/tests/imported/expected/edgespan.rs @@ -3,7 +3,10 @@ use ::opentelemetry::trace::{TraceContextExt, Tracer}; use ::std::fmt::Write; /// A request named from attempted methods. -pub struct UpstreamMethodsSpan { span: S } +pub struct UpstreamMethodsSpan { + span: S, +} + impl UpstreamMethodsSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -16,6 +19,7 @@ impl UpstreamMethodsSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } } + impl Default for UpstreamMethodsSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("edge.upstream.methods") } @@ -43,6 +47,7 @@ pub enum UpstreamRequestStartAttr { ErrorType(::opentelemetry::StringValue), HttpRequestMethodList(Vec<::opentelemetry::StringValue>), } + impl From for ::opentelemetry::KeyValue { fn from(value: UpstreamRequestStartAttr) -> Self { match value { @@ -55,6 +60,7 @@ impl From for ::opentelemetry::KeyValue { pub enum UpstreamRequestAttr { HttpRequestMethodList(Vec<::opentelemetry::StringValue>), } + impl From for UpstreamRequestStartAttr { fn from(value: UpstreamRequestAttr) -> Self { match value { @@ -63,7 +69,10 @@ impl From for UpstreamRequestStartAttr { } } /// A request to an upstream server. -pub struct UpstreamRequestSpan { span: S } +pub struct UpstreamRequestSpan { + span: S, +} + impl UpstreamRequestSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -79,6 +88,7 @@ impl UpstreamRequestSpan { for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from(UpstreamRequestStartAttr::from(attribute))); } } } + impl Default for UpstreamRequestSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("edge.upstream.request") } diff --git a/templates/code/rust/tests/imported/expected/logger.rs b/templates/code/rust/tests/imported/expected/logger.rs index 137ef4c..78bcc02 100644 --- a/templates/code/rust/tests/imported/expected/logger.rs +++ b/templates/code/rust/tests/imported/expected/logger.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); + impl Logger { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let logger = provider.logger_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Logger { } pub fn inner(&self) -> &L { &self.0 } } + impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/imported/expected/meter.rs b/templates/code/rust/tests/imported/expected/meter.rs index 3e2e018..a330bd2 100644 --- a/templates/code/rust/tests/imported/expected/meter.rs +++ b/templates/code/rust/tests/imported/expected/meter.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); + impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { let meter = provider.meter_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Meter { } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } + impl Default for Meter { fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/imported/expected/myappattr.rs b/templates/code/rust/tests/imported/expected/myappattr.rs index 0e5c78c..c2a50dd 100644 --- a/templates/code/rust/tests/imported/expected/myappattr.rs +++ b/templates/code/rust/tests/imported/expected/myappattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for TaskIdAttr { Self(value) } } + #[allow(deprecated)] impl From for TaskIdAttr { #[inline] diff --git a/templates/code/rust/tests/imported/expected/myappmetric.rs b/templates/code/rust/tests/imported/expected/myappmetric.rs index 1fed95f..cf876c8 100644 --- a/templates/code/rust/tests/imported/expected/myappmetric.rs +++ b/templates/code/rust/tests/imported/expected/myappmetric.rs @@ -3,6 +3,7 @@ pub enum TaskFailedCounterAttr { HttpRequestMethodList(Vec<::opentelemetry::StringValue>), } + impl From for ::opentelemetry::KeyValue { fn from(value: TaskFailedCounterAttr) -> Self { match value { @@ -12,7 +13,10 @@ impl From for ::opentelemetry::KeyValue { } /// Number of tasks that failed. #[derive(Clone)] -pub struct TaskFailedCounter { instrument: ::opentelemetry::metrics::Counter } +pub struct TaskFailedCounter { + instrument: ::opentelemetry::metrics::Counter, +} + impl TaskFailedCounter { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().u64_counter("myapp.task.failed") @@ -28,10 +32,14 @@ impl TaskFailedCounter { self.instrument.add(value, &attributes); } } + impl Default for TaskFailedCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct TaskFailedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct TaskFailedCounterObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl TaskFailedCounterObserver<'_> { pub fn observe(&self, value: u64, r#error_type: ::opentelemetry::StringValue, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 3]>::new(); @@ -42,7 +50,10 @@ impl TaskFailedCounterObserver<'_> { } #[derive(Clone)] -pub struct TaskFailedObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +pub struct TaskFailedObservableCounter { + _instrument: ::opentelemetry::metrics::ObservableCounter, +} + impl TaskFailedObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFailedCounterObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().u64_observable_counter("myapp.task.failed") @@ -53,6 +64,7 @@ impl TaskFailedObservableCounter { Self { _instrument: instrument } } } + impl Default for TaskFailedObservableCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } diff --git a/templates/code/rust/tests/imported/expected/scope.rs b/templates/code/rust/tests/imported/expected/scope.rs index 920a74d..6f66e86 100644 --- a/templates/code/rust/tests/imported/expected/scope.rs +++ b/templates/code/rust/tests/imported/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("generated-semconv") diff --git a/templates/code/rust/tests/imported/expected/tracer.rs b/templates/code/rust/tests/imported/expected/tracer.rs index 0dc2a89..d684a8d 100644 --- a/templates/code/rust/tests/imported/expected/tracer.rs +++ b/templates/code/rust/tests/imported/expected/tracer.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Tracer(T); + impl Tracer { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let tracer = provider.tracer_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Tracer { } pub fn inner(&self) -> &T { &self.0 } } + impl Default for Tracer { fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/imported_typed/expected/logger.rs b/templates/code/rust/tests/imported_typed/expected/logger.rs index 137ef4c..78bcc02 100644 --- a/templates/code/rust/tests/imported_typed/expected/logger.rs +++ b/templates/code/rust/tests/imported_typed/expected/logger.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); + impl Logger { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let logger = provider.logger_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Logger { } pub fn inner(&self) -> &L { &self.0 } } + impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/imported_typed/expected/meter.rs b/templates/code/rust/tests/imported_typed/expected/meter.rs index 3e2e018..a330bd2 100644 --- a/templates/code/rust/tests/imported_typed/expected/meter.rs +++ b/templates/code/rust/tests/imported_typed/expected/meter.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); + impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { let meter = provider.meter_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Meter { } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } + impl Default for Meter { fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/imported_typed/expected/myappattr.rs b/templates/code/rust/tests/imported_typed/expected/myappattr.rs index 0e5c78c..c2a50dd 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappattr.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for TaskIdAttr { Self(value) } } + #[allow(deprecated)] impl From for TaskIdAttr { #[inline] diff --git a/templates/code/rust/tests/imported_typed/expected/myappmetric.rs b/templates/code/rust/tests/imported_typed/expected/myappmetric.rs index 2305ffa..cfc1605 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappmetric.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappmetric.rs @@ -3,6 +3,7 @@ pub enum TaskFailedCounterAttr { ServerPort(i64), } + impl From for ::opentelemetry::KeyValue { fn from(value: TaskFailedCounterAttr) -> Self { match value { @@ -12,7 +13,10 @@ impl From for ::opentelemetry::KeyValue { } /// Number of tasks that failed. #[derive(Clone)] -pub struct TaskFailedCounter { instrument: ::opentelemetry::metrics::Counter } +pub struct TaskFailedCounter { + instrument: ::opentelemetry::metrics::Counter, +} + impl TaskFailedCounter { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().u64_counter("myapp.task.failed") @@ -28,10 +32,14 @@ impl TaskFailedCounter { self.instrument.add(value, &attributes); } } + impl Default for TaskFailedCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct TaskFailedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct TaskFailedCounterObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl TaskFailedCounterObserver<'_> { pub fn observe(&self, value: u64, r#error_type: upstream::errorattr::TypeAttr, r#myapp_task_id: super::myappattr::TaskIdAttr, options: impl IntoIterator) { let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 3]>::new(); @@ -42,7 +50,10 @@ impl TaskFailedCounterObserver<'_> { } #[derive(Clone)] -pub struct TaskFailedObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +pub struct TaskFailedObservableCounter { + _instrument: ::opentelemetry::metrics::ObservableCounter, +} + impl TaskFailedObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFailedCounterObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().u64_observable_counter("myapp.task.failed") @@ -53,6 +64,7 @@ impl TaskFailedObservableCounter { Self { _instrument: instrument } } } + impl Default for TaskFailedObservableCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } diff --git a/templates/code/rust/tests/imported_typed/expected/myappspan.rs b/templates/code/rust/tests/imported_typed/expected/myappspan.rs index c6c0856..abd5d30 100644 --- a/templates/code/rust/tests/imported_typed/expected/myappspan.rs +++ b/templates/code/rust/tests/imported_typed/expected/myappspan.rs @@ -6,6 +6,7 @@ use ::std::fmt::Write; pub enum TaskDispatchStartAttr { ServerPort(i64), } + impl From for ::opentelemetry::KeyValue { fn from(value: TaskDispatchStartAttr) -> Self { match value { @@ -17,6 +18,7 @@ impl From for ::opentelemetry::KeyValue { pub enum TaskDispatchAttr { ServerPort(i64), } + impl From for TaskDispatchStartAttr { fn from(value: TaskDispatchAttr) -> Self { match value { @@ -25,7 +27,10 @@ impl From for TaskDispatchStartAttr { } } /// Dispatch of a task. -pub struct TaskDispatchSpan { span: S } +pub struct TaskDispatchSpan { + span: S, +} + impl TaskDispatchSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -41,6 +46,7 @@ impl TaskDispatchSpan { for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from(TaskDispatchStartAttr::from(attribute))); } } } + impl Default for TaskDispatchSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("myapp.task.dispatch") } diff --git a/templates/code/rust/tests/imported_typed/expected/scope.rs b/templates/code/rust/tests/imported_typed/expected/scope.rs index 920a74d..6f66e86 100644 --- a/templates/code/rust/tests/imported_typed/expected/scope.rs +++ b/templates/code/rust/tests/imported_typed/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("generated-semconv") diff --git a/templates/code/rust/tests/imported_typed/expected/tracer.rs b/templates/code/rust/tests/imported_typed/expected/tracer.rs index 0dc2a89..d684a8d 100644 --- a/templates/code/rust/tests/imported_typed/expected/tracer.rs +++ b/templates/code/rust/tests/imported_typed/expected/tracer.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Tracer(T); + impl Tracer { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let tracer = provider.tracer_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Tracer { } pub fn inner(&self) -> &T { &self.0 } } + impl Default for Tracer { fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/literal_escaping/expected/demometric.rs b/templates/code/rust/tests/literal_escaping/expected/demometric.rs index e66f6e1..1b3a78b 100644 --- a/templates/code/rust/tests/literal_escaping/expected/demometric.rs +++ b/templates/code/rust/tests/literal_escaping/expected/demometric.rs @@ -1,7 +1,10 @@ #![allow(deprecated)] /// literal \b \f \u1234 #[derive(Clone)] -pub struct LiteralCountCounter { instrument: ::opentelemetry::metrics::Counter } +pub struct LiteralCountCounter { + instrument: ::opentelemetry::metrics::Counter, +} + impl LiteralCountCounter { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().u64_counter("demo.literal.count") @@ -15,10 +18,14 @@ impl LiteralCountCounter { self.instrument.add(value, &attributes); } } + impl Default for LiteralCountCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct LiteralCountCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct LiteralCountCounterObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl LiteralCountCounterObserver<'_> { pub fn observe(&self, value: u64, r#demo_literal: super::demoattr::LiteralAttr) { let attributes = [::opentelemetry::KeyValue::from(r#demo_literal)]; @@ -27,7 +34,10 @@ impl LiteralCountCounterObserver<'_> { } #[derive(Clone)] -pub struct LiteralCountObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +pub struct LiteralCountObservableCounter { + _instrument: ::opentelemetry::metrics::ObservableCounter, +} + impl LiteralCountObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(LiteralCountCounterObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().u64_observable_counter("demo.literal.count") @@ -38,6 +48,7 @@ impl LiteralCountObservableCounter { Self { _instrument: instrument } } } + impl Default for LiteralCountObservableCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } diff --git a/templates/code/rust/tests/literal_escaping/expected/meter.rs b/templates/code/rust/tests/literal_escaping/expected/meter.rs index 3e2e018..a330bd2 100644 --- a/templates/code/rust/tests/literal_escaping/expected/meter.rs +++ b/templates/code/rust/tests/literal_escaping/expected/meter.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); + impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { let meter = provider.meter_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Meter { } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } + impl Default for Meter { fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/literal_escaping/expected/scope.rs b/templates/code/rust/tests/literal_escaping/expected/scope.rs index e45ba81..6eb6ff7 100644 --- a/templates/code/rust/tests/literal_escaping/expected/scope.rs +++ b/templates/code/rust/tests/literal_escaping/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("literal \\b \\f \\u1234 quote\" double\\\\slash") diff --git a/templates/code/rust/tests/metrics/expected/authattr.rs b/templates/code/rust/tests/metrics/expected/authattr.rs index 03ad451..ff9bba6 100644 --- a/templates/code/rust/tests/metrics/expected/authattr.rs +++ b/templates/code/rust/tests/metrics/expected/authattr.rs @@ -55,6 +55,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.into() } } + /// Whether the attempt succeeded. #[derive(Debug, Clone, PartialEq, Copy)] pub struct SuccessAttr(bool); diff --git a/templates/code/rust/tests/metrics/expected/authmetric.rs b/templates/code/rust/tests/metrics/expected/authmetric.rs index 11d5a53..7a2580e 100644 --- a/templates/code/rust/tests/metrics/expected/authmetric.rs +++ b/templates/code/rust/tests/metrics/expected/authmetric.rs @@ -1,7 +1,10 @@ #![allow(deprecated)] /// Number of authentication attempts. #[derive(Clone)] -pub struct AttemptsCounter { instrument: ::opentelemetry::metrics::Counter } +pub struct AttemptsCounter { + instrument: ::opentelemetry::metrics::Counter, +} + impl AttemptsCounter { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().u64_counter("auth.attempts") @@ -15,10 +18,14 @@ impl AttemptsCounter { self.instrument.add(value, &attributes); } } + impl Default for AttemptsCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct AttemptsCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct AttemptsCounterObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl AttemptsCounterObserver<'_> { pub fn observe(&self, value: u64, r#auth_method: super::authattr::MethodAttr, r#auth_success: super::authattr::SuccessAttr) { let attributes = [::opentelemetry::KeyValue::from(r#auth_method), ::opentelemetry::KeyValue::from(r#auth_success)]; @@ -27,7 +34,10 @@ impl AttemptsCounterObserver<'_> { } #[derive(Clone)] -pub struct AttemptsObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +pub struct AttemptsObservableCounter { + _instrument: ::opentelemetry::metrics::ObservableCounter, +} + impl AttemptsObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(AttemptsCounterObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().u64_observable_counter("auth.attempts") @@ -38,6 +48,7 @@ impl AttemptsObservableCounter { Self { _instrument: instrument } } } + impl Default for AttemptsObservableCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } diff --git a/templates/code/rust/tests/metrics/expected/meter.rs b/templates/code/rust/tests/metrics/expected/meter.rs index 3e2e018..a330bd2 100644 --- a/templates/code/rust/tests/metrics/expected/meter.rs +++ b/templates/code/rust/tests/metrics/expected/meter.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); + impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { let meter = provider.meter_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Meter { } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } + impl Default for Meter { fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/metrics/expected/myappattr.rs b/templates/code/rust/tests/metrics/expected/myappattr.rs index a1b18f0..8928c88 100644 --- a/templates/code/rust/tests/metrics/expected/myappattr.rs +++ b/templates/code/rust/tests/metrics/expected/myappattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for TaskIdAttr { Self(value) } } + #[allow(deprecated)] impl From for TaskIdAttr { #[inline] @@ -62,6 +63,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskStateAttr { diff --git a/templates/code/rust/tests/metrics/expected/myappmetric.rs b/templates/code/rust/tests/metrics/expected/myappmetric.rs index d5ea051..8a269e4 100644 --- a/templates/code/rust/tests/metrics/expected/myappmetric.rs +++ b/templates/code/rust/tests/metrics/expected/myappmetric.rs @@ -2,7 +2,10 @@ /// Number of tasks waiting in the queue. #[deprecated(note = "Replaced by `myapp.task.active`.")] #[derive(Clone)] -pub struct QueueDepthGauge { instrument: ::opentelemetry::metrics::Gauge } +pub struct QueueDepthGauge { + instrument: ::opentelemetry::metrics::Gauge, +} + impl QueueDepthGauge { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().i64_gauge("myapp.queue.depth") @@ -16,10 +19,14 @@ impl QueueDepthGauge { self.instrument.record(value, &attributes); } } + impl Default for QueueDepthGauge { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct QueueDepthGaugeObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct QueueDepthGaugeObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl QueueDepthGaugeObserver<'_> { pub fn observe(&self, value: i64) { let attributes = []; @@ -28,7 +35,10 @@ impl QueueDepthGaugeObserver<'_> { } #[deprecated(note = "Replaced by `myapp.task.active`.")] #[derive(Clone)] -pub struct QueueDepthObservableGauge { _instrument: ::opentelemetry::metrics::ObservableGauge } +pub struct QueueDepthObservableGauge { + _instrument: ::opentelemetry::metrics::ObservableGauge, +} + impl QueueDepthObservableGauge { pub fn new(meter: &super::meter::Meter, callback: impl Fn(QueueDepthGaugeObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().i64_observable_gauge("myapp.queue.depth") @@ -39,12 +49,16 @@ impl QueueDepthObservableGauge { Self { _instrument: instrument } } } + impl Default for QueueDepthObservableGauge { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } /// Number of tasks currently running. #[derive(Clone)] -pub struct TaskActiveUpDownCounter { instrument: ::opentelemetry::metrics::UpDownCounter } +pub struct TaskActiveUpDownCounter { + instrument: ::opentelemetry::metrics::UpDownCounter, +} + impl TaskActiveUpDownCounter { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().i64_up_down_counter("myapp.task.active") @@ -58,10 +72,14 @@ impl TaskActiveUpDownCounter { self.instrument.add(value, &attributes); } } + impl Default for TaskActiveUpDownCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct TaskActiveUpDownCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct TaskActiveUpDownCounterObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl TaskActiveUpDownCounterObserver<'_> { pub fn observe(&self, value: i64, r#myapp_task_state: super::myappattr::TaskStateAttr) { let attributes = [::opentelemetry::KeyValue::from(r#myapp_task_state)]; @@ -70,7 +88,10 @@ impl TaskActiveUpDownCounterObserver<'_> { } #[derive(Clone)] -pub struct TaskActiveObservableUpDownCounter { _instrument: ::opentelemetry::metrics::ObservableUpDownCounter } +pub struct TaskActiveObservableUpDownCounter { + _instrument: ::opentelemetry::metrics::ObservableUpDownCounter, +} + impl TaskActiveObservableUpDownCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskActiveUpDownCounterObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().i64_observable_up_down_counter("myapp.task.active") @@ -81,6 +102,7 @@ impl TaskActiveObservableUpDownCounter { Self { _instrument: instrument } } } + impl Default for TaskActiveObservableUpDownCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } @@ -91,6 +113,7 @@ pub enum TaskDurationHistogramAttr { /// Conditionally required: If the task reached a final state. TaskState(super::myappattr::TaskStateAttr), } + impl From for ::opentelemetry::KeyValue { fn from(value: TaskDurationHistogramAttr) -> Self { match value { @@ -103,7 +126,10 @@ impl From for ::opentelemetry::KeyValue { /// /// Measured by the worker that ran the task. #[derive(Clone)] -pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +pub struct TaskDurationHistogram { + instrument: ::opentelemetry::metrics::Histogram, +} + impl TaskDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_histogram("myapp.task.duration") @@ -120,12 +146,16 @@ impl TaskDurationHistogram { self.instrument.record(value, &attributes); } } + impl Default for TaskDurationHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } /// Fractional active task adjustment. #[derive(Clone)] -pub struct TaskFloatActiveUpDownCounter { instrument: ::opentelemetry::metrics::UpDownCounter } +pub struct TaskFloatActiveUpDownCounter { + instrument: ::opentelemetry::metrics::UpDownCounter, +} + impl TaskFloatActiveUpDownCounter { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_up_down_counter("myapp.task.float.active") @@ -139,10 +169,14 @@ impl TaskFloatActiveUpDownCounter { self.instrument.add(value, &attributes); } } + impl Default for TaskFloatActiveUpDownCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct TaskFloatActiveUpDownCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct TaskFloatActiveUpDownCounterObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl TaskFloatActiveUpDownCounterObserver<'_> { pub fn observe(&self, value: f64) { let attributes = []; @@ -151,7 +185,10 @@ impl TaskFloatActiveUpDownCounterObserver<'_> { } #[derive(Clone)] -pub struct TaskFloatActiveObservableUpDownCounter { _instrument: ::opentelemetry::metrics::ObservableUpDownCounter } +pub struct TaskFloatActiveObservableUpDownCounter { + _instrument: ::opentelemetry::metrics::ObservableUpDownCounter, +} + impl TaskFloatActiveObservableUpDownCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFloatActiveUpDownCounterObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().f64_observable_up_down_counter("myapp.task.float.active") @@ -162,12 +199,16 @@ impl TaskFloatActiveObservableUpDownCounter { Self { _instrument: instrument } } } + impl Default for TaskFloatActiveObservableUpDownCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } /// Fractional queue depth. #[derive(Clone)] -pub struct TaskFloatDepthGauge { instrument: ::opentelemetry::metrics::Gauge } +pub struct TaskFloatDepthGauge { + instrument: ::opentelemetry::metrics::Gauge, +} + impl TaskFloatDepthGauge { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_gauge("myapp.task.float.depth") @@ -181,10 +222,14 @@ impl TaskFloatDepthGauge { self.instrument.record(value, &attributes); } } + impl Default for TaskFloatDepthGauge { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct TaskFloatDepthGaugeObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct TaskFloatDepthGaugeObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl TaskFloatDepthGaugeObserver<'_> { pub fn observe(&self, value: f64) { let attributes = []; @@ -193,7 +238,10 @@ impl TaskFloatDepthGaugeObserver<'_> { } #[derive(Clone)] -pub struct TaskFloatDepthObservableGauge { _instrument: ::opentelemetry::metrics::ObservableGauge } +pub struct TaskFloatDepthObservableGauge { + _instrument: ::opentelemetry::metrics::ObservableGauge, +} + impl TaskFloatDepthObservableGauge { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFloatDepthGaugeObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().f64_observable_gauge("myapp.task.float.depth") @@ -204,12 +252,16 @@ impl TaskFloatDepthObservableGauge { Self { _instrument: instrument } } } + impl Default for TaskFloatDepthObservableGauge { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } /// Fractional tasks started. #[derive(Clone)] -pub struct TaskFloatStartedCounter { instrument: ::opentelemetry::metrics::Counter } +pub struct TaskFloatStartedCounter { + instrument: ::opentelemetry::metrics::Counter, +} + impl TaskFloatStartedCounter { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_counter("myapp.task.float.started") @@ -223,10 +275,14 @@ impl TaskFloatStartedCounter { self.instrument.add(value, &attributes); } } + impl Default for TaskFloatStartedCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct TaskFloatStartedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct TaskFloatStartedCounterObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl TaskFloatStartedCounterObserver<'_> { pub fn observe(&self, value: f64) { let attributes = []; @@ -235,7 +291,10 @@ impl TaskFloatStartedCounterObserver<'_> { } #[derive(Clone)] -pub struct TaskFloatStartedObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +pub struct TaskFloatStartedObservableCounter { + _instrument: ::opentelemetry::metrics::ObservableCounter, +} + impl TaskFloatStartedObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskFloatStartedCounterObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().f64_observable_counter("myapp.task.float.started") @@ -246,12 +305,16 @@ impl TaskFloatStartedObservableCounter { Self { _instrument: instrument } } } + impl Default for TaskFloatStartedObservableCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } /// Task payload size. #[derive(Clone)] -pub struct TaskPayloadHistogram { instrument: ::opentelemetry::metrics::Histogram } +pub struct TaskPayloadHistogram { + instrument: ::opentelemetry::metrics::Histogram, +} + impl TaskPayloadHistogram { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().u64_histogram("myapp.task.payload") @@ -266,6 +329,7 @@ impl TaskPayloadHistogram { self.instrument.record(value, &attributes); } } + impl Default for TaskPayloadHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } @@ -274,6 +338,7 @@ pub enum TaskRetryDurationHistogramAttr { /// Opt-in: the convention records it only when a user asks for it. Method(super::authattr::MethodAttr), } + impl From for ::opentelemetry::KeyValue { fn from(value: TaskRetryDurationHistogramAttr) -> Self { match value { @@ -285,7 +350,10 @@ impl From for ::opentelemetry::KeyValue { /// /// Recorded only for tasks that ran more than once. #[derive(Clone)] -pub struct TaskRetryDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +pub struct TaskRetryDurationHistogram { + instrument: ::opentelemetry::metrics::Histogram, +} + impl TaskRetryDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_histogram("myapp.task.duration") @@ -302,6 +370,7 @@ impl TaskRetryDurationHistogram { self.instrument.record(value, &attributes); } } + impl Default for TaskRetryDurationHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } @@ -310,6 +379,7 @@ pub enum TaskStartedCounterAttr { /// Recommended: When the scheduler assigned an id before the task started. TaskId(super::myappattr::TaskIdAttr), } + impl From for ::opentelemetry::KeyValue { fn from(value: TaskStartedCounterAttr) -> Self { match value { @@ -320,7 +390,10 @@ impl From for ::opentelemetry::KeyValue { /// Number of tasks started. /// Opt-in: record only when the user requests it. #[derive(Clone)] -pub struct TaskStartedCounter { instrument: ::opentelemetry::metrics::Counter } +pub struct TaskStartedCounter { + instrument: ::opentelemetry::metrics::Counter, +} + impl TaskStartedCounter { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().u64_counter("myapp.task.started") @@ -335,10 +408,14 @@ impl TaskStartedCounter { self.instrument.add(value, &attributes); } } + impl Default for TaskStartedCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct TaskStartedCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct TaskStartedCounterObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl TaskStartedCounterObserver<'_> { pub fn observe(&self, value: u64, options: impl IntoIterator) { let mut attributes = ::smallvec::SmallVec::<[::opentelemetry::KeyValue; 1]>::new(); @@ -348,7 +425,10 @@ impl TaskStartedCounterObserver<'_> { } #[derive(Clone)] -pub struct TaskStartedObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +pub struct TaskStartedObservableCounter { + _instrument: ::opentelemetry::metrics::ObservableCounter, +} + impl TaskStartedObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(TaskStartedCounterObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().u64_observable_counter("myapp.task.started") @@ -359,6 +439,7 @@ impl TaskStartedObservableCounter { Self { _instrument: instrument } } } + impl Default for TaskStartedObservableCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } diff --git a/templates/code/rust/tests/metrics/expected/scope.rs b/templates/code/rust/tests/metrics/expected/scope.rs index 920a74d..6f66e86 100644 --- a/templates/code/rust/tests/metrics/expected/scope.rs +++ b/templates/code/rust/tests/metrics/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("generated-semconv") diff --git a/templates/code/rust/tests/metrics/expected/workermetric.rs b/templates/code/rust/tests/metrics/expected/workermetric.rs index e19e682..21f03e7 100644 --- a/templates/code/rust/tests/metrics/expected/workermetric.rs +++ b/templates/code/rust/tests/metrics/expected/workermetric.rs @@ -6,6 +6,7 @@ pub enum TaskDurationHistogramAttr { /// Conditionally required: If the task reached a final state. TaskState(super::myappattr::TaskStateAttr), } + impl From for ::opentelemetry::KeyValue { fn from(value: TaskDurationHistogramAttr) -> Self { match value { @@ -18,7 +19,10 @@ impl From for ::opentelemetry::KeyValue { /// /// Measured by the worker that ran the task. #[derive(Clone)] -pub struct TaskDurationHistogram { instrument: ::opentelemetry::metrics::Histogram } +pub struct TaskDurationHistogram { + instrument: ::opentelemetry::metrics::Histogram, +} + impl TaskDurationHistogram { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_histogram("myapp.task.duration") @@ -35,6 +39,7 @@ impl TaskDurationHistogram { self.instrument.record(value, &attributes); } } + impl Default for TaskDurationHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } diff --git a/templates/code/rust/tests/naming/expected/capsattr.rs b/templates/code/rust/tests/naming/expected/capsattr.rs index 1a956da..66d2edf 100644 --- a/templates/code/rust/tests/naming/expected/capsattr.rs +++ b/templates/code/rust/tests/naming/expected/capsattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for Http2STATUSApiIDAttr { Self(value) } } + #[allow(deprecated)] impl From for Http2STATUSApiIDAttr { #[inline] @@ -62,6 +63,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Synthetic mode. #[derive(Debug, Clone, PartialEq, Copy)] pub enum Mode2STATEAttr { diff --git a/templates/code/rust/tests/naming/expected/capsmetric.rs b/templates/code/rust/tests/naming/expected/capsmetric.rs index 5447fd8..eac6967 100644 --- a/templates/code/rust/tests/naming/expected/capsmetric.rs +++ b/templates/code/rust/tests/naming/expected/capsmetric.rs @@ -1,7 +1,10 @@ #![allow(deprecated)] /// Synthetic count. #[derive(Clone)] -pub struct Http2STATUSCountCounter { instrument: ::opentelemetry::metrics::Counter } +pub struct Http2STATUSCountCounter { + instrument: ::opentelemetry::metrics::Counter, +} + impl Http2STATUSCountCounter { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().u64_counter("caps.http2_STATUS.count") @@ -15,10 +18,14 @@ impl Http2STATUSCountCounter { self.instrument.add(value, &attributes); } } + impl Default for Http2STATUSCountCounter { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } -pub struct Http2STATUSCountCounterObserver<'a> { observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument } +pub struct Http2STATUSCountCounterObserver<'a> { + observer: &'a dyn ::opentelemetry::metrics::AsyncInstrument, +} + impl Http2STATUSCountCounterObserver<'_> { pub fn observe(&self, value: u64, r#caps_http2_status_api_id: super::capsattr::Http2STATUSApiIDAttr, r#caps_mode2_state: super::capsattr::Mode2STATEAttr) { let attributes = [::opentelemetry::KeyValue::from(r#caps_http2_status_api_id), ::opentelemetry::KeyValue::from(r#caps_mode2_state)]; @@ -27,7 +34,10 @@ impl Http2STATUSCountCounterObserver<'_> { } #[derive(Clone)] -pub struct Http2STATUSCountObservableCounter { _instrument: ::opentelemetry::metrics::ObservableCounter } +pub struct Http2STATUSCountObservableCounter { + _instrument: ::opentelemetry::metrics::ObservableCounter, +} + impl Http2STATUSCountObservableCounter { pub fn new(meter: &super::meter::Meter, callback: impl Fn(Http2STATUSCountCounterObserver<'_>) + Send + Sync + 'static) -> Self { let instrument = meter.inner().u64_observable_counter("caps.http2_STATUS.count") @@ -38,6 +48,7 @@ impl Http2STATUSCountObservableCounter { Self { _instrument: instrument } } } + impl Default for Http2STATUSCountObservableCounter { fn default() -> Self { Self::new(&super::meter::Meter::default(), |_| {}) } } diff --git a/templates/code/rust/tests/naming/expected/meter.rs b/templates/code/rust/tests/naming/expected/meter.rs index 3e2e018..a330bd2 100644 --- a/templates/code/rust/tests/naming/expected/meter.rs +++ b/templates/code/rust/tests/naming/expected/meter.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); + impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { let meter = provider.meter_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Meter { } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } + impl Default for Meter { fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/naming/expected/scope.rs b/templates/code/rust/tests/naming/expected/scope.rs index 920a74d..6f66e86 100644 --- a/templates/code/rust/tests/naming/expected/scope.rs +++ b/templates/code/rust/tests/naming/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("generated-semconv") diff --git a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs index b2b99fc..35411bd 100644 --- a/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/exceptionattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for MessageAttr { Self(value) } } + #[allow(deprecated)] impl From for MessageAttr { #[inline] @@ -62,6 +63,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// The type of the exception. #[derive(Debug, Clone, PartialEq)] pub struct TypeAttr(::opentelemetry::StringValue); @@ -78,6 +80,7 @@ impl From<::opentelemetry::StringValue> for TypeAttr { Self(value) } } + #[allow(deprecated)] impl From for TypeAttr { #[inline] diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs index c38b36f..b43d822 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatattr.rs @@ -39,6 +39,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Name of the component that sent the heartbeat. #[derive(Debug, Clone, PartialEq)] pub struct SourceAttr(::opentelemetry::StringValue); @@ -55,6 +56,7 @@ impl From<::opentelemetry::StringValue> for SourceAttr { Self(value) } } + #[allow(deprecated)] impl From for SourceAttr { #[inline] diff --git a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs index c356b3b..4b05f1f 100644 --- a/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs +++ b/templates/code/rust/tests/no_namespace/expected/heartbeatspan.rs @@ -5,6 +5,7 @@ use ::opentelemetry::trace::{TraceContextExt, Tracer}; pub enum StartAttr { Source(super::heartbeatattr::SourceAttr), } + impl From for ::opentelemetry::KeyValue { fn from(value: StartAttr) -> Self { match value { @@ -16,6 +17,7 @@ impl From for ::opentelemetry::KeyValue { pub enum Attr { Source(super::heartbeatattr::SourceAttr), } + impl From for StartAttr { fn from(value: Attr) -> Self { match value { @@ -25,17 +27,23 @@ impl From for StartAttr { } #[derive(Clone, Debug, Default)] pub struct Name(::std::borrow::Cow<'static, str>); + impl From<&'static str> for Name { fn from(value: &'static str) -> Self { Self(::std::borrow::Cow::Borrowed(value)) } } + impl From for Name { fn from(value: String) -> Self { Self(::std::borrow::Cow::Owned(value)) } } + impl From<::std::borrow::Cow<'static, str>> for Name { fn from(value: ::std::borrow::Cow<'static, str>) -> Self { Self(value) } } /// A periodic liveness signal. -pub struct Span { span: S } +pub struct Span { + span: S, +} + impl Span { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -51,6 +59,7 @@ impl Span { for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from(StartAttr::from(attribute))); } } } + impl Default for Span { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("heartbeat") } diff --git a/templates/code/rust/tests/no_namespace/expected/hostattr.rs b/templates/code/rust/tests/no_namespace/expected/hostattr.rs index be04645..b8c90eb 100644 --- a/templates/code/rust/tests/no_namespace/expected/hostattr.rs +++ b/templates/code/rust/tests/no_namespace/expected/hostattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for IdAttr { Self(value) } } + #[allow(deprecated)] impl From for IdAttr { #[inline] @@ -62,6 +63,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Name of the host. #[derive(Debug, Clone, PartialEq)] pub struct NameAttr(::opentelemetry::StringValue); @@ -78,6 +80,7 @@ impl From<::opentelemetry::StringValue> for NameAttr { Self(value) } } + #[allow(deprecated)] impl From for NameAttr { #[inline] diff --git a/templates/code/rust/tests/no_namespace/expected/logger.rs b/templates/code/rust/tests/no_namespace/expected/logger.rs index 137ef4c..78bcc02 100644 --- a/templates/code/rust/tests/no_namespace/expected/logger.rs +++ b/templates/code/rust/tests/no_namespace/expected/logger.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); + impl Logger { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let logger = provider.logger_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Logger { } pub fn inner(&self) -> &L { &self.0 } } + impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/no_namespace/expected/scope.rs b/templates/code/rust/tests/no_namespace/expected/scope.rs index 920a74d..6f66e86 100644 --- a/templates/code/rust/tests/no_namespace/expected/scope.rs +++ b/templates/code/rust/tests/no_namespace/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("generated-semconv") diff --git a/templates/code/rust/tests/no_namespace/expected/tracer.rs b/templates/code/rust/tests/no_namespace/expected/tracer.rs index 0dc2a89..d684a8d 100644 --- a/templates/code/rust/tests/no_namespace/expected/tracer.rs +++ b/templates/code/rust/tests/no_namespace/expected/tracer.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Tracer(T); + impl Tracer { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let tracer = provider.tracer_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Tracer { } pub fn inner(&self) -> &T { &self.0 } } + impl Default for Tracer { fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/params/expected/billingattr.rs b/templates/code/rust/tests/params/expected/billingattr.rs index b49ff5f..c00f2e5 100644 --- a/templates/code/rust/tests/params/expected/billingattr.rs +++ b/templates/code/rust/tests/params/expected/billingattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for InvoiceIdAttr { Self(value) } } + #[allow(deprecated)] impl From for InvoiceIdAttr { #[inline] @@ -62,6 +63,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// ISO 4217 currency code of the amount. #[derive(Debug, Clone, PartialEq)] pub struct CurrencyAttr(::opentelemetry::StringValue); @@ -78,6 +80,7 @@ impl From<::opentelemetry::StringValue> for CurrencyAttr { Self(value) } } + #[allow(deprecated)] impl From for CurrencyAttr { #[inline] diff --git a/templates/code/rust/tests/params/expected/billingmetric.rs b/templates/code/rust/tests/params/expected/billingmetric.rs index bbdc365..7b20973 100644 --- a/templates/code/rust/tests/params/expected/billingmetric.rs +++ b/templates/code/rust/tests/params/expected/billingmetric.rs @@ -4,6 +4,7 @@ pub enum InvoiceAmountHistogramAttr { Currency(super::billingattr::CurrencyAttr), RequestUrl(super::myappattr::RequestUrlAttr), } + impl From for ::opentelemetry::KeyValue { fn from(value: InvoiceAmountHistogramAttr) -> Self { match value { @@ -14,7 +15,10 @@ impl From for ::opentelemetry::KeyValue { } /// Amount of each issued invoice. #[derive(Clone)] -pub struct InvoiceAmountHistogram { instrument: ::opentelemetry::metrics::Histogram } +pub struct InvoiceAmountHistogram { + instrument: ::opentelemetry::metrics::Histogram, +} + impl InvoiceAmountHistogram { pub fn new(meter: &super::meter::Meter) -> Self { let instrument = meter.inner().f64_histogram("acme.billing.invoice.amount") @@ -30,6 +34,7 @@ impl InvoiceAmountHistogram { self.instrument.record(value, &attributes); } } + impl Default for InvoiceAmountHistogram { fn default() -> Self { Self::new(&super::meter::Meter::default()) } } diff --git a/templates/code/rust/tests/params/expected/billingspan.rs b/templates/code/rust/tests/params/expected/billingspan.rs index fff58fb..d745290 100644 --- a/templates/code/rust/tests/params/expected/billingspan.rs +++ b/templates/code/rust/tests/params/expected/billingspan.rs @@ -3,7 +3,10 @@ use ::opentelemetry::trace::{TraceContextExt, Tracer}; use ::std::fmt::Write; /// An invoice is being issued. -pub struct InvoiceIssueSpan { span: S } +pub struct InvoiceIssueSpan { + span: S, +} + impl InvoiceIssueSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -16,6 +19,7 @@ impl InvoiceIssueSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } } + impl Default for InvoiceIssueSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("acme.billing.invoice.issue") } diff --git a/templates/code/rust/tests/params/expected/logger.rs b/templates/code/rust/tests/params/expected/logger.rs index 137ef4c..78bcc02 100644 --- a/templates/code/rust/tests/params/expected/logger.rs +++ b/templates/code/rust/tests/params/expected/logger.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Logger::Logger>(L); + impl Logger { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let logger = provider.logger_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Logger { } pub fn inner(&self) -> &L { &self.0 } } + impl Default for Logger { fn default() -> Self { Self::new(&opentelemetry::logs::NoopLoggerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/params/expected/meter.rs b/templates/code/rust/tests/params/expected/meter.rs index 3e2e018..a330bd2 100644 --- a/templates/code/rust/tests/params/expected/meter.rs +++ b/templates/code/rust/tests/params/expected/meter.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Meter(opentelemetry::metrics::Meter); + impl Meter { pub fn new(provider: &impl opentelemetry::metrics::MeterProvider, options: InstrumentationOptions) -> Self { let meter = provider.meter_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Meter { } pub fn inner(&self) -> &opentelemetry::metrics::Meter { &self.0 } } + impl Default for Meter { fn default() -> Self { Self::new(&opentelemetry::metrics::noop::NoopMeterProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/params/expected/myappattr.rs b/templates/code/rust/tests/params/expected/myappattr.rs index 85bebf0..a771ccb 100644 --- a/templates/code/rust/tests/params/expected/myappattr.rs +++ b/templates/code/rust/tests/params/expected/myappattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for RequestUrlAttr { Self(value) } } + #[allow(deprecated)] impl From for RequestUrlAttr { #[inline] diff --git a/templates/code/rust/tests/params/expected/scope.rs b/templates/code/rust/tests/params/expected/scope.rs index f5c5ec7..bb5d98e 100644 --- a/templates/code/rust/tests/params/expected/scope.rs +++ b/templates/code/rust/tests/params/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("synthetic-billing") diff --git a/templates/code/rust/tests/params/expected/tracer.rs b/templates/code/rust/tests/params/expected/tracer.rs index 0dc2a89..d684a8d 100644 --- a/templates/code/rust/tests/params/expected/tracer.rs +++ b/templates/code/rust/tests/params/expected/tracer.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Tracer(T); + impl Tracer { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let tracer = provider.tracer_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Tracer { } pub fn inner(&self) -> &T { &self.0 } } + impl Default for Tracer { fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/spans/expected/myappattr.rs b/templates/code/rust/tests/spans/expected/myappattr.rs index ff0f2b5..f7c83c4 100644 --- a/templates/code/rust/tests/spans/expected/myappattr.rs +++ b/templates/code/rust/tests/spans/expected/myappattr.rs @@ -53,6 +53,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() } } + /// Synthetic naming value. #[derive(Debug, Clone, PartialEq)] pub struct ArrayIndicesAttr(Vec); @@ -107,6 +108,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() } } + /// Synthetic naming value. #[derive(Debug, Clone, PartialEq)] pub struct ArraySamplesAttr(Vec); @@ -161,6 +163,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() } } + /// Synthetic naming value. #[derive(Debug, Clone, PartialEq)] pub struct ArrayTagsAttr(Vec<::opentelemetry::StringValue>); @@ -177,6 +180,7 @@ impl From> for ArrayTagsAttr { Self(value) } } + #[allow(deprecated)] impl From> for ArrayTagsAttr { fn from(value: Vec) -> Self { @@ -221,6 +225,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into_iter().collect::<::opentelemetry::logs::AnyValue>() } } + /// Synthetic naming value. #[derive(Debug, Clone, PartialEq, Copy)] pub struct NumberValueAttr(f64); @@ -261,6 +266,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Name of the queue the task came from. #[derive(Debug, Clone, PartialEq)] pub struct QueueNameAttr(::opentelemetry::StringValue); @@ -277,6 +283,7 @@ impl From<::opentelemetry::StringValue> for QueueNameAttr { Self(value) } } + #[allow(deprecated)] impl From for QueueNameAttr { #[inline] @@ -324,6 +331,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Number of the attempt, starting at one. #[derive(Debug, Clone, PartialEq, Copy)] pub struct TaskAttemptAttr(i64); @@ -364,6 +372,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Unique identifier of the task. #[derive(Debug, Clone, PartialEq)] pub struct TaskIdAttr(::opentelemetry::StringValue); @@ -380,6 +389,7 @@ impl From<::opentelemetry::StringValue> for TaskIdAttr { Self(value) } } + #[allow(deprecated)] impl From for TaskIdAttr { #[inline] @@ -427,6 +437,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Current state of the task. #[derive(Debug, Clone, PartialEq, Copy)] pub enum TaskStateAttr { diff --git a/templates/code/rust/tests/spans/expected/myappspan.rs b/templates/code/rust/tests/spans/expected/myappspan.rs index e8a5666..f144d17 100644 --- a/templates/code/rust/tests/spans/expected/myappspan.rs +++ b/templates/code/rust/tests/spans/expected/myappspan.rs @@ -3,7 +3,10 @@ use ::opentelemetry::trace::{TraceContextExt, Tracer}; use ::std::fmt::Write; /// Synthetic escaped name. -pub struct NameApostropheSpan { span: S } +pub struct NameApostropheSpan { + span: S, +} + impl NameApostropheSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -16,6 +19,7 @@ impl NameApostropheSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } } + impl Default for NameApostropheSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("myapp.name.apostrophe") } @@ -34,7 +38,10 @@ pub fn r#start_name_apostrophe(context: &::op NameApostropheSpan { span } } /// A span named from array values. -pub struct NameArraysSpan { span: S } +pub struct NameArraysSpan { + span: S, +} + impl NameArraysSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -47,6 +54,7 @@ impl NameArraysSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } } + impl Default for NameArraysSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("myapp.name.arrays") } @@ -70,7 +78,10 @@ pub fn r#start_name_arrays(context: &::opente NameArraysSpan { span } } /// Synthetic escaped name. -pub struct NameBackslashSpan { span: S } +pub struct NameBackslashSpan { + span: S, +} + impl NameBackslashSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -83,6 +94,7 @@ impl NameBackslashSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } } + impl Default for NameBackslashSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("myapp.name.backslash") } @@ -101,7 +113,10 @@ pub fn r#start_name_backslash(context: &::ope NameBackslashSpan { span } } /// Synthetic escaped name. -pub struct NameControlSpan { span: S } +pub struct NameControlSpan { + span: S, +} + impl NameControlSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -114,6 +129,7 @@ impl NameControlSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } } + impl Default for NameControlSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("myapp.name.control") } @@ -132,7 +148,10 @@ pub fn r#start_name_control(context: &::opent NameControlSpan { span } } /// A span named from a floating point value. -pub struct NameFloatSpan { span: S } +pub struct NameFloatSpan { + span: S, +} + impl NameFloatSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -145,6 +164,7 @@ impl NameFloatSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } } + impl Default for NameFloatSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("myapp.name.float") } @@ -163,17 +183,23 @@ pub fn r#start_name_float(context: &::opentel } #[derive(Clone, Debug, Default)] pub struct NameStaticName(::std::borrow::Cow<'static, str>); + impl From<&'static str> for NameStaticName { fn from(value: &'static str) -> Self { Self(::std::borrow::Cow::Borrowed(value)) } } + impl From for NameStaticName { fn from(value: String) -> Self { Self(::std::borrow::Cow::Owned(value)) } } + impl From<::std::borrow::Cow<'static, str>> for NameStaticName { fn from(value: ::std::borrow::Cow<'static, str>) -> Self { Self(value) } } /// A span with an unconstrained caller supplied name. -pub struct NameStaticSpan { span: S } +pub struct NameStaticSpan { + span: S, +} + impl NameStaticSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -186,6 +212,7 @@ impl NameStaticSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } } + impl Default for NameStaticSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("myapp.name.static") } @@ -202,7 +229,10 @@ pub fn r#start_name_static(context: &::opente NameStaticSpan { span } } /// Synthetic escaped name. -pub struct NameUnicodeSpan { span: S } +pub struct NameUnicodeSpan { + span: S, +} + impl NameUnicodeSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -215,6 +245,7 @@ impl NameUnicodeSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } } + impl Default for NameUnicodeSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("myapp.name.unicode") } @@ -234,19 +265,25 @@ pub fn r#start_name_unicode(context: &::opent } #[derive(Clone, Debug, Default)] pub struct QueueDrainName(::std::borrow::Cow<'static, str>); + impl From<&'static str> for QueueDrainName { fn from(value: &'static str) -> Self { Self(::std::borrow::Cow::Borrowed(value)) } } + impl From for QueueDrainName { fn from(value: String) -> Self { Self(::std::borrow::Cow::Owned(value)) } } + impl From<::std::borrow::Cow<'static, str>> for QueueDrainName { fn from(value: ::std::borrow::Cow<'static, str>) -> Self { Self(value) } } /// Removing every task from a queue. /// Opt-in: record only when the user requests it. #[deprecated(note = "Drain queues by dispatching their tasks instead.")] -pub struct QueueDrainSpan { span: S } +pub struct QueueDrainSpan { + span: S, +} + impl QueueDrainSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -259,6 +296,7 @@ impl QueueDrainSpan { pub fn record_error(&mut self, error: &dyn ::std::error::Error) { ::opentelemetry::trace::Span::record_error(&mut self.span, error); } pub fn set_status(&mut self, status: ::opentelemetry::trace::Status) { ::opentelemetry::trace::Span::set_status(&mut self.span, status); } } + impl Default for QueueDrainSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("myapp.queue.drain") } @@ -282,6 +320,7 @@ pub enum TaskDispatchStartAttr { TaskAttempt(super::myappattr::TaskAttemptAttr), TaskId(super::myappattr::TaskIdAttr), } + impl From for ::opentelemetry::KeyValue { fn from(value: TaskDispatchStartAttr) -> Self { match value { @@ -296,6 +335,7 @@ pub enum TaskDispatchAttr { QueueName(super::myappattr::QueueNameAttr), TaskAttempt(super::myappattr::TaskAttemptAttr), } + impl From for TaskDispatchStartAttr { fn from(value: TaskDispatchAttr) -> Self { match value { @@ -307,7 +347,10 @@ impl From for TaskDispatchStartAttr { /// The scheduler handing a task to a worker. /// /// Ends when the worker accepts the task. -pub struct TaskDispatchSpan { span: S } +pub struct TaskDispatchSpan { + span: S, +} + impl TaskDispatchSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -323,6 +366,7 @@ impl TaskDispatchSpan { for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from(TaskDispatchStartAttr::from(attribute))); } } } + impl Default for TaskDispatchSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("myapp.task.dispatch") } @@ -346,6 +390,7 @@ pub fn r#start_task_dispatch(context: &::open pub enum TaskRunStartAttr { TaskId(super::myappattr::TaskIdAttr), } + impl From for ::opentelemetry::KeyValue { fn from(value: TaskRunStartAttr) -> Self { match value { @@ -357,6 +402,7 @@ impl From for ::opentelemetry::KeyValue { pub enum TaskRunAttr { TaskId(super::myappattr::TaskIdAttr), } + impl From for TaskRunStartAttr { fn from(value: TaskRunAttr) -> Self { match value { @@ -366,17 +412,23 @@ impl From for TaskRunStartAttr { } #[derive(Clone, Debug, Default)] pub struct TaskRunName(::std::borrow::Cow<'static, str>); + impl From<&'static str> for TaskRunName { fn from(value: &'static str) -> Self { Self(::std::borrow::Cow::Borrowed(value)) } } + impl From for TaskRunName { fn from(value: String) -> Self { Self(::std::borrow::Cow::Owned(value)) } } + impl From<::std::borrow::Cow<'static, str>> for TaskRunName { fn from(value: ::std::borrow::Cow<'static, str>) -> Self { Self(value) } } /// One run of a task. -pub struct TaskRunSpan { span: S } +pub struct TaskRunSpan { + span: S, +} + impl TaskRunSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -392,6 +444,7 @@ impl TaskRunSpan { for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from(TaskRunStartAttr::from(attribute))); } } } + impl Default for TaskRunSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("myapp.task.run") } diff --git a/templates/code/rust/tests/spans/expected/scope.rs b/templates/code/rust/tests/spans/expected/scope.rs index 920a74d..6f66e86 100644 --- a/templates/code/rust/tests/spans/expected/scope.rs +++ b/templates/code/rust/tests/spans/expected/scope.rs @@ -2,6 +2,7 @@ pub struct Scope { pub attributes: Vec<::opentelemetry::KeyValue>, } + impl From for ::opentelemetry::InstrumentationScope { fn from(value: Scope) -> Self { Self::builder("generated-semconv") diff --git a/templates/code/rust/tests/spans/expected/tracer.rs b/templates/code/rust/tests/spans/expected/tracer.rs index 0dc2a89..d684a8d 100644 --- a/templates/code/rust/tests/spans/expected/tracer.rs +++ b/templates/code/rust/tests/spans/expected/tracer.rs @@ -2,6 +2,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Tracer(T); + impl Tracer { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let tracer = provider.tracer_with_scope(options.scope.into()); @@ -9,6 +10,7 @@ impl Tracer { } pub fn inner(&self) -> &T { &self.0 } } + impl Default for Tracer { fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), InstrumentationOptions::default()) } } diff --git a/templates/code/rust/tests/spans/expected/workerattr.rs b/templates/code/rust/tests/spans/expected/workerattr.rs index 46d82cb..431c6c0 100644 --- a/templates/code/rust/tests/spans/expected/workerattr.rs +++ b/templates/code/rust/tests/spans/expected/workerattr.rs @@ -15,6 +15,7 @@ impl From<::opentelemetry::StringValue> for HostNameAttr { Self(value) } } + #[allow(deprecated)] impl From for HostNameAttr { #[inline] @@ -62,6 +63,7 @@ impl From for ::opentelemetry::logs::AnyValue { value.0.into() } } + /// Port the worker listens on. #[derive(Debug, Clone, PartialEq, Copy)] pub struct HostPortAttr(i64); diff --git a/templates/code/rust/tests/spans/expected/workerspan.rs b/templates/code/rust/tests/spans/expected/workerspan.rs index 708fbe6..7fc031f 100644 --- a/templates/code/rust/tests/spans/expected/workerspan.rs +++ b/templates/code/rust/tests/spans/expected/workerspan.rs @@ -8,6 +8,7 @@ pub enum TaskDispatchStartAttr { QueueName(super::myappattr::QueueNameAttr), TaskId(super::myappattr::TaskIdAttr), } + impl From for ::opentelemetry::KeyValue { fn from(value: TaskDispatchStartAttr) -> Self { match value { @@ -20,6 +21,7 @@ impl From for ::opentelemetry::KeyValue { pub enum TaskDispatchAttr { QueueName(super::myappattr::QueueNameAttr), } + impl From for TaskDispatchStartAttr { fn from(value: TaskDispatchAttr) -> Self { match value { @@ -30,7 +32,10 @@ impl From for TaskDispatchStartAttr { /// The scheduler handing a task to a worker. /// /// Ends when the worker accepts the task. -pub struct TaskDispatchSpan { span: S } +pub struct TaskDispatchSpan { + span: S, +} + impl TaskDispatchSpan { pub fn into_context(self, parent: &::opentelemetry::Context) -> ::opentelemetry::Context where S: Send + Sync + 'static, @@ -46,6 +51,7 @@ impl TaskDispatchSpan { for attribute in attributes { ::opentelemetry::trace::Span::set_attribute(&mut self.span, ::opentelemetry::KeyValue::from(TaskDispatchStartAttr::from(attribute))); } } } + impl Default for TaskDispatchSpan { fn default() -> Self { Self { span: super::tracer::Tracer::default().inner().start("myapp.task.dispatch") } diff --git a/templates/code/rust/tracer.rs.j2 b/templates/code/rust/tracer.rs.j2 index ccca159..e1cd4be 100644 --- a/templates/code/rust/tracer.rs.j2 +++ b/templates/code/rust/tracer.rs.j2 @@ -3,6 +3,7 @@ use super::options::InstrumentationOptions; #[derive(Clone, Debug)] pub struct Tracer(T); + impl Tracer { pub fn new>(provider: &P, options: InstrumentationOptions) -> Self { let tracer = provider.tracer_with_scope(options.scope.into()); @@ -10,6 +11,7 @@ impl Tracer { } pub fn inner(&self) -> &T { &self.0 } } + impl Default for Tracer { fn default() -> Self { Self::new(&opentelemetry::trace::noop::NoopTracerProvider::new(), InstrumentationOptions::default()) } }