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

Add Jinja whitespace control #224

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 8 additions & 6 deletions crates/weaver_forge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ templates/
html/ <-- Templates to generate the semantic conventions in HTML
...
markdown/ <-- Templates to generate the semantic conventions in markdown
...
...
rust/ <-- Templates to generate the semantic conventions in Rust
...
...
go/ <-- Templates to generate the semantic conventions in Go
...
schema/
Expand Down Expand Up @@ -78,6 +78,7 @@ documentation for more details.
## Global Variables

All templates have access to the following global variables:

- `ctx`: The context object that contains the resolved registry or the output of
the JQ filter if defined in the `weaver.yaml` configuration file.
- `params`: The parameters defined in the `weaver.yaml` configuration file or overridden
Expand Down Expand Up @@ -130,12 +131,13 @@ Jinja templates can also access the parameters:
## Jinja Filters

All the filters available in the MiniJinja template engine are available (see
this online [documentation](https://docs.rs/minijinja/latest/minijinja/filters/index.html)).
this online [documentation](https://docs.rs/minijinja/latest/minijinja/filters/index.html)).

In addition, OTel Weaver provides a set of custom filters to facilitate the
generation of documentation and code.

The following filters are available:

- `lower_case`: Converts a string to lowercase.
- `upper_case`: Converts a string to UPPERCASE.
- `title_case`: Converts a string to TitleCase.
Expand All @@ -146,7 +148,7 @@ The following filters are available:
- `kebab_case`: Converts a string to kebab-case.
- `screaming_kebab_case`: Converts a string to SCREAMING-KEBAB-CASE.
- `capitalize_first`: Capitalizes the first letter of a string.
- `kebab_case_const`: Generates kebab-case constants which follow semantic convention namespacing rules (underscores are ignored, but . is meaningful).
- `kebab_case_const`: Generates kebab-case constants which follow semantic convention namespacing rules (underscores are ignored, but . is meaningful).
- `pascal_case_const`: Generates PascalCase constants which follow semantic convention namespacing rules (underscores are ignored, but . is meaningful).
- `camel_case_const`: Generates camelCase constants which follow semantic convention namespacing rules (underscores are ignored, but . is meaningful).
- `snake_case_const`: Generates snake_case constants which follow semantic convention namespacing rules (underscores are ignored, but . is meaningful).
Expand All @@ -165,7 +167,7 @@ e.g. \[\[a,b\],\[c\]\] => \[a,b,c\]
- `attribute_namespace`: Converts {namespace}.{attribute_id} to {namespace}.
- `required`: Filters a list of `Attribute`s to include only the required attributes. The "conditionally_required" attributes are not returned by this filter.
- `not_required`: Filters a list of `Attribute`s to only include non-required attributes. The "conditionally_required" attributes are returned by this filter.
- `instantiated_type`: Filters a type to return the instantiated type.
- `instantiated_type`: Filters a type to return the instantiated type.
- `enum_type`: Filters a type to return the enum type or an error if the type is not an enum.
- `markdown_to_html`: Converts a markdown string to an HTML string.
- `map_text`: Converts an input into a string based on the `text_maps` section of the `weaver.yaml` configuration file
Expand Down Expand Up @@ -212,7 +214,7 @@ value if the name of the text map or the input are not found in the `text_maps`

## Jinja Functions

All the functions available in the MiniJinja template engine are available (see
All the functions available in the MiniJinja template engine are available (see
this online [documentation](https://docs.rs/minijinja/latest/minijinja/functions/index.html)).

Right now, OTel Weaver does not provide any custom functions but feel free to
Expand Down
17 changes: 17 additions & 0 deletions crates/weaver_forge/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ pub(crate) struct TargetConfig {
/// Configuration for the template syntax.
#[serde(default)]
pub(crate) template_syntax: TemplateSyntax,
/// Configuration for the whitespace behavior on the template engine.
#[serde(default)]
pub(crate) whitespace_control: WhitespaceControl,

/// Parameters for the templates.
/// These parameters can be overridden by parameters passed to the CLI.
Expand Down Expand Up @@ -298,6 +301,20 @@ impl Default for TemplateSyntax {
}
}

/// Whitespace control configuration for the template engine.
#[derive(Deserialize, Debug, Clone, Default)]
pub struct WhitespaceControl {
/// Configures the behavior of the first newline after a block.
/// See <https://docs.rs/minijinja/latest/minijinja/struct.Environment.html#method.set_trim_blocks>
pub trim_blocks: bool,
/// Configures the behavior of leading spaces and tabs from the start of a line to a block.
/// See <https://docs.rs/minijinja/latest/minijinja/struct.Environment.html#method.set_lstrip_blocks>
pub lstrip_blocks: bool,
/// Configures whether trailing newline are preserved when rendering templates.
/// See <https://docs.rs/minijinja/latest/minijinja/struct.Environment.html#method.set_keep_trailing_newline>
pub keep_trailing_newline: bool,
}

impl Default for CaseConvention {
/// Default case convention is PascalCase
fn default() -> Self {
Expand Down
51 changes: 51 additions & 0 deletions crates/weaver_forge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,13 @@ impl TemplateEngine {
});
env.set_syntax(syntax);

// Jinja whitespace control
// https://docs.rs/minijinja/latest/minijinja/syntax/index.html#whitespace-control
let whitespace_control = self.target_config.whitespace_control.clone();
env.set_trim_blocks(whitespace_control.trim_blocks);
env.set_lstrip_blocks(whitespace_control.lstrip_blocks);
env.set_keep_trailing_newline(whitespace_control.keep_trailing_newline);

code::add_filters(&mut env, &self.target_config);
ansi::add_filters(&mut env);
case::add_filters(&mut env, &self.target_config);
Expand Down Expand Up @@ -682,4 +689,48 @@ mod tests {

assert!(diff_dir("expected_output", "observed_output").unwrap());
}

#[test]
fn test_whitespace_control() {
let logger = TestLogger::default();
let loader = FileSystemFileLoader::try_new("whitespace_control_templates".into(), "test")
.expect("Failed to create file system loader");
let engine = super::TemplateEngine::try_new(loader, Params::default())
.expect("Failed to create template engine");

let registry_id = "default";
let mut registry = SemConvRegistry::try_from_path_pattern(registry_id, "data/*.yaml")
.expect("Failed to load registry");
let schema = SchemaResolver::resolve_semantic_convention_registry(&mut registry)
.expect("Failed to resolve registry");

let template_registry = ResolvedRegistry::try_from_resolved_registry(
schema.registry(registry_id).expect("registry not found"),
schema.catalog(),
)
.unwrap_or_else(|e| {
panic!(
"Failed to create the context for the template evaluation: {:?}",
e
)
});

engine
.generate(
logger.clone(),
&template_registry,
Path::new("whitespace_control_templates/test/observed_output"),
&OutputDirective::File,
)
.inspect_err(|e| {
print_dedup_errors(logger.clone(), e.clone());
})
.expect("Failed to generate registry assets");

assert!(diff_dir(
"whitespace_control_templates/test/expected_output",
"whitespace_control_templates/test/observed_output"
)
.unwrap());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Semantic Convention Registry

Url:

## Attribute Groups

- [attributes.jvm.memory](attribute_group/attributes_jvm_memory.md)
- [registry.db](attribute_group/registry_db.md)
- [registry.http](attribute_group/registry_http.md)
- [registry.network](attribute_group/registry_network.md)
- [server](attribute_group/server.md)
- [registry.url](attribute_group/registry_url.md)
- [registry.user_agent](attribute_group/registry_user_agent.md)

## Events

- [ios.lifecycle.events](event/ios_lifecycle_events.md)
- [android.lifecycle.events](event/android_lifecycle_events.md)

## Metrics

- [metric.jvm.memory.used](metric/metric_jvm_memory_used.md)
- [metric.jvm.memory.committed](metric/metric_jvm_memory_committed.md)
- [metric.jvm.memory.limit](metric/metric_jvm_memory_limit.md)
- [metric.jvm.memory.used_after_last_gc](metric/metric_jvm_memory_used_after_last_gc.md)
- [metric.jvm.gc.duration](metric/metric_jvm_gc_duration.md)
- [metric.jvm.thread.count](metric/metric_jvm_thread_count.md)
- [metric.jvm.class.loaded](metric/metric_jvm_class_loaded.md)
- [metric.jvm.class.unloaded](metric/metric_jvm_class_unloaded.md)
- [metric.jvm.class.count](metric/metric_jvm_class_count.md)
- [metric.jvm.cpu.count](metric/metric_jvm_cpu_count.md)
- [metric.jvm.cpu.time](metric/metric_jvm_cpu_time.md)
- [metric.jvm.cpu.recent_utilization](metric/metric_jvm_cpu_recent_utilization.md)

## Metric Groups

## Resource

- [otel.scope](resource/otel_scope.md)
- [otel.library](resource/otel_library.md)

## Scope

## Span

- [db](span/db.md)
- [db.mssql](span/db_mssql.md)
- [db.cassandra](span/db_cassandra.md)
- [db.hbase](span/db_hbase.md)
- [db.couchdb](span/db_couchdb.md)
- [db.redis](span/db_redis.md)
- [db.mongodb](span/db_mongodb.md)
- [db.elasticsearch](span/db_elasticsearch.md)
- [db.sql](span/db_sql.md)
- [db.cosmosdb](span/db_cosmosdb.md)
- [db.tech](span/db_tech.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Semantic Convention Registry

Url:{{ registry_url }}

## Attribute Groups

{% for group in ctx.groups %}
{% if group.type == "attribute_group" %}
- [{{ group.id }}](attribute_group/{{ group.id | file_name }}.md)
{% endif %}
{% endfor %}

## Events

{% for group in ctx.groups %}
{% if group.type == "event" %}
- [{{ group.id }}](event/{{ group.id | file_name }}.md)
{% endif %}
{% endfor %}

## Metrics

{% for group in ctx.groups %}
{% if group.type == "metric" %}
- [{{ group.id }}](metric/{{ group.id | file_name }}.md)
{% endif %}
{% endfor %}

## Metric Groups
{% for group in ctx.groups %}
{% if group.type == "metric_group" %}
- [{{ group.id }}](metric_group/{{ group.id | file_name }}.md)
{% endif %}
{% endfor %}

## Resource

{% for group in ctx.groups %}
{% if group.type == "resource" %}
- [{{ group.id }}](resource/{{ group.id | file_name }}.md)
{% endif %}
{% endfor %}

## Scope
{% for group in ctx.groups %}
{% if group.type == "scope" %}
- [{{ group.id }}](scope/{{ group.id | file_name }}.md)
{% endif %}
{% endfor %}

## Span

{% for group in ctx.groups %}
{% if group.type == "span" %}
- [{{ group.id }}](span/{{ group.id | file_name }}.md)
{% endif %}
{% endfor %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
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"

acronyms: ["iOS", "API", "URL"]

whitespace_control:
trim_blocks: true
lstrip_blocks: true
keep_trailing_newline: true
5 changes: 1 addition & 4 deletions crates/weaver_semconv/src/semconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,7 @@ mod tests {
let semconv_url = "http://unknown.com/unknown-semconv.yaml";
let semconv_spec = SemConvSpec::from_url(semconv_url);
assert!(semconv_spec.is_err());
assert!(matches!(
semconv_spec.unwrap_err(),
InvalidSemConvSpec { .. }
));
assert!(matches!(semconv_spec.unwrap_err(), RegistryNotFound { .. }));
}

#[test]
Expand Down
14 changes: 11 additions & 3 deletions docs/weaver-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ following options:
# double: doubleKey
# boolean: booleanKey
# string: stringKey

# Deprecated, please use text_maps instead
# Configuration of the type mapping. This is useful to generate code in a
# specific language. This is optional.
Expand All @@ -33,7 +33,8 @@ following options:
# "string[]": "[]string"
# ...

# Uncomment this section to specify the configuration of the Jinja template syntax.
# Uncomment this section to specify the configuration of the Jinja template syntax
# and control whitespace behavior.
# Note: The default syntax is strongly recommended.
#template_syntax:
# block_start: "{%"
Expand All @@ -43,6 +44,13 @@ following options:
# comment_start: "{#"
# comment_end: "#}"

# Uncomment this section to specify the whitespace behavior of the Jinja template engine.
# For more info, see: https://docs.rs/minijinja/latest/minijinja/syntax/index.html#whitespace-control
# whitespace_control:
# trim_blocks: true
# lstrip_blocks: true
# keep_trailing_newline: true

# Uncomment the following section to specify a list of acronyms that
# will be interpreted by the acronym filter. This is optional.
# acronyms: ["iOS", "HTTP", "API", "SDK", "CLI", "URL", "JSON", "XML", "HTML"]
Expand All @@ -52,7 +60,7 @@ following options:
# params:
# param1: val1
# param2: val2

# Uncomment the following templates to override the default template
# mapping. Each template mapping specifies a jaq filter (compatible with jq)
# to apply to every file matching the pattern. The application_mode specifies
Expand Down
Loading