diff --git a/jmx-scraper/Makefile b/jmx-scraper/Makefile new file mode 100644 index 000000000..a11fb1247 --- /dev/null +++ b/jmx-scraper/Makefile @@ -0,0 +1,56 @@ +# https://github.com/open-telemetry/weaver/releases +# v0.18.0 +WEAVER_CONTAINER=otel/weaver@sha256:5425ade81dc22ddd840902b0638b4b6a9186fb654c5b50c1d1ccd31299437390 + +# Next - we want to run docker as our local file user, so generated code is not +# owned by root, and we don't give unnecessary access. +# +# Determine if "docker" is actually podman +DOCKER_VERSION_OUTPUT := $(shell docker --version 2>&1) +DOCKER_IS_PODMAN := $(shell echo $(DOCKER_VERSION_OUTPUT) | grep -c podman) +ifeq ($(DOCKER_IS_PODMAN),0) + DOCKER_COMMAND := docker +else + DOCKER_COMMAND := podman +endif +DOCKER_RUN=$(DOCKER_COMMAND) run +DOCKER_USER=$(shell id -u):$(shell id -g) +DOCKER_USER_IS_HOST_USER_ARG=-u $(DOCKER_USER) +ifeq ($(DOCKER_COMMAND),podman) + # On podman, additional arguments are needed to make "-u" work + # correctly with the host user ID and host group ID. + # + # Error: OCI runtime error: crun: setgroups: Invalid argument + DOCKER_USER_IS_HOST_USER_ARG=--userns=keep-id -u $(DOCKER_USER) +endif + +# Generate the rules files from the model +.PHONY: generate-rules +generate-rules: + mkdir -p output + $(DOCKER_RUN) \ + $(DOCKER_USER_IS_HOST_USER_ARG) \ + --mount 'type=bind,source=$(PWD)/model,target=/home/weaver/model,readonly' \ + --mount 'type=bind,source=$(PWD)/templates,target=/home/weaver/templates,readonly' \ + --mount 'type=bind,source=$(PWD)/output,target=/home/weaver/output' \ + --mount 'type=bind,source=$(PWD),target=/home/weaver' \ + ${WEAVER_CONTAINER} registry generate \ + --registry /home/weaver/model \ + rules \ + --future \ + /home/weaver/output + cp ./output/jvm.yaml ./src/main/resources/jvm.yaml + +# for Debugging purposes only: run a shell in the weaver container +.PHONY: weaver-shell +weaver-shell: + mkdir -p output + @echo "DOCKER_USER_IS_HOST_USER_ARG is: $(DOCKER_USER_IS_HOST_USER_ARG)" + $(DOCKER_RUN) \ + $(DOCKER_USER_IS_HOST_USER_ARG) \ + --mount 'type=bind,source=$(PWD)/model,target=/home/weaver/model,readonly' \ + --mount 'type=bind,source=$(PWD)/templates,target=/home/weaver/templates,readonly' \ + --mount 'type=bind,source=$(PWD)/output,target=/home/weaver/output' \ + --mount 'type=bind,source=$(PWD),target=/home/weaver' \ + --entrypoint sh \ + -it ${WEAVER_CONTAINER} 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