Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Code Generation with Weaver - Example of Code Generation for SemConv Attribute Registry and SemConv Metrics #136

Merged
merged 47 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
328a89f
feat(codegen): create an example of codegen for SemConv Rust
lquerel Apr 26, 2024
d430eb6
feat(codegen): create lib.rs and one rs file per group prefix
lquerel Apr 26, 2024
35959a7
feat(codegen): remove old tera templates
lquerel Apr 26, 2024
618b8d2
feat(codegen): add support for semconv_experimental feature
lquerel Apr 26, 2024
db4dec4
chore: bump minijinja version to 1.0.21
lquerel Apr 27, 2024
d404191
chore: Fix fmt and clippy issues
lquerel Apr 27, 2024
628d46e
feat(forge): Add type_mapping filter
lquerel Apr 28, 2024
65c2464
doc(forge): Update documentation
lquerel Apr 28, 2024
7d26226
chore(forge): Improve test coverage
lquerel Apr 28, 2024
c821e55
feat(forge): Improve SemConv codegen example for Rust
lquerel Apr 29, 2024
00e11d2
chore(forge): Add mini registry and prepare for unit tests
lquerel Apr 29, 2024
37acc4b
chore(forge): Simplify mini_registry
lquerel Apr 29, 2024
074fe69
doc(forge): Add documentation on the JQ filter.
lquerel Apr 29, 2024
f930e80
chore(forge): Fix clippy issue
lquerel Apr 30, 2024
d65680c
Merge branch 'main' into example-codegen-semconv-rust
lquerel Apr 30, 2024
30876fc
chore(forge): Add experimental and deprecated attributes in the gener…
lquerel Apr 30, 2024
9483d63
feat(forge): Add enum string representation support.
lquerel Apr 30, 2024
e2e2df1
feat(forge): Use attribute registry namespace instead of group prefix.
lquerel Apr 30, 2024
8f6826b
feat(forge): Generate metrics and attributes
lquerel May 1, 2024
48403fc
feat(forge): Generate type-safe API for metrics
lquerel May 2, 2024
5fc3248
Merge branch 'main' into example-codegen-semconv-rust
lquerel May 2, 2024
ecbd76d
feat(forge): Separate required from optional attributes in the genera…
lquerel May 2, 2024
34db6ad
feat(forge): Improve metrics type-safe API
lquerel May 3, 2024
405331f
Merge branch 'main' into example-codegen-semconv-rust
lquerel May 3, 2024
581c08c
feat(forge): Add support for Counter and Gauge
lquerel May 3, 2024
0832fb2
feat(forge): Update generated code
lquerel May 3, 2024
5d8bf55
feat(forge): Update documentation
lquerel May 3, 2024
064e844
feat(forge): Fix Clippy lint issues
lquerel May 4, 2024
3f2e188
chore(forge): Exclude generated file from code coverage
lquerel May 4, 2024
3b26644
Merge branch 'main' into example-codegen-semconv-rust
lquerel May 4, 2024
7ec190d
chore(forge): Test infra for code gen [WIP]
lquerel May 4, 2024
da441c3
chore(forge): Remove build.rs
lquerel May 5, 2024
7ee2235
Merge branch 'main' into example-codegen-semconv-rust
lquerel May 6, 2024
c006d17
chore(forge): Move to not_required filter
lquerel May 6, 2024
8757379
Merge remote-tracking branch 'origin/example-codegen-semconv-rust' in…
lquerel May 6, 2024
97ee4a3
chore(forge): Improve error messages
lquerel May 6, 2024
9045e05
chore(forge): Create code generation test infrastructure
lquerel May 7, 2024
423111b
chore(forge): Create code generation test infrastructure
lquerel May 7, 2024
1306e6a
chore(forge): Create code generation test infrastructure
lquerel May 7, 2024
19e07c2
chore(forge): Remove duplicated codes and semconv registry
lquerel May 7, 2024
3534c42
chore(forge): Fix Windows specific issue.
lquerel May 7, 2024
964a5cb
Merge branch 'main' into example-codegen-semconv-rust
lquerel May 7, 2024
b858e7c
chore(forge): Improve error message to debug Windows specific issue.
lquerel May 7, 2024
c0aea47
Merge remote-tracking branch 'origin/example-codegen-semconv-rust' in…
lquerel May 7, 2024
baa9e2a
chore(forge): Add traces to debug Windows specific issue.
lquerel May 7, 2024
2f2ce45
chore(forge): Fix MiniJinja template loader for Windows.
lquerel May 8, 2024
dd0dc61
chore(forge): Fix MiniJinja template loader for Windows.
lquerel May 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions crates/weaver_forge/src/extensions/code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: Apache-2.0

//! Set of filters used to facilitate the generation of code.

