Skip to content

Commit

Permalink
semconv: generate metrics specs
Browse files Browse the repository at this point in the history
  • Loading branch information
iRevive committed Sep 9, 2024
1 parent 3c07667 commit 531d46a
Show file tree
Hide file tree
Showing 22 changed files with 10,281 additions and 7 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@ jobs:

- name: Make target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
run: mkdir -p semconv/stable/.jvm/target oteljava/metrics/target sdk-exporter/common/.js/target sdk/common/native/target sdk/common/js/target core/trace/.js/target sdk-exporter/all/.jvm/target semconv/experimental/.js/target sdk/trace/.js/target core/common/.jvm/target sdk-exporter/common/.native/target oteljava/common-testkit/target sdk/metrics/.native/target sdk-exporter/metrics/.jvm/target sdk-exporter/trace/.jvm/target unidocs/target sdk-exporter/metrics/.native/target oteljava/trace-testkit/target core/metrics/.native/target core/all/.native/target sdk/trace-testkit/.jvm/target sdk/trace-testkit/.native/target sdk/testkit/.native/target semconv/experimental/.native/target core/metrics/.jvm/target core/all/.js/target sdk-exporter/proto/.jvm/target sdk-exporter/proto/.js/target sdk-exporter/metrics/.js/target semconv/stable/.native/target sdk/all/.native/target sdk/metrics-testkit/.js/target sdk-contrib/aws/xray-propagator/.native/target core/metrics/.js/target sdk/testkit/.js/target core/all/.jvm/target sdk-exporter/trace/.native/target sdk/common/jvm/target core/trace/.native/target oteljava/metrics-testkit/target sdk/trace/.native/target semconv/experimental/.jvm/target sdk/metrics-testkit/.native/target sdk/metrics/.jvm/target oteljava/common/target scalafix/rules/target sdk-exporter/proto/.native/target core/trace/.jvm/target sdk-exporter/common/.jvm/target sdk/metrics-testkit/.jvm/target sdk/metrics/.js/target sdk-exporter/trace/.js/target core/common/.native/target sdk/trace-testkit/.js/target core/common/.js/target oteljava/trace/target oteljava/testkit/target sdk/testkit/.jvm/target sdk-exporter/all/.js/target sdk-contrib/aws/xray-propagator/.js/target sdk/all/.js/target sdk/all/.jvm/target sdk-exporter/all/.native/target oteljava/all/target sdk/trace/.jvm/target sdk-contrib/aws/xray-propagator/.jvm/target semconv/stable/.js/target project/target
run: mkdir -p semconv/stable/.jvm/target oteljava/metrics/target sdk-exporter/common/.js/target sdk/common/native/target sdk/common/js/target core/trace/.js/target semconv/metrics/stable/.jvm/target semconv/metrics/experimental/.jvm/target semconv/metrics/stable/.native/target sdk-exporter/all/.jvm/target semconv/experimental/.js/target sdk/trace/.js/target core/common/.jvm/target sdk-exporter/common/.native/target oteljava/common-testkit/target sdk/metrics/.native/target sdk-exporter/metrics/.jvm/target sdk-exporter/trace/.jvm/target unidocs/target sdk-exporter/metrics/.native/target oteljava/trace-testkit/target core/metrics/.native/target core/all/.native/target sdk/trace-testkit/.jvm/target sdk/trace-testkit/.native/target sdk/testkit/.native/target semconv/experimental/.native/target core/metrics/.jvm/target core/all/.js/target sdk-exporter/proto/.jvm/target sdk-exporter/proto/.js/target sdk-exporter/metrics/.js/target semconv/stable/.native/target sdk/all/.native/target sdk/metrics-testkit/.js/target sdk-contrib/aws/xray-propagator/.native/target core/metrics/.js/target sdk/testkit/.js/target core/all/.jvm/target sdk-exporter/trace/.native/target sdk/common/jvm/target core/trace/.native/target oteljava/metrics-testkit/target sdk/trace/.native/target semconv/experimental/.jvm/target sdk/metrics-testkit/.native/target sdk/metrics/.jvm/target oteljava/common/target scalafix/rules/target sdk-exporter/proto/.native/target core/trace/.jvm/target sdk-exporter/common/.jvm/target sdk/metrics-testkit/.jvm/target sdk/metrics/.js/target sdk-exporter/trace/.js/target core/common/.native/target sdk/trace-testkit/.js/target core/common/.js/target oteljava/trace/target semconv/metrics/experimental/.native/target oteljava/testkit/target sdk/testkit/.jvm/target sdk-exporter/all/.js/target sdk-contrib/aws/xray-propagator/.js/target semconv/metrics/experimental/.js/target semconv/metrics/stable/.js/target sdk/all/.js/target sdk/all/.jvm/target sdk-exporter/all/.native/target oteljava/all/target sdk/trace/.jvm/target sdk-contrib/aws/xray-propagator/.jvm/target semconv/stable/.js/target project/target

