{"slug": "send-metrics-from-java-application-using-opentelemetry", "title": "Send Metrics from Java Application using OpenTelemetry", "summary": "SigNoz released a guide for sending custom and JVM runtime metrics from Java applications to its observability platform using the OpenTelemetry Java agent, enabling developers to monitor application performance with minimal code changes.", "body_md": "This guide shows you how to send custom and JVM runtime metrics from your Java application to SigNoz using the OpenTelemetry Java agent.\n\nPrerequisites\n\n-\n[Java 8+](https://github.com/open-telemetry/opentelemetry-java#requirements) - A SigNoz Cloud account or self-hosted SigNoz instance\n\nSend metrics to SigNoz\n\nStep 1. Download the OpenTelemetry Java agent\n\n```\nwget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar\n```\n\nStep 2. Set environment variables\n\n```\nexport OTEL_SERVICE_NAME=\"<service-name>\"\nexport OTEL_EXPORTER_OTLP_ENDPOINT=\"https://ingest.<region>.signoz.cloud:443\"\nexport OTEL_EXPORTER_OTLP_HEADERS=\"signoz-ingestion-key=<your-ingestion-key>\"\nexport OTEL_METRICS_EXPORTER=\"otlp\"\nexport OTEL_METRIC_EXPORT_INTERVAL=\"60000\"\nexport OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=\"delta\"\nexport OTEL_TRACES_EXPORTER=\"none\"\nexport OTEL_LOGS_EXPORTER=\"none\"\n```\n\nReplace the following:\n\n`<region>`\n\n: Your SigNoz Cloud region. See[endpoints](https://signoz.io/docs/ingestion/signoz-cloud/overview/#endpoint).`<your-ingestion-key>`\n\n: Your SigNoz[ingestion key](https://signoz.io/docs/ingestion/signoz-cloud/keys/).`<service-name>`\n\n: A descriptive name for your service (e.g.,`payment-service`\n\n).\n\nStep 3. Add OpenTelemetry API dependency\n\nAdd the OpenTelemetry API to your project. The agent provides the implementation at runtime.\n\n```\n<dependency>\n  <groupId>io.opentelemetry</groupId>\n  <artifactId>opentelemetry-api</artifactId>\n  <version>1.57.0</version>\n</dependency>\nimplementation 'io.opentelemetry:opentelemetry-api:1.57.0'\n```\n\nThe version above is current as of this writing. Check the [OpenTelemetry Java releases](https://github.com/open-telemetry/opentelemetry-java/releases) for the latest versions.\n\nStep 4. Add custom metrics to your application\n\nUse `GlobalOpenTelemetry.getMeter()`\n\nto create metrics. The agent configures the MeterProvider automatically.\n\n``` python\nimport io.opentelemetry.api.GlobalOpenTelemetry;\nimport io.opentelemetry.api.metrics.LongCounter;\nimport io.opentelemetry.api.metrics.Meter;\n\npublic class OrderService {\n    private static final Meter meter = GlobalOpenTelemetry.getMeter(\"order-service\");\n    private static final LongCounter ordersCounter = meter\n            .counterBuilder(\"orders.processed\")\n            .setDescription(\"Total number of orders processed\")\n            .build();\n\n    public void processOrder(String orderId) {\n        // Your business logic here\n        ordersCounter.add(1);\n    }\n}\n```\n\nThis example shows a Counter, which only increases. OpenTelemetry supports other metric types like UpDownCounter, Histogram, and Observable Gauge. See [Custom Metrics Examples](#custom-metrics-examples) for complete examples of each type.\n\nStep 5. Run your application\n\n```\njava -javaagent:./opentelemetry-javaagent.jar -jar your-app.jar\n```\n\nStep 1. Add the agent to your Dockerfile\n\n```\nFROM eclipse-temurin:17-jre\nWORKDIR /app\n\nCOPY target/<my-app>.jar app.jar\n\nRUN wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar -O opentelemetry-javaagent.jar\n\nENTRYPOINT [\"java\", \"-javaagent:/app/opentelemetry-javaagent.jar\", \"-jar\", \"app.jar\"]\n```\n\nStep 2. Add environment variables to your deployment\n\n```\nenv:\n- name: OTEL_SERVICE_NAME\n  value: '<service-name>'\n- name: OTEL_EXPORTER_OTLP_ENDPOINT\n  value: 'https://ingest.<region>.signoz.cloud:443'\n- name: OTEL_EXPORTER_OTLP_HEADERS\n  value: 'signoz-ingestion-key=<your-ingestion-key>'\n- name: OTEL_METRICS_EXPORTER\n  value: 'otlp'\n- name: OTEL_METRIC_EXPORT_INTERVAL\n  value: '60000'\n- name: OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE\n  value: 'delta'\n- name: OTEL_TRACES_EXPORTER\n  value: 'none'\n- name: OTEL_LOGS_EXPORTER\n  value: 'none'\n```\n\nReplace `<region>`\n\n, `<your-ingestion-key>`\n\n, and `<service-name>`\n\nwith your values.\n\nStep 3. Add OpenTelemetry API and custom metrics\n\nFollow Step 3 and Step 4 from the VM tab to add the dependency and custom metrics code.\n\nStep 1. Download the OpenTelemetry Java agent\n\n```\nInvoke-WebRequest -Uri \"https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar\" -OutFile \"opentelemetry-javaagent.jar\"\n```\n\nStep 2. Set environment variables\n\n```\n$env:OTEL_SERVICE_NAME = \"<service-name>\"\n$env:OTEL_EXPORTER_OTLP_ENDPOINT = \"https://ingest.<region>.signoz.cloud:443\"\n$env:OTEL_EXPORTER_OTLP_HEADERS = \"signoz-ingestion-key=<your-ingestion-key>\"\n$env:OTEL_METRICS_EXPORTER = \"otlp\"\n$env:OTEL_METRIC_EXPORT_INTERVAL = \"60000\"\n$env:OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE = \"delta\"\n$env:OTEL_TRACES_EXPORTER = \"none\"\n$env:OTEL_LOGS_EXPORTER = \"none\"\n```\n\nReplace `<region>`\n\n, `<your-ingestion-key>`\n\n, and `<service-name>`\n\nwith your values.\n\nStep 3. Add OpenTelemetry API and custom metrics\n\nFollow Step 3 and Step 4 from the VM tab to add the dependency and custom metrics code.\n\nStep 4. Run your application\n\n```\njava -javaagent:.\\opentelemetry-javaagent.jar -jar your-app.jar\n```\n\nStep 1. Add the agent to your Dockerfile\n\n```\nFROM eclipse-temurin:17-jre\nWORKDIR /app\n\nCOPY target/<my-app>.jar app.jar\n\nRUN wget https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar -O opentelemetry-javaagent.jar\n\nENV OTEL_SERVICE_NAME=\"<service-name>\"\nENV OTEL_EXPORTER_OTLP_ENDPOINT=\"https://ingest.<region>.signoz.cloud:443\"\nENV OTEL_EXPORTER_OTLP_HEADERS=\"signoz-ingestion-key=<your-ingestion-key>\"\nENV OTEL_METRICS_EXPORTER=\"otlp\"\nENV OTEL_METRIC_EXPORT_INTERVAL=\"60000\"\nENV OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=\"delta\"\nENV OTEL_TRACES_EXPORTER=\"none\"\nENV OTEL_LOGS_EXPORTER=\"none\"\n\nENTRYPOINT [\"java\", \"-javaagent:/app/opentelemetry-javaagent.jar\", \"-jar\", \"app.jar\"]\n```\n\nReplace `<my-app>.jar`\n\n, `<region>`\n\n, `<your-ingestion-key>`\n\n, and `<service-name>`\n\nwith your values.\n\nStep 2. Add OpenTelemetry API and custom metrics\n\nFollow Step 3 and Step 4 from the VM tab to add the dependency and custom metrics code.\n\nStep 3. Build and run\n\n```\ndocker build -t my-java-app .\ndocker run -p 8080:8080 my-java-app\n```\n\nOr pass environment variables at runtime:\n\n```\ndocker run -p 8080:8080 \\\n  -e OTEL_SERVICE_NAME=\"my-service\" \\\n  -e OTEL_EXPORTER_OTLP_ENDPOINT=\"https://ingest.<region>.signoz.cloud:443\" \\\n  -e OTEL_EXPORTER_OTLP_HEADERS=\"signoz-ingestion-key=<key>\" \\\n  -e OTEL_METRICS_EXPORTER=\"otlp\" \\\n  -e OTEL_METRIC_EXPORT_INTERVAL=\"60000\" \\\n  -e OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=\"delta\" \\\n  -e OTEL_TRACES_EXPORTER=\"none\" \\\n  -e OTEL_LOGS_EXPORTER=\"none\" \\\n  my-java-app\n```\n\nThe Java agent automatically generates HTTP metrics (`http.server.request.duration`\n\nand `http.client.request.duration`\n\n) for instrumented web frameworks like Spring Boot, JAX-RS, and Servlet containers. See the [HTTP metrics semantic conventions](https://opentelemetry.io/docs/specs/semconv/http/http-metrics/) for details.\n\nValidate\n\nOnce your application is running with the Java agent:\n\n- Trigger some application activity to generate metrics.\n- In SigNoz, go to\n**Metrics**>** Metrics Explorer**. - Search for your custom metric (e.g.,\n`orders.processed`\n\n). - JVM metrics like\n`jvm.memory.used`\n\nand`jvm.cpu.time`\n\nare collected automatically by the agent. See[JVM Runtime Metrics](#jvm-runtime-metrics)for the full list.\n\nJVM Runtime Metrics\n\n[JVM Runtime Metrics](#jvm-runtime-metrics)\n\nThe Java agent automatically collects JVM runtime metrics with zero configuration. These metrics are exported alongside any custom metrics you define, providing visibility into memory usage, garbage collection, threads, and CPU utilization.\n\nExported Metrics\n\n| Category | Metric | Description |\n|---|---|---|\nMemory | `jvm.memory.used` | Current memory usage by memory pool |\n`jvm.memory.committed` | Committed memory by memory pool | |\n`jvm.memory.limit` | Maximum memory available by memory pool | |\n`jvm.memory.used_after_last_gc` | Memory used after the last garbage collection | |\nGC | `jvm.gc.duration` | Time spent in garbage collection (histogram) |\nThreads | `jvm.thread.count` | Number of executing threads |\nClasses | `jvm.class.loaded` | Number of classes loaded since JVM start |\n`jvm.class.unloaded` | Total number of classes unloaded | |\n`jvm.class.count` | Number of classes currently loaded | |\nCPU | `jvm.cpu.time` | CPU time used by the process |\n`jvm.cpu.count` | Number of available processors | |\n`jvm.cpu.recent_utilization` | Recent CPU utilization |\n\nVisualize Runtime Metrics\n\nImport the pre-built JVM dashboard to visualize these metrics:\n\n- Download the\n[JVM dashboard JSON](https://github.com/SigNoz/dashboards/tree/main/jvm) - In SigNoz, go to\n**Dashboards**→** New Dashboard**→** Import JSON** - Paste the JSON content or upload the file\n\nSee the [JVM Dashboard Template](https://signoz.io/docs/dashboards/dashboard-templates/jvm-metrics/) for details on available panels.\n\nCustom Metrics Examples\n\n[Custom Metrics Examples](#custom-metrics-examples)\n\nOpenTelemetry provides four metric instrument types. Each example shows how to create and use the instrument.\n\nCounter\n\nA value that only increases (e.g., total requests, orders processed).\n\n``` python\nimport io.opentelemetry.api.GlobalOpenTelemetry;\nimport io.opentelemetry.api.metrics.LongCounter;\nimport io.opentelemetry.api.metrics.Meter;\n\nMeter meter = GlobalOpenTelemetry.getMeter(\"my-service\");\n\nLongCounter requestCounter = meter\n        .counterBuilder(\"http.requests.total\")\n        .setDescription(\"Total number of HTTP requests\")\n        .build();\n\n// Increment the counter\nrequestCounter.add(1);\n```\n\nUpDownCounter\n\nA value that can increase or decrease (e.g., queue size, active connections).\n\n``` python\nimport io.opentelemetry.api.GlobalOpenTelemetry;\nimport io.opentelemetry.api.metrics.LongUpDownCounter;\nimport io.opentelemetry.api.metrics.Meter;\n\nMeter meter = GlobalOpenTelemetry.getMeter(\"my-service\");\n\nLongUpDownCounter activeRequests = meter\n        .upDownCounterBuilder(\"http.requests.active\")\n        .setDescription(\"Number of active requests\")\n        .build();\n\n// Increment when request starts\nactiveRequests.add(1);\n\n// Decrement when request ends\nactiveRequests.add(-1);\n```\n\nHistogram\n\nA distribution of values (e.g., request duration, response size).\n\n``` python\nimport io.opentelemetry.api.GlobalOpenTelemetry;\nimport io.opentelemetry.api.metrics.DoubleHistogram;\nimport io.opentelemetry.api.metrics.Meter;\n\nMeter meter = GlobalOpenTelemetry.getMeter(\"my-service\");\n\nDoubleHistogram requestDuration = meter\n        .histogramBuilder(\"http.request.duration\")\n        .setDescription(\"HTTP request duration\")\n        .setUnit(\"ms\")\n        .build();\n\n// Record a duration value\nlong startTime = System.currentTimeMillis();\n// ... process request ...\nrequestDuration.record(System.currentTimeMillis() - startTime);\n```\n\nGauge\n\nA point-in-time value via callback (e.g., temperature, memory usage).\n\n``` python\nimport io.opentelemetry.api.GlobalOpenTelemetry;\nimport io.opentelemetry.api.metrics.Meter;\nimport io.opentelemetry.api.metrics.ObservableDoubleGauge;\n\nMeter meter = GlobalOpenTelemetry.getMeter(\"my-service\");\n\nObservableDoubleGauge memoryGauge = meter\n        .gaugeBuilder(\"app.memory.usage\")\n        .setDescription(\"Current memory usage\")\n        .setUnit(\"By\")\n        .buildWithCallback(measurement -> {\n            Runtime runtime = Runtime.getRuntime();\n            measurement.record(runtime.totalMemory() - runtime.freeMemory());\n        });\n```\n\nTroubleshooting\n\n[Troubleshooting](#troubleshooting)\n\nMetrics not appearing?\n\n**Check environment variables:**\n\n```\necho $OTEL_EXPORTER_OTLP_ENDPOINT\necho $OTEL_METRICS_EXPORTER\n```\n\n**Enable debug logging:**\n\n```\nOTEL_LOG_LEVEL=debug java -javaagent:./opentelemetry-javaagent.jar -jar app.jar\n```\n\n**Verify agent is attached:**\nLook for this log line on startup:\n\n```\n[otel.javaagent] INFO io.opentelemetry.javaagent.tooling.VersionLogger - opentelemetry-javaagent - version: X.X.X\n```\n\nGlobalOpenTelemetry.getMeter() returns no-op?\n\nMake sure the Java agent is attached. Without the agent, `GlobalOpenTelemetry`\n\nreturns a no-op implementation.\n\n```\n# Correct - agent flag before -jar\njava -javaagent:./agent.jar -jar app.jar\n\n# Wrong - agent flag after -jar is ignored\njava -jar app.jar -javaagent:./agent.jar\n```\n\nMetrics delayed or not updating?\n\n`OTEL_METRIC_EXPORT_INTERVAL`\n\ncontrols how often metrics are exported in milliseconds. The default is 60000 (60 seconds), so metrics may take up to a minute to appear.\n\nTo reduce the interval for testing:\n\n```\nexport OTEL_METRIC_EXPORT_INTERVAL=10000  # 10 seconds\n```\n\nAuthentication errors\n\nIf you see \"Unauthorized\" or \"403 Forbidden\":\n\n- Verify your ingestion key is correct in\n`OTEL_EXPORTER_OTLP_HEADERS`\n\n- Ensure the header format is exactly:\n`signoz-ingestion-key=<your-key>`\n\n(no extra spaces)\n\nSetup OpenTelemetry Collector (Optional)\n\n[Setup OpenTelemetry Collector (Optional)](#setup-opentelemetry-collector-optional)\n\nWhat is the OpenTelemetry Collector?\n\nThink of the OTel Collector as a middleman between your app and SigNoz. Instead of your application sending data directly to SigNoz, it sends everything to the Collector first, which then forwards it along.\n\nWhy use it?\n\n**Cleaning up data**- Filter out noisy metrics you don't care about, or remove sensitive info before it leaves your servers.** Keeping your app lightweight**- Let the Collector handle batching, retries, and compression instead of your application code.** Adding context automatically**- The Collector can tag your data with useful info like which Kubernetes pod or cloud region it came from.** Future flexibility**- Want to send data to multiple backends later? The Collector makes that easy without changing your app.\n\nSee [Switch from direct export to Collector](https://signoz.io/docs/opentelemetry-collection-agents/opentelemetry-collector/switch-to-collector/) for step-by-step instructions to convert your setup.\n\nFor more details, see [Why use the OpenTelemetry Collector?](https://signoz.io/docs/opentelemetry-collection-agents/opentelemetry-collector/why-to-use-collector/) and the [Collector configuration guide](https://signoz.io/docs/opentelemetry-collection-agents/opentelemetry-collector/configuration/).\n\nNext Steps\n\n[Create Dashboards](https://signoz.io/docs/userguide/manage-dashboards/)to visualize your custom metrics.[Set up Alerts](https://signoz.io/docs/setup-alerts-notification/)on your metrics.- Instrument your Java application with\n[traces](https://signoz.io/docs/instrumentation/java/opentelemetry-java/)and[logs](https://signoz.io/docs/logs-management/send-logs/java-logs/)for complete observability.", "url": "https://wpnews.pro/news/send-metrics-from-java-application-using-opentelemetry", "canonical_source": "https://signoz.io/docs/metrics-management/send-metrics/applications/opentelemetry-java", "published_at": "2026-06-23 00:00:00+00:00", "updated_at": "2026-06-24 06:45:24.024568+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["SigNoz", "OpenTelemetry", "Java"], "alternates": {"html": "https://wpnews.pro/news/send-metrics-from-java-application-using-opentelemetry", "markdown": "https://wpnews.pro/news/send-metrics-from-java-application-using-opentelemetry.md", "text": "https://wpnews.pro/news/send-metrics-from-java-application-using-opentelemetry.txt", "jsonld": "https://wpnews.pro/news/send-metrics-from-java-application-using-opentelemetry.jsonld"}}