/// Converts the input string into a comment with a prefix.
pub fn comment_with_prefix(input: &str, prefix: &str) -> String {
Fixed Show fixed Hide fixed
let mut comment = String::new();
for line in input.lines() {
if !comment.is_empty() {
comment.push_str("\n");
Fixed Show fixed Hide fixed
}
comment.push_str(&format!("{}{}", prefix, line));
}
comment
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_comment() {
assert_eq!(comment_with_prefix("test", "// "), "// test");

let brief = r#"These attributes may be used to describe the client in a connection-based network interaction
where there is one side that initiates the connection (the client is the side that initiates the connection).
This covers all TCP network interactions since TCP is connection-based and one side initiates the
connection (an exception is made for peer-to-peer communication over TCP where the "user-facing" surface of the
protocol / API doesn't expose a clear notion of client and server).
This also covers UDP network interactions where one side initiates the interaction, e.g. QUIC (HTTP/3) and DNS."#;

let expected_brief = r#"/// These attributes may be used to describe the client in a connection-based network interaction
/// where there is one side that initiates the connection (the client is the side that initiates the connection).
/// This covers all TCP network interactions since TCP is connection-based and one side initiates the
/// connection (an exception is made for peer-to-peer communication over TCP where the "user-facing" surface of the
/// protocol / API doesn't expose a clear notion of client and server).
/// This also covers UDP network interactions where one side initiates the interaction, e.g. QUIC (HTTP/3) and DNS."#;

assert_eq!(comment_with_prefix(brief, "/// "), expected_brief);
}
}
2 changes: 2 additions & 0 deletions crates/weaver_forge/src/extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
//! Custom filters used by the template engine.
pub mod acronym;
pub mod case_converter;
pub mod code;
pub mod tests;
124 changes: 124 additions & 0 deletions crates/weaver_forge/src/extensions/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// SPDX-License-Identifier: Apache-2.0

//! Set of tests

use minijinja::Value;

/// Checks if the input value is an object with a field named "stability" that has the value "stable".
/// Otherwise, it returns false.
pub fn is_stable(input: Value) -> bool {
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
if let Some(object) = input.as_struct() {
let stability = object.get_field("stability");
if let Some(stability) = stability {
if let Some(stability) = stability.as_str() {
return stability == "stable";
}
}
}
false
}

/// Checks if the input value is an object with a field named "stability" that has the value "deprecated".
/// Otherwise, it returns false.
pub fn is_deprecated(input: Value) -> bool {
Fixed Show fixed Hide fixed
Fixed Show fixed Hide fixed
if let Some(object) = input.as_struct() {
let stability = object.get_field("stability");
if let Some(stability) = stability {
if let Some(stability) = stability.as_str() {
return stability == "deprecated";
}
}
}
false
}

#[cfg(test)]
mod tests {
use minijinja::value::StructObject;

use super::*;

struct DynAttr {
id: String,
r#type: String,
stability: String,
}

impl StructObject for DynAttr {
fn get_field(&self, field: &str) -> Option<Value> {
match field {
"id" => Some(Value::from(self.id.as_str())),
"type" => Some(Value::from(self.r#type.as_str())),
"stability" => Some(Value::from(self.stability.as_str())),
_ => None,
}
}
}

struct DynSomethingElse {
id: String,
r#type: String,
}

impl StructObject for DynSomethingElse {
fn get_field(&self, field: &str) -> Option<Value> {
match field {
"id" => Some(Value::from(self.id.as_str())),
"type" => Some(Value::from(self.r#type.as_str())),
_ => None,
}
}
}

#[test]
fn test_is_stable() {
// An attribute with stability "stable"
let attr = Value::from_struct_object(DynAttr {
id: "test".to_owned(),
r#type: "test".to_owned(),
stability: "stable".to_owned(),
});
assert!(is_stable(attr));

// An attribute with stability "deprecated"
let attr = Value::from_struct_object(DynAttr {
id: "test".to_owned(),
r#type: "test".to_owned(),
stability: "deprecated".to_owned(),
});
assert!(!is_stable(attr));

// An object without a stability field
let object = Value::from_struct_object(DynSomethingElse {
id: "test".to_owned(),
r#type: "test".to_owned(),
});
assert!(!is_stable(object));
}

#[test]
fn test_is_deprecated() {
// An attribute with stability "deprecated"
let attr = Value::from_struct_object(DynAttr {
id: "test".to_owned(),
r#type: "test".to_owned(),
stability: "deprecated".to_owned(),
});
assert!(is_deprecated(attr));

// An attribute with stability "stable"
let attr = Value::from_struct_object(DynAttr {
id: "test".to_owned(),
r#type: "test".to_owned(),
stability: "stable".to_owned(),
});
assert!(!is_deprecated(attr));

// An object without a stability field
let object = Value::from_struct_object(DynSomethingElse {
id: "test".to_owned(),
r#type: "test".to_owned(),
});
assert!(!is_deprecated(object));
}
}
6 changes: 6 additions & 0 deletions crates/weaver_forge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::debug::error_summary;
use crate::error::Error::InvalidConfigFile;
use crate::extensions::acronym::acronym;
use crate::extensions::case_converter::case_converter;
use crate::extensions::code;
use crate::registry::{TemplateGroup, TemplateRegistry};

mod config;
Expand Down Expand Up @@ -375,6 +376,11 @@ impl TemplateEngine {

env.add_filter("acronym", acronym(self.target_config.acronyms.clone()));

env.add_filter("comment_with_prefix", code::comment_with_prefix);

env.add_test("stable", extensions::tests::is_stable);
env.add_test("deprecated", extensions::tests::is_deprecated);

// env.add_filter("unique_attributes", extensions::unique_attributes);
// env.add_filter("instrument", extensions::instrument);
// env.add_filter("required", extensions::required);
Expand Down
15 changes: 0 additions & 15 deletions templates/go/config.yaml

This file was deleted.

52 changes: 0 additions & 52 deletions templates/go/optional_attrs.macro.tera

This file was deleted.

15 changes: 0 additions & 15 deletions templates/go/otel/attribute/attrs.go.tera

This file was deleted.

Loading
Loading