- name: Compress target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
run: tar cf targets.tar semconv/stable/.jvm/target oteljava/metrics/target sdk-exporter/common/.js/target sdk/common/native/target sdk/common/js/target core/trace/.js/target sdk-exporter/all/.jvm/target semconv/experimental/.js/target sdk/trace/.js/target core/common/.jvm/target sdk-exporter/common/.native/target oteljava/common-testkit/target sdk/metrics/.native/target sdk-exporter/metrics/.jvm/target sdk-exporter/trace/.jvm/target unidocs/target sdk-exporter/metrics/.native/target oteljava/trace-testkit/target core/metrics/.native/target core/all/.native/target sdk/trace-testkit/.jvm/target sdk/trace-testkit/.native/target sdk/testkit/.native/target semconv/experimental/.native/target core/metrics/.jvm/target core/all/.js/target sdk-exporter/proto/.jvm/target sdk-exporter/proto/.js/target sdk-exporter/metrics/.js/target semconv/stable/.native/target sdk/all/.native/target sdk/metrics-testkit/.js/target sdk-contrib/aws/xray-propagator/.native/target core/metrics/.js/target sdk/testkit/.js/target core/all/.jvm/target sdk-exporter/trace/.native/target sdk/common/jvm/target core/trace/.native/target oteljava/metrics-testkit/target sdk/trace/.native/target semconv/experimental/.jvm/target sdk/metrics-testkit/.native/target sdk/metrics/.jvm/target oteljava/common/target scalafix/rules/target sdk-exporter/proto/.native/target core/trace/.jvm/target sdk-exporter/common/.jvm/target sdk/metrics-testkit/.jvm/target sdk/metrics/.js/target sdk-exporter/trace/.js/target core/common/.native/target sdk/trace-testkit/.js/target core/common/.js/target oteljava/trace/target oteljava/testkit/target sdk/testkit/.jvm/target sdk-exporter/all/.js/target sdk-contrib/aws/xray-propagator/.js/target sdk/all/.js/target sdk/all/.jvm/target sdk-exporter/all/.native/target oteljava/all/target sdk/trace/.jvm/target sdk-contrib/aws/xray-propagator/.jvm/target semconv/stable/.js/target project/target
run: tar cf targets.tar semconv/stable/.jvm/target oteljava/metrics/target sdk-exporter/common/.js/target sdk/common/native/target sdk/common/js/target core/trace/.js/target semconv/metrics/stable/.jvm/target semconv/metrics/experimental/.jvm/target semconv/metrics/stable/.native/target sdk-exporter/all/.jvm/target semconv/experimental/.js/target sdk/trace/.js/target core/common/.jvm/target sdk-exporter/common/.native/target oteljava/common-testkit/target sdk/metrics/.native/target sdk-exporter/metrics/.jvm/target sdk-exporter/trace/.jvm/target unidocs/target sdk-exporter/metrics/.native/target oteljava/trace-testkit/target core/metrics/.native/target core/all/.native/target sdk/trace-testkit/.jvm/target sdk/trace-testkit/.native/target sdk/testkit/.native/target semconv/experimental/.native/target core/metrics/.jvm/target core/all/.js/target sdk-exporter/proto/.jvm/target sdk-exporter/proto/.js/target sdk-exporter/metrics/.js/target semconv/stable/.native/target sdk/all/.native/target sdk/metrics-testkit/.js/target sdk-contrib/aws/xray-propagator/.native/target core/metrics/.js/target sdk/testkit/.js/target core/all/.jvm/target sdk-exporter/trace/.native/target sdk/common/jvm/target core/trace/.native/target oteljava/metrics-testkit/target sdk/trace/.native/target semconv/experimental/.jvm/target sdk/metrics-testkit/.native/target sdk/metrics/.jvm/target oteljava/common/target scalafix/rules/target sdk-exporter/proto/.native/target core/trace/.jvm/target sdk-exporter/common/.jvm/target sdk/metrics-testkit/.jvm/target sdk/metrics/.js/target sdk-exporter/trace/.js/target core/common/.native/target sdk/trace-testkit/.js/target core/common/.js/target oteljava/trace/target semconv/metrics/experimental/.native/target oteljava/testkit/target sdk/testkit/.jvm/target sdk-exporter/all/.js/target sdk-contrib/aws/xray-propagator/.js/target semconv/metrics/experimental/.js/target semconv/metrics/stable/.js/target sdk/all/.js/target sdk/all/.jvm/target sdk-exporter/all/.native/target oteljava/all/target sdk/trace/.jvm/target sdk-contrib/aws/xray-propagator/.jvm/target semconv/stable/.js/target project/target

