From 2506d20643a7948340760b57d83c151ccc5aa380 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 14:58:53 -0700 Subject: [PATCH 01/22] chore(code): make error enums non-exhaustive --- CHANGELOG.md | 87 +++++++++++++++++++++++++++- Cargo.toml | 67 +++++++++++++++++++++ crates/weaver_cache/src/lib.rs | 1 + crates/weaver_forge/src/error.rs | 1 + crates/weaver_resolver/src/lib.rs | 1 + crates/weaver_schema/src/lib.rs | 1 + crates/weaver_semconv/src/lib.rs | 1 + crates/weaver_semconv_gen/src/lib.rs | 1 + crates/weaver_template/src/lib.rs | 1 + crates/weaver_version/src/lib.rs | 1 + justfile | 1 + 11 files changed, 161 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d013ff9..f784b4de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,5 +2,88 @@ All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [unreleased] + +### ๐Ÿš€ Features + +- *(registry)* Improve resolved schema and registry api usability. +- *(registry)* Introduce the concept of named registries +- *(stats)* Implement registry stats command +- *(resolve)* Implement registry resolve command +- *(template)* Add a more complex example generating markdown files per group prefix +- *(template)* Reimplement template generation based on minijinja + jaq (jq-like filters) +- *(cli)* Add quiet mode +- *(generator)* Add support for all group types +- *(generator)* Add jq-like filter support to make artifact generation more flexible +- *(generator)* Complete the weaver registry generate command. +- *(cli)* Add update-markdown sub-command and align sub-command args in the registry command. +- *(registry)* Improve unit test to check the generated markdown +- *(registry)* Add unit test to check the generated markdown +- *(registry)* Generate markdown from jinja2 templates +- *(template)* Generate markdown files describing a registry +- *(template)* Add template syntax configuration +- *(template)* Initialize template engine with a root directory to support include clause. +- *(template)* Expose template.set_file_name method to dynamically define the file name of the output. +- *(template)* Generate registry from templates +- *(resolve)* Improve error reporting +- *(resolve)* Fix typo +- *(resolve)* Implement `include` constraint +- *(resolve)* Check `any_of` constraints +- *(template)* Integrate with minininja +- *(template)* Start integration of the case converter +- *(template)* Replace tera with minijinja to improve error handling +- *(registry)* Refactor registry sub-commands. +- *(registry)* Add `weaver check registry` command +- *(resolver)* Simplify semantic convention registry resolution function + +### ๐Ÿ› Bug Fixes + +- *(resolution)* Adjust other unit tests to take into account the fix +- *(resolution)* Make resolution process easy to test in unit tests +- *(resolution)* Fix resolution order +- *(resolution)* Create minimal example reproducing the bug + +### ๐Ÿ“š Documentation + +- *(template)* Add documentation to describe the template engine. +- Describe crates layout and add README.md files for every crates in the workspace. +- Clean up README.md + +### ๐Ÿงช Testing + +- *(integration)* Create integration test to check parsing and resolution of the official semconv repo. + +### โš™๏ธ Miscellaneous Tasks + +- *(code)* Implement #54 +- *(code)* Fix str_to_string clippy lint issues +- *(code)* Implement #54 + new clippy lint rule +- *(build)* Fix doc lint issue +- *(build)* Fix GH action +- *(build)* Add xtask +- *(build)* Replace script/check_workspace with cargo xtask validate +- *(build)* Define lint rules globally from the cargo workspace +- *(build)* Clippy lint rules to remove unwrap and enforce must_use when needed +- *(build)* Fix clippy issues +- *(doc)* Update README.md to describe check and generate sub-commands +- *(build)* Fix clippy issue +- *(build)* Fix merge issue. +- *(build)* Update cargo lock +- *(compatibility)* Align attribute type and examples definitions +- *(compatibility)* Align requirement level definition +- *(compatibility)* Align stability definition +- *(compatibility)* Make resolved registry compatible with official registry syntax +- *(clippy)* Fix clippy lint issues +- *(error)* Improve compound error management +- *(ci)* Fix toolchain version issue +- *(ci)* Attempt to fix toolchain version issue +- *(build)* Fix ci workflow +- *(build)* Fix scripts path +- *(build)* Remove allowed-external-types.toml files from the Typos control. +- *(build)* Add control procedures for workspace and public API policies +- *(build)* Run build and test only with ubuntu target for now. +- *(build)* Remove macos target for the build (API rate limit reached, we need to figure out that later). +- Add cargo lock file. +- *(dep)* Bump dependency versions +- Migrate f5/otel-weaver repo to open-telemetry/weaver repo + diff --git a/Cargo.toml b/Cargo.toml index 6b41e1b7..74fbd9f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,6 +92,9 @@ unused_qualifications = "deny" unused_results = "deny" unused_extern_crates = "deny" +unsafe_op_in_unsafe_fn = "warn" +unused_macro_rules = "warn" + [lints] workspace = true @@ -117,3 +120,67 @@ type_complexity = "allow" wrong_self_convention = "allow" rc_buffer = "warn" str_to_string = "warn" +checked_conversions = "warn" +create_dir = "warn" +dbg_macro = "warn" +debug_assert_with_mut_call = "warn" + +#exhaustive_enums = "warn" + +## +#bool_assert_comparison = "allow" +#branches_sharing_code = "allow" +#collapsible_else_if = "allow" +doc_markdown = "warn" +empty_enum = "warn" +#enum_glob_use = "warn" +#exhaustive_structs = "warn" +#exit = "warn" +#expl_impl_clone_on_copy = "warn" +#explicit_deref_methods = "warn" +#explicit_into_iter_loop = "warn" +#fallible_impl_from = "warn" +#filter_map_next = "warn" +#flat_map_option = "warn" +#float_cmp_const = "warn" +#fn_params_excessive_bools = "warn" +#from_iter_instead_of_collect = "warn" +#if_same_then_else = "allow" +#implicit_clone = "warn" +#imprecise_flops = "warn" +#inefficient_to_string = "warn" +#infinite_loop = "warn" +#invalid_upcast_comparisons = "warn" +#items_after_statements = "warn" +#large_digit_groups = "warn" +#large_stack_arrays = "warn" +#large_types_passed_by_value = "warn" +#let_and_return = "allow" # sometimes good to name what you are returning +#linkedlist = "warn" +#lossy_float_literal = "warn" +#macro_use_imports = "warn" +#match_wildcard_for_single_variants = "warn" +#mem_forget = "warn" +#mutex_integer = "warn" +#needless_continue = "warn" +#needless_for_each = "warn" +#negative_feature_names = "warn" +#path_buf_push_overwrite = "warn" +#ptr_as_ptr = "warn" +#rc_mutex = "warn" +#redundant_feature_names = "warn" +#ref_option_ref = "warn" +#rest_pat_in_fully_bound_structs = "warn" +#same_functions_in_if_condition = "warn" +#self_named_module_files = "warn" +#semicolon_if_nothing_returned = "warn" +#single_match_else = "warn" +#string_add = "warn" +#string_add_assign = "warn" +#string_lit_as_bytes = "warn" +#string_to_string = "warn" +#todo = "warn" +#trait_duplication_in_bounds = "warn" +#verbose_file_reads = "warn" +#wildcard_imports = "warn" +#zero_sized_map_values = "warn" \ No newline at end of file diff --git a/crates/weaver_cache/src/lib.rs b/crates/weaver_cache/src/lib.rs index 2faf90a5..46b20433 100644 --- a/crates/weaver_cache/src/lib.rs +++ b/crates/weaver_cache/src/lib.rs @@ -21,6 +21,7 @@ use tempdir::TempDir; /// An error that can occur while creating or using a cache. #[derive(thiserror::Error, Debug)] +#[non_exhaustive] pub enum Error { /// Home directory not found. #[error("Home directory not found")] diff --git a/crates/weaver_forge/src/error.rs b/crates/weaver_forge/src/error.rs index a51bfa65..2f012925 100644 --- a/crates/weaver_forge/src/error.rs +++ b/crates/weaver_forge/src/error.rs @@ -8,6 +8,7 @@ use weaver_resolved_schema::attribute::AttributeRef; /// Errors emitted by this crate. #[derive(thiserror::Error, Debug, Clone)] +#[non_exhaustive] pub enum Error { /// Invalid config file. #[error("Invalid config file `{config_file}`: {error}")] diff --git a/crates/weaver_resolver/src/lib.rs b/crates/weaver_resolver/src/lib.rs index 34d31936..466ba1c5 100644 --- a/crates/weaver_resolver/src/lib.rs +++ b/crates/weaver_resolver/src/lib.rs @@ -46,6 +46,7 @@ pub struct SchemaResolver {} /// An error that can occur while resolving a telemetry schema. #[derive(thiserror::Error, Debug)] #[must_use] +#[non_exhaustive] pub enum Error { /// A telemetry schema error. #[error("Telemetry schema error (error: {0:?})")] diff --git a/crates/weaver_schema/src/lib.rs b/crates/weaver_schema/src/lib.rs index 2f2995ac..1ffb2d7c 100644 --- a/crates/weaver_schema/src/lib.rs +++ b/crates/weaver_schema/src/lib.rs @@ -35,6 +35,7 @@ pub mod univariate_metric; /// An error that can occur while loading a telemetry schema. #[derive(thiserror::Error, Debug)] +#[non_exhaustive] pub enum Error { /// The telemetry schema was not found. #[error("Schema {path_or_url:?} not found\n{error:?}")] diff --git a/crates/weaver_semconv/src/lib.rs b/crates/weaver_semconv/src/lib.rs index 953dd5e1..a9200535 100644 --- a/crates/weaver_semconv/src/lib.rs +++ b/crates/weaver_semconv/src/lib.rs @@ -26,6 +26,7 @@ pub mod stability; /// An error that can occur while loading a semantic convention registry. #[derive(thiserror::Error, Debug)] +#[non_exhaustive] pub enum Error { /// The semantic convention registry path pattern is invalid. #[error("Invalid semantic convention registry path pattern '{path_pattern:?}'.\n{error}")] diff --git a/crates/weaver_semconv_gen/src/lib.rs b/crates/weaver_semconv_gen/src/lib.rs index 84301f1c..37ca19f1 100644 --- a/crates/weaver_semconv_gen/src/lib.rs +++ b/crates/weaver_semconv_gen/src/lib.rs @@ -21,6 +21,7 @@ use crate::gen::{AttributeTableView, GenerateMarkdownContext, MetricView}; /// Errors emitted by this crate. #[derive(thiserror::Error, Debug)] +#[non_exhaustive] pub enum Error { /// Thrown when we are unable to find a semconv by id. #[error("Could not find: {id}")] diff --git a/crates/weaver_template/src/lib.rs b/crates/weaver_template/src/lib.rs index a93a1a42..1c637f38 100644 --- a/crates/weaver_template/src/lib.rs +++ b/crates/weaver_template/src/lib.rs @@ -14,6 +14,7 @@ mod testers; /// An error that can occur while generating a client SDK. #[derive(thiserror::Error, Debug)] +#[non_exhaustive] pub enum Error { /// Invalid config file. #[error("Invalid config file `{config_file}`: {error}")] diff --git a/crates/weaver_version/src/lib.rs b/crates/weaver_version/src/lib.rs index bdc1d684..7b4c74b5 100644 --- a/crates/weaver_version/src/lib.rs +++ b/crates/weaver_version/src/lib.rs @@ -29,6 +29,7 @@ pub mod spans_version; /// An error that can occur while loading or resolving version changes. #[derive(thiserror::Error, Debug)] +#[non_exhaustive] pub enum Error { /// The `versions` file was not found. #[error("Versions {path_or_url:?} not found\n{error:?}")] diff --git a/justfile b/justfile index de65949f..5a355d8d 100644 --- a/justfile +++ b/justfile @@ -6,6 +6,7 @@ install: cargo install cargo-edit rustup install nightly-2023-10-10 # used by cargo-check-external-types cargo install cargo-check-external-types + cargo install git-cliff pre-push-check: rustup update From 0255eaeb3eda8ebbc112507ad0aab5a8633ba408 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 14:59:53 -0700 Subject: [PATCH 02/22] chore(changelog): add git cliff configuration --- cliff.toml | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 cliff.toml diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 00000000..8f9f4c27 --- /dev/null +++ b/cliff.toml @@ -0,0 +1,89 @@ +# git-cliff ~ default configuration file +# https://git-cliff.org/docs/configuration +# +# Lines starting with "#" are comments. +# Configuration options are organized into tables and keys. +# See documentation for more information on available options. + +[changelog] +# changelog header +header = """ +# Changelog\n +All notable changes to this project will be documented in this file.\n +""" +# template for the changelog body +# https://keats.github.io/tera/docs/#introduction +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | striptags | trim | upper_first }} + {% for commit in commits | unique(attribute="message") %} + - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\ + {% if commit.breaking %}[**breaking**] {% endif %}\ + {{ commit.message | upper_first }}\ + {% endfor %} +{% endfor %}\n +""" +# template for the changelog footer +footer = """ + +""" +# remove the leading and trailing s +trim = true +# postprocessors +postprocessors = [ + # { pattern = '', replace = "https://github.com/orhun/git-cliff" }, # replace repository URL +] + +[git] +# parse the commits based on https://www.conventionalcommits.org +conventional_commits = true +# filter out the commits that are not conventional +filter_unconventional = true +# process each line of a commit as an individual commit +split_commits = false +# regex for preprocessing the commit messages +commit_preprocessors = [ + # Replace issue numbers + #{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))"}, + # Check spelling of the commit with https://github.com/crate-ci/typos + # If the spelling is incorrect, it will be automatically fixed. + #{ pattern = '.*', replace_command = 'typos --write-changes -' }, +] +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^feat", group = "๐Ÿš€ Features" }, + { message = "^fix", group = "๐Ÿ› Bug Fixes" }, + { message = "^doc", group = "๐Ÿ“š Documentation" }, + { message = "^perf", group = "โšก Performance" }, + { message = "^refactor", group = "๐Ÿšœ Refactor" }, + { message = "^style", group = "๐ŸŽจ Styling" }, + { message = "^test", group = "๐Ÿงช Testing" }, + { message = "^chore\\(release\\): prepare for", skip = true }, + { message = "^chore\\(deps.*\\)", skip = true }, + { message = "^chore\\(pr\\)", skip = true }, + { message = "^chore\\(pull\\)", skip = true }, + { message = "^chore|^ci", group = "โš™๏ธ Miscellaneous Tasks" }, + { body = ".*security", group = "๐Ÿ›ก๏ธ Security" }, + { message = "^revert", group = "โ—€๏ธ Revert" }, +] +# protect breaking changes from being skipped due to matching a skipping commit_parser +protect_breaking_commits = false +# filter out the commits that are not matched by commit parsers +filter_commits = false +# regex for matching git tags +# tag_pattern = "v[0-9].*" +# regex for skipping tags +# skip_tags = "" +# regex for ignoring tags +# ignore_tags = "" +# sort the tags topologically +topo_order = false +# sort the commits inside sections by oldest/newest order +sort_commits = "newest" +# limit the number of commits included in the changelog. +# limit_commits = 42 From 28ad246ec190eb75a7b1d08fef14c91d76601d97 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 15:01:45 -0700 Subject: [PATCH 03/22] chore(git): make the output dir invisible for git --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 8a0c86c6..742dedd1 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ just.zsh # test generated code **/observed_output/* + +/output \ No newline at end of file From 2b085d91cac0648244a4f853642a55131eddae86 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 15:10:36 -0700 Subject: [PATCH 04/22] chore(clippy): fix explicit_into_iter_loop clippy issue --- Cargo.toml | 14 +++++++------- crates/weaver_semconv/src/lib.rs | 6 +++--- crates/weaver_version/src/lib.rs | 2 +- crates/xtask/src/validate.rs | 1 + 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 74fbd9f7..260bdaa4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -124,6 +124,12 @@ checked_conversions = "warn" create_dir = "warn" dbg_macro = "warn" debug_assert_with_mut_call = "warn" +empty_enum = "warn" +enum_glob_use = "warn" +exit = "warn" +expl_impl_clone_on_copy = "warn" +explicit_deref_methods = "warn" +explicit_into_iter_loop = "warn" #exhaustive_enums = "warn" @@ -131,14 +137,8 @@ debug_assert_with_mut_call = "warn" #bool_assert_comparison = "allow" #branches_sharing_code = "allow" #collapsible_else_if = "allow" -doc_markdown = "warn" -empty_enum = "warn" -#enum_glob_use = "warn" +#doc_markdown = "warn" #exhaustive_structs = "warn" -#exit = "warn" -#expl_impl_clone_on_copy = "warn" -#explicit_deref_methods = "warn" -#explicit_into_iter_loop = "warn" #fallible_impl_from = "warn" #filter_map_next = "warn" #flat_map_option = "warn" diff --git a/crates/weaver_semconv/src/lib.rs b/crates/weaver_semconv/src/lib.rs index a9200535..28e8208f 100644 --- a/crates/weaver_semconv/src/lib.rs +++ b/crates/weaver_semconv/src/lib.rs @@ -429,7 +429,7 @@ impl SemConvRegistry { let mut metrics_to_resolve = HashMap::new(); // Add all the attributes with an id to the semantic convention registry. - for SemConvSpecWithProvenance { spec, provenance } in self.specs.clone().into_iter() { + for SemConvSpecWithProvenance { spec, provenance } in self.specs.clone() { for group in spec.groups.iter() { // Process attributes match group.r#type { @@ -551,7 +551,7 @@ impl SemConvRegistry { } // Resolve all the attributes with a reference. - for attr_to_resolve in attributes_to_resolve.into_iter() { + for attr_to_resolve in attributes_to_resolve { let resolved_attr = self.all_attributes.get(&attr_to_resolve.r#ref); if resolved_attr.is_none() { @@ -748,7 +748,7 @@ impl SemConvRegistry { attributes_to_resolve: &mut Vec, ) -> Result, Error> { let mut attributes_in_group = HashSet::new(); - for mut attr in attrs.into_iter() { + for mut attr in attrs { match &attr { AttributeSpec::Id { id, .. } => { // The attribute has an id, so add it to the semantic convention registry diff --git a/crates/weaver_version/src/lib.rs b/crates/weaver_version/src/lib.rs index 7b4c74b5..604a1f6d 100644 --- a/crates/weaver_version/src/lib.rs +++ b/crates/weaver_version/src/lib.rs @@ -275,7 +275,7 @@ impl Versions { /// Update the current `Versions` to include the transformations of the parent `Versions`. /// Transformations of the current `Versions` take precedence over the parent `Versions`. pub fn extend(&mut self, parent_versions: Versions) { - for (version, spec) in parent_versions.versions.into_iter() { + for (version, spec) in parent_versions.versions { match self.versions.get_mut(&version) { Some(current_spec) => { current_spec.extend(spec); diff --git a/crates/xtask/src/validate.rs b/crates/xtask/src/validate.rs index 13a8e176..fc136bd3 100644 --- a/crates/xtask/src/validate.rs +++ b/crates/xtask/src/validate.rs @@ -81,6 +81,7 @@ pub fn run() -> anyhow::Result<()> { eprintln!("{}", error); eprintln!() } + #[allow(clippy::exit)] // This is an expected exit std::process::exit(1); } From 759e2db670822c2abab1253c6393e716ddabd9ad Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 15:19:54 -0700 Subject: [PATCH 05/22] chore(clippy): fix more clippy issues --- Cargo.toml | 8 ++++---- crates/weaver_forge/src/config.rs | 1 + crates/weaver_forge/src/registry.rs | 2 +- crates/weaver_resolved_schema/src/registry.rs | 2 +- src/registry/generate.rs | 1 + src/registry/mod.rs | 1 + 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 260bdaa4..30aac5a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -139,10 +139,10 @@ explicit_into_iter_loop = "warn" #collapsible_else_if = "allow" #doc_markdown = "warn" #exhaustive_structs = "warn" -#fallible_impl_from = "warn" -#filter_map_next = "warn" -#flat_map_option = "warn" -#float_cmp_const = "warn" +fallible_impl_from = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +float_cmp_const = "warn" #fn_params_excessive_bools = "warn" #from_iter_instead_of_collect = "warn" #if_same_then_else = "allow" diff --git a/crates/weaver_forge/src/config.rs b/crates/weaver_forge/src/config.rs index f71a2cf0..9d72f137 100644 --- a/crates/weaver_forge/src/config.rs +++ b/crates/weaver_forge/src/config.rs @@ -56,6 +56,7 @@ pub struct TargetConfig { pub field_name: CaseConvention, /// Type mapping for target specific types (OTel types -> Target language types). #[serde(default)] + #[allow(dead_code)] // ToDo create a Jinja macro to generate the mapping semconv -> target language pub type_mapping: HashMap, /// Configuration for the template syntax. #[serde(default)] diff --git a/crates/weaver_forge/src/registry.rs b/crates/weaver_forge/src/registry.rs index e57e7d77..3c2a0d62 100644 --- a/crates/weaver_forge/src/registry.rs +++ b/crates/weaver_forge/src/registry.rs @@ -126,7 +126,7 @@ impl TemplateRegistry { let attributes = group .attributes .iter() - .flat_map(|attr_ref| { + .filter_map(|attr_ref| { let attr = catalog.attribute(attr_ref).cloned(); if attr.is_none() { errors.push(Error::AttributeNotFound { diff --git a/crates/weaver_resolved_schema/src/registry.rs b/crates/weaver_resolved_schema/src/registry.rs index ef23183f..897eabcd 100644 --- a/crates/weaver_resolved_schema/src/registry.rs +++ b/crates/weaver_resolved_schema/src/registry.rs @@ -347,7 +347,7 @@ impl Group { let attributes = self .attributes .iter() - .flat_map(|attr_ref| match catalog.attribute(attr_ref) { + .filter_map(|attr_ref| match catalog.attribute(attr_ref) { Some(attr) => Some(attr), None => { errors.push(Error::AttributeNotFound { diff --git a/src/registry/generate.rs b/src/registry/generate.rs index 6405bd7d..42fae162 100644 --- a/src/registry/generate.rs +++ b/src/registry/generate.rs @@ -95,6 +95,7 @@ pub(crate) fn command( Ok(_) => logger.success("Artifacts generated successfully"), Err(e) => { print_dedup_errors(logger.clone(), e); + #[allow(clippy::exit)] // Expected behavior std::process::exit(1); } }; diff --git a/src/registry/mod.rs b/src/registry/mod.rs index 062fc23f..e600a0a4 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -67,6 +67,7 @@ pub struct RegistryArgs { pub fn semconv_registry(log: impl Logger + Sync + Clone, command: &RegistryCommand) { let cache = Cache::try_new().unwrap_or_else(|e| { log.error(&e.to_string()); + #[allow(clippy::exit)] // Expected behavior std::process::exit(1); }); From f03e49a40758616947602e5991154ed872224bc7 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 15:25:10 -0700 Subject: [PATCH 06/22] chore(clippy): add more clippy lints --- Cargo.toml | 29 +++++++++++++-------------- crates/weaver_template/src/filters.rs | 13 ++++++------ src/registry/update_markdown.rs | 11 +++++----- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 30aac5a7..4cbac08d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -130,6 +130,15 @@ exit = "warn" expl_impl_clone_on_copy = "warn" explicit_deref_methods = "warn" explicit_into_iter_loop = "warn" +fallible_impl_from = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +float_cmp_const = "warn" +fn_params_excessive_bools = "warn" +from_iter_instead_of_collect = "warn" +imprecise_flops = "warn" +inefficient_to_string = "warn" +infinite_loop = "warn" #exhaustive_enums = "warn" @@ -139,22 +148,12 @@ explicit_into_iter_loop = "warn" #collapsible_else_if = "allow" #doc_markdown = "warn" #exhaustive_structs = "warn" -fallible_impl_from = "warn" -filter_map_next = "warn" -flat_map_option = "warn" -float_cmp_const = "warn" -#fn_params_excessive_bools = "warn" -#from_iter_instead_of_collect = "warn" #if_same_then_else = "allow" -#implicit_clone = "warn" -#imprecise_flops = "warn" -#inefficient_to_string = "warn" -#infinite_loop = "warn" -#invalid_upcast_comparisons = "warn" -#items_after_statements = "warn" -#large_digit_groups = "warn" -#large_stack_arrays = "warn" -#large_types_passed_by_value = "warn" +invalid_upcast_comparisons = "warn" +items_after_statements = "warn" +large_digit_groups = "warn" +large_stack_arrays = "warn" +large_types_passed_by_value = "warn" #let_and_return = "allow" # sometimes good to name what you are returning #linkedlist = "warn" #lossy_float_literal = "warn" diff --git a/crates/weaver_template/src/filters.rs b/crates/weaver_template/src/filters.rs index 3d66fee7..ec4e53e3 100644 --- a/crates/weaver_template/src/filters.rs +++ b/crates/weaver_template/src/filters.rs @@ -57,13 +57,6 @@ pub fn instrument(value: &Value, _: &HashMap) -> Result { /// The result is a list of unique attributes sorted by their id or an empty list if no attributes /// are found. pub fn unique_attributes(value: &Value, ctx: &HashMap) -> Result { - let mut unique_attributes = BTreeMap::new(); - - let recursive = match ctx.get("recursive") { - Some(Value::Bool(v)) => *v, - _ => false, - }; - fn visit_attributes( value: &Value, unique_attributes: &mut BTreeMap, @@ -106,6 +99,12 @@ pub fn unique_attributes(value: &Value, ctx: &HashMap) -> Result< } } + let mut unique_attributes = BTreeMap::new(); + let recursive = match ctx.get("recursive") { + Some(Value::Bool(v)) => *v, + _ => false, + }; + visit_attributes( value, &mut unique_attributes, diff --git a/src/registry/update_markdown.rs b/src/registry/update_markdown.rs index cf6f59db..97528c63 100644 --- a/src/registry/update_markdown.rs +++ b/src/registry/update_markdown.rs @@ -38,6 +38,12 @@ pub(crate) fn command( cache: &Cache, args: &RegistryUpdateMarkdownArgs, ) { + fn is_markdown(entry: &walkdir::DirEntry) -> bool { + let path = entry.path(); + let extension = path.extension().unwrap_or_else(|| std::ffi::OsStr::new("")); + path.is_file() && extension == "md" + } + let registry = ResolvedSemconvRegistry::try_from_url( args.registry.clone(), args.registry_git_sub_dir.clone(), @@ -48,11 +54,6 @@ pub(crate) fn command( panic!("Failed to resolve the semantic convention registry.\n{e}"); }); log.success("Registry resolved successfully"); - fn is_markdown(entry: &walkdir::DirEntry) -> bool { - let path = entry.path(); - let extension = path.extension().unwrap_or_else(|| std::ffi::OsStr::new("")); - path.is_file() && extension == "md" - } let operation = if args.dry_run { "Validating" } else { From 1844e054875f73e76665701af5ded72d5181d152 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 15:35:34 -0700 Subject: [PATCH 07/22] chore(clippy): add more clippy lints --- Cargo.toml | 24 +++++++++++----------- crates/weaver_resolved_schema/src/error.rs | 4 ++-- crates/weaver_semconv/src/lib.rs | 15 +++++++------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4cbac08d..2a16bc32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -139,6 +139,11 @@ from_iter_instead_of_collect = "warn" imprecise_flops = "warn" inefficient_to_string = "warn" infinite_loop = "warn" +invalid_upcast_comparisons = "warn" +items_after_statements = "warn" +large_digit_groups = "warn" +large_stack_arrays = "warn" +large_types_passed_by_value = "warn" #exhaustive_enums = "warn" @@ -149,19 +154,14 @@ infinite_loop = "warn" #doc_markdown = "warn" #exhaustive_structs = "warn" #if_same_then_else = "allow" -invalid_upcast_comparisons = "warn" -items_after_statements = "warn" -large_digit_groups = "warn" -large_stack_arrays = "warn" -large_types_passed_by_value = "warn" #let_and_return = "allow" # sometimes good to name what you are returning -#linkedlist = "warn" -#lossy_float_literal = "warn" -#macro_use_imports = "warn" -#match_wildcard_for_single_variants = "warn" -#mem_forget = "warn" -#mutex_integer = "warn" -#needless_continue = "warn" +linkedlist = "warn" +lossy_float_literal = "warn" +macro_use_imports = "warn" +match_wildcard_for_single_variants = "warn" +mem_forget = "warn" +mutex_integer = "warn" +needless_continue = "warn" #needless_for_each = "warn" #negative_feature_names = "warn" #path_buf_push_overwrite = "warn" diff --git a/crates/weaver_resolved_schema/src/error.rs b/crates/weaver_resolved_schema/src/error.rs index 18162ade..fe7f23c5 100644 --- a/crates/weaver_resolved_schema/src/error.rs +++ b/crates/weaver_resolved_schema/src/error.rs @@ -3,7 +3,7 @@ //! Error types and utilities. use crate::attribute::AttributeRef; -use crate::error::Error::CompoundError; +use crate::error::Error::{AttributeNotFound, CompoundError}; /// Errors emitted by this crate. #[derive(thiserror::Error, Debug, Clone)] @@ -41,7 +41,7 @@ impl Error { .into_iter() .flat_map(|e| match e { CompoundError(errors) => errors, - e => vec![e], + e @ AttributeNotFound{ .. } => vec![e], }) .collect(), ) diff --git a/crates/weaver_semconv/src/lib.rs b/crates/weaver_semconv/src/lib.rs index 28e8208f..297cacd4 100644 --- a/crates/weaver_semconv/src/lib.rs +++ b/crates/weaver_semconv/src/lib.rs @@ -215,6 +215,12 @@ pub struct SemConvRegistry { /// all_attributes field. event_group_attributes: HashMap, + /// Collection of attribute ids index by group id and defined in a + /// `scope` semantic convention group. + /// Attribute ids are references to of attributes defined in the + /// all_attributes field. + scope_group_attributes: HashMap, + /// Collection of attribute ids index by group id and defined in a /// `metric` semantic convention group. /// Attribute ids are references to of attributes defined in the @@ -438,6 +444,7 @@ impl SemConvRegistry { | GroupType::Resource | GroupType::Metric | GroupType::Event + | GroupType::Scope | GroupType::MetricGroup => { let attributes_in_group = self.process_attributes( provenance.clone(), @@ -454,7 +461,7 @@ impl SemConvRegistry { GroupType::Metric => Some(&mut self.metric_group_attributes), GroupType::Event => Some(&mut self.event_group_attributes), GroupType::MetricGroup => Some(&mut self.metric_group_group_attributes), - _ => None, + GroupType::Scope => Some(&mut self.scope_group_attributes), }; if let Some(group_attributes) = group_attributes { @@ -472,12 +479,6 @@ impl SemConvRegistry { )?; } } - _ => { - panic!( - "Warning: group type `{:?}` not implemented yet", - group.r#type - ); - } } // Process metrics From c8a8f577693a3054ff2420c88575ce469b2deb00 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 15:39:04 -0700 Subject: [PATCH 08/22] chore(clippy): add more clippy lints --- Cargo.toml | 28 +++++++++++++-------------- crates/weaver_resolver/src/metrics.rs | 6 +++--- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2a16bc32..984de9ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -144,6 +144,13 @@ items_after_statements = "warn" large_digit_groups = "warn" large_stack_arrays = "warn" large_types_passed_by_value = "warn" +linkedlist = "warn" +lossy_float_literal = "warn" +macro_use_imports = "warn" +match_wildcard_for_single_variants = "warn" +mem_forget = "warn" +mutex_integer = "warn" +needless_continue = "warn" #exhaustive_enums = "warn" @@ -155,20 +162,13 @@ large_types_passed_by_value = "warn" #exhaustive_structs = "warn" #if_same_then_else = "allow" #let_and_return = "allow" # sometimes good to name what you are returning -linkedlist = "warn" -lossy_float_literal = "warn" -macro_use_imports = "warn" -match_wildcard_for_single_variants = "warn" -mem_forget = "warn" -mutex_integer = "warn" -needless_continue = "warn" -#needless_for_each = "warn" -#negative_feature_names = "warn" -#path_buf_push_overwrite = "warn" -#ptr_as_ptr = "warn" -#rc_mutex = "warn" -#redundant_feature_names = "warn" -#ref_option_ref = "warn" +needless_for_each = "warn" +negative_feature_names = "warn" +path_buf_push_overwrite = "warn" +ptr_as_ptr = "warn" +rc_mutex = "warn" +redundant_feature_names = "warn" +ref_option_ref = "warn" #rest_pat_in_fully_bound_structs = "warn" #same_functions_in_if_condition = "warn" #self_named_module_files = "warn" diff --git a/crates/weaver_resolver/src/metrics.rs b/crates/weaver_resolver/src/metrics.rs index 8577e987..81e51b70 100644 --- a/crates/weaver_resolver/src/metrics.rs +++ b/crates/weaver_resolver/src/metrics.rs @@ -145,9 +145,9 @@ pub fn resolve_metrics( semconv_registry, version_changes.metric_attribute_changes(), )?; - all_shared_attributes - .into_iter() - .for_each(|attr| _ = metric_group_attrs.insert(attr.id(), attr)); + for attr in all_shared_attributes { + _ = metric_group_attrs.insert(attr.id(), attr) + } metrics.attributes = metric_group_attrs.into_values().collect(); } From 6fbb5285f7ce69fa6f31c6e8f3f938f567c54ffe Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 15:52:01 -0700 Subject: [PATCH 09/22] chore(clippy): add more clippy lints --- Cargo.toml | 38 +++++++++---------- crates/weaver_resolved_schema/src/registry.rs | 19 ++++------ crates/weaver_resolver/src/metrics.rs | 2 +- crates/weaver_resolver/src/registry.rs | 10 ++--- crates/weaver_semconv/src/lib.rs | 2 +- crates/weaver_semconv_gen/src/gen.rs | 4 +- crates/weaver_template/src/filters.rs | 2 +- crates/weaver_template/src/sdkgen.rs | 10 ++--- crates/xtask/src/validate.rs | 2 +- src/registry/resolve.rs | 31 ++++++++------- 10 files changed, 58 insertions(+), 62 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 984de9ca..a3324e52 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -151,6 +151,25 @@ match_wildcard_for_single_variants = "warn" mem_forget = "warn" mutex_integer = "warn" needless_continue = "warn" +needless_for_each = "warn" +negative_feature_names = "warn" +path_buf_push_overwrite = "warn" +ptr_as_ptr = "warn" +rc_mutex = "warn" +redundant_feature_names = "warn" +ref_option_ref = "warn" +rest_pat_in_fully_bound_structs = "warn" +same_functions_in_if_condition = "warn" +self_named_module_files = "warn" +semicolon_if_nothing_returned = "warn" +single_match_else = "warn" +string_add = "warn" +string_add_assign = "warn" +string_lit_as_bytes = "warn" +trait_duplication_in_bounds = "warn" +verbose_file_reads = "warn" +wildcard_imports = "warn" +zero_sized_map_values = "warn" #exhaustive_enums = "warn" @@ -162,24 +181,5 @@ needless_continue = "warn" #exhaustive_structs = "warn" #if_same_then_else = "allow" #let_and_return = "allow" # sometimes good to name what you are returning -needless_for_each = "warn" -negative_feature_names = "warn" -path_buf_push_overwrite = "warn" -ptr_as_ptr = "warn" -rc_mutex = "warn" -redundant_feature_names = "warn" -ref_option_ref = "warn" -#rest_pat_in_fully_bound_structs = "warn" -#same_functions_in_if_condition = "warn" -#self_named_module_files = "warn" -#semicolon_if_nothing_returned = "warn" -#single_match_else = "warn" -#string_add = "warn" -#string_add_assign = "warn" -#string_lit_as_bytes = "warn" #string_to_string = "warn" #todo = "warn" -#trait_duplication_in_bounds = "warn" -#verbose_file_reads = "warn" -#wildcard_imports = "warn" -#zero_sized_map_values = "warn" \ No newline at end of file diff --git a/crates/weaver_resolved_schema/src/registry.rs b/crates/weaver_resolved_schema/src/registry.rs index 897eabcd..b818519f 100644 --- a/crates/weaver_resolved_schema/src/registry.rs +++ b/crates/weaver_resolved_schema/src/registry.rs @@ -13,7 +13,7 @@ use weaver_semconv::stability::Stability; use crate::attribute::{Attribute, AttributeRef}; use crate::catalog::Catalog; -use crate::error::{handle_errors, Error}; +use crate::error::{Error, handle_errors}; use crate::lineage::GroupLineage; use crate::registry::GroupStats::{ AttributeGroup, Event, Metric, MetricGroup, Resource, Scope, Span, @@ -229,7 +229,7 @@ impl Registry { /// # Arguments /// /// * `group_type` - The type of the groups to return. - pub fn groups(&self, group_type: GroupType) -> impl Iterator { + pub fn groups(&self, group_type: GroupType) -> impl Iterator { self.groups .iter() .filter(move |group| group_type == group.r#type) @@ -347,15 +347,12 @@ impl Group { let attributes = self .attributes .iter() - .filter_map(|attr_ref| match catalog.attribute(attr_ref) { - Some(attr) => Some(attr), - None => { - errors.push(Error::AttributeNotFound { - group_id: self.id.clone(), - attr_ref: *attr_ref, - }); - None - } + .filter_map(|attr_ref| if let Some(attr) = catalog.attribute(attr_ref) { Some(attr) } else { + errors.push(Error::AttributeNotFound { + group_id: self.id.clone(), + attr_ref: *attr_ref, + }); + None }) .collect(); diff --git a/crates/weaver_resolver/src/metrics.rs b/crates/weaver_resolver/src/metrics.rs index 81e51b70..6a7ff7c3 100644 --- a/crates/weaver_resolver/src/metrics.rs +++ b/crates/weaver_resolver/src/metrics.rs @@ -146,7 +146,7 @@ pub fn resolve_metrics( version_changes.metric_attribute_changes(), )?; for attr in all_shared_attributes { - _ = metric_group_attrs.insert(attr.id(), attr) + _ = metric_group_attrs.insert(attr.id(), attr); } metrics.attributes = metric_group_attrs.into_values().collect(); diff --git a/crates/weaver_resolver/src/registry.rs b/crates/weaver_resolver/src/registry.rs index 90ac4961..71cecc5b 100644 --- a/crates/weaver_resolver/src/registry.rs +++ b/crates/weaver_resolver/src/registry.rs @@ -544,10 +544,10 @@ fn resolve_inheritance_attrs( for parent_attr in attrs_parent_group.iter() { match &parent_attr.spec { AttributeSpec::Ref { r#ref, .. } => { - _ = resolved_attrs.insert(r#ref.clone(), parent_attr.spec.clone()) + _ = resolved_attrs.insert(r#ref.clone(), parent_attr.spec.clone()); } AttributeSpec::Id { id, .. } => { - _ = resolved_attrs.insert(id.clone(), parent_attr.spec.clone()) + _ = resolved_attrs.insert(id.clone(), parent_attr.spec.clone()); } } } @@ -560,13 +560,13 @@ fn resolve_inheritance_attrs( _ = resolved_attrs.insert( r#ref.clone(), resolve_inheritance_attr(&attr.spec, parent_attr), - ) + ); } else { - _ = resolved_attrs.insert(r#ref.clone(), attr.spec.clone()) + _ = resolved_attrs.insert(r#ref.clone(), attr.spec.clone()); } } AttributeSpec::Id { id, .. } => { - _ = resolved_attrs.insert(id.clone(), attr.spec.clone()) + _ = resolved_attrs.insert(id.clone(), attr.spec.clone()); } } } diff --git a/crates/weaver_semconv/src/lib.rs b/crates/weaver_semconv/src/lib.rs index 297cacd4..2e00c758 100644 --- a/crates/weaver_semconv/src/lib.rs +++ b/crates/weaver_semconv/src/lib.rs @@ -762,7 +762,7 @@ impl SemConvRegistry { format!("{}.{}", prefix, id) }; if let AttributeSpec::Id { id, .. } = &mut attr { - id.clone_from(&fq_attr_id) + id.clone_from(&fq_attr_id); } let prev_val = self.all_attributes.insert( fq_attr_id.clone(), diff --git a/crates/weaver_semconv_gen/src/gen.rs b/crates/weaver_semconv_gen/src/gen.rs index 63d4bc89..9e8e5c32 100644 --- a/crates/weaver_semconv_gen/src/gen.rs +++ b/crates/weaver_semconv_gen/src/gen.rs @@ -465,14 +465,14 @@ impl<'a> MetricView<'a> { ) -> Result<(), Error> { // TODO - add note if needed. if self.group.note.is_empty() { - write!(out, "{}", &self.group.brief)? + write!(out, "{}", &self.group.brief)?; } else { write!( out, "{} {}", &self.group.brief, ctx.add_note(self.group.note.clone()) - )? + )?; } Ok(()) } diff --git a/crates/weaver_template/src/filters.rs b/crates/weaver_template/src/filters.rs index ec4e53e3..e75f9596 100644 --- a/crates/weaver_template/src/filters.rs +++ b/crates/weaver_template/src/filters.rs @@ -324,7 +324,7 @@ pub fn comment(value: &Value, ctx: &HashMap) -> Result { Value::Array(values) => { for value in values { if let Value::String(value) = value { - wrap_comment(value, "- ", &mut lines) + wrap_comment(value, "- ", &mut lines); } } } diff --git a/crates/weaver_template/src/sdkgen.rs b/crates/weaver_template/src/sdkgen.rs index 80158bbf..7ea0b162 100644 --- a/crates/weaver_template/src/sdkgen.rs +++ b/crates/weaver_template/src/sdkgen.rs @@ -271,7 +271,7 @@ impl ClientSdkGenerator { templates.push(TemplateObjectPair::Metric { template: tmpl_file.into(), metric, - }) + }); } } } @@ -281,7 +281,7 @@ impl ClientSdkGenerator { templates.push(TemplateObjectPair::MetricGroup { template: tmpl_file.into(), metric_group, - }) + }); } } } @@ -291,7 +291,7 @@ impl ClientSdkGenerator { templates.push(TemplateObjectPair::Event { template: tmpl_file.into(), event, - }) + }); } } } @@ -301,7 +301,7 @@ impl ClientSdkGenerator { templates.push(TemplateObjectPair::Span { template: tmpl_file.into(), span, - }) + }); } } } @@ -314,7 +314,7 @@ impl ClientSdkGenerator { template: tmpl_file.into(), relative_path, object: schema, - }) + }); } } } else { diff --git a/crates/xtask/src/validate.rs b/crates/xtask/src/validate.rs index fc136bd3..dbe1d425 100644 --- a/crates/xtask/src/validate.rs +++ b/crates/xtask/src/validate.rs @@ -79,7 +79,7 @@ pub fn run() -> anyhow::Result<()> { if !errors.is_empty() { for error in errors { eprintln!("{}", error); - eprintln!() + eprintln!(); } #[allow(clippy::exit)] // This is an expected exit std::process::exit(1); diff --git a/src/registry/resolve.rs b/src/registry/resolve.rs index adbe15d2..e9a3a98b 100644 --- a/src/registry/resolve.rs +++ b/src/registry/resolve.rs @@ -72,9 +72,9 @@ pub(crate) fn command( cache, logger.clone(), ) - .unwrap_or_else(|e| { - panic!("Failed to load and parse the semantic convention registry, error: {e}"); - }); + .unwrap_or_else(|e| { + panic!("Failed to load and parse the semantic convention registry, error: {e}"); + }); // Resolve the semantic convention registry. let schema = @@ -98,25 +98,24 @@ pub(crate) fn command( .expect("Failed to get the registry from the resolved schema"), schema.catalog(), ) - .unwrap_or_else(|e| panic!("Failed to create the registry without catalog: {e:?}")); + .unwrap_or_else(|e| panic!("Failed to create the registry without catalog: {e:?}")); apply_format(&args.format, ®istry) .map_err(|e| format!("Failed to serialize the registry: {e:?}")) } } - .and_then(|s| match args.output { - // Write the resolved registry to a file. - Some(ref path) => std::fs::write(path, s) - .map_err(|e| format!("Failed to write the resolved registry to file: {e:?}")), - // Print the resolved registry to stdout. - None => { + .and_then(|s| if let Some(ref path) = args.output { + // Write the resolved registry to a file. + std::fs::write(path, s) + .map_err(|e| format!("Failed to write the resolved registry to file: {e:?}")) + } else { + // Print the resolved registry to stdout. println!("{}", s); Ok(()) - } - }) - .unwrap_or_else(|e| { - // Capture all the errors - panic!("{}", e); - }); + }) + .unwrap_or_else(|e| { + // Capture all the errors + panic!("{}", e); + }); } fn apply_format(format: &Format, object: &T) -> Result { From 7527a41243c28ee0694e7d0dc2812afb890c1a95 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 16:11:16 -0700 Subject: [PATCH 10/22] chore(clippy): add more clippy lints --- Cargo.lock | 358 ++++++++---------- Cargo.toml | 13 +- crates/weaver_cache/Cargo.toml | 2 +- crates/weaver_cache/src/lib.rs | 12 +- crates/weaver_forge/src/config.rs | 3 +- crates/weaver_forge/src/debug.rs | 2 +- crates/weaver_resolved_schema/src/error.rs | 2 +- crates/weaver_resolved_schema/src/registry.rs | 20 +- crates/weaver_resolver/src/lib.rs | 1 + crates/weaver_semconv_gen/Cargo.toml | 10 +- crates/weaver_semconv_gen/src/lib.rs | 2 +- crates/xtask/src/validate.rs | 2 +- justfile | 10 +- src/registry/check.rs | 2 +- src/registry/generate.rs | 4 +- src/registry/mod.rs | 2 +- src/registry/resolve.rs | 24 +- src/registry/stats.rs | 2 +- 18 files changed, 217 insertions(+), 254 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7410c9e0..6f65f5fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,9 +32,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -116,9 +116,9 @@ checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "arc-swap" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b3d0060af21e8d11a926981cc00c6c1541aa91dd64b9f881985c3da1094425f" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "arrayvec" @@ -128,26 +128,26 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-trait" -version = "0.1.78" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -228,9 +228,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "bytesize" @@ -277,9 +277,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" dependencies = [ "android-tzdata", "iana-time-zone", @@ -320,9 +320,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -342,14 +342,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] @@ -544,7 +544,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] @@ -555,7 +555,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] @@ -656,9 +656,9 @@ dependencies = [ [[package]] name = "fastdivide" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25c7df09945d65ea8d70b3321547ed414bbc540aad5bac6883d021b970f35b04" +checksum = "59668941c55e5c186b8b58c391629af56774ec768f73c08bbcd56f09348eb00b" [[package]] name = "faster-hex" @@ -668,9 +668,9 @@ checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "filetime" @@ -732,7 +732,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", - "futures-sink", ] [[package]] @@ -767,7 +766,6 @@ checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-io", - "futures-sink", "futures-task", "memchr", "pin-project-lite", @@ -817,9 +815,9 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "gix" -version = "0.61.1" +version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d03e6e306a2c85bcd8e1de93dfd061531068ccd45eb05633d80c7e93f7e55fb9" +checksum = "e4e0e59a44bf00de058ee98d6ecf3c9ed8f8842c1da642258ae4120d41ded8f7" dependencies = [ "gix-actor", "gix-attributes", @@ -1183,7 +1181,7 @@ checksum = "1dff438f14e67e7713ab9332f5fd18c8f20eb7eb249494f6c2bf170522224032" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] @@ -1471,9 +1469,9 @@ checksum = "9b838b2db8f62c9447d483a4c28d251b67fee32741a82cb4d35e9eb4e9fdc5ab" [[package]] name = "gix-transport" -version = "0.41.3" +version = "0.41.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8fc0eb54e495d384c1d973b55d54437daa989991da9f927b1e2e29c1d5f3dfa" +checksum = "cf8e5f72ec9cad9ee44714b9a4ec7427b540a2418b62111f5e3a715bebe1ed9d" dependencies = [ "base64", "bstr", @@ -1592,7 +1590,7 @@ dependencies = [ "bstr", "log", "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", "serde", ] @@ -1609,9 +1607,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.3" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" dependencies = [ "bytes", "fnv", @@ -1628,9 +1626,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.4" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57fa0ae458eb99874f54c09f4f9174f8b45fb87e854536a4e608696247f0c23" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash", "allocator-api2", @@ -1677,9 +1675,9 @@ checksum = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" [[package]] name = "http" -version = "1.1.0" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1688,24 +1686,12 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.1" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "futures-core", "http", - "http-body", "pin-project-lite", ] @@ -1715,6 +1701,12 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + [[package]] name = "human_format" version = "1.1.0" @@ -1732,59 +1724,40 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", + "futures-core", "futures-util", "h2", "http", "http-body", "httparse", + "httpdate", "itoa", "pin-project-lite", - "smallvec", + "socket2", "tokio", + "tower-service", + "tracing", "want", ] [[package]] name = "hyper-rustls" -version = "0.26.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http", "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", + "rustls 0.21.10", "tokio", "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower", - "tower-service", - "tracing", ] [[package]] @@ -1854,9 +1827,9 @@ dependencies = [ [[package]] name = "indoc" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "instant" @@ -1906,9 +1879,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jaq-core" @@ -2035,13 +2008,12 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.5.0", "libc", - "redox_syscall", ] [[package]] @@ -2100,9 +2072,9 @@ dependencies = [ [[package]] name = "lz4_flex" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912b45c753ff5f7f5208307e8ace7d2a2e30d024e26d3509f3dce546c044ce15" +checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" [[package]] name = "matchers" @@ -2121,7 +2093,7 @@ checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] @@ -2136,9 +2108,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "memmap2" @@ -2406,7 +2378,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] @@ -2458,31 +2430,11 @@ dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.53", -] - [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2680,9 +2632,9 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", "libredox", @@ -2691,14 +2643,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -2718,7 +2670,7 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.3", ] [[package]] @@ -2729,9 +2681,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "remove_dir_all" @@ -2744,23 +2696,20 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.1" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e333b1eb9fe677f6893a9efcb0d277a2d3edd83f358a236b657c32301dc6e5f6" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64", "bytes", "encoding_rs", - "futures-channel", "futures-core", "futures-util", "h2", "http", "http-body", - "http-body-util", "hyper", "hyper-rustls", - "hyper-util", "ipnet", "js-sys", "log", @@ -2768,9 +2717,8 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", + "rustls 0.21.10", "rustls-pemfile", - "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", @@ -2783,7 +2731,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", + "webpki-roots 0.25.4", "winreg", ] @@ -2826,9 +2774,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ "bitflags 2.5.0", "errno", @@ -2839,14 +2787,26 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.2" +version = "0.21.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" dependencies = [ "log", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.102.2", "subtle", "zeroize", ] @@ -2862,9 +2822,19 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.3.1" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] [[package]] name = "rustls-webpki" @@ -2910,6 +2880,16 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "self_cell" version = "1.0.3" @@ -2942,14 +2922,14 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -2979,9 +2959,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.33" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0623d197252096520c6f2a5e1171ee436e5af99a5d7caa2891e55e61950e6d9" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ "indexmap", "itoa", @@ -3054,9 +3034,9 @@ dependencies = [ [[package]] name = "similar" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21" +checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" [[package]] name = "siphasher" @@ -3094,9 +3074,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smawk" @@ -3173,7 +3153,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] @@ -3195,9 +3175,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.53" +version = "2.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +checksum = "11a6ae1e52eb25aab8f3fb9fca13be982a373b8f1157ca14b897a825ba4a2d35" dependencies = [ "proc-macro2", "quote", @@ -3443,7 +3423,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] @@ -3506,15 +3486,14 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "pin-project-lite", "socket2", "windows-sys 0.48.0", @@ -3522,12 +3501,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.25.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls", - "rustls-pki-types", + "rustls 0.21.10", "tokio", ] @@ -3568,9 +3546,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.8" +version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c12219811e0c1ba077867254e5ad62ee2c9c190b0d957110750ac0cda1ae96cd" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ "indexmap", "serde", @@ -3579,28 +3557,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - [[package]] name = "tower-service" version = "0.3.2" @@ -3613,7 +3569,6 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -3627,7 +3582,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] @@ -3824,11 +3779,11 @@ dependencies = [ "flate2", "log", "once_cell", - "rustls", + "rustls 0.22.3", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.102.2", "url", - "webpki-roots", + "webpki-roots 0.26.1", ] [[package]] @@ -3898,7 +3853,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] @@ -3959,7 +3914,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.57", "wasm-bindgen-shared", ] @@ -3993,7 +3948,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.57", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4133,13 +4088,8 @@ version = "0.1.0" dependencies = [ "itertools 0.12.1", "nom", - "rayon", - "serde", - "serde_json", - "serde_yaml", "similar", "thiserror", - "walkdir", "weaver_cache", "weaver_logger", "weaver_resolved_schema", @@ -4186,6 +4136,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + [[package]] name = "webpki-roots" version = "0.26.1" @@ -4420,7 +4376,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.53", + "syn 2.0.57", ] [[package]] @@ -4450,9 +4406,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.10+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index a3324e52..e601e36c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ anyhow = "1.0.81" # Features definition ========================================================= [features] -experimental = [] +experimental = ["tantivy"] # Crate definitions =========================================================== [[bin]] @@ -63,7 +63,7 @@ clap = { version = "4.5.3", features = ["derive"] } crossterm = "0.27.0" ratatui = "0.26.1" tui-textarea = "0.4.0" -tantivy = "0.21.1" +tantivy = { version = "0.21.1", optional = true } # workspace dependencies serde.workspace = true @@ -170,16 +170,9 @@ trait_duplication_in_bounds = "warn" verbose_file_reads = "warn" wildcard_imports = "warn" zero_sized_map_values = "warn" +string_to_string = "warn" #exhaustive_enums = "warn" - -## -#bool_assert_comparison = "allow" -#branches_sharing_code = "allow" -#collapsible_else_if = "allow" #doc_markdown = "warn" #exhaustive_structs = "warn" -#if_same_then_else = "allow" -#let_and_return = "allow" # sometimes good to name what you are returning -#string_to_string = "warn" #todo = "warn" diff --git a/crates/weaver_cache/Cargo.toml b/crates/weaver_cache/Cargo.toml index 2fe00d5b..59762e85 100644 --- a/crates/weaver_cache/Cargo.toml +++ b/crates/weaver_cache/Cargo.toml @@ -14,7 +14,7 @@ workspace = true [dependencies] tempdir = "0.3.7" dirs = "5.0.1" -gix = { version = "0.61.1", default-features = false, features = [ +gix = { version = "0.61.0", default-features = false, features = [ "comfort", "blocking-http-transport-reqwest", "max-performance-safe", diff --git a/crates/weaver_cache/src/lib.rs b/crates/weaver_cache/src/lib.rs index 46b20433..0dbded3b 100644 --- a/crates/weaver_cache/src/lib.rs +++ b/crates/weaver_cache/src/lib.rs @@ -109,7 +109,7 @@ impl Cache { // in the git_repo_dirs hashmap. let git_repo_dir = TempDir::new_in(self.path.as_path(), "git-repo").map_err(|e| { Error::GitRepoNotCreated { - repo_url: repo_url.to_string(), + repo_url: repo_url.clone(), message: e.to_string(), } })?; @@ -129,7 +129,7 @@ impl Cache { open::Options::isolated(), ) .map_err(|e| GitError { - repo_url: repo_url.to_string(), + repo_url: repo_url.clone(), message: e.to_string(), })? .with_shallow(Shallow::DepthAtRemote( @@ -139,14 +139,14 @@ impl Cache { let (mut prepare, _outcome) = fetch .fetch_then_checkout(progress::Discard, &AtomicBool::new(false)) .map_err(|e| GitError { - repo_url: repo_url.to_string(), + repo_url: repo_url.clone(), message: e.to_string(), })?; let (_repo, _outcome) = prepare .main_worktree(progress::Discard, &AtomicBool::new(false)) .map_err(|e| GitError { - repo_url: repo_url.to_string(), + repo_url: repo_url.clone(), message: e.to_string(), })?; @@ -156,7 +156,7 @@ impl Cache { // If the path doesn't exist, returns an error. if !git_repo_path.join(path).exists() { return Err(GitError { - repo_url: repo_url.to_string(), + repo_url: repo_url.clone(), message: format!("Path `{}` not found in repo", path), }); } @@ -172,7 +172,7 @@ impl Cache { .lock() .expect("git_repo_dirs lock failed") .insert( - repo_url.to_string(), + repo_url.clone(), GitRepo { temp_dir: git_repo_dir, path: git_repo_path, diff --git a/crates/weaver_forge/src/config.rs b/crates/weaver_forge/src/config.rs index 9d72f137..fdd525d4 100644 --- a/crates/weaver_forge/src/config.rs +++ b/crates/weaver_forge/src/config.rs @@ -56,7 +56,8 @@ pub struct TargetConfig { pub field_name: CaseConvention, /// Type mapping for target specific types (OTel types -> Target language types). #[serde(default)] - #[allow(dead_code)] // ToDo create a Jinja macro to generate the mapping semconv -> target language + #[allow(dead_code)] + // ToDo create a Jinja macro to generate the mapping semconv -> target language pub type_mapping: HashMap, /// Configuration for the template syntax. #[serde(default)] diff --git a/crates/weaver_forge/src/debug.rs b/crates/weaver_forge/src/debug.rs index 25bf4f8a..b7fdef75 100644 --- a/crates/weaver_forge/src/debug.rs +++ b/crates/weaver_forge/src/debug.rs @@ -72,7 +72,7 @@ pub fn print_dedup_errors(logger: impl Logger + Sync + Clone, error: Error) { } dedup_errs.iter().for_each(|(_, err)| { let output = match err.occurrences { - 1 => err.error.to_string(), + 1 => err.error.clone(), 2 => format!("{}\n\nFound 1 similar error", err.error), _ => format!( "{}\n\nFound {} similar errors", diff --git a/crates/weaver_resolved_schema/src/error.rs b/crates/weaver_resolved_schema/src/error.rs index fe7f23c5..f38f43ff 100644 --- a/crates/weaver_resolved_schema/src/error.rs +++ b/crates/weaver_resolved_schema/src/error.rs @@ -41,7 +41,7 @@ impl Error { .into_iter() .flat_map(|e| match e { CompoundError(errors) => errors, - e @ AttributeNotFound{ .. } => vec![e], + e @ AttributeNotFound { .. } => vec![e], }) .collect(), ) diff --git a/crates/weaver_resolved_schema/src/registry.rs b/crates/weaver_resolved_schema/src/registry.rs index b818519f..2e422913 100644 --- a/crates/weaver_resolved_schema/src/registry.rs +++ b/crates/weaver_resolved_schema/src/registry.rs @@ -13,7 +13,7 @@ use weaver_semconv::stability::Stability; use crate::attribute::{Attribute, AttributeRef}; use crate::catalog::Catalog; -use crate::error::{Error, handle_errors}; +use crate::error::{handle_errors, Error}; use crate::lineage::GroupLineage; use crate::registry::GroupStats::{ AttributeGroup, Event, Metric, MetricGroup, Resource, Scope, Span, @@ -229,7 +229,7 @@ impl Registry { /// # Arguments /// /// * `group_type` - The type of the groups to return. - pub fn groups(&self, group_type: GroupType) -> impl Iterator { + pub fn groups(&self, group_type: GroupType) -> impl Iterator { self.groups .iter() .filter(move |group| group_type == group.r#type) @@ -347,12 +347,16 @@ impl Group { let attributes = self .attributes .iter() - .filter_map(|attr_ref| if let Some(attr) = catalog.attribute(attr_ref) { Some(attr) } else { - errors.push(Error::AttributeNotFound { - group_id: self.id.clone(), - attr_ref: *attr_ref, - }); - None + .filter_map(|attr_ref| { + if let Some(attr) = catalog.attribute(attr_ref) { + Some(attr) + } else { + errors.push(Error::AttributeNotFound { + group_id: self.id.clone(), + attr_ref: *attr_ref, + }); + None + } }) .collect(); diff --git a/crates/weaver_resolver/src/lib.rs b/crates/weaver_resolver/src/lib.rs index 466ba1c5..7d694924 100644 --- a/crates/weaver_resolver/src/lib.rs +++ b/crates/weaver_resolver/src/lib.rs @@ -700,6 +700,7 @@ mod test { let log = ConsoleLogger::new(0); let cache = Cache::try_new().unwrap_or_else(|e| { log.error(&e.to_string()); + #[allow(clippy::exit)] // Expected exit std::process::exit(1); }); let schema = SchemaResolver::resolve_schema_file( diff --git a/crates/weaver_semconv_gen/Cargo.toml b/crates/weaver_semconv_gen/Cargo.toml index f3867cb9..9012c3f8 100644 --- a/crates/weaver_semconv_gen/Cargo.toml +++ b/crates/weaver_semconv_gen/Cargo.toml @@ -19,11 +19,11 @@ similar = "2.4.0" nom = "7.1.3" thiserror.workspace = true -serde.workspace = true -serde_yaml.workspace = true -serde_json.workspace = true -rayon.workspace = true -walkdir.workspace = true +#serde.workspace = true +#serde_yaml.workspace = true +#serde_json.workspace = true +#rayon.workspace = true +#walkdir.workspace = true [lints] workspace = true diff --git a/crates/weaver_semconv_gen/src/lib.rs b/crates/weaver_semconv_gen/src/lib.rs index 37ca19f1..6ae62cc4 100644 --- a/crates/weaver_semconv_gen/src/lib.rs +++ b/crates/weaver_semconv_gen/src/lib.rs @@ -299,7 +299,7 @@ mod tests { println!(); println!("--- Running test: {} ---", dir.path().display()); println!(); - force_print_error(run_legacy_test(dir.path())) + force_print_error(run_legacy_test(dir.path())); } } } diff --git a/crates/xtask/src/validate.rs b/crates/xtask/src/validate.rs index dbe1d425..3d48fd35 100644 --- a/crates/xtask/src/validate.rs +++ b/crates/xtask/src/validate.rs @@ -81,7 +81,7 @@ pub fn run() -> anyhow::Result<()> { eprintln!("{}", error); eprintln!(); } - #[allow(clippy::exit)] // This is an expected exit + #[allow(clippy::exit)] // This is an expected exit std::process::exit(1); } diff --git a/justfile b/justfile index 5a355d8d..c508eb29 100644 --- a/justfile +++ b/justfile @@ -14,9 +14,15 @@ pre-push-check: cargo update cargo machete cargo fmt --all - cargo clippy --workspace --all-features --all-targets -- -D warnings --allow deprecated + # [workaround] removed --all-features due to an issue in one of the dependency in Tantity (zstd-safe) + # [ToDo LQ] Re-enable --all-features once the issue is resolved + # cargo clippy --workspace --all-features --all-targets -- -D warnings --allow deprecated + cargo clippy --workspace --all-targets -- -D warnings --allow deprecated cargo test --all - cargo doc --workspace --all-features --no-deps --document-private-items + # [workaround] removed --all-features due to an issue in one of the dependency in Tantity (zstd-safe) + # [ToDo LQ] Re-enable --all-features once the issue is resolved + # cargo doc --workspace --all-features --no-deps --document-private-items + cargo doc --workspace --no-deps --document-private-items cargo deny check licenses pre-push: pre-push-check validate-workspace check-external-types diff --git a/src/registry/check.rs b/src/registry/check.rs index ef480484..fab6473c 100644 --- a/src/registry/check.rs +++ b/src/registry/check.rs @@ -36,7 +36,7 @@ pub(crate) fn command(log: impl Logger + Sync + Clone, cache: &Cache, args: &Reg // No parsing errors should be observed. let semconv_specs = SchemaResolver::load_semconv_registry( registry_id, - args.registry.to_string(), + args.registry.clone(), args.registry_git_sub_dir.clone(), cache, log.clone(), diff --git a/src/registry/generate.rs b/src/registry/generate.rs index 42fae162..bf90e35e 100644 --- a/src/registry/generate.rs +++ b/src/registry/generate.rs @@ -58,7 +58,7 @@ pub(crate) fn command( // Load the semantic convention registry into a local cache. let mut registry = SchemaResolver::load_semconv_registry( registry_id, - args.registry.to_string(), + args.registry.clone(), args.registry_git_sub_dir.clone(), cache, logger.clone(), @@ -95,7 +95,7 @@ pub(crate) fn command( Ok(_) => logger.success("Artifacts generated successfully"), Err(e) => { print_dedup_errors(logger.clone(), e); - #[allow(clippy::exit)] // Expected behavior + #[allow(clippy::exit)] // Expected behavior std::process::exit(1); } }; diff --git a/src/registry/mod.rs b/src/registry/mod.rs index e600a0a4..ec192f82 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -67,7 +67,7 @@ pub struct RegistryArgs { pub fn semconv_registry(log: impl Logger + Sync + Clone, command: &RegistryCommand) { let cache = Cache::try_new().unwrap_or_else(|e| { log.error(&e.to_string()); - #[allow(clippy::exit)] // Expected behavior + #[allow(clippy::exit)] // Expected behavior std::process::exit(1); }); diff --git a/src/registry/resolve.rs b/src/registry/resolve.rs index e9a3a98b..5c562d38 100644 --- a/src/registry/resolve.rs +++ b/src/registry/resolve.rs @@ -67,14 +67,14 @@ pub(crate) fn command( // Load the semantic convention registry into a local cache. let mut registry = SchemaResolver::load_semconv_registry( registry_id, - args.registry.registry.to_string(), + args.registry.registry.clone(), args.registry.registry_git_sub_dir.clone(), cache, logger.clone(), ) - .unwrap_or_else(|e| { - panic!("Failed to load and parse the semantic convention registry, error: {e}"); - }); + .unwrap_or_else(|e| { + panic!("Failed to load and parse the semantic convention registry, error: {e}"); + }); // Resolve the semantic convention registry. let schema = @@ -98,12 +98,13 @@ pub(crate) fn command( .expect("Failed to get the registry from the resolved schema"), schema.catalog(), ) - .unwrap_or_else(|e| panic!("Failed to create the registry without catalog: {e:?}")); + .unwrap_or_else(|e| panic!("Failed to create the registry without catalog: {e:?}")); apply_format(&args.format, ®istry) .map_err(|e| format!("Failed to serialize the registry: {e:?}")) } } - .and_then(|s| if let Some(ref path) = args.output { + .and_then(|s| { + if let Some(ref path) = args.output { // Write the resolved registry to a file. std::fs::write(path, s) .map_err(|e| format!("Failed to write the resolved registry to file: {e:?}")) @@ -111,11 +112,12 @@ pub(crate) fn command( // Print the resolved registry to stdout. println!("{}", s); Ok(()) - }) - .unwrap_or_else(|e| { - // Capture all the errors - panic!("{}", e); - }); + } + }) + .unwrap_or_else(|e| { + // Capture all the errors + panic!("{}", e); + }); } fn apply_format(format: &Format, object: &T) -> Result { diff --git a/src/registry/stats.rs b/src/registry/stats.rs index 80163041..56af7bba 100644 --- a/src/registry/stats.rs +++ b/src/registry/stats.rs @@ -32,7 +32,7 @@ pub(crate) fn command(log: impl Logger + Sync + Clone, cache: &Cache, args: &Reg // Load the semantic convention registry into a local cache. let mut registry = SchemaResolver::load_semconv_registry( registry_id, - args.registry.registry.to_string(), + args.registry.registry.clone(), args.registry.registry_git_sub_dir.clone(), cache, log.clone(), From 28ca47a2e3d8a2c9f5c85eb7f66344a541ed5f16 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 16:17:00 -0700 Subject: [PATCH 11/22] chore(coverage): add test code coverage with cargo tarpaulin --- .github/workflows/ci.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85e32101..7010cf93 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -164,3 +164,18 @@ jobs: wait-for-processing: true - name: Report status run: cargo clippy --workspace --all-features --all-targets -- -D warnings --allow deprecated + coverage: + name: Coverage + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + toolchain: stable + - uses: Swatinem/rust-cache@v2 + - name: Install cargo-tarpaulin + run: cargo install cargo-tarpaulin + - name: Gather coverage + run: cargo tarpaulin --output-dir coverage --out lcov \ No newline at end of file From 2626e0398eccfc30c980467b07875a3f978dbb38 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 16:20:51 -0700 Subject: [PATCH 12/22] chore(build): trigger ci.yml workflow for all push and pull request --- .github/workflows/ci.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7010cf93..891e076d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,11 +3,12 @@ name: CI permissions: contents: read -on: - pull_request: - push: - branches: - - main +on: [push, pull_request] +#on: +# pull_request: +# push: +# branches: +# - main env: RUST_BACKTRACE: 1 From 684020a147f61b6ea688155070780e98ed5a5df3 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 16:25:46 -0700 Subject: [PATCH 13/22] chore(build): trigger ci.yml workflow for all push and pull request --- .github/workflows/ci.yml | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 891e076d..ff27697f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,11 +45,13 @@ jobs: uses: arduino/setup-protoc@v2 - uses: Swatinem/rust-cache@v2 - name: Build - run: cargo test --no-run --workspace --all-features + # [ToDo LQ] Re-enable --all-features once the issue is resolved in Tantivy (zstd-safe). This is an experimental feature anyway. + run: cargo test --no-run --workspace - name: Default features run: cargo test --workspace - - name: All features - run: cargo test --workspace --all-features +# [ToDo LQ] Re-enable --all-features once the issue is resolved in Tantivy (zstd-safe). This is an experimental feature anyway. +# - name: All features +# run: cargo test --workspace --all-features - name: No-default features run: cargo test --workspace --no-default-features msrv: @@ -67,8 +69,9 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: Default features run: cargo check --workspace --all-targets - - name: All features - run: cargo check --workspace --all-targets --all-features +# [ToDo LQ] Re-enable --all-features once the issue is resolved in Tantivy (zstd-safe). This is an experimental feature anyway. +# - name: All features +# run: cargo check --workspace --all-targets --all-features - name: No-default features run: cargo check --workspace --all-targets --no-default-features lockfile: @@ -99,9 +102,11 @@ jobs: - name: Check documentation env: RUSTDOCFLAGS: -D warnings - run: cargo doc --workspace --all-features --no-deps --document-private-items + # [ToDo LQ] Re-enable --all-features once the issue is resolved in Tantivy (zstd-safe). This is an experimental feature anyway. + # run: cargo doc --workspace --all-features --no-deps --document-private-items + run: cargo doc --workspace --no-deps --document-private-items rustfmt: - name: rustfmt + name: Rustfmt runs-on: ubuntu-latest steps: - name: Checkout repository @@ -117,6 +122,7 @@ jobs: - name: Check formatting run: cargo fmt --all -- --check check-external-types: + name: Check external types runs-on: ubuntu-latest steps: - name: Checkout repository @@ -132,7 +138,7 @@ jobs: cargo install cargo-check-external-types ./scripts/check_external_types.sh clippy: - name: clippy + name: Clippy runs-on: ubuntu-latest permissions: security-events: write # to upload sarif results @@ -152,8 +158,10 @@ jobs: - name: Install protoc uses: arduino/setup-protoc@v2 - name: Check + # [workaround] removed --all-features due to an issue in one of the dependency in Tantity (zstd-safe) + # [ToDo LQ] Re-enable --all-features once the issue is resolved run: > - cargo clippy --workspace --all-features --all-targets --message-format=json -- -D warnings --allow deprecated + cargo clippy --workspace --all-targets --message-format=json -- -D warnings --allow deprecated | clippy-sarif | tee clippy-results.sarif | sarif-fmt @@ -164,7 +172,7 @@ jobs: sarif_file: clippy-results.sarif wait-for-processing: true - name: Report status - run: cargo clippy --workspace --all-features --all-targets -- -D warnings --allow deprecated + run: cargo clippy --workspace --all-targets -- -D warnings --allow deprecated coverage: name: Coverage runs-on: ubuntu-latest From bd25a3e749c41cdfab8061454236a13d79dbd120 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 16:36:17 -0700 Subject: [PATCH 14/22] chore(install): add cargo tarpaulin in the list of tools to install --- justfile | 1 + 1 file changed, 1 insertion(+) diff --git a/justfile b/justfile index c508eb29..efb2639f 100644 --- a/justfile +++ b/justfile @@ -7,6 +7,7 @@ install: rustup install nightly-2023-10-10 # used by cargo-check-external-types cargo install cargo-check-external-types cargo install git-cliff + cargo install cargo-tarpaulin pre-push-check: rustup update From 2d8ea896bf685e062d09a2b82cdc566413f10f4d Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 16:47:01 -0700 Subject: [PATCH 15/22] chore(coverage): apply tarpauling coverage on the entire workspace --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff27697f..9978e87f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -187,4 +187,4 @@ jobs: - name: Install cargo-tarpaulin run: cargo install cargo-tarpaulin - name: Gather coverage - run: cargo tarpaulin --output-dir coverage --out lcov \ No newline at end of file + run: cargo tarpaulin --workspace --output-dir coverage --out lcov \ No newline at end of file From 97fb436672e46fc9cf0dca520febc2d458c5b3a9 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 17:01:25 -0700 Subject: [PATCH 16/22] chore(coverage): apply tarpauling coverage on the entire workspace --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9978e87f..d64b62af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -187,4 +187,4 @@ jobs: - name: Install cargo-tarpaulin run: cargo install cargo-tarpaulin - name: Gather coverage - run: cargo tarpaulin --workspace --output-dir coverage --out lcov \ No newline at end of file + run: cargo tarpaulin --workspace --output-dir coverage --out lcov -e xtask -e weaver \ No newline at end of file From d221ad890c53ced2ae75adc9260df7c554679277 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 17:26:20 -0700 Subject: [PATCH 17/22] chore(coverage): remove xtask and main command line from the code coverage --- crates/xtask/src/main.rs | 2 ++ crates/xtask/src/validate.rs | 5 +++++ src/gen_client.rs | 1 + src/languages.rs | 1 + src/main.rs | 2 ++ src/registry/check.rs | 1 + src/registry/generate.rs | 1 + src/registry/mod.rs | 1 + src/registry/resolve.rs | 2 ++ src/registry/stats.rs | 4 ++++ src/resolve.rs | 1 + src/search/mod.rs | 10 ++++++++++ 12 files changed, 31 insertions(+) diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 6a9fd237..9b3dfd69 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -12,6 +12,7 @@ mod validate; +#[no_coverage] fn main() -> anyhow::Result<()> { let task = std::env::args().nth(1); @@ -29,6 +30,7 @@ fn main() -> anyhow::Result<()> { } /// Prints help message. +#[no_coverage] pub fn print_help() -> anyhow::Result<()> { println!( " diff --git a/crates/xtask/src/validate.rs b/crates/xtask/src/validate.rs index 3d48fd35..077af94b 100644 --- a/crates/xtask/src/validate.rs +++ b/crates/xtask/src/validate.rs @@ -18,6 +18,7 @@ use toml::Value; /// that are allowed to be used in the public API. /// - Each Cargo.toml must contain \[lints\] workspace = true and few other fields /// in the \[package\] section. +#[no_coverage] pub fn run() -> anyhow::Result<()> { let mut errors = vec![]; @@ -90,6 +91,7 @@ pub fn run() -> anyhow::Result<()> { Ok(()) } +#[no_coverage] fn check_presence_of(path: &Path, file_name: &str, crate_name: &str, errors: &mut Vec) { let readme_path = path.join(file_name); if !readme_path.exists() { @@ -101,6 +103,7 @@ fn check_presence_of(path: &Path, file_name: &str, crate_name: &str, errors: &mu } } +#[no_coverage] fn check_path_is_true>( cargo_toml_path: P, path: &[&str], @@ -141,6 +144,7 @@ fn check_path_is_true>( } /// Checks the `package` section of a Cargo.toml file. +#[no_coverage] fn check_package>(cargo_toml_path: P, toml: &Value) -> anyhow::Result<()> { let package = toml.get("package").ok_or_else(|| { anyhow::anyhow!( @@ -182,6 +186,7 @@ fn check_package>(cargo_toml_path: P, toml: &Value) -> anyhow::Re } /// Checks the `lints` section of a Cargo.toml file. +#[no_coverage] fn check_lints_workspace>(cargo_toml_path: P, toml: &Value) -> anyhow::Result<()> { let expected_lints = r#"Please add the following to your crate Cargo.toml: [lints] diff --git a/src/gen_client.rs b/src/gen_client.rs index 8652d382..b729dee5 100644 --- a/src/gen_client.rs +++ b/src/gen_client.rs @@ -27,6 +27,7 @@ pub struct GenClientCommand { } /// Generate a client SDK (application) +#[no_coverage] pub fn command_gen_client(log: impl Logger + Sync + Clone, params: &GenClientCommand) { log.loading(&format!( "Generating client SDK for language {}", diff --git a/src/languages.rs b/src/languages.rs index 73c61d89..f1b58d49 100644 --- a/src/languages.rs +++ b/src/languages.rs @@ -16,6 +16,7 @@ pub struct LanguagesParams { } /// List of supported languages +#[no_coverage] pub fn command_languages(log: impl Logger + Sync + Clone, params: &LanguagesParams) { // List all directories in the templates directory log.log("List of supported languages:"); diff --git a/src/main.rs b/src/main.rs index 4225ef7d..5d54c6b4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ mod resolve; #[cfg(feature = "experimental")] mod search; +#[no_coverage] fn main() { let cli = Cli::parse(); @@ -40,6 +41,7 @@ fn main() { println!("Total execution time: {:?}s", elapsed.as_secs_f64()); } +#[no_coverage] fn run_command(cli: &Cli, log: impl Logger + Sync + Clone) { match &cli.command { #[cfg(feature = "experimental")] diff --git a/src/registry/check.rs b/src/registry/check.rs index fab6473c..e7c86d21 100644 --- a/src/registry/check.rs +++ b/src/registry/check.rs @@ -27,6 +27,7 @@ pub struct RegistryCheckArgs { } /// Check a semantic convention registry. +#[no_coverage] pub(crate) fn command(log: impl Logger + Sync + Clone, cache: &Cache, args: &RegistryCheckArgs) { log.loading(&format!("Checking registry `{}`", args.registry)); diff --git a/src/registry/generate.rs b/src/registry/generate.rs index bf90e35e..63eddfee 100644 --- a/src/registry/generate.rs +++ b/src/registry/generate.rs @@ -43,6 +43,7 @@ pub struct RegistryGenerateArgs { } /// Generate artifacts from a semantic convention registry. +#[no_coverage] pub(crate) fn command( logger: impl Logger + Sync + Clone, cache: &Cache, diff --git a/src/registry/mod.rs b/src/registry/mod.rs index ec192f82..bf1b81c9 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -64,6 +64,7 @@ pub struct RegistryArgs { } /// Manage a semantic convention registry. +#[no_coverage] pub fn semconv_registry(log: impl Logger + Sync + Clone, command: &RegistryCommand) { let cache = Cache::try_new().unwrap_or_else(|e| { log.error(&e.to_string()); diff --git a/src/registry/resolve.rs b/src/registry/resolve.rs index 5c562d38..6af1ff09 100644 --- a/src/registry/resolve.rs +++ b/src/registry/resolve.rs @@ -55,6 +55,7 @@ pub struct RegistryResolveArgs { /// Resolve a semantic convention registry and write the resolved schema to a /// file or print it to stdout. +#[no_coverage] pub(crate) fn command( logger: impl Logger + Sync + Clone, cache: &Cache, @@ -120,6 +121,7 @@ pub(crate) fn command( }); } +#[no_coverage] fn apply_format(format: &Format, object: &T) -> Result { match format { Format::Yaml => serde_yaml::to_string(object) diff --git a/src/registry/stats.rs b/src/registry/stats.rs index 56af7bba..6884f2ee 100644 --- a/src/registry/stats.rs +++ b/src/registry/stats.rs @@ -21,6 +21,7 @@ pub struct RegistryStatsArgs { } /// Compute stats on a semantic convention registry. +#[no_coverage] pub(crate) fn command(log: impl Logger + Sync + Clone, cache: &Cache, args: &RegistryStatsArgs) { log.loading(&format!( "Compute statistics on the registry `{}`", @@ -50,12 +51,14 @@ pub(crate) fn command(log: impl Logger + Sync + Clone, cache: &Cache, args: &Reg display_schema_stats(&schema); } +#[no_coverage] fn display_semconv_registry_stats(semconv_registry: &SemConvRegistry) { let stats = semconv_registry.stats(); println!("Semantic Convention Registry Stats:"); println!(" - Total number of files: {}", stats.file_count); } +#[no_coverage] fn display_schema_stats(schema: &ResolvedTelemetrySchema) { let stats = schema.stats(); println!("Resolved Telemetry Schema Stats:"); @@ -155,6 +158,7 @@ fn display_schema_stats(schema: &ResolvedTelemetrySchema) { } } +#[no_coverage] fn display_common_group_stats(group_type: &GroupType, common_stats: &CommonGroupStats) { println!(" - {} {:#?}s", common_stats.count, group_type); println!( diff --git a/src/resolve.rs b/src/resolve.rs index 4668ec88..16d2b3be 100644 --- a/src/resolve.rs +++ b/src/resolve.rs @@ -58,6 +58,7 @@ pub struct ResolveSchema { } /// Resolve a schema file and print the result +#[no_coverage] pub fn command_resolve(log: impl Logger + Sync + Clone, command: &ResolveCommand) { let cache = Cache::try_new().unwrap_or_else(|e| { log.error(&e.to_string()); diff --git a/src/search/mod.rs b/src/search/mod.rs index 74623f70..28fedbfc 100644 --- a/src/search/mod.rs +++ b/src/search/mod.rs @@ -194,6 +194,7 @@ impl StatefulResults { } /// Search for attributes and metrics in a schema file +#[no_coverage] pub fn command_search(log: impl Logger + Sync + Clone, command: &SearchCommand) { let cache = Cache::try_new().unwrap_or_else(|e| { log.error(&e.to_string()); @@ -208,6 +209,7 @@ pub fn command_search(log: impl Logger + Sync + Clone, command: &SearchCommand) } /// Search semantic convention registry command [todo, WIP]. +#[no_coverage] fn search_registry_command2( log: impl Logger + Sync + Clone, cache: &Cache, @@ -262,6 +264,7 @@ fn search_registry_command2( } /// Search semantic convention registry command. +#[no_coverage] fn search_registry_command( log: impl Logger + Sync + Clone, cache: &Cache, @@ -305,6 +308,7 @@ fn search_registry_command( } /// Search schema command. +#[no_coverage] fn search_schema_command( log: impl Logger + Sync + Clone, cache: &Cache, @@ -320,6 +324,7 @@ fn search_schema_command( search_schema_tui(log, schema); } +#[no_coverage] fn search_schema_tui(log: impl Logger + Sync + Clone, schema: TelemetrySchema) { let semconv_registry = schema.semantic_convention_catalog(); @@ -408,6 +413,7 @@ fn search_schema_tui(log: impl Logger + Sync + Clone, schema: TelemetrySchema) { }); } +#[no_coverage] fn search_tui(app: &mut SearchApp<'_>) -> Result<()> { // Startup let stdout = io::stdout(); @@ -533,6 +539,7 @@ fn ui(app: &mut SearchApp<'_>, frame: &mut Frame<'_>) { frame.render_widget(app.search_area.widget(), outer_layout[1]); } +#[no_coverage] fn summary_area<'a>(app: &'a SearchApp<'a>) -> Paragraph<'a> { let area_title = "Summary"; let semconv_catalog = app.schema.semantic_convention_catalog(); @@ -578,6 +585,7 @@ fn summary_area<'a>(app: &'a SearchApp<'a>) -> Paragraph<'a> { .wrap(Wrap { trim: true }) } +#[no_coverage] fn detail_area<'a>(app: &'a SearchApp<'a>, item: Option<&'a ResultItem>) -> Paragraph<'a> { let mut area_title = "Details"; let paragraph = if let Some(item) = item { @@ -719,6 +727,7 @@ fn detail_area<'a>(app: &'a SearchApp<'a>, item: Option<&'a ResultItem>) -> Para .wrap(Wrap { trim: true }) } +#[no_coverage] fn update(app: &mut SearchApp<'_>) -> Result<()> { if event::poll(std::time::Duration::from_millis(250))? { let event = event::read()?; @@ -744,6 +753,7 @@ fn update(app: &mut SearchApp<'_>) -> Result<()> { Ok(()) } +#[no_coverage] fn run(app: &mut SearchApp<'_>) -> Result<()> { // ratatui terminal let mut t = Terminal::new(CrosstermBackend::new(io::stderr()))?; From 70eaf584b4fc0cca8a51a5d010c9e55c739fdc1f Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 17:36:49 -0700 Subject: [PATCH 18/22] chore(coverage): remove xtask and main command line from the code coverage --- Cargo.toml | 2 ++ crates/xtask/src/main.rs | 4 ++-- crates/xtask/src/validate.rs | 10 +++++----- src/gen_client.rs | 2 +- src/languages.rs | 2 +- src/main.rs | 4 ++-- src/registry/check.rs | 2 +- src/registry/generate.rs | 2 +- src/registry/mod.rs | 2 +- src/registry/resolve.rs | 4 ++-- src/registry/stats.rs | 8 ++++---- src/resolve.rs | 2 +- src/search/mod.rs | 20 ++++++++++---------- 13 files changed, 33 insertions(+), 31 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e601e36c..e3201412 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -176,3 +176,5 @@ string_to_string = "warn" #doc_markdown = "warn" #exhaustive_structs = "warn" #todo = "warn" +#implicit_clone = "warn" +#inconsistent_struct_constructor = "warn" diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index 9b3dfd69..0ed363d5 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -12,7 +12,7 @@ mod validate; -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn main() -> anyhow::Result<()> { let task = std::env::args().nth(1); @@ -30,7 +30,7 @@ fn main() -> anyhow::Result<()> { } /// Prints help message. -#[no_coverage] +#[cfg(not(tarpaulin_include))] pub fn print_help() -> anyhow::Result<()> { println!( " diff --git a/crates/xtask/src/validate.rs b/crates/xtask/src/validate.rs index 077af94b..eabcb015 100644 --- a/crates/xtask/src/validate.rs +++ b/crates/xtask/src/validate.rs @@ -18,7 +18,7 @@ use toml::Value; /// that are allowed to be used in the public API. /// - Each Cargo.toml must contain \[lints\] workspace = true and few other fields /// in the \[package\] section. -#[no_coverage] +#[cfg(not(tarpaulin_include))] pub fn run() -> anyhow::Result<()> { let mut errors = vec![]; @@ -91,7 +91,7 @@ pub fn run() -> anyhow::Result<()> { Ok(()) } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn check_presence_of(path: &Path, file_name: &str, crate_name: &str, errors: &mut Vec) { let readme_path = path.join(file_name); if !readme_path.exists() { @@ -103,7 +103,7 @@ fn check_presence_of(path: &Path, file_name: &str, crate_name: &str, errors: &mu } } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn check_path_is_true>( cargo_toml_path: P, path: &[&str], @@ -144,7 +144,7 @@ fn check_path_is_true>( } /// Checks the `package` section of a Cargo.toml file. -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn check_package>(cargo_toml_path: P, toml: &Value) -> anyhow::Result<()> { let package = toml.get("package").ok_or_else(|| { anyhow::anyhow!( @@ -186,7 +186,7 @@ fn check_package>(cargo_toml_path: P, toml: &Value) -> anyhow::Re } /// Checks the `lints` section of a Cargo.toml file. -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn check_lints_workspace>(cargo_toml_path: P, toml: &Value) -> anyhow::Result<()> { let expected_lints = r#"Please add the following to your crate Cargo.toml: [lints] diff --git a/src/gen_client.rs b/src/gen_client.rs index b729dee5..3ef62e78 100644 --- a/src/gen_client.rs +++ b/src/gen_client.rs @@ -27,7 +27,7 @@ pub struct GenClientCommand { } /// Generate a client SDK (application) -#[no_coverage] +#[cfg(not(tarpaulin_include))] pub fn command_gen_client(log: impl Logger + Sync + Clone, params: &GenClientCommand) { log.loading(&format!( "Generating client SDK for language {}", diff --git a/src/languages.rs b/src/languages.rs index f1b58d49..60c207bc 100644 --- a/src/languages.rs +++ b/src/languages.rs @@ -16,7 +16,7 @@ pub struct LanguagesParams { } /// List of supported languages -#[no_coverage] +#[cfg(not(tarpaulin_include))] pub fn command_languages(log: impl Logger + Sync + Clone, params: &LanguagesParams) { // List all directories in the templates directory log.log("List of supported languages:"); diff --git a/src/main.rs b/src/main.rs index 5d54c6b4..96a189ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,7 @@ mod resolve; #[cfg(feature = "experimental")] mod search; -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn main() { let cli = Cli::parse(); @@ -41,7 +41,7 @@ fn main() { println!("Total execution time: {:?}s", elapsed.as_secs_f64()); } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn run_command(cli: &Cli, log: impl Logger + Sync + Clone) { match &cli.command { #[cfg(feature = "experimental")] diff --git a/src/registry/check.rs b/src/registry/check.rs index e7c86d21..5066be72 100644 --- a/src/registry/check.rs +++ b/src/registry/check.rs @@ -27,7 +27,7 @@ pub struct RegistryCheckArgs { } /// Check a semantic convention registry. -#[no_coverage] +#[cfg(not(tarpaulin_include))] pub(crate) fn command(log: impl Logger + Sync + Clone, cache: &Cache, args: &RegistryCheckArgs) { log.loading(&format!("Checking registry `{}`", args.registry)); diff --git a/src/registry/generate.rs b/src/registry/generate.rs index 63eddfee..849acfbe 100644 --- a/src/registry/generate.rs +++ b/src/registry/generate.rs @@ -43,7 +43,7 @@ pub struct RegistryGenerateArgs { } /// Generate artifacts from a semantic convention registry. -#[no_coverage] +#[cfg(not(tarpaulin_include))] pub(crate) fn command( logger: impl Logger + Sync + Clone, cache: &Cache, diff --git a/src/registry/mod.rs b/src/registry/mod.rs index bf1b81c9..33c63e5c 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -64,7 +64,7 @@ pub struct RegistryArgs { } /// Manage a semantic convention registry. -#[no_coverage] +#[cfg(not(tarpaulin_include))] pub fn semconv_registry(log: impl Logger + Sync + Clone, command: &RegistryCommand) { let cache = Cache::try_new().unwrap_or_else(|e| { log.error(&e.to_string()); diff --git a/src/registry/resolve.rs b/src/registry/resolve.rs index 6af1ff09..0f1aa723 100644 --- a/src/registry/resolve.rs +++ b/src/registry/resolve.rs @@ -55,7 +55,7 @@ pub struct RegistryResolveArgs { /// Resolve a semantic convention registry and write the resolved schema to a /// file or print it to stdout. -#[no_coverage] +#[cfg(not(tarpaulin_include))] pub(crate) fn command( logger: impl Logger + Sync + Clone, cache: &Cache, @@ -121,7 +121,7 @@ pub(crate) fn command( }); } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn apply_format(format: &Format, object: &T) -> Result { match format { Format::Yaml => serde_yaml::to_string(object) diff --git a/src/registry/stats.rs b/src/registry/stats.rs index 6884f2ee..9afb4feb 100644 --- a/src/registry/stats.rs +++ b/src/registry/stats.rs @@ -21,7 +21,7 @@ pub struct RegistryStatsArgs { } /// Compute stats on a semantic convention registry. -#[no_coverage] +#[cfg(not(tarpaulin_include))] pub(crate) fn command(log: impl Logger + Sync + Clone, cache: &Cache, args: &RegistryStatsArgs) { log.loading(&format!( "Compute statistics on the registry `{}`", @@ -51,14 +51,14 @@ pub(crate) fn command(log: impl Logger + Sync + Clone, cache: &Cache, args: &Reg display_schema_stats(&schema); } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn display_semconv_registry_stats(semconv_registry: &SemConvRegistry) { let stats = semconv_registry.stats(); println!("Semantic Convention Registry Stats:"); println!(" - Total number of files: {}", stats.file_count); } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn display_schema_stats(schema: &ResolvedTelemetrySchema) { let stats = schema.stats(); println!("Resolved Telemetry Schema Stats:"); @@ -158,7 +158,7 @@ fn display_schema_stats(schema: &ResolvedTelemetrySchema) { } } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn display_common_group_stats(group_type: &GroupType, common_stats: &CommonGroupStats) { println!(" - {} {:#?}s", common_stats.count, group_type); println!( diff --git a/src/resolve.rs b/src/resolve.rs index 16d2b3be..adf62abb 100644 --- a/src/resolve.rs +++ b/src/resolve.rs @@ -58,7 +58,7 @@ pub struct ResolveSchema { } /// Resolve a schema file and print the result -#[no_coverage] +#[cfg(not(tarpaulin_include))] pub fn command_resolve(log: impl Logger + Sync + Clone, command: &ResolveCommand) { let cache = Cache::try_new().unwrap_or_else(|e| { log.error(&e.to_string()); diff --git a/src/search/mod.rs b/src/search/mod.rs index 28fedbfc..9396f13a 100644 --- a/src/search/mod.rs +++ b/src/search/mod.rs @@ -194,7 +194,7 @@ impl StatefulResults { } /// Search for attributes and metrics in a schema file -#[no_coverage] +#[cfg(not(tarpaulin_include))] pub fn command_search(log: impl Logger + Sync + Clone, command: &SearchCommand) { let cache = Cache::try_new().unwrap_or_else(|e| { log.error(&e.to_string()); @@ -209,7 +209,7 @@ pub fn command_search(log: impl Logger + Sync + Clone, command: &SearchCommand) } /// Search semantic convention registry command [todo, WIP]. -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn search_registry_command2( log: impl Logger + Sync + Clone, cache: &Cache, @@ -264,7 +264,7 @@ fn search_registry_command2( } /// Search semantic convention registry command. -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn search_registry_command( log: impl Logger + Sync + Clone, cache: &Cache, @@ -308,7 +308,7 @@ fn search_registry_command( } /// Search schema command. -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn search_schema_command( log: impl Logger + Sync + Clone, cache: &Cache, @@ -324,7 +324,7 @@ fn search_schema_command( search_schema_tui(log, schema); } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn search_schema_tui(log: impl Logger + Sync + Clone, schema: TelemetrySchema) { let semconv_registry = schema.semantic_convention_catalog(); @@ -413,7 +413,7 @@ fn search_schema_tui(log: impl Logger + Sync + Clone, schema: TelemetrySchema) { }); } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn search_tui(app: &mut SearchApp<'_>) -> Result<()> { // Startup let stdout = io::stdout(); @@ -539,7 +539,7 @@ fn ui(app: &mut SearchApp<'_>, frame: &mut Frame<'_>) { frame.render_widget(app.search_area.widget(), outer_layout[1]); } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn summary_area<'a>(app: &'a SearchApp<'a>) -> Paragraph<'a> { let area_title = "Summary"; let semconv_catalog = app.schema.semantic_convention_catalog(); @@ -585,7 +585,7 @@ fn summary_area<'a>(app: &'a SearchApp<'a>) -> Paragraph<'a> { .wrap(Wrap { trim: true }) } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn detail_area<'a>(app: &'a SearchApp<'a>, item: Option<&'a ResultItem>) -> Paragraph<'a> { let mut area_title = "Details"; let paragraph = if let Some(item) = item { @@ -727,7 +727,7 @@ fn detail_area<'a>(app: &'a SearchApp<'a>, item: Option<&'a ResultItem>) -> Para .wrap(Wrap { trim: true }) } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn update(app: &mut SearchApp<'_>) -> Result<()> { if event::poll(std::time::Duration::from_millis(250))? { let event = event::read()?; @@ -753,7 +753,7 @@ fn update(app: &mut SearchApp<'_>) -> Result<()> { Ok(()) } -#[no_coverage] +#[cfg(not(tarpaulin_include))] fn run(app: &mut SearchApp<'_>) -> Result<()> { // ratatui terminal let mut t = Terminal::new(CrosstermBackend::new(io::stderr()))?; From a11008ad9db07c577dda94435a829fec6b791c1d Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 19:05:22 -0700 Subject: [PATCH 19/22] chore(coverage): improve test coverage --- crates/weaver_forge/src/debug.rs | 33 ++ crates/weaver_forge/src/lib.rs | 10 +- crates/weaver_semconv/src/group.rs | 40 ++ .../schemas/app-telemetry-schema.yaml | 149 ++++++ .../schemas/root-telemetry-schema.1.22.0.yaml | 354 ++++++++++++++ crates/weaver_template/src/lib.rs | 24 + .../weaver_template/templates/go/config.yaml | 15 + .../templates/go/optional_attrs.macro.tera | 52 ++ .../templates/go/otel/attribute/attrs.go.tera | 15 + .../templates/go/otel/client.go.tera | 181 +++++++ .../templates/go/otel/eventer/event.tera | 57 +++ .../templates/go/otel/meter/metric.tera | 462 ++++++++++++++++++ .../templates/go/otel/meter/metric_group.tera | 20 + .../templates/go/otel/tracer/span.tera | 160 ++++++ .../templates/go/required_attrs.macro.tera | 54 ++ src/search/schema/attribute.rs | 3 + src/search/schema/attributes.rs | 1 + src/search/schema/event.rs | 2 + src/search/schema/metric.rs | 3 + src/search/schema/metric_group.rs | 2 + src/search/schema/resource.rs | 1 + src/search/schema/span.rs | 2 + src/search/schema/tags.rs | 1 + src/search/semconv/attribute.rs | 1 + src/search/semconv/attributes.rs | 1 + src/search/semconv/examples.rs | 1 + src/search/semconv/metric.rs | 1 + 27 files changed, 1644 insertions(+), 1 deletion(-) create mode 100644 crates/weaver_template/schemas/app-telemetry-schema.yaml create mode 100644 crates/weaver_template/schemas/root-telemetry-schema.1.22.0.yaml create mode 100644 crates/weaver_template/templates/go/config.yaml create mode 100644 crates/weaver_template/templates/go/optional_attrs.macro.tera create mode 100644 crates/weaver_template/templates/go/otel/attribute/attrs.go.tera create mode 100644 crates/weaver_template/templates/go/otel/client.go.tera create mode 100644 crates/weaver_template/templates/go/otel/eventer/event.tera create mode 100644 crates/weaver_template/templates/go/otel/meter/metric.tera create mode 100644 crates/weaver_template/templates/go/otel/meter/metric_group.tera create mode 100644 crates/weaver_template/templates/go/otel/tracer/span.tera create mode 100644 crates/weaver_template/templates/go/required_attrs.macro.tera diff --git a/crates/weaver_forge/src/debug.rs b/crates/weaver_forge/src/debug.rs index b7fdef75..8bf65124 100644 --- a/crates/weaver_forge/src/debug.rs +++ b/crates/weaver_forge/src/debug.rs @@ -83,3 +83,36 @@ pub fn print_dedup_errors(logger: impl Logger + Sync + Clone, error: Error) { logger.error(&output); }); } + +#[cfg(test)] +mod tests { + use super::*; + use crate::error::Error::TargetNotSupported; + + #[test] + fn test_print_dedup_errors() { + let logger = weaver_logger::TestLogger::new(); + let error = CompoundError(vec![ + TargetNotSupported { + // <-- These 3 errors are deduplicated + root_path: "target".to_owned(), + target: "target".to_owned(), + }, + TargetNotSupported { + root_path: "target".to_owned(), + target: "target".to_owned(), + }, + TargetNotSupported { + root_path: "target".to_owned(), + target: "target".to_owned(), + }, + TargetNotSupported { + // <-- This error is not deduplicated + root_path: "target".to_owned(), + target: "other_target".to_owned(), + }, + ]); + print_dedup_errors(logger.clone(), error); + assert_eq!(logger.error_count(), 2); + } +} diff --git a/crates/weaver_forge/src/lib.rs b/crates/weaver_forge/src/lib.rs index 63e86304..62aae57a 100644 --- a/crates/weaver_forge/src/lib.rs +++ b/crates/weaver_forge/src/lib.rs @@ -416,6 +416,7 @@ mod tests { use walkdir::WalkDir; + use crate::debug::print_dedup_errors; use weaver_logger::TestLogger; use weaver_resolver::SchemaResolver; use weaver_semconv::SemConvRegistry; @@ -447,7 +448,14 @@ mod tests { }); engine - .generate(logger, &template_registry, Path::new("observed_output")) + .generate( + logger.clone(), + &template_registry, + Path::new("observed_output"), + ) + .inspect_err(|e| { + print_dedup_errors(logger.clone(), e.clone()); + }) .expect("Failed to generate registry assets"); assert!(cmp_dir("expected_output", "observed_output").unwrap()); diff --git a/crates/weaver_semconv/src/group.rs b/crates/weaver_semconv/src/group.rs index bb619349..abcfceb3 100644 --- a/crates/weaver_semconv/src/group.rs +++ b/crates/weaver_semconv/src/group.rs @@ -288,3 +288,43 @@ impl Display for InstrumentSpec { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::attribute::Examples; + + #[test] + fn test_validate_group() { + let group = GroupSpec { + id: "test".to_owned(), + r#type: GroupType::Span, + brief: "test".to_owned(), + note: "test".to_owned(), + prefix: "test".to_owned(), + extends: None, + stability: Some(Stability::Deprecated), + deprecated: Some("true".to_owned()), + attributes: vec![AttributeSpec::Id { + id: "test".to_owned(), + r#type: AttributeType::PrimitiveOrArray(PrimitiveOrArrayTypeSpec::String), + brief: None, + stability: Some(Stability::Deprecated), + deprecated: Some("true".to_owned()), + examples: Some(Examples::String("test".to_owned())), + tag: None, + requirement_level: Default::default(), + sampling_relevant: None, + note: "".to_owned(), + }], + constraints: vec![], + span_kind: Some(SpanKindSpec::Client), + events: vec![], + metric_name: None, + instrument: None, + unit: None, + name: None, + }; + assert!(validate_group(&group).is_ok()); + } +} diff --git a/crates/weaver_template/schemas/app-telemetry-schema.yaml b/crates/weaver_template/schemas/app-telemetry-schema.yaml new file mode 100644 index 00000000..d6c31c3c --- /dev/null +++ b/crates/weaver_template/schemas/app-telemetry-schema.yaml @@ -0,0 +1,149 @@ +file_format: 1.2.0 +parent_schema_url: schemas/root-telemetry-schema.1.22.0.yaml +# Current schema url +schema_url: https://mycompany.com/schemas/1.0.0 + +# The section below outlines the telemetry schema for a service or application. +# This schema details all the metrics, logs, and spans specifically generated +# by that service or application. +# +# Note: Frameworks or libraries linked with the application that produce OTel +# telemetry data might also have their own telemetry schema, detailing the +# metrics, logs, and spans they generate locally. +schema: + # Resource attributes + # Only used when a Client SDK is generated + resource: + attributes: + - ref: service.name + value: "my-service" + - ref: service.version + requirement_level: required + - id: service.instance.id + type: string + brief: The unique identifier of the service instance + + # Instrumentation library + instrumentation_library: + name: "my-service" + version: "1.0.0" + # schema url? + + # Metrics declaration + resource_metrics: + # Declaration of all the univariate metrics + metrics: + - ref: jvm.thread.count + attributes: + - ref: server.address + - ref: server.port + - ref: network.protocol.name + - ref: network.protocol.version + - ref: url.scheme + requirement_level: required + - ref: jvm.class.loaded + attributes: + - ref: server.address + - ref: server.port + - ref: network.protocol.name + - ref: network.protocol.version + - ref: url.scheme + requirement_level: required + tags: + sensitivity: PII + tags: + sensitivity: PII + - ref: jvm.cpu.recent_utilization + attributes: + - ref: server.address + - ref: server.port + - ref: network.protocol.name + - ref: network.protocol.version + - ref: url.scheme + requirement_level: required + - ref: jvm.gc.duration + # Declaration of all the multivariate metrics + metric_groups: + - name: http # name of a metrics group + attributes: + - ref: server.address + - ref: server.port + - ref: network.protocol.name + - ref: network.protocol.version + - ref: url.scheme + - id: url.host + type: string + brief: The host of the request + requirement_level: required + metrics: # metrics sharing the same attributes + - ref: jvm.class.loaded + - ref: jvm.cpu.recent_utilization + + # Events declaration + resource_events: + events: + - event_name: request + domain: http + attributes: + - ref: server.address + - ref: server.port + - ref: network.protocol.name + - ref: network.protocol.version + - ref: url.scheme + - id: url.host + type: string + brief: The host of the request + requirement_level: required + - event_name: response + domain: http + attributes: + - ref: server.address + - ref: server.port + - ref: network.protocol.name + - ref: network.protocol.version + - ref: url.scheme + - id: url.host + type: string + brief: The host of the request + requirement_level: required + + # Spans declaration + resource_spans: + spans: + - span_name: http.request # name of a specific tracer + attributes: + - ref: server.address + - ref: server.port + - ref: client.address + - ref: client.port + - ref: url.scheme + - id: url.host + type: string + brief: The host of the request + requirement_level: required + events: + - event_name: error + attributes: + - ref: exception.type + - ref: exception.message + requirement_level: required + - ref: exception.stacktrace + # links: + - span_name: database.query + attributes: + - ref: server.address + - ref: server.port + - ref: client.address + - ref: client.port + - ref: url.scheme + requirement_level: required + - id: url.host + type: string + brief: The host of the request + requirement_level: required + events: + - event_name: error + attributes: + - ref: exception.type + - ref: exception.message + - ref: exception.stacktrace \ No newline at end of file diff --git a/crates/weaver_template/schemas/root-telemetry-schema.1.22.0.yaml b/crates/weaver_template/schemas/root-telemetry-schema.1.22.0.yaml new file mode 100644 index 00000000..6ab7886e --- /dev/null +++ b/crates/weaver_template/schemas/root-telemetry-schema.1.22.0.yaml @@ -0,0 +1,354 @@ +file_format: 1.2.0 +schema_url: https://opentelemetry.io/schemas/1.21.0 + +# Semantic conventions can be loaded from a list of URLs or from a git repository. +# The git repository approach is usually faster and download all the semantic +# conventions files dynamically without the need to update the schema file. +semantic_conventions: + - git_url: https://github.com/open-telemetry/semantic-conventions.git + path: model +#semantic_conventions: +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/client.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/destination.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/error.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/exception.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/faas-common.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/general.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/http-common.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/network.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/server.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/session.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/source.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/url.yaml +# # logs +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/logs/events.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/logs/general.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/logs/log-exception.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/logs/log-feature_flag.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/logs/media.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/logs/mobile-events.yaml +# #metrics +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/metrics/database-metrics.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/metrics/faas-metrics.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/metrics/http.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/metrics/jvm-metrics-experimental.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/metrics/jvm-metrics.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/metrics/rpc-metrics.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/metrics/system-metrics.yaml +# # registry +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/registry/http.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/registry/network.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/registry/rpc.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/registry/url.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/registry/user-agent.yaml +# # resources +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/android.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/browser.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/cloud.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/container.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/deployment_environment.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/device.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/faas.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/host.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/k8s.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/oci.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/os.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/process.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/service.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/service_experimental.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/telemetry.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/telemetry_experimental.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/webengine.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/cloud_provider/aws/ecs.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/cloud_provider/aws/eks.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/cloud_provider/aws/logs.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/cloud_provider/gcp/cloud_run.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/cloud_provider/gcp/gce.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/resource/cloud_provider/heroku.yaml +# # scope +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/scope/exporter/exporter.yaml +# # trace +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/cloudevents.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/compatibility.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/database.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/faas.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/feature-flag.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/http.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/messaging.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/rpc.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/trace-exception.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/aws/lambda.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/exporter/exporter.yaml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/instrumentation/aws-sdk.yml +# - url: https://raw.githubusercontent.com/open-telemetry/semantic-conventions/main/model/trace/instrumentation/graphql.yml + +versions: + 1.22.0: + metrics: + changes: + # https://github.com/open-telemetry/semantic-conventions/pull/229 + - rename_attributes: + attribute_map: + messaging.message.payload_size_bytes: messaging.message.body.size + # https://github.com/open-telemetry/semantic-conventions/pull/224 + - rename_metrics: + http.client.duration: http.client.request.duration + http.server.duration: http.server.request.duration + # https://github.com/open-telemetry/semantic-conventions/pull/241 + - rename_metrics: + process.runtime.jvm.memory.usage: jvm.memory.usage + process.runtime.jvm.memory.committed: jvm.memory.committed + process.runtime.jvm.memory.limit: jvm.memory.limit + process.runtime.jvm.memory.usage_after_last_gc: jvm.memory.usage_after_last_gc + process.runtime.jvm.gc.duration: jvm.gc.duration + # also https://github.com/open-telemetry/semantic-conventions/pull/252 + process.runtime.jvm.threads.count: jvm.thread.count + # also https://github.com/open-telemetry/semantic-conventions/pull/252 + process.runtime.jvm.classes.loaded: jvm.class.loaded + # also https://github.com/open-telemetry/semantic-conventions/pull/252 + process.runtime.jvm.classes.unloaded: jvm.class.unloaded + # also https://github.com/open-telemetry/semantic-conventions/pull/252 + # and https://github.com/open-telemetry/semantic-conventions/pull/60 + process.runtime.jvm.classes.current_loaded: jvm.class.count + process.runtime.jvm.cpu.time: jvm.cpu.time + process.runtime.jvm.cpu.recent_utilization: jvm.cpu.recent_utilization + process.runtime.jvm.memory.init: jvm.memory.init + process.runtime.jvm.system.cpu.utilization: jvm.system.cpu.utilization + process.runtime.jvm.system.cpu.load_1m: jvm.system.cpu.load_1m + # https://github.com/open-telemetry/semantic-conventions/pull/253 + process.runtime.jvm.buffer.usage: jvm.buffer.memory.usage + # https://github.com/open-telemetry/semantic-conventions/pull/253 + process.runtime.jvm.buffer.limit: jvm.buffer.memory.limit + process.runtime.jvm.buffer.count: jvm.buffer.count + # https://github.com/open-telemetry/semantic-conventions/pull/20 + - rename_attributes: + attribute_map: + type: jvm.memory.type + pool: jvm.memory.pool.name + apply_to_metrics: + - jvm.memory.usage + - jvm.memory.committed + - jvm.memory.limit + - jvm.memory.usage_after_last_gc + - jvm.memory.init + - rename_attributes: + attribute_map: + name: jvm.gc.name + action: jvm.gc.action + apply_to_metrics: + - jvm.gc.duration + - rename_attributes: + attribute_map: + daemon: thread.daemon + apply_to_metrics: + - jvm.threads.count + - rename_attributes: + attribute_map: + pool: jvm.buffer.pool.name + apply_to_metrics: + - jvm.buffer.usage + - jvm.buffer.limit + - jvm.buffer.count + # https://github.com/open-telemetry/semantic-conventions/pull/89 + - rename_attributes: + attribute_map: + state: system.cpu.state + cpu: system.cpu.logical_number + apply_to_metrics: + - system.cpu.time + - system.cpu.utilization + - rename_attributes: + attribute_map: + state: system.memory.state + apply_to_metrics: + - system.memory.usage + - system.memory.utilization + - rename_attributes: + attribute_map: + state: system.paging.state + apply_to_metrics: + - system.paging.usage + - system.paging.utilization + - rename_attributes: + attribute_map: + type: system.paging.type + direction: system.paging.direction + apply_to_metrics: + - system.paging.faults + - system.paging.operations + - rename_attributes: + attribute_map: + device: system.device + direction: system.disk.direction + apply_to_metrics: + - system.disk.io + - system.disk.operations + - system.disk.io_time + - system.disk.operation_time + - system.disk.merged + - rename_attributes: + attribute_map: + device: system.device + state: system.filesystem.state + type: system.filesystem.type + mode: system.filesystem.mode + mountpoint: system.filesystem.mountpoint + apply_to_metrics: + - system.filesystem.usage + - system.filesystem.utilization + - rename_attributes: + attribute_map: + device: system.device + direction: system.network.direction + protocol: network.protocol + state: system.network.state + apply_to_metrics: + - system.network.dropped + - system.network.packets + - system.network.errors + - system.network.io + - system.network.connections + - rename_attributes: + attribute_map: + status: system.processes.status + apply_to_metrics: + - system.processes.count + # https://github.com/open-telemetry/semantic-conventions/pull/247 + - rename_metrics: + http.server.request.size: http.server.request.body.size + http.server.response.size: http.server.response.body.size + 1.21.0: + spans: + changes: + # https://github.com/open-telemetry/opentelemetry-specification/pull/3336 + - rename_attributes: + attribute_map: + messaging.kafka.client_id: messaging.client_id + messaging.rocketmq.client_id: messaging.client_id + # https://github.com/open-telemetry/opentelemetry-specification/pull/3402 + - rename_attributes: + attribute_map: + # net.peer.(name|port) attributes were usually populated on client side + # so they should be usually translated to server.(address|port) + # net.host.* attributes were only populated on server side + net.host.name: server.address + net.host.port: server.port + # was only populated on client side + net.sock.peer.name: server.socket.domain + # net.sock.peer.(addr|port) mapping is not possible + # since they applied to both client and server side + # were only populated on server side + net.sock.host.addr: server.socket.address + net.sock.host.port: server.socket.port + http.client_ip: client.address + # https://github.com/open-telemetry/opentelemetry-specification/pull/3426 + - rename_attributes: + attribute_map: + net.protocol.name: network.protocol.name + net.protocol.version: network.protocol.version + net.host.connection.type: network.connection.type + net.host.connection.subtype: network.connection.subtype + net.host.carrier.name: network.carrier.name + net.host.carrier.mcc: network.carrier.mcc + net.host.carrier.mnc: network.carrier.mnc + net.host.carrier.icc: network.carrier.icc + # https://github.com/open-telemetry/opentelemetry-specification/pull/3355 + - rename_attributes: + attribute_map: + http.method: http.request.method + http.status_code: http.response.status_code + http.scheme: url.scheme + http.url: url.full + http.request_content_length: http.request.body.size + http.response_content_length: http.response.body.size + metrics: + changes: + # https://github.com/open-telemetry/semantic-conventions/pull/53 + - rename_metrics: + process.runtime.jvm.cpu.utilization: process.runtime.jvm.cpu.recent_utilization + 1.20.0: + spans: + changes: + # https://github.com/open-telemetry/opentelemetry-specification/pull/3272 + - rename_attributes: + attribute_map: + net.app.protocol.name: net.protocol.name + net.app.protocol.version: net.protocol.version + 1.19.0: + spans: + changes: + # https://github.com/open-telemetry/opentelemetry-specification/pull/3209 + - rename_attributes: + attribute_map: + faas.execution: faas.invocation_id + # https://github.com/open-telemetry/opentelemetry-specification/pull/3188 + - rename_attributes: + attribute_map: + faas.id: cloud.resource_id + # https://github.com/open-telemetry/opentelemetry-specification/pull/3190 + - rename_attributes: + attribute_map: + http.user_agent: user_agent.original + resources: + changes: + # https://github.com/open-telemetry/opentelemetry-specification/pull/3190 + - rename_attributes: + attribute_map: + browser.user_agent: user_agent.original + 1.18.0: + 1.17.0: + spans: + changes: + # https://github.com/open-telemetry/opentelemetry-specification/pull/2957 + - rename_attributes: + attribute_map: + messaging.consumer_id: messaging.consumer.id + messaging.protocol: net.app.protocol.name + messaging.protocol_version: net.app.protocol.version + messaging.destination: messaging.destination.name + messaging.temp_destination: messaging.destination.temporary + messaging.destination_kind: messaging.destination.kind + messaging.message_id: messaging.message.id + messaging.conversation_id: messaging.message.conversation_id + messaging.message_payload_size_bytes: messaging.message.payload_size_bytes + messaging.message_payload_compressed_size_bytes: messaging.message.payload_compressed_size_bytes + messaging.rabbitmq.routing_key: messaging.rabbitmq.destination.routing_key + messaging.kafka.message_key: messaging.kafka.message.key + messaging.kafka.partition: messaging.kafka.destination.partition + messaging.kafka.tombstone: messaging.kafka.message.tombstone + messaging.rocketmq.message_type: messaging.rocketmq.message.type + messaging.rocketmq.message_tag: messaging.rocketmq.message.tag + messaging.rocketmq.message_keys: messaging.rocketmq.message.keys + messaging.kafka.consumer_group: messaging.kafka.consumer.group + 1.16.0: + 1.15.0: + spans: + changes: + # https://github.com/open-telemetry/opentelemetry-specification/pull/2743 + - rename_attributes: + attribute_map: + http.retry_count: http.resend_count + 1.14.0: + 1.13.0: + spans: + changes: + # https://github.com/open-telemetry/opentelemetry-specification/pull/2614 + - rename_attributes: + attribute_map: + net.peer.ip: net.sock.peer.addr + net.host.ip: net.sock.host.addr + 1.12.0: + 1.11.0: + 1.10.0: + 1.9.0: + 1.8.0: + spans: + changes: + - rename_attributes: + attribute_map: + db.cassandra.keyspace: db.name + db.hbase.namespace: db.name + 1.7.0: + 1.6.1: + 1.5.0: + 1.4.0: \ No newline at end of file diff --git a/crates/weaver_template/src/lib.rs b/crates/weaver_template/src/lib.rs index 1c637f38..fbbd225a 100644 --- a/crates/weaver_template/src/lib.rs +++ b/crates/weaver_template/src/lib.rs @@ -91,3 +91,27 @@ impl Default for GeneratorConfig { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::sdkgen::ClientSdkGenerator; + use weaver_logger::Logger; + + #[test] + fn test_default_generator_config() { + let log = weaver_logger::ConsoleLogger::new(0); + let generator = ClientSdkGenerator::try_new("go", GeneratorConfig::default()).unwrap(); + + generator + .generate( + log.clone(), + "schemas/app-telemetry-schema.yaml".into(), + "output".into(), + ) + .inspect_err(|e| { + log.error(&format!("{}", e)); + }) + .expect("Failed to generate client SDK"); + } +} diff --git a/crates/weaver_template/templates/go/config.yaml b/crates/weaver_template/templates/go/config.yaml new file mode 100644 index 00000000..452e1bf4 --- /dev/null +++ b/crates/weaver_template/templates/go/config.yaml @@ -0,0 +1,15 @@ +file_name: snake_case +function_name: PascalCase +arg_name: camelCase +struct_name: PascalCase +field_name: PascalCase + +type_mapping: + int: int64 + double: double + boolean: bool + string: string + "int[]": "[]int64" + "double[]": "[]double" + "boolean[]": "[]bool" + "string[]": "[]string" \ No newline at end of file diff --git a/crates/weaver_template/templates/go/optional_attrs.macro.tera b/crates/weaver_template/templates/go/optional_attrs.macro.tera new file mode 100644 index 00000000..89fcf653 --- /dev/null +++ b/crates/weaver_template/templates/go/optional_attrs.macro.tera @@ -0,0 +1,52 @@ +{% macro attr_type(prefix) -%}Optional{{prefix}}Attribute{% endmacro attr_type %} + +{% macro declare_attrs(prefix="", marker, attrs) -%} +{% set not_require_attrs = attrs | not_required | without_value %} +{%- if not_require_attrs | length > 0 -%} +// =============================================== +// ====== Definition of optional attributes ====== +// =============================================== + +// Optional{{marker}}Attribute is an interface implemented by all optional attributes of the {{marker}}. +type Optional{{marker}}Attribute interface { + Attribute() otel_attr.KeyValue + {{ marker | function_name }}Marker() +} + +{% for attr in not_require_attrs | without_enum %} +// {{prefix}}{{attr.id | struct_name}}OptAttr represents an optional attribute. +// {{ [attr.brief, attr.note, "", "# Examples", attr.examples] | comment(prefix="// ") }} +func {{prefix}}{{attr.id | struct_name}}OptAttr(v {{ attr.type | type_mapping(enum=attr.id | struct_name) }}) {{prefix}}{{attr.id | struct_name}}OptAttrWrapper { return {{prefix}}{{attr.id | struct_name}}OptAttrWrapper{v} } +// {{prefix}}{{attr.id | struct_name}}OptAttrWrapper is a wrapper for the attribute `{{attr.id}}`. +// Use the function {{attr.id | struct_name}}OptAttr(value) to create an instance. +type {{prefix}}{{attr.id | struct_name}}OptAttrWrapper struct { {{ attr.type | type_mapping(enum=attr.id | struct_name) }} } +func (w {{prefix}}{{attr.id | struct_name}}OptAttrWrapper) Attribute() otel_attr.KeyValue { + return attribute.{{ attr.id | field_name }}Key.{{ attr.type | type_mapping(enum="String" | struct_name) | function_name }}(w.{{ attr.type | type_mapping(enum="string" | struct_name) }}) +} +func (w {{prefix}}{{attr.id | struct_name}}OptAttrWrapper) {{marker}}Marker() {} + +{% endfor %} + +{% for attr in not_require_attrs | with_enum %} +// {{prefix}}{{attr.id | struct_name}}OptAttr represents an optional attribute. +// {{ [attr.brief, attr.note, "", "# Examples", attr.examples] | comment(prefix="// ") }} +func {{prefix}}{{attr.id | struct_name}}OptAttr(v {{ attr.type | type_mapping(enum=attr.id | struct_name) }}) {{prefix}}{{attr.id | struct_name}}OptAttrWrapper { return {{prefix}}{{attr.id | struct_name}}OptAttrWrapper{v} } +// {{prefix}}{{attr.id | struct_name}}OptAttrWrapper is a wrapper for the attribute `{{attr.id}}`. +// Use the function {{attr.id | struct_name}}OptAttr(value) to create an instance. +type {{prefix}}{{attr.id | struct_name}}OptAttrWrapper struct { {{ attr.type | type_mapping(enum=attr.id | struct_name) }} } +func (w {{prefix}}{{attr.id | struct_name}}OptAttrWrapper) Attribute() otel_attr.KeyValue { + return attribute.{{ attr.id | field_name }}Key.String(string(w.{{ attr.type | type_mapping(enum=attr.id | struct_name) }})) +} +func (w {{prefix}}{{attr.id | struct_name}}OptAttrWrapper) {{marker}}Marker() {} + +type {{attr.id | struct_name}} string +const ( +{% for variant in attr.type.members %} + // {{variant.id | struct_name}} is a possible value of {{attr.id | struct_name}}. + // {{ [variant.brief, variant.note] | comment(prefix=" // ") }} + {{variant.id | struct_name}} {{attr.id | struct_name}} = "{{variant.id}}" +{%- endfor %} +) +{% endfor %} +{%- endif -%} +{% endmacro declare_attrs %} \ No newline at end of file diff --git a/crates/weaver_template/templates/go/otel/attribute/attrs.go.tera b/crates/weaver_template/templates/go/otel/attribute/attrs.go.tera new file mode 100644 index 00000000..ec1fd2f3 --- /dev/null +++ b/crates/weaver_template/templates/go/otel/attribute/attrs.go.tera @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: Apache-2.0 + +package attribute + +import ( + "go.opentelemetry.io/otel/attribute" +) + +{% set attrs = schema | unique_attributes(recursive=true) -%} +// Declaration of all attribute keys. +var ( +{%- for attr in attrs %} + {{ attr.id | field_name }}Key = attribute.Key("{{attr.id}}") +{%- endfor %} +) \ No newline at end of file diff --git a/crates/weaver_template/templates/go/otel/client.go.tera b/crates/weaver_template/templates/go/otel/client.go.tera new file mode 100644 index 00000000..7ec1ba53 --- /dev/null +++ b/crates/weaver_template/templates/go/otel/client.go.tera @@ -0,0 +1,181 @@ +{% import "required_attrs.macro.tera" as required %} +{% import "optional_attrs.macro.tera" as optional %} +package otel + +import ( + "context" + "fmt" + "log" + "os" + "time" + + "go.opentelemetry.io/otel" + otel_attr "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" + "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" + "go.opentelemetry.io/otel/metric" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/trace" + + "go_test/pkg/otel/attribute" +) + +const ( + InstrumentationName = "{{ schema.instrumentation_library.name }}" + InstrumentationVersion = "{{ schema.instrumentation_library.version }}" +) + +var ( + Meter = otel.GetMeterProvider().Meter( + InstrumentationName, + metric.WithInstrumentationVersion(InstrumentationVersion), + metric.WithSchemaURL("{{ schema_url }}"), + ) + Tracer = otel.GetTracerProvider().Tracer( + InstrumentationName, + trace.WithInstrumentationVersion(InstrumentationVersion), + trace.WithSchemaURL("{{ schema_url }}"), + ) +) + +// ClientHandler is a handler for the OTel Weaver client. +type ClientHandler struct { + ctx context.Context + metricShutdown func(context.Context) error + traceShutdown func(context.Context) error +} + +{%- set required_attrs = schema.resource.attributes | required | without_value -%} +{%- set not_required_attrs = schema.resource.attributes | not_required | without_value %} + +{{ required::declare_attrs(attrs=required_attrs) }} +{{ optional::declare_attrs(marker="Resource", attrs=not_required_attrs) }} + +// ================== +// ===== Client ===== +// ================== + +// Client returns a OTel client (generated by OTel Weaver). +// It uses a context initialized with `context.Background()`. +func Client( + {{- required::declare_args(attrs=required_attrs) }} + {% if not_required_attrs | length > 0 -%}optionalAttributes ...OptionalResourceAttribute,{% endif %} +) *ClientHandler { + return ClientWithContext( + context.Background(), + {%- for attr in required_attrs %} + {{attr.id | arg_name}}, + {%- endfor %} + {% if not_required_attrs | length > 0 -%}optionalAttributes...,{% endif %} + ) +} + +// ClientWithContext returns a OTel client with a given context (generated by OTel Weaver). +func ClientWithContext( + ctx context.Context, + {{- required::declare_args(attrs=required_attrs) }} + {% if not_required_attrs | length > 0 -%}optionalAttributes ...OptionalResourceAttribute,{% endif %} +) *ClientHandler { + metricShutdown, traceShutdown, err := installExportPipeline( + {%- for attr in required_attrs %} + {{attr.id | arg_name}}, + {%- endfor %} + {% if not_required_attrs | length > 0 -%}optionalAttributes...,{% endif %} + ) + if err != nil { + log.Fatal(err) + } + + return &ClientHandler{ + ctx: ctx, + metricShutdown: metricShutdown, + traceShutdown: traceShutdown, + } +} + +func (o *ClientHandler) Shutdown() { + metricErr := o.metricShutdown(o.ctx) + traceErr := o.traceShutdown(o.ctx) + + mustExit := false + if metricErr != nil { + log.Println(metricErr) + mustExit = true + } + if traceErr != nil { + log.Println(traceErr) + mustExit = true + } + if mustExit { + os.Exit(1) + } +} + +func resourceBuilder( + {%- for attr in required_attrs %} + {{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, + {%- endfor %} + {% if not_required_attrs | length > 0 -%}optionalAttributes ...OptionalResourceAttribute,{% endif %} +) *resource.Resource { + attrs := []otel_attr.KeyValue { + {%- for attr in schema.resource.attributes | with_value %} + attribute.{{ attr.id | field_name }}Key.{{ attr.type | type_mapping(enum=attr.id | struct_name) | function_name }}({{ attr.value | value }}), + {%- endfor %} + {%- for attr in required_attrs %} + {{attr.id | arg_name}}.Attribute(), + {%- endfor %} + } + {% if not_required_attrs | length > 0 -%} + for _, attr := range optionalAttributes { + attrs = append(attrs, attr.Attribute()) + } + {% endif %} + return resource.NewWithAttributes("{{ schema_url }}", attrs...) +} + +func installExportPipeline( + {%- for attr in required_attrs %} + {{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, + {%- endfor %} + {% if not_required_attrs | length > 0 -%}optionalAttributes ...OptionalResourceAttribute,{% endif %} +) (metricShutdown func(context.Context) error, traceShutdown func(context.Context) error, err error) { + metricExporter, err := stdoutmetric.New(stdoutmetric.WithPrettyPrint()) + if err != nil { + err = fmt.Errorf("creating metric stdout exporter: %w", err) + return + } + + traceExporter, err := stdouttrace.New(stdouttrace.WithPrettyPrint()) + if err != nil { + err = fmt.Errorf("creating trace stdout exporter: %w", err) + return + } + + metricProvider := sdkmetric.NewMeterProvider( + sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExporter, sdkmetric.WithInterval(3*time.Second))), + sdkmetric.WithResource(resourceBuilder( + {%- for attr in required_attrs %} + {{attr.id | arg_name}}, + {%- endfor %} + {% if not_required_attrs | length > 0 -%}optionalAttributes...,{% endif %} + )), + ) + otel.SetMeterProvider(metricProvider) + + tracerProvider := sdktrace.NewTracerProvider( + sdktrace.WithBatcher(traceExporter), + sdktrace.WithResource(resourceBuilder( + {%- for attr in required_attrs %} + {{attr.id | arg_name}}, + {%- endfor %} + {% if not_required_attrs | length > 0 -%}optionalAttributes...,{% endif %} + )), + ) + otel.SetTracerProvider(tracerProvider) + + metricShutdown = metricProvider.Shutdown + traceShutdown = tracerProvider.Shutdown + return +} \ No newline at end of file diff --git a/crates/weaver_template/templates/go/otel/eventer/event.tera b/crates/weaver_template/templates/go/otel/eventer/event.tera new file mode 100644 index 00000000..5e489334 --- /dev/null +++ b/crates/weaver_template/templates/go/otel/eventer/event.tera @@ -0,0 +1,57 @@ +{% import "required_attrs.macro.tera" as required %} +{% import "optional_attrs.macro.tera" as optional %} +{# Define the file name for the generated code #} +{%- set file_name = event_name | file_name -%} +{{- config(file_name="otel/eventer/event_" ~ file_name ~ "/event.go") -}} +// SPDX-License-Identifier: Apache-2.0 + +package {{ event_name | file_name }} + +import ( + "context" + + otel_attr "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + + client "go_test/pkg/otel" + "go_test/pkg/otel/attribute" +) + +// Event records a new `{{ event_name }}` event with +// the given required attributes. +func Event( + {{- required::declare_args(attrs=attributes) }} + optionalAttributes ...{{ optional::attr_type(prefix="Span") }}, +) { + EventWithContext( + context.TODO(), + {%- for attr in attributes | required | without_value %} + {{attr.id | arg_name}}, + {%- endfor %} + optionalAttributes..., + ) +} + +// EventWithContext records a new `{{ event_name }}` event with +// the given context and required attributes. +func EventWithContext( + ctx context.Context, + {{- required::declare_args(attrs=attributes) }} + optionalAttributes ...{{ optional::attr_type(prefix="Span") }}, +) { + + ctx, span := client.Tracer.Start(ctx, "{{ event_name }}", + {%- for attr in attributes | with_value %} + trace.WithAttributes(attribute.{{ attr.id | function_name }}Key.{{attr.type | type_mapping(enum=attr.id) | function_name}}({{attr.value | value}})), + {%- endfor %} + {%- for attr in attributes | required | without_value %} + trace.WithAttributes({{ attr.id | arg_name }}.Attribute()), + {%- endfor %} + ) + for _, opt := range optionalAttributes { + span.SetAttributes(opt.Attribute()) + } +} + +{{ required::declare_attrs(attrs=attributes) }} +{{ optional::declare_attrs(marker="Span", attrs=attributes) }} diff --git a/crates/weaver_template/templates/go/otel/meter/metric.tera b/crates/weaver_template/templates/go/otel/meter/metric.tera new file mode 100644 index 00000000..4e2a5cc7 --- /dev/null +++ b/crates/weaver_template/templates/go/otel/meter/metric.tera @@ -0,0 +1,462 @@ +{% import "required_attrs.macro.tera" as required %} +{% import "optional_attrs.macro.tera" as optional %} +{# Define the file name for the generated code #} +{%- set file_name = name | file_name -%} +{{- config(file_name="otel/meter/metric_" ~ file_name ~ "/metric.go") -}} +// SPDX-License-Identifier: Apache-2.0 + +package {{ name | file_name }} + +import ( + "context" + + otel_attr "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/metric" + + client "go_test/pkg/otel" + "go_test/pkg/otel/attribute" +) + +type Int64Observer func() (int64, {% for attr in attributes | required | without_value %}{{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}[]OptionalMetricAttribute, error) +type Float64Observer func() (float64, {% for attr in attributes | required | without_value %}{{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}[]OptionalMetricAttribute, error) + +{% if instrument == "counter" %} +// ===== Synchronous Counter Declaration ===== +type Int64Counter_ struct { + ctx context.Context + counter metric.Int64Counter +} + +type Float64Counter_ struct { + ctx context.Context + counter metric.Float64Counter +} + +func Int64Counter() (*Int64Counter_, error) { + return Int64CounterWithContext(context.TODO()) +} + +func Int64CounterWithContext(ctx context.Context) (*Int64Counter_, error) { + counter, err := client.Meter.Int64Counter( + "{{name}}", + metric.WithDescription("{{brief}}"), + metric.WithUnit("{{unit}}"), + ) + if err != nil { + return nil, err + } + return &Int64Counter_{ + ctx: ctx, + counter: counter, + }, nil +} + +func (g *Int64Counter_) Add(incr uint64, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}optAttrs ...OptionalMetricAttribute) { + options := []metric.AddOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + g.counter.Add(g.ctx, int64(incr), options...) +} + +func (g *Int64Counter_) AddWithContext(ctx context.Context, incr uint64, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}optAttrs ...OptionalMetricAttribute) { + options := []metric.AddOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + g.counter.Add(ctx, int64(incr), options...) +} + +func Float64Counter() (*Float64Counter_, error) { + return Float64CounterWithContext(context.TODO()) +} + +func Float64CounterWithContext(ctx context.Context) (*Float64Counter_, error) { + counter, err := client.Meter.Float64Counter( + "{{name}}", + metric.WithDescription("{{brief}}"), + metric.WithUnit("{{unit}}"), + ) + if err != nil { + return nil, err + } + return &Float64Counter_{ + ctx: ctx, + counter: counter, + }, nil +} + +func (g *Float64Counter_) Add(incr float64, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}optAttrs ...OptionalMetricAttribute) { + options := []metric.AddOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + g.counter.Add(g.ctx, incr, options...) +} + +func (g *Float64Counter_) AddWithContext(ctx context.Context, incr float64, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}optAttrs ...OptionalMetricAttribute) { + options := []metric.AddOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + g.counter.Add(ctx, incr, options...) +} + +// ============================================ +// ===== Asynchronous Counter Declaration ===== +// ============================================ + +func Int64ObservableCounter(observer Int64Observer) error { + _, err := client.Meter.Int64ObservableCounter( + "{{name}}", + metric.WithDescription("{{brief}}"), + metric.WithUnit("{{unit}}"), + metric.WithInt64Callback(func(ctx context.Context, otelObserver metric.Int64Observer) error { + v, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}}, {% endfor %}optAttrs, err := observer() + if err != nil { + return err + } + options := []metric.ObserveOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + otelObserver.Observe(v, options...) + return nil + })) + if err != nil { + return err + } + return nil +} + +func Float64ObservableCounter(observer Float64Observer) error { + _, err := client.Meter.Float64ObservableCounter( + "{{name}}", + metric.WithDescription("{{brief}}"), + metric.WithUnit("{{unit}}"), + metric.WithFloat64Callback(func(ctx context.Context, otelObserver metric.Float64Observer) error { + v, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}}, {% endfor %}optAttrs, err := observer() + if err != nil { + return err + } + options := []metric.ObserveOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + otelObserver.Observe(v, options...) + return nil + })) + if err != nil { + return err + } + return nil +} + +{% elif instrument == "updowncounter" %} +// ===== Synchronous UpDownCounter Declaration ===== +type Int64UpDownCounter_ struct { + ctx context.Context + counter metric.Int64UpDownCounter +} + +type Float64UpDownCounter_ struct { + ctx context.Context + counter metric.Float64UpDownCounter +} + +func Int64UpDownCounter() (*Int64UpDownCounter_, error) { + return Int64UpDownCounterWithContext(context.TODO()) +} + +func Int64UpDownCounterWithContext(ctx context.Context) (*Int64UpDownCounter_, error) { + counter, err := client.Meter.Int64UpDownCounter( + "{{name}}", + metric.WithDescription("{{brief}}"), + metric.WithUnit("{{unit}}"), + ) + if err != nil { + return nil, err + } + return &Int64UpDownCounter_{ + ctx: ctx, + counter: counter, + }, nil +} + +func (g *Int64UpDownCounter_) Add(incr uint64, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}optAttrs ...OptionalMetricAttribute) { + options := []metric.AddOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + g.counter.Add(g.ctx, int64(incr), options...) +} + +func (g *Int64UpDownCounter_) AddWithContext(ctx context.Context, incr uint64, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}optAttrs ...OptionalMetricAttribute) { + options := []metric.AddOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + g.counter.Add(ctx, int64(incr), options...) +} + +func Float64UpDownCounter() (*Float64UpDownCounter_, error) { + return Float64UpDownCounterWithContext(context.TODO()) +} + +func Float64UpDownCounterWithContext(ctx context.Context) (*Float64UpDownCounter_, error) { + counter, err := client.Meter.Float64UpDownCounter( + "{{name}}", + metric.WithDescription("{{brief}}"), + metric.WithUnit("{{unit}}"), + ) + if err != nil { + return nil, err + } + return &Float64UpDownCounter_{ + ctx: ctx, + counter: counter, + }, nil +} + +func (g *Float64UpDownCounter_) Add(incr float64, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}optAttrs ...OptionalMetricAttribute) { + options := []metric.AddOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + g.counter.Add(g.ctx, incr, options...) +} + +func (g *Float64UpDownCounter_) AddWithContext(ctx context.Context, incr float64, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}optAttrs ...OptionalMetricAttribute) { + options := []metric.AddOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + g.counter.Add(ctx, incr, options...) +} + +// ============================================ +// ===== Asynchronous UpDownCounter Declaration ===== +// ============================================ + +func Int64ObservableUpDownCounter(observer Int64Observer) error { + _, err := client.Meter.Int64ObservableUpDownCounter( + "{{name}}", + metric.WithDescription("{{brief}}"), + metric.WithUnit("{{unit}}"), + metric.WithInt64Callback(func(ctx context.Context, otelObserver metric.Int64Observer) error { + v, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}}, {% endfor %}optAttrs, err := observer() + if err != nil { + return err + } + options := []metric.ObserveOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + otelObserver.Observe(v, options...) + return nil + })) + if err != nil { + return err + } + return nil +} + +func Float64ObservableUpDownCounter(observer Float64Observer) error { + _, err := client.Meter.Float64ObservableUpDownCounter( + "{{name}}", + metric.WithDescription("{{brief}}"), + metric.WithUnit("{{unit}}"), + metric.WithFloat64Callback(func(ctx context.Context, otelObserver metric.Float64Observer) error { + v, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}}, {% endfor %}optAttrs, err := observer() + if err != nil { + return err + } + options := []metric.ObserveOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + otelObserver.Observe(v, options...) + return nil + })) + if err != nil { + return err + } + return nil +} + +{% elif instrument == "gauge" %} +// ========================================== +// ===== Asynchronous Gauge Declaration ===== +// ========================================== + +func Int64ObservableGauge(observer Int64Observer) error { + _, err := client.Meter.Int64ObservableGauge( + "{{name}}", + metric.WithDescription("{{brief}}"), + metric.WithUnit("{{unit}}"), + metric.WithInt64Callback(func(ctx context.Context, otelObserver metric.Int64Observer) error { + v, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}}, {% endfor %}optAttrs, err := observer() + if err != nil { + return err + } + options := []metric.ObserveOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + otelObserver.Observe(v, options...) + return nil + })) + if err != nil { + return err + } + return nil +} + +func Float64ObservableGauge(observer Float64Observer) error { + _, err := client.Meter.Float64ObservableGauge( + "{{name}}", + metric.WithDescription("{{brief}}"), + metric.WithUnit("{{unit}}"), + metric.WithFloat64Callback(func(ctx context.Context, otelObserver metric.Float64Observer) error { + v, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}}, {% endfor %}optAttrs, err := observer() + if err != nil { + return err + } + options := []metric.ObserveOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + otelObserver.Observe(v, options...) + return nil + })) + if err != nil { + return err + } + return nil +} + +{% elif instrument == "histogram" %} +// ============================================= +// ===== Synchronous Histogram Declaration ===== +// ============================================= + +type Int64Histogram_ struct { + ctx context.Context + histogram metric.Int64Histogram +} + +type Float64Histogram_ struct { + ctx context.Context + histogram metric.Float64Histogram +} + +func Int64Histogram() (*Int64Histogram_, error) { + return Int64HistogramWithContext(context.TODO()) +} + +func Int64HistogramWithContext(ctx context.Context) (*Int64Histogram_, error) { + histogram, err := client.Meter.Int64Histogram( + "{{name}}", + metric.WithDescription("{{brief}}"), + metric.WithUnit("{{unit}}"), + ) + if err != nil { + return nil, err + } + return &Int64Histogram_{ + ctx: ctx, + histogram: histogram, + }, nil +} + +func (g *Int64Histogram_) Record(incr uint64, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}optAttrs ...OptionalMetricAttribute) { + options := []metric.RecordOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + g.histogram.Record(g.ctx, int64(incr), options...) +} + +func (g *Int64Histogram_) RecordWithContext(ctx context.Context, incr uint64, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}optAttrs ...OptionalMetricAttribute) { + options := []metric.RecordOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + g.histogram.Record(ctx, int64(incr), options...) +} + +func Float64Histogram() (*Float64Histogram_, error) { + return Float64HistogramWithContext(context.TODO()) +} + +func Float64HistogramWithContext(ctx context.Context) (*Float64Histogram_, error) { + histogram, err := client.Meter.Float64Histogram( + "{{name}}", + metric.WithDescription("{{brief}}"), + metric.WithUnit("{{unit}}"), + ) + if err != nil { + return nil, err + } + return &Float64Histogram_{ + ctx: ctx, + histogram: histogram, + }, nil +} + +func (g *Float64Histogram_) Record(incr float64, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}optAttrs ...OptionalMetricAttribute) { + options := []metric.RecordOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + g.histogram.Record(g.ctx, incr, options...) +} + +func (g *Float64Histogram_) RecordWithContext(ctx context.Context, incr float64, {% for attr in attributes | required | without_value %}{{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}optAttrs ...OptionalMetricAttribute) { + options := []metric.RecordOption { + {% for attr in attributes | required | without_value %}metric.WithAttributes({{attr.id | arg_name}}.Attribute()),{% endfor %} + } + for _, opt := range optAttrs { + options = append(options, metric.WithAttributes(opt.Attribute())) + } + g.histogram.Record(ctx, incr, options...) +} + +{% endif %} + +{{ required::declare_attrs(attrs=attributes) }} +{{ optional::declare_attrs(marker="Metric", attrs=attributes) }} diff --git a/crates/weaver_template/templates/go/otel/meter/metric_group.tera b/crates/weaver_template/templates/go/otel/meter/metric_group.tera new file mode 100644 index 00000000..900dbad2 --- /dev/null +++ b/crates/weaver_template/templates/go/otel/meter/metric_group.tera @@ -0,0 +1,20 @@ +{% import "required_attrs.macro.tera" as required %} +{% import "optional_attrs.macro.tera" as optional %} +{# Define the file name for the generated code #} +{%- set file_name = name | file_name -%} +{{- config(file_name="otel/meter/metric_group_" ~ file_name ~ "/metric_group.go") -}} +// SPDX-License-Identifier: Apache-2.0 + +package {{ name | file_name }} + +import ( + otel_attr "go.opentelemetry.io/otel/attribute" + + "go_test/pkg/otel/attribute" +) + +type Int64Observer func() (int64, {% for attr in attributes | required | without_value %}{{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}[]OptionalMetricAttribute, error) +type Float64Observer func() (float64, {% for attr in attributes | required | without_value %}{{attr.id | struct_name}}ReqAttrWrapper, {% endfor %}[]OptionalMetricAttribute, error) + +{{ required::declare_attrs(attrs=attributes) }} +{{ optional::declare_attrs(marker="Metric", attrs=attributes) }} diff --git a/crates/weaver_template/templates/go/otel/tracer/span.tera b/crates/weaver_template/templates/go/otel/tracer/span.tera new file mode 100644 index 00000000..0c4fd4ce --- /dev/null +++ b/crates/weaver_template/templates/go/otel/tracer/span.tera @@ -0,0 +1,160 @@ +{% import "required_attrs.macro.tera" as required %} +{% import "optional_attrs.macro.tera" as optional %} +{# Define the file name for the generated code #} +{%- set file_name = span_name | file_name -%} +{{- config(file_name="otel/tracer/" ~ file_name ~ "/span.go") -}} +// SPDX-License-Identifier: Apache-2.0 + +package {{ span_name | file_name }} + +import ( + "context" + + otel_attr "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/trace" + + client "go_test/pkg/otel" + "go_test/pkg/otel/attribute" +) + +{%- if attributes | required | without_value | length > 0 %} +// Start starts a new `{{ span_name }}` span with +// the given required attributes. +func Start( + {{- required::declare_args(attrs=attributes) }} + optionalAttributes ...{{ optional::attr_type(prefix="Span") }}, +) *{{span_name | struct_name}}Span { + return StartWithContext( + context.TODO(), + {%- for attr in attributes | required | without_value %} + {{attr.id | arg_name}}, + {%- endfor %} + optionalAttributes..., + ) +} + +// StartWithContext starts a new `{{ span_name }}` span with +// the given required attributes and context. +func StartWithContext( + ctx context.Context, + {{- required::declare_args(attrs=attributes) }} + optionalAttributes ...{{ optional::attr_type(prefix="Span") }}, +) *{{span_name | struct_name}}Span { + ctx, span := client.Tracer.Start(ctx, "{{ span_name }}", + {%- for attr in attributes | with_value %} + trace.WithAttributes(attribute.{{ attr.id | function_name }}Key.{{attr.type | type_mapping(enum=attr.id) | function_name}}({{attr.value | value}})), + {%- endfor %} + {%- for attr in attributes | required | without_value %} + trace.WithAttributes({{ attr.id | arg_name }}.Attribute()), + {%- endfor %} + ) + for _, opt := range optionalAttributes { + span.SetAttributes(opt.Attribute()) + } + return &{{span_name | struct_name}}Span { + ctx: ctx, + span: span, + } +} +{%- else %} +// Start starts a new named `{{ span_name }}` span. +func Start{{ span_name | function_name }}(ctx context.Context, optionalAttributes ...{{ optional::attr_type(prefix="Span") }}) *{{span_name | struct_name}}Span { + ctx, span := client.Tracer.Start(ctx, "{{ span_name }}") + for _, opt := range optionalAttributes { + span.SetAttributes(opt.Attribute()) + } + return &{{span_name | struct_name}}Span { + ctx: ctx, + span: span, + } +} +{%- endif %} + +{{ required::declare_attrs(attrs=attributes) }} +{{ optional::declare_attrs(marker="Span", attrs=attributes) }} + +// {{span_name | struct_name}}Span is a span for `{{ span_name }}`. +type {{span_name | struct_name}}Span struct { + ctx context.Context + span trace.Span +} + +{% if events | length > 0 -%} +// {{ span_name | struct_name }}Event is interface implemented by all events for `{{ span_name }}`. +type {{ span_name | struct_name }}Event interface { + EventOptions() []trace.EventOption +} + +{% for event in events -%} + +{% set event_name = event.event_name | function_name -%} +{{ required::declare_attrs(prefix="Event" ~ event_name, attrs=event.attributes) }} +{{ optional::declare_attrs(prefix="Event" ~ event_name, marker="Event" ~ event_name, attrs=event.attributes) }} + +// Event adds an event to the span. +func (s *{{span_name | struct_name}}Span) Event{{ event.event_name | function_name }}( + {%- for attr in event.attributes | required %} + {{attr.id | field_name}} Event{{ event.event_name | function_name }}{{attr.id | struct_name}}ReqAttrWrapper, + {%- endfor %} + optionalAttributes ...{{ optional::attr_type(prefix="Event" ~ event_name) }}, +) *{{span_name | struct_name}}Span { + eventOptions := []trace.EventOption{ + {%- for attr in event.attributes | with_value %} + trace.WithAttributes(attribute.{{ attr.id | function_name }}Key.{{attr.type | type_mapping(enum=attr.id) | function_name}}({{attr.value | value}})), + {%- endfor %} + {%- for attr in event.attributes | required %} + trace.WithAttributes({{ attr.id | field_name }}.Attribute()), + {%- endfor %} + } + for _, opt := range optionalAttributes { + eventOptions = append(eventOptions, trace.WithAttributes(opt.Attribute())) + } + s.span.AddEvent("{{ event.event_name }}", eventOptions...) + return s +} +{% endfor %} + +{%- endif %} + +{% for attr in attributes | not_required | without_value %} +// Attr{{ attr.id | function_name }} sets the optional attribute `{{ attr.id }}` for the span. +// {{ [attr.brief, attr.note, "", "# Examples", attr.examples] | comment(prefix="// ") }} +func (s *{{span_name | struct_name}}Span) {{attr.id | function_name}}OptAttr(value {{ attr.type | type_mapping(enum=attr.id | struct_name) }}) *{{span_name | struct_name}}Span { + s.span.SetAttributes(attribute.{{ attr.id | field_name }}Key.{{ attr.type | type_mapping(enum=attr.id) | function_name }}(value)) + return s +} +{% endfor %} + +func (s *{{span_name | struct_name}}Span) StatusOk() *{{span_name | struct_name}}Span { + s.span.SetStatus(codes.Ok, "") + return s +} + +// Error sets the error for the span. +func (s *{{span_name | struct_name}}Span) Error(err error, description string) *{{span_name | struct_name}}Span { + s.span.SetStatus(codes.Error, description) + s.span.RecordError(err) + return s +} + +// Context returns the context of the current span. +func (s *{{span_name | struct_name }}Span) Context() context.Context { return s.ctx } + +// End ends the span with status OK. +func (s *{{span_name | struct_name}}Span) EndWithOk() { + s.span.SetStatus(codes.Ok, "") + s.span.End() +} + +// End ends the span with status Error and a given description. +func (s *{{span_name | struct_name}}Span) EndWithError(err error, description string) { + s.span.SetStatus(codes.Error, description) + s.span.RecordError(err) + s.span.End() +} + +// End ends the span. +func (s *{{span_name | struct_name}}Span) End() { + s.span.End() +} diff --git a/crates/weaver_template/templates/go/required_attrs.macro.tera b/crates/weaver_template/templates/go/required_attrs.macro.tera new file mode 100644 index 00000000..793f628b --- /dev/null +++ b/crates/weaver_template/templates/go/required_attrs.macro.tera @@ -0,0 +1,54 @@ +{% macro declare_args(attrs) -%} + {%- for attr in attrs | required | without_value %} + {{attr.id | arg_name}} {{attr.id | struct_name}}ReqAttrWrapper, + {%- endfor %} +{% endmacro declare_args %} + + +{% macro declare_attrs(prefix="", attrs) -%} +{% set require_attrs = attrs | required | without_value %} +{% if require_attrs | length > 0 -%} +// =============================================== +// ====== Definition of required attributes ====== +// =============================================== + +{% for attr in require_attrs | without_enum %} +// {{prefix}}{{attr.id | struct_name}}ReqAttr is a wrapper for a required attribute. +// {{ [attr.brief, attr.note, "", "# Examples", attr.examples] | comment(prefix="// ") }} +func {{prefix}}{{attr.id | struct_name}}ReqAttr(v {{ attr.type | type_mapping(enum=attr.id | struct_name) }}) {{prefix}}{{attr.id | struct_name}}ReqAttrWrapper { + return {{prefix}}{{attr.id | struct_name}}ReqAttrWrapper{v} +} +// {{prefix}}{{attr.id | struct_name}}ReqAttrWrapper is a wrapper for the attribute `{{attr.id}}`. +// Use the function {{prefix}}{{attr.id | struct_name}}ReqAttr(value) to create an instance. +type {{prefix}}{{attr.id | struct_name}}ReqAttrWrapper struct { {{ attr.type | type_mapping(enum=attr.id | struct_name) }} } +func (w {{prefix}}{{attr.id | struct_name}}ReqAttrWrapper) Attribute() otel_attr.KeyValue { + return attribute.{{ attr.id | field_name }}Key.String(w.{{ attr.type | type_mapping(enum=attr.id | struct_name) }}) +} + +{% endfor %} + +{% for attr in require_attrs | with_enum %} +// {{prefix}}{{attr.id | struct_name}}ReqAttr is a wrapper for a required attribute. +// {{ [attr.brief, attr.note, "", "# Examples", attr.examples] | comment(prefix="// ") }} +func {{prefix}}{{attr.id | struct_name}}ReqAttr(v {{ attr.type | type_mapping(enum=attr.id | struct_name) }}) {{prefix}}{{attr.id | struct_name}}ReqAttrWrapper { + return {{prefix}}{{attr.id | struct_name}}ReqAttrWrapper{v} +} +// {{prefix}}{{attr.id | struct_name}}ReqAttrWrapper is a wrapper for the attribute `{{attr.id}}`. +// Use the function {{prefix}}{{attr.id | struct_name}}ReqAttr(value) to create an instance. +type {{prefix}}{{attr.id | struct_name}}ReqAttrWrapper struct { {{ attr.type | type_mapping(enum=attr.id | struct_name) }} } +func (w {{prefix}}{{attr.id | struct_name}}ReqAttrWrapper) Attribute() otel_attr.KeyValue { + return attribute.{{ attr.id | field_name }}Key.String(w.{{ attr.type | type_mapping(enum=attr.id | struct_name) }}) +} + +type {{attr.id | struct_name}} string +const ( +{% for variant in attr.type.members %} + // {{variant.id | struct_name}} is a possible value of {{attr.id | struct_name}}. + // {{ [variant.brief, variant.note] | comment(prefix=" // ") }} + {{variant.id | struct_name}} {{attr.id | struct_name}} = "{{variant.id}}" +{%- endfor %} +) +{% endfor %} + +{%- endif %} +{% endmacro declare_attrs %} \ No newline at end of file diff --git a/src/search/schema/attribute.rs b/src/search/schema/attribute.rs index 26829ccc..e6e53bdb 100644 --- a/src/search/schema/attribute.rs +++ b/src/search/schema/attribute.rs @@ -13,6 +13,7 @@ use tantivy::{doc, IndexWriter}; use weaver_schema::attribute::Attribute; /// Build index for semantic convention attributes. +#[cfg(not(tarpaulin_include))] pub fn index_semconv_attributes<'a>( attributes: impl Iterator, path: &str, @@ -32,6 +33,7 @@ pub fn index_semconv_attributes<'a>( } /// Build index for schema attributes. +#[cfg(not(tarpaulin_include))] pub fn index_schema_attribute<'a>( attributes: impl Iterator, path: &str, @@ -67,6 +69,7 @@ pub fn index_schema_attribute<'a>( } /// Render an attribute details. +#[cfg(not(tarpaulin_include))] pub fn widget<'a>( attribute: Option<&'a Attribute>, provenance: &'a str, diff --git a/src/search/schema/attributes.rs b/src/search/schema/attributes.rs index dfbcc4d3..045b5752 100644 --- a/src/search/schema/attributes.rs +++ b/src/search/schema/attributes.rs @@ -9,6 +9,7 @@ use weaver_schema::attribute::Attribute; use weaver_semconv::attribute::{BasicRequirementLevelSpec, RequirementLevel}; /// Append attributes to the text. +#[cfg(not(tarpaulin_include))] pub fn append_lines(attributes: &[Attribute], text: &mut Vec>, theme: &ThemeConfig) { if !attributes.is_empty() { text.push(Line::from(Span::styled( diff --git a/src/search/schema/event.rs b/src/search/schema/event.rs index 72a50c17..4b964d4f 100644 --- a/src/search/schema/event.rs +++ b/src/search/schema/event.rs @@ -12,6 +12,7 @@ use tantivy::{doc, IndexWriter}; use weaver_schema::TelemetrySchema; /// Build index for events. +#[cfg(not(tarpaulin_include))] pub fn index(schema: &TelemetrySchema, fields: &DocFields, index_writer: &mut IndexWriter) { for event in schema.events() { let tags: String = event.tags.clone().map_or("".to_owned(), |tags| { @@ -39,6 +40,7 @@ pub fn index(schema: &TelemetrySchema, fields: &DocFields, index_writer: &mut In } /// Render a span details. +#[cfg(not(tarpaulin_include))] pub fn widget<'a>( event: Option<&'a weaver_schema::event::Event>, provenance: &'a str, diff --git a/src/search/schema/metric.rs b/src/search/schema/metric.rs index e61feff6..b114669f 100644 --- a/src/search/schema/metric.rs +++ b/src/search/schema/metric.rs @@ -15,6 +15,7 @@ use crate::search::theme::ThemeConfig; use crate::search::DocFields; /// Build index for semantic convention metrics. +#[cfg(not(tarpaulin_include))] pub fn index_semconv_metrics<'a>( metrics: impl Iterator, path: &str, @@ -34,6 +35,7 @@ pub fn index_semconv_metrics<'a>( } /// Build index for schema metrics. +#[cfg(not(tarpaulin_include))] pub fn index_schema_metrics( schema: &TelemetrySchema, fields: &DocFields, @@ -67,6 +69,7 @@ pub fn index_schema_metrics( } /// Render a metric details. +#[cfg(not(tarpaulin_include))] pub fn widget<'a>( metric: Option<&'a UnivariateMetric>, provenance: &'a str, diff --git a/src/search/schema/metric_group.rs b/src/search/schema/metric_group.rs index dec7a528..35956f4d 100644 --- a/src/search/schema/metric_group.rs +++ b/src/search/schema/metric_group.rs @@ -15,6 +15,7 @@ use crate::search::theme::ThemeConfig; use crate::search::DocFields; /// Build index for metrics. +#[cfg(not(tarpaulin_include))] pub fn index(schema: &TelemetrySchema, fields: &DocFields, index_writer: &mut IndexWriter) { for metric_group in schema.metric_groups() { let tags: String = metric_group.tags().map_or("".to_owned(), |tags| { @@ -36,6 +37,7 @@ pub fn index(schema: &TelemetrySchema, fields: &DocFields, index_writer: &mut In } /// Render a metric details. +#[cfg(not(tarpaulin_include))] pub fn widget<'a>( metric_group: Option<&'a MetricGroup>, provenance: &'a str, diff --git a/src/search/schema/resource.rs b/src/search/schema/resource.rs index 1234ed9d..936d94e7 100644 --- a/src/search/schema/resource.rs +++ b/src/search/schema/resource.rs @@ -8,6 +8,7 @@ use weaver_schema::attribute::Attribute; use weaver_schema::TelemetrySchema; /// Build index for resources. +#[cfg(not(tarpaulin_include))] pub fn index(schema: &TelemetrySchema, fields: &DocFields, index_writer: &mut IndexWriter) { if let Some(resource) = schema.resource() { for attr in resource.attributes() { diff --git a/src/search/schema/span.rs b/src/search/schema/span.rs index a8c5974b..36c2765f 100644 --- a/src/search/schema/span.rs +++ b/src/search/schema/span.rs @@ -12,6 +12,7 @@ use tantivy::{doc, IndexWriter}; use weaver_schema::TelemetrySchema; /// Build index for spans. +#[cfg(not(tarpaulin_include))] pub fn index(schema: &TelemetrySchema, fields: &DocFields, index_writer: &mut IndexWriter) { for span in schema.spans() { let tags: String = span.tags.clone().map_or("".to_owned(), |tags| { @@ -62,6 +63,7 @@ pub fn index(schema: &TelemetrySchema, fields: &DocFields, index_writer: &mut In } /// Render a span details. +#[cfg(not(tarpaulin_include))] pub fn widget<'a>( span: Option<&'a weaver_schema::span::Span>, provenance: &'a str, diff --git a/src/search/schema/tags.rs b/src/search/schema/tags.rs index 16bea4ab..94fa45b7 100644 --- a/src/search/schema/tags.rs +++ b/src/search/schema/tags.rs @@ -7,6 +7,7 @@ use ratatui::prelude::{Line, Span, Style}; use weaver_schema::tags::Tags; /// Append tags to the text. +#[cfg(not(tarpaulin_include))] pub fn append_lines<'a>(tags: Option<&'a Tags>, text: &mut Vec>, theme: &'a ThemeConfig) { if let Some(tags) = tags { if tags.is_empty() { diff --git a/src/search/semconv/attribute.rs b/src/search/semconv/attribute.rs index 1ed48687..f6677e77 100644 --- a/src/search/semconv/attribute.rs +++ b/src/search/semconv/attribute.rs @@ -11,6 +11,7 @@ use weaver_semconv::AttributeSpecWithProvenance; use crate::search::semconv::examples; +#[cfg(not(tarpaulin_include))] pub fn widget<'a>( attribute: Option<&'a AttributeSpecWithProvenance>, theme: &'a ThemeConfig, diff --git a/src/search/semconv/attributes.rs b/src/search/semconv/attributes.rs index 26b60e88..b6c59e52 100644 --- a/src/search/semconv/attributes.rs +++ b/src/search/semconv/attributes.rs @@ -8,6 +8,7 @@ use ratatui::text::{Line, Span}; use weaver_semconv::attribute::{AttributeSpec, BasicRequirementLevelSpec, RequirementLevel}; /// Append attributes to the text. +#[cfg(not(tarpaulin_include))] pub fn append_lines(attributes: &[AttributeSpec], text: &mut Vec>, theme: &ThemeConfig) { if !attributes.is_empty() { text.push(Line::from(Span::styled( diff --git a/src/search/semconv/examples.rs b/src/search/semconv/examples.rs index 9e55487a..d204992e 100644 --- a/src/search/semconv/examples.rs +++ b/src/search/semconv/examples.rs @@ -7,6 +7,7 @@ use ratatui::prelude::{Line, Span, Style}; use weaver_semconv::attribute::Examples; /// Append examples to the text. +#[cfg(not(tarpaulin_include))] pub fn append_lines(examples: &Examples, text: &mut Vec>, theme: &ThemeConfig) { text.push(Line::from(Span::styled( "Examples: ", diff --git a/src/search/semconv/metric.rs b/src/search/semconv/metric.rs index bdc2d4cf..94f71b66 100644 --- a/src/search/semconv/metric.rs +++ b/src/search/semconv/metric.rs @@ -10,6 +10,7 @@ use weaver_semconv::MetricSpecWithProvenance; use crate::search::semconv::attributes; +#[cfg(not(tarpaulin_include))] pub fn widget<'a>( metric: Option<&'a MetricSpecWithProvenance>, theme: &'a ThemeConfig, From efbfae5a106ff1f9e125140fc236ba333489830d Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Mon, 1 Apr 2024 21:37:10 -0700 Subject: [PATCH 20/22] chore(changelog): update CHANGELOG.md --- CHANGELOG.md | 15 ++- Cargo.lock | 16 +-- docs/images/dependencies.svg | 252 ++++++++++++++++++++--------------- 3 files changed, 168 insertions(+), 115 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f784b4de..3db0af6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,18 @@ All notable changes to this project will be documented in this file. ### โš™๏ธ Miscellaneous Tasks +- *(coverage)* Improve test coverage +- *(coverage)* Remove xtask and main command line from the code coverage +- *(coverage)* Apply `tarpaulin` coverage to the entire workspace +- *(install)* Add `cargo tarpaulin` in the list of tools to install +- *(build)* Trigger ci.yml workflow for all push and pull request +- *(coverage)* Add test code coverage with cargo tarpaulin +- *(clippy)* Add more clippy lints +- *(clippy)* Fix more clippy issues +- *(clippy)* Fix explicit_into_iter_loop clippy issue +- *(git)* Make the output dir invisible for git +- *(changelog)* Add git cliff configuration +- *(code)* Make error enums non-exhaustive - *(code)* Implement #54 - *(code)* Fix str_to_string clippy lint issues - *(code)* Implement #54 + new clippy lint rule @@ -85,5 +97,4 @@ All notable changes to this project will be documented in this file. - *(build)* Remove macos target for the build (API rate limit reached, we need to figure out that later). - Add cargo lock file. - *(dep)* Bump dependency versions -- Migrate f5/otel-weaver repo to open-telemetry/weaver repo - +- Migrate f5/otel-weaver repo to open-telemetry/weaver repo \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 6f65f5fb..35c0f87a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2349,9 +2349,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" +checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" dependencies = [ "memchr", "thiserror", @@ -2360,9 +2360,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d24f72393fd16ab6ac5738bc33cdb6a9aa73f8b902e8fe29cf4e67d7dd1026" +checksum = "f73541b156d32197eecda1a4014d7f868fd2bcb3c550d5386087cfba442bf69c" dependencies = [ "pest", "pest_generator", @@ -2370,9 +2370,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc17e2a6c7d0a492f0158d7a4bd66cc17280308bbaff78d5bef566dca35ab80" +checksum = "c35eeed0a3fab112f75165fdc026b3913f4183133f19b49be773ac9ea966e8bd" dependencies = [ "pest", "pest_meta", @@ -2383,9 +2383,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.8" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934cd7631c050f4674352a6e835d5f6711ffbfb9345c2fc0107155ac495ae293" +checksum = "2adbf29bb9776f28caece835398781ab24435585fe0d4dc1374a61db5accedca" dependencies = [ "once_cell", "pest", diff --git a/docs/images/dependencies.svg b/docs/images/dependencies.svg index 3c9db8eb..48f6c1b2 100644 --- a/docs/images/dependencies.svg +++ b/docs/images/dependencies.svg @@ -4,231 +4,273 @@ - + - + 0 - -weaver_cache + +weaver_cache 1 - -weaver_forge + +weaver_forge 2 - -weaver_logger + +weaver_logger 1->2 - - + + 3 - -weaver_resolved_schema + +weaver_resolved_schema 1->3 - - + + 4 - -weaver_semconv + +weaver_semconv 1->4 - - + + 6 - -weaver_resolver + +weaver_resolver 1->6 - - + + 3->4 - - + + 5 - -weaver_version + +weaver_version 3->5 - - + + 6->0 - - + + 6->2 - - + + 6->3 - - + + 6->4 - - + + 6->5 - - + + 7 - -weaver_schema + +weaver_schema 6->7 - - + + 7->4 - - + + 7->5 - - + + 8 - -weaver_template + +weaver_semconv_gen 8->0 - - + + 8->2 - - + + - + -8->6 - - +8->3 + + + + + +8->4 + + - + -8->7 - - +8->6 + + 9 - -xtask + +weaver_template - - -10 - -weaver - - - -10->0 - - - - + -10->1 - - +9->0 + + - + -10->2 - - +9->2 + + - + -10->3 - - - - - -10->4 - - +9->6 + + - + -10->6 - - +9->7 + + + + + +10 + +xtask + + + +11 + +weaver - + -10->7 - - +11->0 + + + + + +11->1 + + - + -10->8 - - +11->2 + + + + + +11->3 + + + + + +11->4 + + + + + +11->6 + + + + + +11->7 + + + + + +11->8 + + + + + +11->9 + + From 634bb263bac9bcbd12bc4e9811ab0dc07fde1143 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Tue, 2 Apr 2024 08:24:16 -0700 Subject: [PATCH 21/22] ci(coverage): publish code coverage results on Codecov --- .github/codecov.yaml | 16 ++++++++++++++++ .github/workflows/ci.yml | 7 ++++++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 .github/codecov.yaml diff --git a/.github/codecov.yaml b/.github/codecov.yaml new file mode 100644 index 00000000..f39c5bbe --- /dev/null +++ b/.github/codecov.yaml @@ -0,0 +1,16 @@ +codecov: + require_ci_to_pass: yes + +coverage: + precision: 1 + round: down + range: "60...100" + status: + project: + default: + target: auto + threshold: 0.5% + +ignore: + - "crates/xtask" # Part of the build system + - "src" # CLI (not tested yet) \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d64b62af..4e203a16 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -187,4 +187,9 @@ jobs: - name: Install cargo-tarpaulin run: cargo install cargo-tarpaulin - name: Gather coverage - run: cargo tarpaulin --workspace --output-dir coverage --out lcov -e xtask -e weaver \ No newline at end of file + run: cargo tarpaulin --workspace --output-dir coverage --out lcov -e xtask -e weaver + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v4.0.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + slug: open-telemetry/weaver \ No newline at end of file From 3af97afd72b1a2f9b232eb4e3d2b8e3f1f9333a4 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Tue, 2 Apr 2024 16:31:10 -0700 Subject: [PATCH 22/22] ci: follow the same naming convention for all the jobs Jobs starts with capital letter. Jobs doesn't contain version numbers that could change in the future in order to make ci controls more robust. --- .github/workflows/ci.yml | 7 +------ Cargo.lock | 6 +++--- crates/weaver_semconv_gen/Cargo.toml | 7 +------ 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e203a16..dfdf0216 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,11 +4,6 @@ permissions: contents: read on: [push, pull_request] -#on: -# pull_request: -# push: -# branches: -# - main env: RUST_BACKTRACE: 1 @@ -55,7 +50,7 @@ jobs: - name: No-default features run: cargo test --workspace --no-default-features msrv: - name: "Check MSRV: 1.70.0" + name: Check MSRV runs-on: ubuntu-latest steps: - name: Checkout repository diff --git a/Cargo.lock b/Cargo.lock index 35c0f87a..084e20b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,7 +337,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.0", + "strsim 0.11.1", ] [[package]] @@ -3130,9 +3130,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" diff --git a/crates/weaver_semconv_gen/Cargo.toml b/crates/weaver_semconv_gen/Cargo.toml index 0ac18188..4015213b 100644 --- a/crates/weaver_semconv_gen/Cargo.toml +++ b/crates/weaver_semconv_gen/Cargo.toml @@ -19,11 +19,6 @@ similar = "2.5.0" nom = "7.1.3" thiserror.workspace = true -#serde.workspace = true -#serde_yaml.workspace = true -#serde_json.workspace = true -#rayon.workspace = true -#walkdir.workspace = true [lints] workspace = true @@ -32,4 +27,4 @@ workspace = true # force cargo machete to ignore the following crates # remove this section once this crate is integrated into the rest # of the project -ignored = ["serde", "rayon", "walkdir", "serde_json", "serde_yaml"] +ignored = []