Heroku OpenTelemetry Signals and Attributes Reference
Last updated August 29, 2025
Table of Contents
This article covers Heroku’s OpenTelemetry (OTel) signals and attributes. If you’re new to OpenTelemetry, additional articles are available:
Signals
Heroku Telemetry provides comprehensive observability for your applications by leveraging the OpenTelemetry framework. We deliver a complete view by collecting signals from the following sources:
- Application telemetry: Heroku provides application metrics for all running applications by default. Users can also send additional traces, metrics, and logs from their applications via an OpenTelemetry gRPC or HTTP exporters, as well as all
stdout
andstderr
logs. - First-party services telemetry: We provide visibility into Heroku’s own services and add-ons. We provide logs from the Heroku Platform API, metrics, traces, and logs from the Heroku Router. We also provide logs from add-ons such as Heroku Key-Value, Heroku Postgres, Heroku Scheduler, and Apache Kafka on Heroku.
For additional language-specific telemetry data, instrument your application with one of the open-source SDKs.
An attribute provides additional context or metadata about a signal. The availability of the following signals and attributes depends on your application’s configuration:
Common Resource Attributes
These attributes are automatically added to all application signals at the resource attribute level and aren’t user-configurable.
Although you can set these attributes at the log, metric, or trace level, be aware that your values may override the resource-level attributes when exporting these signals.
Service Attributes
Heroku provides comprehensive out-of-the-box telemetry, ensuring consistency by adhering to Semantic Conventions. Service level attributes are automatically added to all telemetry, which users can configure within their applications.
For application telemetry, it is possible to set service-level attributes using OpenTelemetry (OTel) exporters within application code to export traces, logs, and metrics. However, we recommend configuring these attributes on the application itself by setting the OTEL_RESOURCE_ATTRIBUTES
and OTEL_SERVICE_NAME
config variables. You can’t customize first-party service signals.
Attribute | Type | Description | Example | User-Configurable |
---|---|---|---|---|
service.instance.id | string | unique identifier for dyno | "web-12a34bcd56-7efgh" |
no, Heroku-provided value |
service.name | string | service name of application, if not set, defaults to application name | "my-service-app" |
yes, and Heroku provides default |
service.namespace | string | namespace name for service name | "my-test-namespace" |
yes, and Heroku provides default |
service.version | string | version of app release when telemetry generated | "v19" |
yes, and Heroku provides default |
Heroku Cloud Provider Attributes
In addition to the Service attributes described above, Heroku automatically adds Cloud Provider specific information to all telemetry data. These attributes are fixed and aren’t customizable unless specified.
Attribute | Type | Description | Example | User-Configurable |
---|---|---|---|---|
cloud.provider | string | name of cloud provider, appears on all signals | "heroku" |
no, Heroku-provided default |
heroku.app.id | string | unique identifier of app | "9daa2797-e49b-4624-932f-ec3f9688e3da" |
no, Heroku-provided value |
heroku.app.name | string | name of application | "test-app" |
yes, set on application creation or renaming |
heroku.release.id | string | unique identifier of app release | "release-afc4d88c-7d89-4bc6-b364-7658cd60ba57" |
no, Heroku-provided value |
heroku.release.version | string | version of app release when telemetry is generated | "v19" |
no, Heroku-provided value |
heroku.workload.id | string | workload identifier, as defined by the process type | "web" |
no, Heroku-provided value |
Application Telemetry
Dyno Runtime Metrics
Heroku captures dyno-level metrics. We follow the semantic convention for container metrics.
Instrument Type | Unit | Description | Example | User-Configurable |
---|---|---|---|---|
container.cpu_usage | double | dyno CPU usage, as a percentage of capacity | 0.00029895 |
no, Heroku-provided value |
container.memory.available | integer | dyno memory available, in bytes | 530911232 |
no, Heroku-provided value |
container.memory.usage | integer | dyno total memory usage, in bytes | 6291456 |
no, Heroku-provided value |
container.uptime | integer | time elapsed since dyno started, in seconds | 348223 |
no, Heroku-provided value |
Example of a JSON dyno metric:
{
"resource_schema_url":null,
"resource_attributes":{
"heroku.app.id":"c3d3df33-8afb-4323-ac49-a9bf41a50dd1",
"heroku.workload.id":"web",
"heroku.release.version":"v6",
"service.version":"v6",
"heroku.release.id":"release-3bd90b80-16a1-4f5b-9465-a61e1b7464d4",
"cloud.provider":"heroku",
"service.instance.id":"web-67dbf78464-q6kc6",
"heroku.app.name":"test-app",
"service.namespace":"test-namespace",
"service.name":"test-app"
},
"scope_metrics":[
{
"scope_schema_url":null,
"instrumentation_scope":"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/kubeletstatsreceiver 0.0.9",
"metrics":[
{
"descriptor":{
"name":"container.memory.available",
"description":"Container memory available",
"unit":"By",
"data_type":"Gauge"
},
"number_data_points":[
{
"start_timestamp":"2025-08-13T20:23:20Z",
"timestamp":"2025-08-13T20:45:15.767066105Z",
"value":460095488
}
]
},
{
"descriptor":{
"name":"container.memory.usage",
"description":"Container memory usage",
"unit":"By",
"data_type":"Gauge"
},
"number_data_points":[
{
"start_timestamp":"2025-08-13T20:23:20Z",
"timestamp":"2025-08-13T20:45:15.767066105Z",
"value":76775424
}
]
},
{
"descriptor":{
"name":"container.uptime",
"description":"The time since the container started",
"unit":"s",
"data_type":"Sum",
"is_monotonic":true,
"aggregation_temporality":"Cumulative"
},
"number_data_points":[
{
"start_timestamp":"2025-08-13T20:23:20Z",
"timestamp":"2025-08-13T20:45:15.767066105Z",
"value":1315
}
]
},
{
"descriptor":{
"name":"container.cpu.usage",
"description":"Container cpu utilization as a ratio of the container's limits",
"unit":"1",
"data_type":"Gauge"
},
"number_data_points":[
{
"start_timestamp":"2025-08-13T20:23:20Z",
"timestamp":"2025-08-13T20:45:15.767066105Z",
"value":0.001771
}
]
}
]
}
]
}
Router Signals
The Heroku Router manages web application traffic, automatically directing incoming HTTP requests to the appropriate web dynos within the Heroku platform. The router emits various signals.
Router Trace Spans
Router traces always have the service.name
attribute set to heroku-router
. They include standard Heroku attributes, along with specific additions relevant to the request.
Attribute | Type | Description | Example | User-Configurable |
---|---|---|---|---|
client.address | string | IP address of forwarding client | “204.14.236.213” | no, Heroku-provided value |
heroku.router.connect | double | time taken to establish connection, in milliseconds | 0.000873262 | no, Heroku-provided value |
heroku.router.service | double | time taken to service the request, in milliseconds | 0.000621714 | no, Heroku-provided value |
http.request.method | string | type of data request | “GET” | no, Heroku-provided value |
http.response.status_code | integer | HTTP status code | 200 | no, Heroku-provided value |
http.response.body.size | integer | size of response, in bytes | 8826 | no, Heroku-provided value |
server.address | string | host identifier the HTTP request is sent to | “example-app.com” | no, Heroku-provided value |
tls.protocol.version | string | version of TLS protocol | “tls1.3” | no, Heroku-provided value |
Example of a JSON router trace:
{
"resource_schema_url":"https://opentelemetry.io/schemas/1.6.1",
"resource_attributes":{
"heroku.dyno.id":"web-67dbf78464-q6kc6",
"service.instance.id":"web-67dbf78464-q6kc6",
"heroku.app.id":"c3d3df33-8afb-4323-ac49-a9bf41a50dd1",
"heroku.workload.id":"web",
"heroku.release.version":"v6",
"service.version":"v6",
"heroku.release.id":"release-3bd90b80-16a1-4f5b-9465-a61e1b7464d4",
"cloud.provider":"heroku",
"heroku.app.name":"test-app",
"service.namespace":"test-namespace",
"service.name":"test-app"
},
"scope_spans":[
{
"scope_schema_url":null,
"instrumentation_scope":"heroku-router",
"spans":[
{
"trace_id":"4b26d26a52bcf26c31f9637a350c5df9",
"parent_id":null,
"id":"147c90133ba98656",
"name":"customer.request",
"kind":"internal",
"start_time":"2025-08-13T21:18:57.589468318Z",
"end_time":"2025-08-13T21:18:57.59109646Z",
"status_code":1,
"status_message":null,
"attributes":{
"client.address":"20.171.207.158",
"duration_ms":1.628142,
"heroku.router.connect":0.000873262,
"heroku.router.service":0.000621714,
"http.request.method":"GET",
"http.response.body.size":19,
"http.response.status_code":404,
"network.protocol.name":"http",
"server.address":"test-app-996f3244724d.redbud-virginia.herokuapp.com",
"span.num_events":0,
"span.num_links":0,
"tls.protocol.version":"tls1.3",
"type":"internal",
"url.path":"/",
"url.query":""
}
}
]
}
]
}
Router Metrics
Router metrics offer request duration statistics, including the standard common attributes, as well as the following attributes. The service.name
is always heroku-router
.
Instrument Type | Unit | Description | Example | User-Configurable |
---|---|---|---|---|
http.server.request.duration | histogram | duration of the incoming HTTP server requests | no, Heroku-provided value |
Example of a JSON router metrics:
{
"resource_schema_url":"https://opentelemetry.io/schemas/1.6.1",
"resource_attributes":{
"service.instance.id":"web-67dbf78464-q6kc6",
"heroku.app.id":"c3d3df33-8afb-4323-ac49-a9bf41a50dd1",
"heroku.workload.id":"web",
"heroku.release.version":"v6",
"service.version":"v6",
"heroku.release.id":"release-3bd90b80-16a1-4f5b-9465-a61e1b7464d4",
"cloud.provider":"heroku",
"heroku.app.name":"test-app",
"service.namespace":"test-namespace",
"service.name":"test-app"
},
"scope_metrics":[
{
"scope_schema_url":null,
"instrumentation_scope":"otel-logger",
"metrics":[
{
"descriptor":{
"name":"http.server.request.duration",
"description":"The duration of incoming HTTP requests.",
"unit":"ms",
"data_type":"Histogram"
},
"summary_data_points":[
{
"time":"2025-08-13T21:19:27Z",
"sum":0.001518499,
"count":1,
"quantile_values":[
{
"quantile":0.001,
"value":0.0015184986321850637
},
{
"quantile":0.01,
"value":0.0015184986321850637
},
{
"quantile":0.05,
"value":0.0015184986321850637
},
{
"quantile":0.1,
"value":0.0015184986321850637
},
{
"quantile":0.2,
"value":0.0015184986321850637
},
{
"quantile":0.25,
"value":0.0015184986321850637
},
{
"quantile":0.5,
"value":0.0015184986321850637
},
{
"quantile":0.75,
"value":0.0015184986321850637
},
{
"quantile":0.8,
"value":0.0015184986321850637
},
{
"quantile":0.9,
"value":0.0015184986321850637
},
{
"quantile":0.95,
"value":0.0015184986321850637
},
{
"quantile":0.99,
"value":0.0015184986321850637
},
{
"quantile":0.999,
"value":0.0015184986321850637
}
]
}
]
}
]
}
]
}
Router Logs
Router logs include standard Heroku attributes in addition to the following attributes. The service.name
is always heroku-router
.
Attribute | Type | Description | Example | User-Configurable |
---|---|---|---|---|
body | string | body of router log | “at=info method=GET path=\”/js/twint_ch.js\“ …” | no, Heroku-provided value |
span_id | string | unique identifier of processing span | “051581bf3cb55c13”, | no, Heroku-provided value |
trace_id | string | unique identifier of trace | “a7d348b6311009c36dda66fd7e6b0685” | no, Heroku-provided value |
severity_number | integer | numerical value of severity | 9 | no, Heroku-provided value |
severity_text | string | severity of an event eg: “Critical”, “Warning”, or “Info” |
“Info” | no, Heroku-provided value |
Example of a JSON router logs:
{
"resource_schema_url":"https://opentelemetry.io/schemas/1.6.1",
"resource_attributes":{
"service.instance.id":"web-67dbf78464-q6kc6",
"heroku.app.id":"c3d3df33-8afb-4323-ac49-a9bf41a50dd1",
"heroku.workload.id":"web",
"heroku.release.version":"v6",
"service.version":"v6",
"heroku.release.id":"release-3bd90b80-16a1-4f5b-9465-a61e1b7464d4",
"cloud.provider":"heroku",
"heroku.app.name":"test-app",
"service.namespace":"test-namespace",
"service.name":"test-app"
},
"scope_logs":[
{
"scope_schema_url":null,
"instrumentation_scope":"otel-logger",
"log_records":[
{
"observed_timestamp":"2025-08-13T21:18:57.590973861Z",
"timestamp":"2025-08-13T21:18:57.590973861Z",
"severity_text":"info",
"severity_number":9,
"body":"at=info method=GET path=\"/\" host=test-app-996f3244724d.test.herokuapp.com",
"attributes":{
"library.name":"heroku-router",
"meta.annotation_type":"span_event",
"flags":"1"
},
"trace_id":"4b26d26a52bcf26c31f9637a350c5df9",
"span_id":"147c90133ba98656"
}
]
}
]
}
Heroku Platform API Logs
Platform Logs
Heroku Platform API logs record administrative actions, like dyno scaling and other management commands, performed on applications. To filter all Heroku API Platform signals, use the service.name
attribute with the value heroku-api
.
Attribute | Type | Description | Example | User-Configurable |
---|---|---|---|---|
body | string | body of API log | "Release v6 created by user heroku-postgresql@addons.heroku.com" |
no, Heroku-provided value |
cloud.provider | string | name of cloud provider, appears on all signals | "heroku" |
no, Heroku-provided default |
heroku.app.id | string | unique identifier of app | "9daa2797-e49b-4624-932f-ec3f9688e3da" |
no, Heroku-provided value |
heroku.app.name | string | application name | "test-app" |
yes, set on application creation or renaming |
service.name | string | service name of the signals source | "heroku-api" |
no, Heroku-provided value |
service.namespace | string | service namespace of the application | "test-namespace" |
no, Heroku-provided value |
severity_number | integer | numerical value of severity | 9 |
no, Heroku-provided value |
severity_text | string | severity of an event eg: “Critical”, “Warning”, or “Info” |
"Info" |
no, Heroku-provided value |
Example of a JSON Heroku Platform API log:
{
"resource_schema_url":null,
"resource_attributes":{
"service.name":"heroku-api",
"cloud.provider":"heroku",
"heroku.app.name":"test-app",
"heroku.app.id":"c3d3df33-8afb-4323-ac49-a9bf41a50dd1",
"service.namespace":"test-namespace"
},
"scope_logs":[
{
"scope_schema_url":null,
"instrumentation_scope":null,
"log_records":[
{
"observed_timestamp":"1970-01-01T00:00:00Z",
"timestamp":"2025-08-13T20:58:50Z",
"severity_text":"Info",
"severity_number":9,
"body":"Release v6 created by user heroku-postgresql@addons.heroku.com",
"flags":0
}
]
}
]
}
Other First-Party Service Signals
Signals relevant to the application are also transmitted from first-party add-ons. These signals, in addition to those directly originating from the application, include a service.name
attribute indicating the source service:
heroku-postgresql
: For Heroku Postgres logsheroku-redis
: For Heroku Key-Value Store logsheroku-kafka
: For Apache Kafka on Heroku logsscheduler
: for Heroku Scheduler logs
Heroku Postgres
Postgres Service and Metric Logs
Heroku Postgres, a managed SQL database service offered by Heroku, captures all PostgreSQL logs, including executed queries, connections, and instance status. To filter all Heroku Postgres signals, use the service.name
attribute with the value heroku-postgresql
.
Name | Type | Description | Example | User-Configurable |
---|---|---|---|---|
body | string | body of API log | "at=info method=GET path=\"/js/twint_ch.js\" ..." |
no, Heroku-provided value |
cloud.provider | string | name of cloud provider, appears on all signals | "heroku" |
no, Heroku-provided default |
heroku.app.id | string | unique identifier of app | "9daa2797-e49b-4624-932f-ec3f9688e3da" |
no, Heroku-provided value |
heroku.app.name | string | application name | "test-app" |
yes, set on application creation or renaming |
service.name | string | service name of the signals source | "heroku-postgresql" |
no, Heroku-provided value |
service.namespace | string | service namespace of the application | "test-namespace" |
no, Heroku-provided value |
severity_number | integer | numerical value of severity | 9 |
no, Heroku-provided value |
severity_text | string | severity of an event one of: “Critical”, “Warning”, or “Info” |
"Info" |
no, Heroku-provided value |
Example of a JSON Heroku Postgres log:
{
"resource_schema_url":null,
"resource_attributes":{
"service.name":"heroku-postgresql",
"cloud.provider":"heroku",
"heroku.app.name":"test-app",
"heroku.app.id":"c3d3df33-8afb-4323-ac49-a9bf41a50dd1",
"service.namespace":"test-namespace"
},
"scope_logs":[
{
"scope_schema_url":null,
"instrumentation_scope":null,
"log_records":[
{
"observed_timestamp":"1970-01-01T00:00:00Z",
"timestamp":"2025-08-13T20:58:50Z",
"severity_text":"Info",
"severity_number":9,
"body":"source=HEROKU_POSTGRESQL_ORANGE addon=postgresql-curved-71720 sample#service-available=1 sample#current_transaction=774 sample#db_size=7957651bytes sample#db-max-size=68719476736bytes sample#db-size-percentage-used=0.00012 sample#tables=0 sample#active-connections=12 sample#waiting-connections=0 sample#max-connections=200 sample#connections-percentage-used=0.06000 sample#index-cache-hit-rate=0 sample#table-cache-hit-rate=0 sample#load-avg-1m=0.02 sample#load-avg-5m=0.005 sample#load-avg-15m=0.01 sample#read-iops=0 sample#write-iops=0.031579 sample#max-iops=3000 sample#iops-percentage-used=0.00001 sample#tmp-disk-used=543600640 sample#tmp-disk-available=72435191808 sample#memory-total=3944372kB sample#memory-free=2797144kB sample#memory-percentage-used=0.29085 sample#memory-cached=859524kB sample#memory-postgres=24288kB sample#wal-percentage-used=0.04938224410022926 sample#rollback-from=2025-08-19T17:21",
"flags":0
}
]
}
]
}
Heroku Key-Value Store
Key/Value Metric Logs
Heroku’s managed key-value store, Heroku Key-Value Store, captures logs that show usage related to the instance. To filter all Heroku Key-Value instance signals, use the service.name
attribute with the value heroku-redis
.
Name | Type | Description | Example | User-Configurable |
---|---|---|---|---|
body | string | body of API log | "at=info method=GET path=\"/js/twint_ch.js\" ..." |
no, Heroku-provided value |
cloud.provider | string | name of cloud provider, appears on all signals | "heroku" |
no, Heroku-provided default |
heroku.app.id | string | unique identifier of app | "9daa2797-e49b-4624-932f-ec3f9688e3da" |
no, Heroku-provided value |
heroku.app.name | string | application name | "test-app" |
yes, set on application creation or renaming |
service.name | string | service name of the signals source | "heroku-redis" |
no, Heroku-provided value |
service.namespace | string | service namespace of the application | "test-namespace" |
no, Heroku-provided value |
severity_number | integer | numerical value of severity | 9 |
no, Heroku-provided value |
severity_text | string | severity of an event eg: “Critical”, “Warning”, or “Info” |
"Info" |
no, Heroku-provided value |
Example of a JSON Heroku Key-Value Store log:
{
"resource_schema_url":null,
"resource_attributes":{
"service.name":"heroku-redis",
"cloud.provider":"heroku",
"heroku.app.name":"test-app",
"heroku.app.id":"c3d3df33-8afb-4323-ac49-a9bf41a50dd1",
"service.namespace":"test-namespace"
},
"scope_logs":[
{
"scope_schema_url":null,
"instrumentation_scope":null,
"log_records":[
{
"observed_timestamp":"1970-01-01T00:00:00Z",
"timestamp":"2025-08-13T20:58:50Z",
"severity_text":"Info",
"severity_number":9,
"body":"source=REDIS addon=redis-amorphous-75821 sample#active-connections=1 sample#max-connections=18 sample#connection-percentage-used=0.05556 sample#load-avg-1m=0.51 sample#load-avg-5m=0.56 sample#load-avg-15m=0.57 sample#read-iops=0 sample#write-iops=0 sample#max-iops=3000 sample#iops-percentage-used=0.00000 sample#memory-total=16167808kB sample#memory-free=6787836kB sample#memory-percentage-used=0.58016 sample#memory-cached=3235532kB sample#memory-redis=4782496bytes sample#hit-rate=1 sample#evicted-keys=0",
"flags":0
}
]
}
]
}
Apache Kafka on Heroku
Kafka Service and Metric Logs
Apache Kafka on Heroku is a Kafka-as-a-service solution integrated with the Heroku platform. It provides detailed logs, capturing metrics and log lines directly from your Kafka cluster. To filter all Apache Kafka on Heroku signals, use the service.name
attribute with the value heroku-kafka
.
Name | Type | Description | Example | User-Configurable |
---|---|---|---|---|
body | string | body of API log | "at=info method=GET path=\"/js/twint_ch.js\" ..." |
no, Heroku-provided value |
cloud.provider | string | name of cloud provider, appears on all signals | "heroku" |
no, Heroku-provided default |
heroku.app.id | string | unique identifier of app | "9daa2797-e49b-4624-932f-ec3f9688e3da" |
no, Heroku-provided value |
heroku.app.name | string | application name | "test-app" |
yes, set on application creation or renaming |
service.name | string | service name of the signals source | "heroku-kafka" |
no, Heroku-provided value |
service.namespace | string | service namespace of the application | "test-namespace" |
no, Heroku-provided value |
severity_number | integer | numerical value of severity | 9 |
no, Heroku-provided value |
severity_text | string | severity of an event eg: “Critical”, “Warning”, or “Info” |
"Info" |
no, Heroku-provided value |
Example of a JSON Apache Kafka on Heroku log:
{
"resource_schema_url":null,
"resource_attributes":{
"service.name":"heroku-kafka",
"cloud.provider":"heroku",
"heroku.app.name":"test-app",
"heroku.app.id":"c3d3df33-8afb-4323-ac49-a9bf41a50dd1",
"service.namespace":"test-namespace"
},
"scope_logs":[
{
"scope_schema_url":null,
"instrumentation_scope":null,
"log_records":[
{
"observed_timestamp":"1970-01-01T00:00:00Z",
"timestamp":"2025-08-13T20:58:50Z",
"severity_text":"Info",
"severity_number":9,
"body":"source=KAFKA addon=kafka-defined-62412 sample#load-avg-1m=0.015 sample#load-avg-5m=0.0425 sample#load-avg-15m=0.0225 sample#read-iops=0 sample#write-iops=0.32099 sample#memory-total=16083140kB sample#memory-free=10618472kB sample#memory-percentage-used=0.33978 sample#memory-cached=655372kB sample#bytes-in-per-second=0.0 sample#bytes-out-per-second=0.0",
"flags":0
}
]
}
]
}
Heroku Scheduler
Scheduler Logs
Heroku Scheduler is an add-on that allows users to run scheduled jobs on applications, much like cron jobs. All logs generated via scheduled tasks include common resource attributes, and you can filter by the attribute heroku.workload.id
with the value scheduler
.
Example of a JSON Heroku Scheduler log:
{
"resource_schema_url":null,
"resource_attributes":{
"service.instance.id":"scheduler-68d8d6dc59-vhjr9",
"heroku.app.id":"c3d3df33-8afb-4323-ac49-a9bf41a50dd1",
"heroku.workload.id":"scheduler",
"heroku.release.version":"v6",
"service.version":"v6",
"heroku.release.id":"release-3bd90b80-16a1-4f5b-9465-a61e1b7464d4",
"cloud.provider":"heroku",
"heroku.app.name":"test-app",
"service.namespace":"test-namespace",
"service.name":"test-app"
},
"scope_logs":[
{
"scope_schema_url":null,
"instrumentation_scope":null,
"log_records":[
{
"observed_timestamp":"2025-08-13T20:44:39.732192581Z",
"timestamp":"2025-08-13T20:44:39.591629411Z",
"severity_text":"INFO",
"severity_number":9,
"body":"Test task",
"attributes":{
"logtag":"F",
"log.iostream":"stdout"
},
"trace_id":null,
"span_id":null,
"flags":0
}
]
}
]
}