- name: Upload target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main')
Expand Down
41 changes: 40 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ lazy val root = tlCrossRootProject
oteljava,
`semconv-stable`,
`semconv-experimental`,
`semconv-metrics-stable`,
`semconv-metrics-experimental`,
benchmarks,
examples,
unidocs
Expand Down Expand Up @@ -574,6 +576,10 @@ lazy val oteljava = project
.settings(munitDependencies)
.settings(scalafixSettings)

//
// Semantic conventions
//

lazy val `semconv-stable` =
crossProject(JVMPlatform, JSPlatform, NativePlatform)
.crossType(CrossType.Pure)
Expand Down Expand Up @@ -611,6 +617,37 @@ lazy val `semconv-experimental` =
.settings(munitDependencies)
.settings(scalafixSettings)

lazy val `semconv-metrics-stable` =
crossProject(JVMPlatform, JSPlatform, NativePlatform)
.crossType(CrossType.Pure)
.in(file("semconv/metrics/stable"))
.dependsOn(`core-metrics`)
.settings(
name := "otel4s-semconv-metrics",
startYear := Some(2024),
description := "Stable semantic metrics.",
)
.settings(munitDependencies)
.settings(scalafixSettings)

lazy val `semconv-metrics-experimental` =
crossProject(JVMPlatform, JSPlatform, NativePlatform)
.crossType(CrossType.Pure)
.in(file("semconv/metrics/experimental"))
.dependsOn(`core-metrics`, `semconv-metrics-stable`)
.settings(
name := "otel4s-semconv-metrics",
startYear := Some(2024),
description := "Experimental (incubating) semantic metrics. Breaking changes expected. Library instrumentation SHOULD NOT depend on this.",
mimaPreviousArtifacts := Set.empty
)
.settings(munitDependencies)
.settings(scalafixSettings)

//
//
//

