Improve Req with OTel http spec (#163)
* Improve span_name Use span_name if provided. Fallback to url.path if there is no path_params. * Add unreleased changelog * Update examples and module description * Change span_name and http.url to follow OTEL spec * Remove unused function * Improve changelog * Fix reading span_name from request.options * Don't use URI.path * address changelog
This commit is contained in:
parent
1de26cce1a
commit
19a44fbd68
|
@ -1,5 +1,14 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
* Change span_name to follow [OpenTelemetry http spec](https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/#name)
|
||||||
|
* Use span_name if provided, otherwise use path_params. If there are no path_params,
|
||||||
|
default to http.method
|
||||||
|
* Change http.url to follow [OpenTelemetry http spec](https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/http/#http-client).
|
||||||
|
Full HTTP request URL in the form scheme://host[:port]/path?query[#fragment].
|
||||||
|
Must not contain credentials passed via URL.
|
||||||
|
|
||||||
## 0.1.2
|
## 0.1.2
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
|
@ -5,17 +5,20 @@ defmodule OpentelemetryReq do
|
||||||
expected by default and an error will be raised if the path params option is
|
expected by default and an error will be raised if the path params option is
|
||||||
not set for the request.
|
not set for the request.
|
||||||
|
|
||||||
Given the steps pipeline can be halted to skip further steps from running, it is important
|
Spans are not created until the request is completed or errored.
|
||||||
to _append_ request and response steps _after_ this step to ensure execution. Spans are not
|
|
||||||
created until the request is completed or errored.
|
|
||||||
|
|
||||||
### Example
|
## Request Options
|
||||||
|
|
||||||
|
* `:span_name` - `String.t()` if provided, overrides the span name. Defaults to `nil`.
|
||||||
|
* `:no_path_params` - `boolean()` when set to `true` no path params are expected for the request. Defaults to `false`
|
||||||
|
* `:propagate_trace_ctx` - `boolean()` when set to `true`, trace headers will be propagated. Defaults to `false`
|
||||||
|
|
||||||
|
### Example with path_params
|
||||||
|
|
||||||
```
|
```
|
||||||
client =
|
client =
|
||||||
Req.new()
|
Req.new()
|
||||||
|> OpentelemetryReq.attach()
|
|> OpentelemetryReq.attach(
|
||||||
|> Req.Request.merge_options(
|
|
||||||
base_url: "http://localhost:4000",
|
base_url: "http://localhost:4000",
|
||||||
propagate_trace_ctx: true
|
propagate_trace_ctx: true
|
||||||
)
|
)
|
||||||
|
@ -26,11 +29,24 @@ defmodule OpentelemetryReq do
|
||||||
path_params: [user_id: user_id]
|
path_params: [user_id: user_id]
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
## Request Options
|
|
||||||
|
|
||||||
* `:span_name` - `String.t()` if provided, overrides the span name. Defaults to `nil`.
|
### Example without path_params
|
||||||
* `:no_path_params` - `boolean()` when set to `true` no path params are expected for the request. Defaults to `false`
|
|
||||||
* `:propagate_trace_ctx` - `boolean()` when set to `true`, trace headers will be propagated. Defaults to `false`
|
```
|
||||||
|
client =
|
||||||
|
Req.new()
|
||||||
|
|> OpentelemetryReq.attach(
|
||||||
|
base_url: "http://localhost:4000",
|
||||||
|
propagate_trace_ctx: true,
|
||||||
|
no_path_params: true
|
||||||
|
)
|
||||||
|
|
||||||
|
client
|
||||||
|
|> Req.get(
|
||||||
|
url: "/api/users"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
If you don't set `path_params` the request will raise.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
alias OpenTelemetry.Tracer
|
alias OpenTelemetry.Tracer
|
||||||
|
@ -106,12 +122,23 @@ defmodule OpentelemetryReq do
|
||||||
defp format_exception(_), do: ""
|
defp format_exception(_), do: ""
|
||||||
|
|
||||||
defp span_name(request) do
|
defp span_name(request) do
|
||||||
Req.Request.get_private(request, :path_params_template)
|
case request.options[:span_name] do
|
||||||
|
nil ->
|
||||||
|
method = http_method(request.method)
|
||||||
|
|
||||||
|
case Req.Request.get_private(request, :path_params_template) do
|
||||||
|
nil -> method
|
||||||
|
params_template -> "#{method} #{params_template}"
|
||||||
|
end
|
||||||
|
|
||||||
|
span_name ->
|
||||||
|
span_name
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp build_req_attrs(request) do
|
defp build_req_attrs(request) do
|
||||||
uri = request.url
|
uri = request.url
|
||||||
url = url(uri)
|
url = sanitize_url(uri)
|
||||||
|
|
||||||
%{
|
%{
|
||||||
Trace.http_method() => http_method(request.method),
|
Trace.http_method() => http_method(request.method),
|
||||||
|
@ -124,6 +151,11 @@ defmodule OpentelemetryReq do
|
||||||
|> maybe_append_retry_count(request)
|
|> maybe_append_retry_count(request)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp sanitize_url(uri) do
|
||||||
|
%{uri | userinfo: nil}
|
||||||
|
|> URI.to_string()
|
||||||
|
end
|
||||||
|
|
||||||
defp maybe_append_req_content_length(attrs, req) do
|
defp maybe_append_req_content_length(attrs, req) do
|
||||||
case Req.Request.get_header(req, "content-length") do
|
case Req.Request.get_header(req, "content-length") do
|
||||||
[] ->
|
[] ->
|
||||||
|
@ -154,14 +186,6 @@ defmodule OpentelemetryReq do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp url(uri) do
|
|
||||||
if uri.query do
|
|
||||||
uri.path <> "?" <> uri.query
|
|
||||||
else
|
|
||||||
uri.path
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defp http_method(method) do
|
defp http_method(method) do
|
||||||
case method do
|
case method do
|
||||||
:get -> :GET
|
:get -> :GET
|
||||||
|
|
Loading…
Reference in New Issue