From ade29bbecd132f96eb66c55a79b0062b7f342555 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Thu, 15 Feb 2024 17:55:20 -0800 Subject: [PATCH 1/3] feat(registry): add `weaver check registry` command --- src/check/mod.rs | 49 +++++++++++++++++++++++++++++++++++++++++++ src/check/registry.rs | 41 ++++++++++++++++++++++++++++++++++++ src/cli.rs | 3 +++ src/main.rs | 4 ++++ 4 files changed, 97 insertions(+) create mode 100644 src/check/mod.rs create mode 100644 src/check/registry.rs diff --git a/src/check/mod.rs b/src/check/mod.rs new file mode 100644 index 00000000..da378fd6 --- /dev/null +++ b/src/check/mod.rs @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! Command to check a semantic convention registry or a telemetry schema. + +mod registry; + +use clap::{Args, Subcommand}; +use weaver_cache::Cache; +use weaver_logger::Logger; + +/// Parameters for the `check` command +#[derive(Debug, Args)] +pub struct CheckCommand { + /// Define the sub-commands for the `check` command + #[clap(subcommand)] + pub command: CheckSubCommand, +} + +/// Sub-commands for the `check` command +#[derive(Debug, Subcommand)] +pub enum CheckSubCommand { + /// Check a semantic convention registry + Registry(CheckRegistry), + // ToDo - Add sub-commands for checking telemetry schemas +} + + +/// Parameters for the `check registry` sub-command +#[derive(Debug, Args)] +pub struct CheckRegistry { + /// Local path or Git URL of the semantic convention registry to check. + pub registry: String, + + /// Optional path in the Git repository where the semantic convention + /// registry is located + pub path: Option, +} + +/// Check a semantic convention registry or a telemetry schema. +pub fn command_check(log: impl Logger + Sync + Clone, command: &CheckCommand) { + let cache = Cache::try_new().unwrap_or_else(|e| { + log.error(&e.to_string()); + std::process::exit(1); + }); + + match &command.command { + CheckSubCommand::Registry(args) => registry::check_registry_command(log, &cache, args), + } +} diff --git a/src/check/registry.rs b/src/check/registry.rs new file mode 100644 index 00000000..b62e3420 --- /dev/null +++ b/src/check/registry.rs @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! Check a semantic convention registry. + +use weaver_cache::Cache; +use weaver_logger::Logger; +use weaver_resolver::attribute::AttributeCatalog; +use weaver_resolver::registry::resolve_semconv_registry; +use weaver_resolver::SchemaResolver; +use crate::check::CheckRegistry; + +/// Check a semantic convention registry. +pub(crate) fn check_registry_command( + log: impl Logger + Sync + Clone + Sized, + cache: &Cache, + registry_args: &CheckRegistry, +) { + log.loading(&format!("Checking registry `{}`", registry_args.registry)); + + // Load the semantic convention registry into a local cache. + // No parsing errors should be observed. + let semconv_specs = SchemaResolver::load_semconv_registry( + registry_args.registry.to_string(), + registry_args.path.clone(), + &cache, + log.clone(), + ) + .unwrap_or_else(|e| { + panic!("Failed to load and parse the semantic convention registry, error: {e}"); + }); + + // Resolve the semantic convention registry. + let mut attr_catalog = AttributeCatalog::default(); + let _ = + resolve_semconv_registry(&mut attr_catalog, ®istry_args.registry, &semconv_specs) + .unwrap_or_else(|e| { + panic!("Failed to resolve the semantic convention registry, error: {e}"); + }); + + log.success(&format!("Registry `{}` checked successfully", registry_args.registry)); +} diff --git a/src/cli.rs b/src/cli.rs index a84aac26..82a88232 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -7,6 +7,7 @@ use crate::languages::LanguagesParams; use crate::resolve::ResolveCommand; use crate::search::SearchCommand; use clap::{Parser, Subcommand}; +use crate::check::CheckCommand; /// Command line arguments. #[derive(Parser)] @@ -32,4 +33,6 @@ pub enum Commands { Languages(LanguagesParams), /// Search in a semantic convention registry or a telemetry schema Search(SearchCommand), + /// Check a semantic convention registry or a telemetry schema + Check(CheckCommand), } diff --git a/src/main.rs b/src/main.rs index e9883783..0dbd92c4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ mod gen_client; mod languages; mod resolve; mod search; +mod check; fn main() { let cli = Cli::parse(); @@ -29,6 +30,9 @@ fn main() { Some(Commands::Search(params)) => { search::command_search(log, params); } + Some(Commands::Check(params)) => { + check::command_check(log, params); + } None => {} } } From c9205a8c6bf78c6845ba507b2d3586cde7f777a2 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Thu, 15 Feb 2024 17:59:26 -0800 Subject: [PATCH 2/3] feat(registry): add `weaver check registry` command --- crates/weaver_resolver/src/registry.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/weaver_resolver/src/registry.rs b/crates/weaver_resolver/src/registry.rs index d66396d3..7f0bb8f0 100644 --- a/crates/weaver_resolver/src/registry.rs +++ b/crates/weaver_resolver/src/registry.rs @@ -63,7 +63,6 @@ pub struct UnresolvedGroup { /// /// This function returns the resolved registry or an error if the resolution process /// failed. -#[allow(dead_code)] // ToDo remove this once this function is called from the CLI. pub fn resolve_semconv_registry( attr_catalog: &mut AttributeCatalog, registry_url: &str, @@ -136,7 +135,6 @@ pub fn resolve_semconv_registry( /// /// This function returns an unresolved registry containing the semantic /// convention specifications. -#[allow(dead_code)] // ToDo remove this once this function is called from the CLI. fn unresolved_registry_from_specs( registry_url: &str, registry: &SemConvRegistry, From 31cc5980bb236ec01ae06234325d6c1bab6e92c5 Mon Sep 17 00:00:00 2001 From: Laurent Querel Date: Fri, 16 Feb 2024 17:55:37 -0800 Subject: [PATCH 3/3] feat(registry): refactor registry sub-commands. --- Cargo.lock | 76 +++++++------------ Cargo.toml | 14 ++-- README.md | 45 ++++++++--- crates/weaver_resolver/README.md | 32 +++++++- .../expected-registry.json | 2 +- .../expected-registry.json | 2 +- .../expected-registry.json | 2 +- .../expected-registry.json | 2 +- .../expected-registry.json | 2 +- .../expected-registry.json | 2 +- .../expected-registry.json | 2 +- crates/weaver_resolver/src/registry.rs | 11 +-- src/check/mod.rs | 49 ------------ src/cli.rs | 14 +++- src/main.rs | 17 ++++- src/{check/registry.rs => registry/check.rs} | 35 ++++++--- src/registry/generate.rs | 17 +++++ src/registry/mod.rs | 65 ++++++++++++++++ src/registry/resolve.rs | 22 ++++++ src/registry/search.rs | 20 +++++ src/registry/stats.rs | 54 +++++++++++++ 21 files changed, 336 insertions(+), 149 deletions(-) delete mode 100644 src/check/mod.rs rename src/{check/registry.rs => registry/check.rs} (55%) create mode 100644 src/registry/generate.rs create mode 100644 src/registry/mod.rs create mode 100644 src/registry/resolve.rs create mode 100644 src/registry/search.rs create mode 100644 src/registry/stats.rs diff --git a/Cargo.lock b/Cargo.lock index e48ff018..cbe24994 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -127,7 +127,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -209,9 +209,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f" [[package]] name = "byteorder" @@ -304,9 +304,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.0" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f" +checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" dependencies = [ "clap_builder", "clap_derive", @@ -314,9 +314,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.0" +version = "4.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99" +checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" dependencies = [ "anstream", "anstyle", @@ -333,7 +333,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -519,9 +519,9 @@ dependencies = [ [[package]] name = "deunicode" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae2a35373c5c74340b79ae6780b498b2b183915ec5dacf263aac5a099bf485a" +checksum = "b6e854126756c496b8c81dec88f9a706b15b875c5849d4097a3854476b9fdf94" [[package]] name = "digest" @@ -1125,7 +1125,7 @@ checksum = "d75e7ab728059f595f6ddc1ad8771b8d6a231971ae493d9d5948ecad366ee8bb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -1598,29 +1598,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "hoot" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df22a4d90f1b0e65fe3e0d6ee6a4608cc4d81f4b2eb3e670f44bb6bde711e452" -dependencies = [ - "httparse", - "log", -] - -[[package]] -name = "hootbin" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "354e60868e49ea1a39c44b9562ad207c4259dc6eabf9863bf3b0f058c55cfdb2" -dependencies = [ - "fastrand", - "hoot", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "htmlescape" version = "0.3.1" @@ -1996,7 +1973,7 @@ checksum = "afc95a651c82daf7004c824405aa1019723644950d488571bd718e3ed84646ed" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2119,9 +2096,9 @@ dependencies = [ [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] @@ -2263,7 +2240,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -2800,7 +2777,7 @@ checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3010,7 +2987,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3032,9 +3009,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" dependencies = [ "proc-macro2", "quote", @@ -3280,7 +3257,7 @@ checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3406,7 +3383,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] @@ -3595,13 +3572,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.9.5" +version = "2.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b52731d03d6bb2fd18289d4028aee361d6c28d44977846793b994b13cdcc64d" +checksum = "11f214ce18d8b2cbe84ed3aa6486ed3f5b285cf8d8fbdbce9f3f767a724adc35" dependencies = [ "base64", "flate2", - "hootbin", "log", "once_cell", "rustls 0.22.2", @@ -3745,7 +3721,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", "wasm-bindgen-shared", ] @@ -3779,7 +3755,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4154,7 +4130,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.49", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a73c9fd0..eebf0321 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,9 @@ name = "weaver" version = "0.1.0" authors = ["Laurent Querel "] edition = "2021" -repository = "https://github.com/f5/otel-weaver" -description = "OTel Weaver - A Schema-Driven Client SDK Generator for OpenTelemetry" -keywords = ["opentelemetry", "client", "schema", "arrow", "generator"] +repository = "https://github.com/open-telemetry/weaver" +description = "Manage semantic convention registry and telemetry schema workflows (OpenTelemetry Project)" +keywords = ["opentelemetry", "semconv", "schema", "registry", "generator"] categories = ["command-line-utilities"] license = "Apache-2.0" readme = "README.md" @@ -29,11 +29,15 @@ serde = { version = "1.0.196", features = ["derive"] } serde_yaml = "0.9.31" serde_json = "1.0.113" thiserror = "1.0.56" -ureq = "2.9.5" +ureq = "2.9.6" regex = "1.10.3" rayon = "1.8.1" ordered-float = { version = "4.2.0", features = ["serde"] } +# Features definition ========================================================= +[features] +experimental = [] + # Crate definitions =========================================================== [[bin]] bench = false @@ -49,7 +53,7 @@ weaver_semconv = { path = "crates/weaver_semconv" } weaver_schema = { path = "crates/weaver_schema" } weaver_cache = { path = "crates/weaver_cache" } -clap = { version = "4.5.0", features = ["derive"] } +clap = { version = "4.5.1", features = ["derive"] } crossterm = "0.27.0" ratatui = "0.26.1" tui-textarea = "0.4.0" diff --git a/README.md b/README.md index bbe5a76d..213ece0e 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,10 @@ OpenTelemetry Weaver is a CLI tool that enables users to: -- Search for and retrieve information from a semantic convention registry or a telemetry schema. -- Resolve a semantic convention registry or a telemetry schema. -- Generate a client SDK/API from a telemetry schema. +- Manage Semantic Convention Registries: check, generate, resolve, search, stats commands. +- Manage Telemetry Schemas: check, generate, resolve, search, stats commands. + +Note: Telemetry Schema commands are only available with the --features experimental flag. ## Install @@ -36,14 +37,13 @@ for debug mode or the `target/release` directory for release mode. ## Usage ``` +Manage semantic convention registry and telemetry schema workflows (OpenTelemetry Project) + Usage: weaver [OPTIONS] [COMMAND] Commands: - resolve Resolve a semantic convention registry or a telemetry schema - gen-client Generate a client SDK or client API - languages List all supported languages - search Search in a semantic convention registry or a telemetry schema - help Print this message or the help of the given subcommand(s) + registry Manage Semantic Convention Registry + help Print this message or the help of the given subcommand(s) Options: -d, --debug... Turn debugging information on @@ -51,7 +51,28 @@ Options: -V, --version Print version ``` -### Command `search` +### Command `registry` + +This command provides subcommands to manage semantic convention registries. + +``` +Manage Semantic Convention Registry + +Usage: weaver registry + +Commands: + check Validates a registry (i.e., parsing, resolution of references, extends clauses, and constraints) + generate Generates documentation or code for a registry (not yet implemented) + resolve Resolves a registry (not yet implemented) + search Searches a registry (not yet implemented) + stats Calculate and display a set of general statistics on a registry (not yet implemented) + help Print this message or the help of the given subcommand(s) + +Options: + -h, --help Print help +``` + +### Command `search` (Experimental) This command provides an interactive terminal UI, allowing users to search for attributes and metrics specified within a given semantic convention registry or @@ -74,7 +95,7 @@ This search engine leverages [Tantivy](https://github.com/quickwit-oss/tantivy) and supports a simple [search syntax](https://docs.rs/tantivy/latest/tantivy/query/struct.QueryParser.html) in the search bar. -### Command `resolve` +### Command `resolve` (Experimental) This command resolves a schema or a semantic convention registry (not yet implemented) and displays the result on the standard output. @@ -91,7 +112,7 @@ A "resolved schema" is one where: - All overrides have been applied. - This resolved schema is what the code generator and upcoming plugins utilize. -### Command `gen-client` +### Command `gen-client` (Experimental) This command generates a client SDK from a telemetry schema for a given language specified with the `--language` option. @@ -103,7 +124,7 @@ weaver gen-client --schema telemetry-schema.yaml --language go In the future, users will be able to specify the protocol to use for the generated client SDK (i.e. OTLP or OTel Arrow Protocol) and few others options. -### Command `languages` +### Command `languages` (Experimental) This command displays all the languages for which a client SDK/API can be generated. diff --git a/crates/weaver_resolver/README.md b/crates/weaver_resolver/README.md index 8f4e0433..2915a8cb 100644 --- a/crates/weaver_resolver/README.md +++ b/crates/weaver_resolver/README.md @@ -11,4 +11,34 @@ validate telemetry data, generate code, and perform other tasks. Important Note: Currently, 2 versions of the resolution process are present in the `weaver_resolver` crate. The first version of the resolution process is incomplete and still used by the `weaver` CLI. A second version is under active -development and is expected to replace the first version in the near future. \ No newline at end of file +development and is expected to replace the first version in the near future. + +## Semantic Conventions - Parsing, Resolution and Validation + +The parsing is implemented using the serde library. A collection of +serde-annotated Rust structures is used to represent semantic convention +entities. Optional fields are represented as `Option` types. + +The attribute macro `#[serde(deny_unknown_fields)]` is used to ensure that +unknown fields are not allowed in the semantic convention entities. This, +combined with the distinction between optional and required fields in the +entities, ensures that the semantic conventions are validated in terms of +structure during the parsing process. + +The resolution process for semantic conventions is a multistep process that +involves the following steps: +- Load all semantic conventions from the registry +- Resolve iteratively all semantic conventions. This involves the maintenance + of an unresolved semantic convention list and a resolved semantic convention + list. The resolution process involves the following steps: + - Resolve iteratively all attributes `ref` until no more resolvable `ref` are + found. + - Resolve iteratively all `extends` parent/child clauses until no more + resolvable `extends` are found. The extended entity inherits prefix, + attributes, and constraints from the parent entity. +- Apply constraints `any_of` and `include` (not yet supported). +- Validate the resolved semantic conventions + - No more unresolved `ref` or `extends` clauses. The unresolved list should + be empty. + - All constraints satisfied. + diff --git a/crates/weaver_resolver/data/registry-test-1-single-attr-ref/expected-registry.json b/crates/weaver_resolver/data/registry-test-1-single-attr-ref/expected-registry.json index 49eb396a..49c7f92f 100644 --- a/crates/weaver_resolver/data/registry-test-1-single-attr-ref/expected-registry.json +++ b/crates/weaver_resolver/data/registry-test-1-single-attr-ref/expected-registry.json @@ -1,5 +1,5 @@ { - "registry_url": "https://semconv-registry.com", + "registry_url": "https://127.0.0.1", "groups": [ { "id": "metric.messaging.attributes", diff --git a/crates/weaver_resolver/data/registry-test-2-multi-attr-refs/expected-registry.json b/crates/weaver_resolver/data/registry-test-2-multi-attr-refs/expected-registry.json index 985316ee..2df81272 100644 --- a/crates/weaver_resolver/data/registry-test-2-multi-attr-refs/expected-registry.json +++ b/crates/weaver_resolver/data/registry-test-2-multi-attr-refs/expected-registry.json @@ -1,5 +1,5 @@ { - "registry_url": "https://semconv-registry.com", + "registry_url": "https://127.0.0.1", "groups": [ { "id": "metric.messaging.attributes", diff --git a/crates/weaver_resolver/data/registry-test-3-extends/expected-registry.json b/crates/weaver_resolver/data/registry-test-3-extends/expected-registry.json index 53995344..9c89edf4 100644 --- a/crates/weaver_resolver/data/registry-test-3-extends/expected-registry.json +++ b/crates/weaver_resolver/data/registry-test-3-extends/expected-registry.json @@ -1,5 +1,5 @@ { - "registry_url": "https://semconv-registry.com", + "registry_url": "https://127.0.0.1", "groups": [ { "id": "attributes.http.common", diff --git a/crates/weaver_resolver/data/registry-test-4-events/expected-registry.json b/crates/weaver_resolver/data/registry-test-4-events/expected-registry.json index ea6b9471..05105035 100644 --- a/crates/weaver_resolver/data/registry-test-4-events/expected-registry.json +++ b/crates/weaver_resolver/data/registry-test-4-events/expected-registry.json @@ -1,5 +1,5 @@ { - "registry_url": "https://semconv-registry.com", + "registry_url": "https://127.0.0.1", "groups": [ { "id": "log-feature_flag", diff --git a/crates/weaver_resolver/data/registry-test-5-metrics/expected-registry.json b/crates/weaver_resolver/data/registry-test-5-metrics/expected-registry.json index cf24712d..8d280565 100644 --- a/crates/weaver_resolver/data/registry-test-5-metrics/expected-registry.json +++ b/crates/weaver_resolver/data/registry-test-5-metrics/expected-registry.json @@ -1,5 +1,5 @@ { - "registry_url": "https://semconv-registry.com", + "registry_url": "https://127.0.0.1", "groups": [ { "id": "attributes.faas.common", diff --git a/crates/weaver_resolver/data/registry-test-6-resources/expected-registry.json b/crates/weaver_resolver/data/registry-test-6-resources/expected-registry.json index e23561f4..dc1d9fe9 100644 --- a/crates/weaver_resolver/data/registry-test-6-resources/expected-registry.json +++ b/crates/weaver_resolver/data/registry-test-6-resources/expected-registry.json @@ -1,5 +1,5 @@ { - "registry_url": "https://semconv-registry.com", + "registry_url": "https://127.0.0.1", "groups": [ { "id": "registry.user_agent", diff --git a/crates/weaver_resolver/data/registry-test-7-spans/expected-registry.json b/crates/weaver_resolver/data/registry-test-7-spans/expected-registry.json index ac588fb7..1220d563 100644 --- a/crates/weaver_resolver/data/registry-test-7-spans/expected-registry.json +++ b/crates/weaver_resolver/data/registry-test-7-spans/expected-registry.json @@ -1,5 +1,5 @@ { - "registry_url": "https://semconv-registry.com", + "registry_url": "https://127.0.0.1", "groups": [ { "id": "registry.db", diff --git a/crates/weaver_resolver/src/registry.rs b/crates/weaver_resolver/src/registry.rs index 7f0bb8f0..016cb1ce 100644 --- a/crates/weaver_resolver/src/registry.rs +++ b/crates/weaver_resolver/src/registry.rs @@ -374,12 +374,9 @@ mod tests { } let mut attr_catalog = AttributeCatalog::default(); - let observed_registry = resolve_semconv_registry( - &mut attr_catalog, - "https://semconv-registry.com", - &sc_specs, - ) - .expect("Failed to resolve registry"); + let observed_registry = + resolve_semconv_registry(&mut attr_catalog, "https://127.0.0.1", &sc_specs) + .expect("Failed to resolve registry"); // Load the expected registry and attribute catalog. let expected_attr_catalog: Vec = serde_json::from_reader( @@ -422,5 +419,3 @@ mod tests { } } } - -// ToDo Remove #[allow(dead_code)] once the corresponding functions are called from the CLI. diff --git a/src/check/mod.rs b/src/check/mod.rs deleted file mode 100644 index da378fd6..00000000 --- a/src/check/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -//! Command to check a semantic convention registry or a telemetry schema. - -mod registry; - -use clap::{Args, Subcommand}; -use weaver_cache::Cache; -use weaver_logger::Logger; - -/// Parameters for the `check` command -#[derive(Debug, Args)] -pub struct CheckCommand { - /// Define the sub-commands for the `check` command - #[clap(subcommand)] - pub command: CheckSubCommand, -} - -/// Sub-commands for the `check` command -#[derive(Debug, Subcommand)] -pub enum CheckSubCommand { - /// Check a semantic convention registry - Registry(CheckRegistry), - // ToDo - Add sub-commands for checking telemetry schemas -} - - -/// Parameters for the `check registry` sub-command -#[derive(Debug, Args)] -pub struct CheckRegistry { - /// Local path or Git URL of the semantic convention registry to check. - pub registry: String, - - /// Optional path in the Git repository where the semantic convention - /// registry is located - pub path: Option, -} - -/// Check a semantic convention registry or a telemetry schema. -pub fn command_check(log: impl Logger + Sync + Clone, command: &CheckCommand) { - let cache = Cache::try_new().unwrap_or_else(|e| { - log.error(&e.to_string()); - std::process::exit(1); - }); - - match &command.command { - CheckSubCommand::Registry(args) => registry::check_registry_command(log, &cache, args), - } -} diff --git a/src/cli.rs b/src/cli.rs index 82a88232..40d8cd79 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -2,12 +2,16 @@ //! Manage command line arguments +#[cfg(feature = "experimental")] use crate::gen_client::GenClientCommand; +#[cfg(feature = "experimental")] use crate::languages::LanguagesParams; +use crate::registry::RegistryCommand; +#[cfg(feature = "experimental")] use crate::resolve::ResolveCommand; +#[cfg(feature = "experimental")] use crate::search::SearchCommand; use clap::{Parser, Subcommand}; -use crate::check::CheckCommand; /// Command line arguments. #[derive(Parser)] @@ -26,13 +30,17 @@ pub struct Cli { #[derive(Subcommand)] pub enum Commands { /// Resolve a semantic convention registry or a telemetry schema + #[cfg(feature = "experimental")] Resolve(ResolveCommand), /// Generate a client SDK or client API + #[cfg(feature = "experimental")] GenClient(GenClientCommand), /// List all supported languages + #[cfg(feature = "experimental")] Languages(LanguagesParams), /// Search in a semantic convention registry or a telemetry schema + #[cfg(feature = "experimental")] Search(SearchCommand), - /// Check a semantic convention registry or a telemetry schema - Check(CheckCommand), + /// Manage Semantic Convention Registry + Registry(RegistryCommand), } diff --git a/src/main.rs b/src/main.rs index 0dbd92c4..cae45e63 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,37 +1,48 @@ use clap::Parser; +use registry::semconv_registry; use weaver_logger::ConsoleLogger; use crate::cli::{Cli, Commands}; +#[cfg(feature = "experimental")] use crate::gen_client::command_gen_client; +#[cfg(feature = "experimental")] use crate::resolve::command_resolve; mod cli; +#[cfg(feature = "experimental")] mod gen_client; +#[cfg(feature = "experimental")] mod languages; +mod registry; +#[cfg(feature = "experimental")] mod resolve; +#[cfg(feature = "experimental")] mod search; -mod check; fn main() { let cli = Cli::parse(); let log = ConsoleLogger::new(cli.debug); match &cli.command { + #[cfg(feature = "experimental")] Some(Commands::Resolve(params)) => { command_resolve(log, params); } + #[cfg(feature = "experimental")] Some(Commands::GenClient(params)) => { command_gen_client(log, params); } + #[cfg(feature = "experimental")] Some(Commands::Languages(params)) => { languages::command_languages(log, params); } + #[cfg(feature = "experimental")] Some(Commands::Search(params)) => { search::command_search(log, params); } - Some(Commands::Check(params)) => { - check::command_check(log, params); + Some(Commands::Registry(params)) => { + semconv_registry(log, params); } None => {} } diff --git a/src/check/registry.rs b/src/registry/check.rs similarity index 55% rename from src/check/registry.rs rename to src/registry/check.rs index b62e3420..d2f84fd4 100644 --- a/src/check/registry.rs +++ b/src/registry/check.rs @@ -2,12 +2,23 @@ //! Check a semantic convention registry. +use clap::Args; use weaver_cache::Cache; use weaver_logger::Logger; use weaver_resolver::attribute::AttributeCatalog; use weaver_resolver::registry::resolve_semconv_registry; use weaver_resolver::SchemaResolver; -use crate::check::CheckRegistry; + +/// Parameters for the `registry check` sub-command +#[derive(Debug, Args)] +pub struct CheckRegistry { + /// Local path or Git URL of the semantic convention registry to check. + pub registry: String, + + /// Optional path in the Git repository where the semantic convention + /// registry is located + pub path: Option, +} /// Check a semantic convention registry. pub(crate) fn check_registry_command( @@ -22,20 +33,22 @@ pub(crate) fn check_registry_command( let semconv_specs = SchemaResolver::load_semconv_registry( registry_args.registry.to_string(), registry_args.path.clone(), - &cache, + cache, log.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 mut attr_catalog = AttributeCatalog::default(); - let _ = - resolve_semconv_registry(&mut attr_catalog, ®istry_args.registry, &semconv_specs) - .unwrap_or_else(|e| { - panic!("Failed to resolve the semantic convention registry, error: {e}"); - }); + let _ = resolve_semconv_registry(&mut attr_catalog, ®istry_args.registry, &semconv_specs) + .unwrap_or_else(|e| { + panic!("Failed to resolve the semantic convention registry, error: {e}"); + }); - log.success(&format!("Registry `{}` checked successfully", registry_args.registry)); + log.success(&format!( + "Registry `{}` checked successfully", + registry_args.registry + )); } diff --git a/src/registry/generate.rs b/src/registry/generate.rs new file mode 100644 index 00000000..c19ca3f0 --- /dev/null +++ b/src/registry/generate.rs @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! Generate artifacts for a semantic convention registry. + +use clap::Args; + +/// Parameters for the `registry generate` sub-command +#[derive(Debug, Args)] +pub struct GenerateRegistry { + /// Registry to resolve + pub registry: String, + + /// Optional path in the git repository where the semantic convention + /// registry is located + pub path: Option, + // ToDo root template directory used to generate the artifacts +} diff --git a/src/registry/mod.rs b/src/registry/mod.rs new file mode 100644 index 00000000..e27fa489 --- /dev/null +++ b/src/registry/mod.rs @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! Commands to manage a semantic convention registry. + +use clap::{Args, Subcommand}; + +use crate::registry::generate::GenerateRegistry; +use crate::registry::resolve::ResolveRegistry; +use crate::registry::search::SearchRegistry; +use check::CheckRegistry; +use weaver_cache::Cache; +use weaver_logger::Logger; + +use crate::registry::stats::StatsRegistry; + +mod check; +mod generate; +mod resolve; +mod search; +mod stats; + +/// Parameters for the `registry` command +#[derive(Debug, Args)] +pub struct RegistryCommand { + /// Define the sub-commands for the `registry` command + #[clap(subcommand)] + pub command: RegistrySubCommand, +} + +/// Sub-commands to manage a `registry`. +#[derive(Debug, Subcommand)] +pub enum RegistrySubCommand { + /// Validates a registry (i.e., parsing, resolution of references, extends clauses, and constraints). + Check(CheckRegistry), + /// Generates documentation or code for a registry (not yet implemented). + Generate(GenerateRegistry), + /// Resolves a registry (not yet implemented). + Resolve(ResolveRegistry), + /// Searches a registry (not yet implemented). + Search(SearchRegistry), + /// Calculate and display a set of general statistics on a registry (not yet implemented). + Stats(StatsRegistry), +} + +/// Manage a semantic convention registry. +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()); + std::process::exit(1); + }); + + match &command.command { + RegistrySubCommand::Check(args) => check::check_registry_command(log, &cache, args), + RegistrySubCommand::Generate(_) => { + unimplemented!() + } + RegistrySubCommand::Stats(args) => stats::stats_registry_command(log, &cache, args), + RegistrySubCommand::Resolve(_) => { + unimplemented!() + } + RegistrySubCommand::Search(_) => { + unimplemented!() + } + } +} diff --git a/src/registry/resolve.rs b/src/registry/resolve.rs new file mode 100644 index 00000000..f555fa7e --- /dev/null +++ b/src/registry/resolve.rs @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! Resolve a semantic convention registry. + +use clap::Args; +use std::path::PathBuf; + +/// Parameters for the `registry resolve` sub-command +#[derive(Debug, Args)] +pub struct ResolveRegistry { + /// Registry to resolve + pub registry: String, + + /// Optional path in the git repository where the semantic convention + /// registry is located + pub path: Option, + + /// Output file to write the resolved schema to + /// If not specified, the resolved schema is printed to stdout + #[arg(short, long)] + pub output: Option, +} diff --git a/src/registry/search.rs b/src/registry/search.rs new file mode 100644 index 00000000..a662e186 --- /dev/null +++ b/src/registry/search.rs @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! Search a semantic convention registry. + +use clap::Args; + +/// Parameters for the `registry search` sub-command +#[derive(Debug, Args)] +pub struct SearchRegistry { + /// Git URL of the semantic convention registry + pub registry: String, + + /// Optional path in the git repository where the semantic convention + /// registry is located + pub path: Option, + + /// The telemetry schema containing the versions (url or file) + #[arg(short, long)] + schema: Option, +} diff --git a/src/registry/stats.rs b/src/registry/stats.rs new file mode 100644 index 00000000..c8e15705 --- /dev/null +++ b/src/registry/stats.rs @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0 + +//! Compute stats on a semantic convention registry. + +use clap::Args; +use weaver_cache::Cache; +use weaver_logger::Logger; +use weaver_resolver::attribute::AttributeCatalog; +use weaver_resolver::registry::resolve_semconv_registry; +use weaver_resolver::SchemaResolver; + +/// Parameters for the `registry stats` sub-command +#[derive(Debug, Args)] +pub struct StatsRegistry { + /// Local path or Git URL of the semantic convention registry. + pub registry: String, + + /// Optional path in the Git repository where the semantic convention + /// registry is located + pub path: Option, +} + +/// Compute stats on a semantic convention registry. +pub(crate) fn stats_registry_command( + log: impl Logger + Sync + Clone + Sized, + cache: &Cache, + registry_args: &StatsRegistry, +) { + log.loading(&format!( + "Compute statistics on the registry `{}`", + registry_args.registry + )); + + // Load the semantic convention registry into a local cache. + // No parsing errors should be observed. + let semconv_specs = SchemaResolver::load_semconv_registry( + registry_args.registry.to_string(), + registry_args.path.clone(), + cache, + log.clone(), + ) + .unwrap_or_else(|e| { + panic!("Failed to load and parse the semantic convention registry, error: {e}"); + }); + + // Resolve the semantic convention registry. + let mut attr_catalog = AttributeCatalog::default(); + let _ = resolve_semconv_registry(&mut attr_catalog, ®istry_args.registry, &semconv_specs) + .unwrap_or_else(|e| { + panic!("Failed to resolve the semantic convention registry, error: {e}"); + }); + + // ToDo display statistics +}