lazy val scalafix = tlScalafixProject
.rulesSettings(
name := "otel4s-scalafix",
Expand Down Expand Up @@ -763,6 +800,8 @@ lazy val unidocs = project
`oteljava-testkit`,
oteljava,
`semconv-stable`.jvm,
`semconv-experimental`.jvm
`semconv-experimental`.jvm,
`semconv-metrics-stable`.jvm,
`semconv-metrics-experimental`.jvm
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
{%- macro to_scala_key_type(attribute) -%}
{{ attribute.type | instantiated_type | map_text("scala_key_type") }}
{%- endmacro %}

{%- macro instrumentType(type) -%}
{%- if type == "gauge" -%}Gauge[F, Long]
{%- elif type == "counter" -%}Counter[F, Long]
{%- elif type == "updowncounter" -%}UpDownCounter[F, Long]
{%- elif type == "histogram" -%}Histogram[F, Double]
{%- else %}{{ type }}
{%- endif -%}
{%- endmacro -%}

{%- macro instrumentFactory(type) -%}
{%- if type == "gauge" -%}gauge[Long]
{%- elif type == "counter" -%}counter[Long]
{%- elif type == "updowncounter" -%}upDownCounter[Long]
{%- elif type == "histogram" -%}histogram[Double]
{%- else %}{{ type }}
{%- endif -%}
{%- endmacro -%}

{%- macro requirement(attribute) -%}
{%- if attribute.requirement_level is mapping -%}
{%- set level = attribute.requirement_level | first -%}
{%- set apply = "(\"" ~ attribute.requirement_level[level] | trim ~ "\")" -%}
{%- else -%}
{%- set level = attribute.requirement_level -%}
{%- set apply = "" -%}
{%- endif -%}
{%- if level == "required" -%} Requirement.required{{ apply }}
{%- elif level == "recommended" -%} Requirement.recommended{{ apply }}
{%- elif level == "conditionally_required" -%} Requirement.conditionallyRequired{{ apply }}
{%- elif level == "opt_in" -%} Requirement.optIn{{ apply }}
{%- else -%} _unknown_requirement_level_{{ attribute.requirement_level }}
{%- endif -%}
{%- endmacro -%}

{%- macro stability(type) -%}
{%- if type == "experimental" -%} Stability.experimental
{%- elif type == "stable" -%} Stability.stable
{%- else -%} _unknown_stability_type_{{ type }}
{%- endif -%}
{%- endmacro -%}

{%- macro exampleValue(type, input) %}
{%- if type == "int" -%} {{ input }}
{%- elif type == "double" -%} {{ input }}
{%- elif type == "boolean" -%} {{ input }}
{%- elif type == "string" -%} "{{ input }}"
{%- else -%} _unknown type_{{ input }}
{%- endif -%}
{% endmacro %}

{%- set object_name = ctx.root_namespace | pascal_case ~ params.object_prefix ~ "Metrics" -%}

/*
* Copyright 2024 Typelevel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.typelevel.otel4s
package semconv
package metrics

import org.typelevel.otel4s.metrics._

// DO NOT EDIT, this is an Auto-generated file from buildscripts/templates/registry/otel4s/metrics/SemanticMetrics.scala.j2
object {{ object_name }} {

{% for metric in ctx.metrics | sort(attribute='metric_name') %}
{{ [metric.brief | replace('$', "$$"), concat_if("\n\n@note\n\n", metric.note)] | comment(indent=2) }}
{%- if metric is deprecated %}
@deprecated("{{ metric.deprecated }}", "")
{%- endif %}
object {{ metric.metric_name[ctx.root_namespace | length:] | pascal_case }} {

val Name = "{{ metric.metric_name }}"
val Description = "{{ metric.brief }}"
val Unit = "{{ metric.unit }}"
{% if metric.attributes | length > 0 %}
object AttributeSpecs {
{% for attribute in metric.attributes | sort(attribute='name') %}
{{ [attribute.brief | replace('$', "$$"), concat_if("\n\n@note\n\n", attribute.note)] | comment(indent=6) }}
{%- if attribute is deprecated %}
@deprecated("{{ attribute.deprecated }}", "")
{%- endif %}
val {{ attribute.name | camel_case }}: AttributeSpec[{{to_scala_key_type(attribute)}}] =
AttributeSpec(
AttributeKey("{{attribute.name}}"),
List(
{% for example in attribute.examples -%} {{ exampleValue(attribute.type | instantiated_type, example) }}, {% endfor %}
),
{{ requirement(attribute) }},
{{ stability(attribute.stability) }}
)
{% endfor %}
val specs: List[AttributeSpec[_]] =
List({%- for attribute in metric.attributes | sort(attribute='name') %}
{{ attribute.name | camel_case }},{% endfor %}
)
}
{% endif %}
def create[F[_]: Meter]{% if metric.instrument == "histogram" %}(boundaries: BucketBoundaries){% endif %}: F[{{ instrumentType(metric.instrument) }}] =
Meter[F]
.{{ instrumentFactory(metric.instrument) }}(Name)
.withDescription(Description)
.withUnit(Unit)
{%- if metric.instrument == "histogram" %}
.withExplicitBucketBoundaries(boundaries)
.create
{% else %}
.create
{% endif %}
}
{% endfor %}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
params:
excluded_namespaces: ["ios", "aspnetcore", "signalr", "kestrel", "veightjs", "go"]
excluded_attributes: ["messaging.client_id"]
excluded_stability: ["experimental", "deprecated"] # stable - ["experimental", "deprecated"]; experimental - []
object_prefix: "" # stable - "", experimental - "Experimental"
comment_formats:
scaladoc:
format: html
header: "/**"
prefix: " * "
footer: " */"
old_style_paragraph: true
omit_closing_li: true
inline_code_snippet: "`{{code}}`"
block_code_snippet: "{{{\n{{code}}}\n}}}"
trim: true
remove_trailing_dots: false
default_comment_format: scaladoc
templates:
- pattern: SemanticMetrics.scala.j2
filter: >
semconv_grouped_metrics({
"exclude_root_namespace": $excluded_namespaces,
"exclude_stability": $excluded_stability,
"exclude_deprecated": false
})
application_mode: each
file_name: "{{ctx.root_namespace | pascal_case}}{{params.object_prefix}}Metrics.scala"
text_maps:
scala_key_type:
int: Long
double: Double
boolean: Boolean
string: String
string[]: Seq[String]
int[]: Seq[Long]
double[]: Seq[Double]
boolean[]: Seq[Boolean]
71 changes: 67 additions & 4 deletions project/SemanticConventionsGenerator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,24 @@ import scala.sys.process._

object SemanticConventionsGenerator {

private val generatorVersion = "0.24.0"
private val generatorVersion = "v0.9.1"

// generates semantic conventions by using `otel/semconvgen` in docker
def generate(version: String, rootDir: File): Unit = {
generateAttributes(version, rootDir)
generateMetrics(version, rootDir)
}

private def generateAttributes(version: String, rootDir: File): Unit = {
generateOne(version, rootDir, experimental = false)
generateOne(version, rootDir, experimental = true)
}

private def generateMetrics(version: String, rootDir: File): Unit = {
generateInstrument(version, rootDir, experimental = false)
generateInstrument(version, rootDir, experimental = true)
}

private def generateOne(
version: String,
rootDir: File,
Expand All @@ -19,9 +29,6 @@ object SemanticConventionsGenerator {
val semanticConventionsRepoZip =
s"https://github.com/open-telemetry/semantic-conventions/archive/v$version.zip"

val schemaUrl =
s"https://opentelemetry.io/schemas/$version"

val filter = if (experimental) "any" else "is_stable"
val classPrefix = if (experimental) "Experimental" else ""

Expand Down Expand Up @@ -77,4 +84,60 @@ object SemanticConventionsGenerator {

Process(command, rootDir).!
}

private def generateInstrument(
version: String,
rootDir: File,
experimental: Boolean
): Unit = {
val semanticConventionsRepoZip =
s"https://github.com/open-telemetry/semantic-conventions/archive/v$version.zip"

val outputDir =
if (experimental)
s"$rootDir/semconv/metrics/experimental/src/main/scala/org/typelevel/otel4s/semconv/experimental/metrics/"
else
s"$rootDir/semconv/metrics/stable/src/main/scala/org/typelevel/otel4s/semconv/metrics/"

val target = "otel4s/metrics"

val params: List[String] =
if (experimental)
List(
"--param=excluded_stability=[]",
"--param=object_prefix=Experimental"
)
else
Nil

val buildDir = rootDir / "buildscripts" / "semantic-convention"
val zip = buildDir / "semantic-conventions.zip"
val conventionsDir = buildDir / s"semantic-conventions-$version"

IO.delete(zip)
IO.delete(conventionsDir)

(url(semanticConventionsRepoZip) #> zip).!

IO.unzip(zip, buildDir)

// format: off
val command = List(
"docker",
"run",
"--rm",
"-v", s"$conventionsDir/model:/home/weaver/source",
"-v", s"$buildDir/templates:/home/weaver/templates",
"-v", s"$outputDir:/home/weaver/target",
"--platform", "linux/amd64",
s"otel/weaver:$generatorVersion",
"registry", "generate",
"--registry=/home/weaver/source",
"--templates=/home/weaver/templates",
) ++ params ++ List(target, "/home/weaver/target/")
// format: on

println(command.mkString(" "))
Process(command, rootDir).!
}
}
Loading

0 comments on commit 531d46a

Please sign in to comment.