|
| 1 | +# OTLP: JSON Encoding for OTLP/HTTP |
| 2 | + |
| 3 | +This is a proposal to add HTTP Transport extension supporting json serialization for |
| 4 | +[OTLP](0035-opentelemetry-protocol.md) (OpenTelemetry Protocol). |
| 5 | + |
| 6 | +## Table of Contents |
| 7 | + |
| 8 | +* [Motivation](#motivation) |
| 9 | +* [OTLP/HTTP+JSON Protocol Details](#otlphttpjson-protocol-details) |
| 10 | + * [JSON Mapping](#json-mapping) |
| 11 | + * [Request](#request) |
| 12 | + * [Response](#response) |
| 13 | + * [Success](#success) |
| 14 | + * [Failures](#failures) |
| 15 | + * [Throttling](#throttling) |
| 16 | + * [All Other Responses](#all-other-responses) |
| 17 | + * [Connection](#connection) |
| 18 | + * [Parallel Connections](#parallel-connections) |
| 19 | + |
| 20 | +## Motivation |
| 21 | + |
| 22 | +Protobuf is a relatively big dependency, which some clients are not willing to take. For example, webjs, iOS/Android (in some scenarios, the size of the installation package is limited, do not want to introduce protobuf dependencies). Plain JSON is a smaller dependency and is built in the standard libraries of many programming languages. |
| 23 | + |
| 24 | +## OTLP/HTTP+JSON Protocol Details |
| 25 | + |
| 26 | +OTLP/HTTP+JSON will be consistent with the [OTLP/HTTP](0099-otlp-http.md) specification except that the payload will use JSON instead of protobuf. |
| 27 | + |
| 28 | +### JSON Mapping |
| 29 | + |
| 30 | +Use proto3 standard defined [JSON Mapping](https://developers.google.com/protocol-buffers/docs/proto3#json) for mapping between protobuf and json. `trace_id` and `span_id` is base64 encoded in OTLP/HTTP+JSON, not hex. |
| 31 | + |
| 32 | +### Request |
| 33 | + |
| 34 | +Telemetry data is sent via HTTP POST request. |
| 35 | + |
| 36 | +The default URL path for requests that carry trace data is `/v1/traces` (for |
| 37 | +example the full URL when connecting to "example.com" server will be |
| 38 | +`https://example.com/v1/traces`). The request body is a JSON-encoded |
| 39 | +[`ExportTraceServiceRequest`](https://github.com/open-telemetry/opentelemetry-proto/blob/e6c3c4a74d57f870a0d781bada02cb2b2c497d14/opentelemetry/proto/collector/trace/v1/trace_service.proto#L38) |
| 40 | +message. |
| 41 | + |
| 42 | +The default URL path for requests that carry metric data is `/v1/metrics` and the |
| 43 | +request body is a JSON-encoded |
| 44 | +[`ExportMetricsServiceRequest`](https://github.com/open-telemetry/opentelemetry-proto/blob/e6c3c4a74d57f870a0d781bada02cb2b2c497d14/opentelemetry/proto/collector/metrics/v1/metrics_service.proto#L35) |
| 45 | +message. |
| 46 | + |
| 47 | +The client MUST set "Content-Type: application/json" request header. The |
| 48 | +client MAY gzip the content and in that case SHOULD include "Content-Encoding: |
| 49 | +gzip" request header. The client MAY include "Accept-Encoding: gzip" request |
| 50 | +header if it can receive gzip-encoded responses. |
| 51 | + |
| 52 | +Non-default URL paths for requests MAY be configured on the client and server |
| 53 | +sides. |
| 54 | + |
| 55 | +### Response |
| 56 | + |
| 57 | +#### Success |
| 58 | + |
| 59 | +On success the server MUST respond with `HTTP 200 OK`. Response body MUST be |
| 60 | +JSON-encoded |
| 61 | +[`ExportTraceServiceResponse`](https://github.com/open-telemetry/opentelemetry-proto/blob/e6c3c4a74d57f870a0d781bada02cb2b2c497d14/opentelemetry/proto/collector/trace/v1/trace_service.proto#L47) |
| 62 | +message for traces and |
| 63 | +[`ExportMetricsServiceResponse`](https://github.com/open-telemetry/opentelemetry-proto/blob/e6c3c4a74d57f870a0d781bada02cb2b2c497d14/opentelemetry/proto/collector/metrics/v1/metrics_service.proto#L44) |
| 64 | +message for metrics. |
| 65 | + |
| 66 | +The server MUST set "Content-Type: application/json" response header. If |
| 67 | +the request header "Accept-Encoding: gzip" is present in the request the server |
| 68 | +MAY gzip-encode the response and set "Content-Encoding: gzip" response header. |
| 69 | + |
| 70 | +The server SHOULD respond with success no sooner than after successfully |
| 71 | +decoding and validating the request. |
| 72 | + |
| 73 | +#### Failures |
| 74 | + |
| 75 | +If the processing of the request fails the server MUST respond with appropriate |
| 76 | +`HTTP 4xx` or `HTTP 5xx` status code. See sections below for more details about |
| 77 | +specific failure cases and HTTP status codes that should be used. |
| 78 | + |
| 79 | +Response body for all `HTTP 4xx` and `HTTP 5xx` responses MUST be a |
| 80 | +JSON-encoded |
| 81 | +[Status](https://godoc.org/google.golang.org/genproto/googleapis/rpc/status#Status) |
| 82 | +message that describes the problem. |
| 83 | + |
| 84 | +This specification does not use `Status.code` field and the server MAY omit |
| 85 | +`Status.code` field. The clients are not expected to alter their behavior based |
| 86 | +on `Status.code` field but MAY record it for troubleshooting purposes. |
| 87 | + |
| 88 | +The `Status.message` field SHOULD contain a developer-facing error message as |
| 89 | +defined in `Status` message schema. |
| 90 | + |
| 91 | +The server MAY include `Status.details` field with additional details. Read |
| 92 | +below about what this field can contain in each specific failure case. |
| 93 | + |
| 94 | +#### Bad Data |
| 95 | + |
| 96 | +If the processing of the request fails because the request contains data that |
| 97 | +cannot be decoded or is otherwise invalid and such failure is permanent then the |
| 98 | +server MUST respond with `HTTP 400 Bad Request`. The `Status.details` field in |
| 99 | +the response SHOULD contain a |
| 100 | +[BadRequest](https://github.com/googleapis/googleapis/blob/d14bf59a446c14ef16e9931ebfc8e63ab549bf07/google/rpc/error_details.proto#L166) |
| 101 | +that describes the bad data. |
| 102 | + |
| 103 | +The client MUST NOT retry the request when it receives `HTTP 400 Bad Request` |
| 104 | +response. |
| 105 | + |
| 106 | +#### Throttling |
| 107 | + |
| 108 | +If the server receives more requests than the client is allowed or the server is |
| 109 | +overloaded the server SHOULD respond with `HTTP 429 Too Many Requests` or |
| 110 | +`HTTP 503 Service Unavailable` and MAY include |
| 111 | +["Retry-After"](https://tools.ietf.org/html/rfc7231#section-7.1.3) header with a |
| 112 | +recommended time interval in seconds to wait before retrying. |
| 113 | + |
| 114 | +The client SHOULD honour the waiting interval specified in "Retry-After" header |
| 115 | +if it is present. If the client receives `HTTP 429` or `HTTP 503` response and |
| 116 | +"Retry-After" header is not present in the response then the client SHOULD |
| 117 | +implement an exponential backoff strategy between retries. |
| 118 | + |
| 119 | +#### All Other Responses |
| 120 | + |
| 121 | +All other HTTP responses that are not explicitly listed in this document should |
| 122 | +be treated according to HTTP specification. |
| 123 | + |
| 124 | +If the server disconnects without returning a response the client SHOULD retry |
| 125 | +and send the same request. The client SHOULD implement an exponential backoff |
| 126 | +strategy between retries to avoid overwhelming the server. |
| 127 | + |
| 128 | +### Connection |
| 129 | + |
| 130 | +If the client is unable to connect to the server the client SHOULD retry the |
| 131 | +connection using exponential backoff strategy between retries. The interval |
| 132 | +between retries must have a random jitter. |
| 133 | + |
| 134 | +The client SHOULD keep the connection alive between requests. |
| 135 | + |
| 136 | +Server implementations MAY handle OTLP/gRPC, OTLP/HTTP requests and OTLP/HTTP+JSON on the same |
| 137 | +port and multiplex the connections to the corresponding transport handler based |
| 138 | +on "Content-Type" request header. |
| 139 | + |
| 140 | +### Parallel Connections |
| 141 | + |
| 142 | +To achieve higher total throughput the client MAY send requests using several |
| 143 | +parallel HTTP connections. In that case the maximum number of parallel |
| 144 | +connections SHOULD be configurable. |
0 commit comments