diff --git a/jmx-scraper/build.gradle.kts b/jmx-scraper/build.gradle.kts index 712e43c0f..9ce2aec1f 100644 --- a/jmx-scraper/build.gradle.kts +++ b/jmx-scraper/build.gradle.kts @@ -25,7 +25,6 @@ dependencies { runtimeOnly("org.terracotta:jmxremote_optional-tc:1.0.8") implementation("io.opentelemetry.instrumentation:opentelemetry-jmx-metrics") - implementation("io.opentelemetry.semconv:opentelemetry-semconv-incubating") testImplementation("org.junit-pioneer:junit-pioneer") @@ -99,6 +98,46 @@ tasks { } } +// +// task that run weaver within gradle; +tasks.register("runWeaver", Exec::class) { + standardOutput = System.out + executable = "docker" + + val WEAVER_CONTAINER = "otel/weaver@sha256:5425ade81dc22ddd840902b0638b4b6a9186fb654c5b50c1d1ccd31299437390" + val projectRoot = project.layout.projectDirectory.asFile.absolutePath + val modelPath = project.layout.projectDirectory.dir("model").asFile.absolutePath + val templatePath = project.layout.projectDirectory.dir("templates").asFile.absolutePath + val outputPath = project.layout.projectDirectory.file("src/main/resources").asFile.absolutePath + + val file_args = if (org.gradle.internal.os.OperatingSystem.current().isWindows()) + // Don't need to worry about file system permissions in docker. + listOf() + else { + // Make sure we run as local file user + val unix = com.sun.security.auth.module.UnixSystem() + val uid = unix.getUid() // $(id -u $USERNAME) + val gid = unix.getGid() // $(id -g $USERNAME) + listOf("-u", "$uid:$gid") + } + + val weaver_args = listOf( + "--rm", + "--platform=linux/x86_64", + "--mount", "type=bind,source=${modelPath},target=/home/weaver/source,readonly", + "--mount", "type=bind,source=${templatePath},target=/home/weaver/templates,readonly", + "--mount", "type=bind,source=${outputPath},target=/home/weaver/target", + "--mount", "type=bind,source=${projectRoot},target=/home/weaver", + "${WEAVER_CONTAINER}", + "registry", "generate", + "--registry=/home/weaver/source", + "--templates=/home/weaver/templates", + "rules", + "/home/weaver/target/") + + setArgs(listOf("run") + file_args + weaver_args) +} + // Don't publish non-shadowed jar (shadowJar is in shadowRuntimeElements) with(components["java"] as AdhocComponentWithVariants) { configurations.forEach { diff --git a/jmx-scraper/model/attributes.yaml b/jmx-scraper/model/attributes.yaml new file mode 100644 index 000000000..5a46c5dcd --- /dev/null +++ b/jmx-scraper/model/attributes.yaml @@ -0,0 +1,16 @@ +groups: + - id: metric.attributes + type: attribute_group + brief: "Metric attributes." + attributes: + - id: pool.name + brief: "Pool name." + type: string + stability: beta + examples: [ "Memory pool 1", "Code Cache", "Metaspace", "Compressed Class Space"] + + - id: gc.name + brief: "Garbage Collector name." + type: string + stability: beta + examples: [ "Parallel GC", "G1 Young Generation"] diff --git a/jmx-scraper/model/metrics.yaml b/jmx-scraper/model/metrics.yaml new file mode 100644 index 000000000..44d1656af --- /dev/null +++ b/jmx-scraper/model/metrics.yaml @@ -0,0 +1,146 @@ +groups: + - id: jvm.classes.loaded + type: metric + brief: "number of loaded classes" + metric_name: jvm.classes.loaded + instrument: updowncounter + unit: "{class}" + stability: beta + + - id: jvm.gc.collections.count + type: metric + brief: "total number of collections that have occurred" + metric_name: jvm.gc.collections.count + instrument: counter + unit: "{collection}" + stability: beta + attributes: + - ref: gc.name + requirement_level: required + + - id: jvm.gc.collections.elapsed + type: metric + brief: "the approximate accumulated collection elapsed time in milliseconds" + metric_name: jvm.gc.collections.elapsed + instrument: counter + unit: ms + stability: beta + attributes: + - ref: gc.name + requirement_level: required + + - id: jvm.memory.heap.committed + type: metric + brief: "current heap size" + metric_name: jvm.memory.heap.committed + instrument: gauge + unit: By + stability: beta + + - id: jvm.memory.heap.init + type: metric + brief: "initial heap size" + metric_name: jvm.memory.heap.init + instrument: gauge + unit: By + stability: beta + + - id: jvm.memory.heap.max + type: metric + brief: "max heap size" + metric_name: jvm.memory.heap.max + instrument: gauge + unit: By + stability: beta + + - id: jvm.memory.heap.used + type: metric + brief: "current heap usage" + metric_name: jvm.memory.heap.used + instrument: gauge + unit: By + stability: beta + + - id: jvm.memory.nonheap.committed + type: metric + brief: "current non-heap size" + metric_name: jvm.memory.nonheap.committed + instrument: gauge + unit: By + stability: beta + + - id: jvm.memory.nonheap.init + type: metric + brief: "initial non-heap size" + metric_name: jvm.memory.nonheap.init + instrument: gauge + unit: By + stability: beta + + - id: jvm.memory.nonheap.max + type: metric + brief: "max non-heap size" + metric_name: jvm.memory.nonheap.max + instrument: gauge + unit: By + stability: beta + + - id: jvm.memory.nonheap.used + type: metric + brief: "current non-heap usage" + metric_name: jvm.memory.nonheap.used + instrument: gauge + unit: By + stability: beta + + - id: jvm.memory.pool.committed + type: metric + brief: "current memory pool size" + metric_name: jvm.memory.pool.committed + instrument: gauge + unit: By + stability: beta + attributes: + - ref: pool.name + requirement_level: required + + - id: jvm.memory.pool.init + type: metric + brief: "initial memory pool size" + metric_name: jvm.memory.pool.init + instrument: gauge + unit: By + stability: beta + attributes: + - ref: pool.name + requirement_level: required + + - id: jvm.memory.pool.max + type: metric + brief: "max memory pool size" + metric_name: jvm.memory.pool.max + instrument: gauge + unit: By + stability: beta + attributes: + - ref: pool.name + requirement_level: required + + - id: jvm.memory.pool.used + type: metric + brief: "current memory pool usage" + metric_name: jvm.memory.pool.used + instrument: gauge + unit: By + stability: beta + attributes: + - ref: pool.name + requirement_level: required + + - id: jvm.threads.count + type: metric + brief: "current number of thread count" + metric_name: jvm.threads.count + instrument: gauge + unit: "{thread}" + stability: beta diff --git a/jmx-scraper/model/registry_manifest.yaml b/jmx-scraper/model/registry_manifest.yaml new file mode 100644 index 000000000..c62e0c632 --- /dev/null +++ b/jmx-scraper/model/registry_manifest.yaml @@ -0,0 +1,8 @@ +name: JMX scraper +semconv_version: v0.1.0 +schema_base_url: https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/jmx-scraper/model + +# Define where weaver should look for templates +templates: + - id: jvm + file: templates/registry/rules/jvm.yaml.j2 diff --git a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JvmIntegrationTest.java b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JvmIntegrationTest.java index be8a04a53..1b229f82f 100644 --- a/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JvmIntegrationTest.java +++ b/jmx-scraper/src/integrationTest/java/io/opentelemetry/contrib/jmxscraper/target_systems/JvmIntegrationTest.java @@ -90,7 +90,7 @@ protected MetricsVerifier createMetricsVerifier() { "jvm.memory.heap.committed", metric -> metric - .hasDescription("current heap usage") + .hasDescription("current heap size") .hasUnit("By") .isGauge() .hasDataPointsWithoutAttributes()) @@ -98,7 +98,7 @@ protected MetricsVerifier createMetricsVerifier() { "jvm.memory.heap.init", metric -> metric - .hasDescription("current heap usage") + .hasDescription("initial heap size") .hasUnit("By") .isGauge() .hasDataPointsWithoutAttributes()) @@ -106,7 +106,7 @@ protected MetricsVerifier createMetricsVerifier() { "jvm.memory.heap.max", metric -> metric - .hasDescription("current heap usage") + .hasDescription("max heap size") .hasUnit("By") .isGauge() .hasDataPointsWithoutAttributes()) @@ -122,7 +122,7 @@ protected MetricsVerifier createMetricsVerifier() { "jvm.memory.nonheap.committed", metric -> metric - .hasDescription("current non-heap usage") + .hasDescription("current non-heap size") .hasUnit("By") .isGauge() .hasDataPointsWithoutAttributes()) @@ -130,7 +130,7 @@ protected MetricsVerifier createMetricsVerifier() { "jvm.memory.nonheap.init", metric -> metric - .hasDescription("current non-heap usage") + .hasDescription("initial non-heap size") .hasUnit("By") .isGauge() .hasDataPointsWithoutAttributes()) @@ -138,7 +138,7 @@ protected MetricsVerifier createMetricsVerifier() { "jvm.memory.nonheap.max", metric -> metric - .hasDescription("current non-heap usage") + .hasDescription("max non-heap size") .hasUnit("By") .isGauge() .hasDataPointsWithoutAttributes()) @@ -154,7 +154,7 @@ protected MetricsVerifier createMetricsVerifier() { "jvm.memory.pool.committed", metric -> metric - .hasDescription("current memory pool usage") + .hasDescription("current memory pool size") .hasUnit("By") .isGauge() .hasDataPointsWithAttributes(memoryAttributes)) @@ -162,7 +162,7 @@ protected MetricsVerifier createMetricsVerifier() { "jvm.memory.pool.init", metric -> metric - .hasDescription("current memory pool usage") + .hasDescription("initial memory pool size") .hasUnit("By") .isGauge() .hasDataPointsWithAttributes(memoryAttributes)) @@ -170,7 +170,7 @@ protected MetricsVerifier createMetricsVerifier() { "jvm.memory.pool.max", metric -> metric - .hasDescription("current memory pool usage") + .hasDescription("max memory pool size") .hasUnit("By") .isGauge() .hasDataPointsWithAttributes(memoryAttributes)) @@ -186,7 +186,7 @@ protected MetricsVerifier createMetricsVerifier() { "jvm.threads.count", metric -> metric - .hasDescription("number of threads") + .hasDescription("current number of thread count") .hasUnit("{thread}") .isGauge() .hasDataPointsWithoutAttributes()); diff --git a/jmx-scraper/src/main/resources/jvm.yaml b/jmx-scraper/src/main/resources/jvm.yaml index 733e679fd..2bf51bf0c 100644 --- a/jmx-scraper/src/main/resources/jvm.yaml +++ b/jmx-scraper/src/main/resources/jvm.yaml @@ -1,7 +1,7 @@ --- rules: - + # Rule for ClassLoading metrics - bean: java.lang:type=ClassLoading mapping: LoadedClassCount: @@ -10,6 +10,7 @@ rules: unit: "{class}" desc: number of loaded classes + # Rule for Garbage Collector metrics - bean: java.lang:type=GarbageCollector,name=* mapping: CollectionCount: @@ -27,21 +28,22 @@ rules: metricAttribute: name: param(name) + # Rule for Heap and Non-Heap Memory metrics - bean: java.lang:type=Memory unit: By prefix: jvm.memory. mapping: HeapMemoryUsage.committed: metric: heap.committed - desc: current heap usage + desc: current heap size type: gauge HeapMemoryUsage.init: metric: heap.init - desc: current heap usage + desc: initial heap size type: gauge HeapMemoryUsage.max: metric: heap.max - desc: current heap usage + desc: max heap size type: gauge HeapMemoryUsage.used: metric: heap.used @@ -49,21 +51,22 @@ rules: type: gauge NonHeapMemoryUsage.committed: metric: nonheap.committed - desc: current non-heap usage + desc: current non-heap size type: gauge NonHeapMemoryUsage.init: metric: nonheap.init - desc: current non-heap usage + desc: initial non-heap size type: gauge NonHeapMemoryUsage.max: metric: nonheap.max - desc: current non-heap usage + desc: max non-heap size type: gauge NonHeapMemoryUsage.used: metric: nonheap.used desc: current non-heap usage type: gauge + # Rule for Memory Pool metrics - bean: java.lang:type=MemoryPool,name=* type: gauge unit: By @@ -72,20 +75,21 @@ rules: mapping: Usage.committed: metric: jvm.memory.pool.committed - desc: current memory pool usage + desc: current memory pool size Usage.init: metric: jvm.memory.pool.init - desc: current memory pool usage + desc: initial memory pool size Usage.max: metric: jvm.memory.pool.max - desc: current memory pool usage + desc: max memory pool size Usage.used: metric: jvm.memory.pool.used desc: current memory pool usage + # Rule for Threading metrics - bean: java.lang:type=Threading mapping: ThreadCount: metric: jvm.threads.count unit: "{thread}" - desc: number of threads + desc: current number of thread count \ No newline at end of file diff --git a/jmx-scraper/templates/registry/rules/jvm.yaml.j2 b/jmx-scraper/templates/registry/rules/jvm.yaml.j2 new file mode 100644 index 000000000..d75f40985 --- /dev/null +++ b/jmx-scraper/templates/registry/rules/jvm.yaml.j2 @@ -0,0 +1,124 @@ +--- +{# Define a variable for the common "jvm.memory." prefix #} +{%- set jvm_memory_prefix = "jvm.memory." %} +rules: + # Rule for ClassLoading metrics + - bean: java.lang:type=ClassLoading + mapping: + LoadedClassCount: + {%- set m_class_loaded = (ctx.groups | selectattr("id", "equalto", "jvm.classes.loaded") | first) %} + metric: {{ m_class_loaded.metric_name | safe }} + type: gauge + unit: "{{ m_class_loaded.unit | safe }}" + desc: {{ m_class_loaded.brief | safe }} + + # Rule for Garbage Collector metrics + - bean: java.lang:type=GarbageCollector,name=* + mapping: + {%- for m in ctx.groups if m.id in ["jvm.gc.collections.count", "jvm.gc.collections.elapsed"] -%} + {%- if m.id == "jvm.gc.collections.count" %} + CollectionCount: + metric: {{ m.id | safe }} + type: {{ m.instrument | safe }} + unit: "{{ m.unit | safe }}" + desc: {{ m.brief | safe }} + metricAttribute: + name: param(name) + {%- elif m.id == "jvm.gc.collections.elapsed" %} + CollectionTime: + metric: {{ m.id | safe}} + type: {{ m.instrument | safe }} + unit: {{ m.unit | safe }} + desc: {{ m.brief | safe }} + metricAttribute: + name: param(name) + {%- endif %} + {%- endfor %} + + # Rule for Heap and Non-Heap Memory metrics + - bean: java.lang:type=Memory + unit: By + prefix: {{ jvm_memory_prefix | safe }} + mapping: + {%- for m in ctx.groups if m.id.startswith(jvm_memory_prefix + "heap") %} + {%- if m.id == jvm_memory_prefix + "heap.committed" %} + HeapMemoryUsage.committed: + metric: {{ m.id | replace(jvm_memory_prefix, "") | safe }} + desc: {{ m.brief | safe }} + type: gauge + {%- elif m.id == jvm_memory_prefix + "heap.init" %} + HeapMemoryUsage.init: + metric: {{ m.id | replace(jvm_memory_prefix, "") | safe }} + desc: {{ m.brief | safe }} + type: gauge + {%- elif m.id == jvm_memory_prefix + "heap.max" %} + HeapMemoryUsage.max: + metric: {{ m.id | replace(jvm_memory_prefix, "") | safe }} + desc: {{ m.brief | safe }} + type: gauge + {%- elif m.id == jvm_memory_prefix + "heap.used" %} + HeapMemoryUsage.used: + metric: {{ m.id | replace(jvm_memory_prefix, "") | safe }} + desc: {{ m.brief | safe }} + type: gauge + {%- endif %} + {%- endfor %} + {%- for m in ctx.groups if m.id.startswith(jvm_memory_prefix + "nonheap") %} + {%- if m.id == jvm_memory_prefix + "nonheap.committed" %} + NonHeapMemoryUsage.committed: + metric: {{ m.id | replace(jvm_memory_prefix, "") | safe }} + desc: {{ m.brief | safe }} + type: gauge + {%- elif m.id == jvm_memory_prefix + "nonheap.init" %} + NonHeapMemoryUsage.init: + metric: {{ m.id | replace(jvm_memory_prefix, "") | safe }} + desc: {{ m.brief | safe }} + type: gauge + {%- elif m.id == jvm_memory_prefix + "nonheap.max" %} + NonHeapMemoryUsage.max: + metric: {{ m.id | replace(jvm_memory_prefix, "") | safe }} + desc: {{ m.brief | safe }} + type: gauge + {%- elif m.id == jvm_memory_prefix + "nonheap.used" %} + NonHeapMemoryUsage.used: + metric: {{ m.id | replace(jvm_memory_prefix, "") | safe }} + desc: {{ m.brief | safe }} + type: gauge + {%- endif %} + {%- endfor %} + + # Rule for Memory Pool metrics + - bean: java.lang:type=MemoryPool,name=* + type: gauge + unit: By + metricAttribute: + name: param(name) + mapping: + {%- for m in ctx.groups if m.id.startswith(jvm_memory_prefix + "pool") %} + {%- if m.id == jvm_memory_prefix + "pool.committed" %} + Usage.committed: + metric: {{ m.id | safe }} + desc: {{ m.brief | safe }} + {%- elif m.id == jvm_memory_prefix + "pool.init" %} + Usage.init: + metric: {{ m.id | safe }} + desc: {{ m.brief | safe }} + {%- elif m.id == jvm_memory_prefix + "pool.max" %} + Usage.max: + metric: {{ m.id | safe }} + desc: {{ m.brief | safe }} + {%- elif m.id == jvm_memory_prefix + "pool.used" %} + Usage.used: + metric: {{ m.id | safe }} + desc: {{ m.brief | safe }} + {%- endif %} + {%- endfor %} + + # Rule for Threading metrics + - bean: java.lang:type=Threading + mapping: + ThreadCount: + {%- set m_threads_count = (ctx.groups | selectattr("id", "equalto", "jvm.threads.count") | first) %} + metric: {{ m_threads_count.id | safe}} + unit: "{{ m_threads_count.unit | safe }}" + desc: {{ m_threads_count.brief | safe }} diff --git a/jmx-scraper/weaver.yaml b/jmx-scraper/weaver.yaml new file mode 100644 index 000000000..a41af21ec --- /dev/null +++ b/jmx-scraper/weaver.yaml @@ -0,0 +1,4 @@ +templates: + - pattern: jvm.yaml.j2 + filter: '.' + application_mode: single