|
| 1 | +--- |
| 2 | +title: HTTP semantic conventions declared stable |
| 3 | +linkTitle: HTTP semconv are stable |
| 4 | +date: 2023-11-06 |
| 5 | +author: '[Trask Stalnaker](https://github.com/trask) (Microsoft)' |
| 6 | +cSpell:ignore: chalin Liudmila Molkova |
| 7 | +--- |
| 8 | + |
| 9 | +Early this year, we launched an effort to stabilize HTTP semantic conventions. |
| 10 | +Today, we proudly announce that the HTTP semantic conventions are the _first_ |
| 11 | +OpenTelemetry semantic conventions to be declared |
| 12 | +**[stable](/docs/specs/otel/document-status/)**! This inaugural stable |
| 13 | +[v1.23.0](https://github.com/open-telemetry/semantic-conventions/releases/tag/v1.23.0) |
| 14 | +release marks a substantial advancement from earlier versions, featuring: |
| 15 | + |
| 16 | +- Enhancements resulting from |
| 17 | + [convergence with the Elastic Common Schema](/blog/2023/ecs-otel-semconv-convergence/), |
| 18 | + such as: |
| 19 | + - The `url.*` namespace, which can be reused in the future by non-HTTP |
| 20 | + semantic conventions |
| 21 | + - Replacing the `net.peer.*` and `net.host.*` namespaces with `client.*` and |
| 22 | + `server.*`, which |
| 23 | + - Works better for logs, where there's no span kind to indicate which side |
| 24 | + is peer and which side is host |
| 25 | + - Simplifies correlation across client and server telemetry (e.g. since you |
| 26 | + can join directly on `server.address` instead of joining where |
| 27 | + `net.peer.addr` == `net.host.addr`) |
| 28 | + - Provides a clean separation from the `network.*` namespace which is now |
| 29 | + only for low-level network attributes |
| 30 | + - More consistency around using the `http.request.*` and `http.response.*` |
| 31 | + namespaces |
| 32 | +- Improved consistency with Prometheus through standardization on seconds for |
| 33 | + metric units. |
| 34 | +- Streamlined attribute capture by omitting less useful attributes, reducing |
| 35 | + telemetry capture, processing, and storage costs. |
| 36 | +- Clarified the definition of default values, eliminating ambiguities when |
| 37 | + attributes are absent. |
| 38 | +- HTTP metrics are no longer vulnerable to cardinality explosion |
| 39 | + - `http.request.method` is limited to a (configurable) set of known methods |
| 40 | + - `server.address` and `server.port`, which are influenced by the `Host` |
| 41 | + header, are now Opt-In on HTTP metrics |
| 42 | + |
| 43 | +## Migration plan |
| 44 | + |
| 45 | +Due to the significant number of modifications and the extensive user base |
| 46 | +affected by them, we require existing HTTP instrumentations published by |
| 47 | +OpenTelemetry to implement a migration plan that will assist users in |
| 48 | +transitioning to stable HTTP semantic conventions. We intend to use a similar |
| 49 | +strategy when stabilizing other semantic conventions. |
| 50 | + |
| 51 | +Specifically, when existing HTTP instrumentations published by OpenTelemetry are |
| 52 | +updated to the stable HTTP semantic conventions, they: |
| 53 | + |
| 54 | +- Need to introduce an environment variable `OTEL_SEMCONV_STABILITY_OPT_IN` in |
| 55 | + their existing major version, which accepts: |
| 56 | + - `http` - emit the stable HTTP and networking conventions, and stop emitting |
| 57 | + the old HTTP and networking conventions that the instrumentation emitted |
| 58 | + previously. |
| 59 | + - `http/dup` - emit both the old and the stable HTTP and networking |
| 60 | + conventions, allowing for a phased rollout of the stable semantic |
| 61 | + conventions. |
| 62 | + - The default behavior (in the absence of one of these values) is to continue |
| 63 | + emitting whatever version of the old HTTP and networking conventions the |
| 64 | + instrumentation was emitting previously. |
| 65 | +- Need to maintain (security patching at a minimum) their existing major version |
| 66 | + for at least six months after it starts emitting both sets of conventions. |
| 67 | +- May drop the environment variable in their next major version and emit only |
| 68 | + the stable HTTP and networking conventions. |
| 69 | + |
| 70 | +## Summary of changes |
| 71 | + |
| 72 | +In this section, we summarize the changes made to the HTTP semantic conventions |
| 73 | +from |
| 74 | +[v1.20.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/trace/semantic_conventions/http.md) |
| 75 | +to |
| 76 | +[v1.23.0 (stable)](https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/). |
| 77 | + |
| 78 | +### Common attributes across HTTP client and server spans |
| 79 | + |
| 80 | +<!-- prettier-ignore-start --> |
| 81 | +| Change | Comments | |
| 82 | +| --- | --- | |
| 83 | +| `http.method` → `http.request.method` | Now captures only 9 common HTTP methods by default (configurable) plus `_OTHER` | |
| 84 | +| `http.status_code` → `http.response.status_code` | | |
| 85 | +| `http.request.header.<key>` | • Dash (`"-"`) to underscore (`"_"`) normalization in `<key>` has been removed<br>• On HTTP server spans: now must be provided to sampler | |
| 86 | +| `http.response.header.<key>` | Dash (`"-"`) to underscore (`"_"`) normalization in `<key>` has been removed | |
| 87 | +| `http.request_content_length` → `http.request.body.size` | • Recommended → Opt-In<br>• _Not marked stable yet_ | |
| 88 | +| `http.response_content_length` → `http.response.body.size` | • Recommended → Opt-In<br>• _Not marked stable yet_ | |
| 89 | +| `user_agent.original` | • On HTTP client spans: Recommended → Opt-In<br>• On HTTP server spans: now must be provided to sampler<br>• See note if [migrating from <= v1.18.0](#migrating-from--v1180) | |
| 90 | +| `net.protocol.name` → `network.protocol.name` | Recommended → Conditionally required if not `http` and `network.protocol.version` is set | |
| 91 | +| `net.protocol.version` → `network.protocol.version` | • Examples fixed: `2.0` → `2` and `3.0` → `3`<br>• See note if [migrating from <= v1.19.0](#migrating-from--v1190) | |
| 92 | +| `net.sock.family` | Removed | |
| 93 | +| `net.sock.peer.addr` → `network.peer.address` | On HTTP server spans: if `http.client_ip` was unknown, then also `net.sock.peer.addr` → `client.address`; `client.address` must be provided to sampler | |
| 94 | +| `net.sock.peer.port` → `network.peer.port` | Now captured even if same as `server.port` | |
| 95 | +| `net.sock.peer.name` | Removed | |
| 96 | +| New: `http.request.method_original` | Only captured when `http.request.method` is `_OTHER` | |
| 97 | +| New: `error.type` | | |
| 98 | +{.td-initial .table .table-responsive} |
| 99 | +<!-- prettier-ignore-end --> |
| 100 | + |
| 101 | +References: |
| 102 | + |
| 103 | +- [Common attributes v1.20.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/trace/semantic_conventions/http.md#common-attributes) |
| 104 | +- [Common attributes v1.23.0 (stable)](https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#common-attributes) |
| 105 | + |
| 106 | +### HTTP client span attributes |
| 107 | + |
| 108 | +<!-- TODO(@chalin): I'll move this embedded style elsewhere in a followup PR --> |
| 109 | +<style> |
| 110 | +.ot-table-first-row-50 td:first-child { width: 50%; } |
| 111 | +.ot-table-first-row-60 td:first-child { width: 60%; } |
| 112 | +</style> |
| 113 | + |
| 114 | +<!-- prettier-ignore-start --> |
| 115 | +| Change | Comments | |
| 116 | +| --- | --- | |
| 117 | +| `http.url` → `url.full` | | |
| 118 | +| `http.resend_count` → `http.request.resend_count` | | |
| 119 | +| `net.peer.name` → `server.address` | | |
| 120 | +| `net.peer.port` → `server.port` | Now captured even when same as default port for scheme | |
| 121 | +{.td-initial .table .table-responsive .ot-table-first-row-60} |
| 122 | +<!-- prettier-ignore-end --> |
| 123 | + |
| 124 | +References: |
| 125 | + |
| 126 | +- [HTTP client span attributes v1.20.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/trace/semantic_conventions/http.md#http-client) |
| 127 | +- [HTTP client span attributes v1.23.0 (stable)](https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#http-client) |
| 128 | + |
| 129 | +### HTTP server span attributes |
| 130 | + |
| 131 | +<!-- prettier-ignore-start --> |
| 132 | +| Change | Comments | |
| 133 | +| --- | --- | |
| 134 | +| `http.route` | No change | |
| 135 | +| `http.target` → `url.path` and `url.query` | Split into two separate attributes | |
| 136 | +| `http.scheme` → `url.scheme` | Now factors in [X-Forwarded-Proto][], [Forwarded#proto][] headers | |
| 137 | +| `http.client_ip` → `client.address` | If `http.client_ip` was unknown (i.e., no [X-Forwarded-For][], [Forwarded#for][] headers), then `net.sock.peer.addr` → `client.address`; now must be provided to sampler | |
| 138 | +| `net.host.name` → `server.address` | Now based only on [Host][Host header], [:authority][HTTP/2 authority], [X-Forwarded-Host][], [Forwarded#host][] headers | |
| 139 | +| `net.host.port` → `server.port` | Now based only on [Host][Host header], [:authority][HTTP/2 authority], [X-Forwarded-Host][X-Forwarded-Host], [Forwarded#host][] headers | |
| 140 | +{.td-initial .table .table-responsive .ot-table-first-row-50} |
| 141 | +<!-- prettier-ignore-end --> |
| 142 | + |
| 143 | +References: |
| 144 | + |
| 145 | +- [HTTP server span attributes v1.20.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/trace/semantic_conventions/http.md#http-server) |
| 146 | +- [HTTP server span attributes v1.23.0 (stable)](https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#http-server) |
| 147 | + |
| 148 | +### HTTP client and server span names |
| 149 | + |
| 150 | +The `{http.method}` portion of span names is replace by `HTTP` when |
| 151 | +`{http.method}` is `_OTHER`. |
| 152 | + |
| 153 | +See note if [migrating from `<= v1.17.0`](#migrating-from--v1170). |
| 154 | + |
| 155 | +References: |
| 156 | + |
| 157 | +- [HTTP client and server span names v1.20.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/trace/semantic_conventions/http.md#name) |
| 158 | +- [HTTP client and server span names v1.23.0 (stable)](https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-spans.md#name) |
| 159 | + |
| 160 | +### HTTP client duration metric |
| 161 | + |
| 162 | +Metric changes: |
| 163 | + |
| 164 | +- **Name**: `http.client.duration` → `http.client.request.duration` |
| 165 | +- **Unit**: `ms` → `s` |
| 166 | +- **Description**: `Measures the duration of inbound HTTP requests.` → |
| 167 | + `Duration of HTTP server requests.` |
| 168 | +- **Histogram buckets**: boundaries updated to reflect change from milliseconds |
| 169 | + to seconds, and zero bucket boundary removed |
| 170 | +- **Attributes**: see table below |
| 171 | + |
| 172 | +<!-- prettier-ignore-start --> |
| 173 | +| Attribute change | Comments | |
| 174 | +| --- | --- | |
| 175 | +| `http.method` → `http.request.method` | Now captures only 9 common HTTP methods by default plus `_OTHER` | |
| 176 | +| `http.status_code` → `http.response.status_code` | | |
| 177 | +| `net.peer.name` → `server.address` | | |
| 178 | +| `net.peer.port` → `server.port` | Now captured even when same as default port for scheme | |
| 179 | +| `net.sock.peer.addr` | Removed | |
| 180 | +| `net.protocol.name` → `network.protocol.name` | Recommended → Conditionally required if not `http` and `network.protocol.version` is set | |
| 181 | +| `net.protocol.version` → `network.protocol.version` | Examples fixed: `2.0` → `2` and `3.0` → `3`; see note if [migrating from `<= v1.19.0`](#migrating-from--v1190) | |
| 182 | +| New: `error.type` | | |
| 183 | +{.td-initial .table .table-responsive} |
| 184 | +<!-- prettier-ignore-end --> |
| 185 | + |
| 186 | +References: |
| 187 | + |
| 188 | +- [Metric `http.client.duration` v1.20.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/metrics/semantic_conventions/http-metrics.md#metric-httpclientduration) |
| 189 | +- [Metric `http.client.request.duration` v1.23.0 (stable)](https://github.com/open-telemetry/semantic-conventions/blob/v1.23.0/docs/http/http-metrics.md#metric-httpclientrequestduration) |
| 190 | + |
| 191 | +### HTTP server duration metric |
| 192 | + |
| 193 | +Metric changes: |
| 194 | + |
| 195 | +- **Name**: `http.server.duration` → `http.server.request.duration` |
| 196 | +- **Unit**: `ms` → `s` |
| 197 | +- **Description**: `Measures the duration of inbound HTTP requests.` → |
| 198 | + `Duration of HTTP server requests.` |
| 199 | +- **Histogram buckets**: boundaries updated to reflect change from milliseconds |
| 200 | + to seconds, and zero bucket boundary removed |
| 201 | +- **Attributes**: see table below |
| 202 | + |
| 203 | +<!-- prettier-ignore-start --> |
| 204 | +| Attribute change | Comments | |
| 205 | +| --- | --- | |
| 206 | +| `http.route` | No change | |
| 207 | +| `http.method` → `http.request.method` | Now captures only 9 common HTTP methods by default plus `_OTHER` | |
| 208 | +| `http.status_code` → `http.response.status_code` | | |
| 209 | +| `http.scheme` → `url.scheme` | Now factors in [`X-Forwarded-Proto` span][X-Forwarded-Proto], [`Forwarded#proto` span][Forwarded#proto] headers | |
| 210 | +| `net.protocol.name` → `network.protocol.name` | Recommended → Conditionally required if not `http` and `network.protocol.version` is set | |
| 211 | +| `net.protocol.version` → `network.protocol.version` | Examples fixed: `2.0` → `2` and `3.0` → `3`; see note if [migrating from `<= v1.19.0`](#migrating-from--v1190) | |
| 212 | +| `net.host.name` → `server.address` | • Recommended → Opt-In (due to high-cardinality vulnerability since based on HTTP headers)<br>• Now based only on [`Host` span][Host header], [`:authority` span][HTTP/2 authority], [`X-Forwarded-Host` span][X-Forwarded-Host], [`Forwarded#host` span][Forwarded#host] headers | |
| 213 | +| `net.host.port` → `server.port` | • Recommended → Opt-In (due to high-cardinality vulnerability since based on HTTP headers)<br>• Now based only on [`Host` span][Host header], [`:authority` span][HTTP/2 authority], [`X-Forwarded-Host` span][X-Forwarded-Host], [`Forwarded#host` span][Forwarded#host] headers | |
| 214 | +| New: `error.type` | | |
| 215 | +{.td-initial .table .table-responsive .ot-table-first-row-50} |
| 216 | +<!-- prettier-ignore-end --> |
| 217 | + |
| 218 | +References: |
| 219 | + |
| 220 | +- [Metric `http.server.duration` v1.20.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.20.0/specification/metrics/semantic_conventions/http-metrics.md#metric-httpserverduration) |
| 221 | +- [Metric `http.server.request.duration` v1.23.0 (stable)](https://github.com/open-telemetry/semantic-conventions/blob/v1.22.0/docs/http/http-metrics.md#metric-httpserverrequestduration) |
| 222 | + |
| 223 | +## Migrating from a version earlier than v1.20.0? |
| 224 | + |
| 225 | +### Migrating from `<= v1.19.0` |
| 226 | + |
| 227 | +- `http.flavor` → `network.protocol.version` |
| 228 | + - Examples fixed: `2.0` → `2` and `3.0` → `3` |
| 229 | + |
| 230 | +### Migrating from `<= v1.18.0` |
| 231 | + |
| 232 | +- `http.user_agent` → `user_agent.original` |
| 233 | + |
| 234 | +### Migrating from `<= v1.17.0` |
| 235 | + |
| 236 | +#### HTTP server span name |
| 237 | + |
| 238 | +- When `http.route` is available:<br> `{http.route}` → |
| 239 | + `{summary} {http.route}` |
| 240 | +- When `http.route` is not available:<br> `HTTP {http.method}` → |
| 241 | + `{summary}` |
| 242 | + |
| 243 | +Where `{summary}` is `{http.method}`, unless `{http.method}` is `_OTHER`, in |
| 244 | +which case `{summary}` is `HTTP`. |
| 245 | + |
| 246 | +#### HTTP client span name |
| 247 | + |
| 248 | +- `HTTP {http.method}` → `{summary}` |
| 249 | + |
| 250 | +Where `{summary}` is `{http.method}`, unless `{http.method}` is `_OTHER`, in |
| 251 | +which case `{summary}` is `HTTP`. |
| 252 | + |
| 253 | +[Host header]: https://tools.ietf.org/html/rfc7230#section-5.4 |
| 254 | +[HTTP/2 authority]: https://tools.ietf.org/html/rfc9113#section-8.3.1 |
| 255 | +[Forwarded#for]: |
| 256 | + https://developer.mozilla.org/docs/Web/HTTP/Headers/Forwarded#for |
| 257 | +[Forwarded#proto]: |
| 258 | + https://developer.mozilla.org/docs/Web/HTTP/Headers/Forwarded#proto |
| 259 | +[Forwarded#host]: |
| 260 | + https://developer.mozilla.org/docs/Web/HTTP/Headers/Forwarded#host |
| 261 | +[X-Forwarded-For]: |
| 262 | + https://developer.mozilla.org/docs/Web/HTTP/Headers/X-Forwarded-For |
| 263 | +[X-Forwarded-Proto]: |
| 264 | + https://developer.mozilla.org/docs/Web/HTTP/Headers/X-Forwarded-Proto |
| 265 | +[X-Forwarded-Host]: |
| 266 | + https://developer.mozilla.org/docs/Web/HTTP/Headers/X-Forwarded-Host |
| 267 | + |
| 268 | +## Community Kudos |
| 269 | + |
| 270 | +This was a massive community effort: thanks to all who got involved! A special |
| 271 | +thanks to [Liudmila Molkova](https://github.com/lmolkova) for sharing her HTTP |
| 272 | +domain expertise, which helped drive this effort every step of the way. |
0 commit comments