Telepoison

Module VersionHex DocsTotal DownloadLicenseLast Updated

Telepoison is a opentelemetry-instrumented wrapper around HTTPoison.

Usage

Replace usages of the HTTPoison module with Telepoison when calling one of the derived request functions provided by HTTPoison (HTTPoison.get/3, HTTPoison.get!/3 etc.)

# Before
HTTPoison.get!(url, headers, opts)

# After
Telepoison.get!(url, headers, opts)

Configuration

Telepoison can be configured through config :telepoison. The configurable options are:

Both of these can be overridden per each call to Telepoison functions that wrap Telepoison.request/1, such as Telepoison.get/3, Telepoison.get!/3, Telepoison.post/3 etc.

See here for examples

Open Telemetry integration

Additionally, Telepoison provides some options that can be added to each derived function via the Keyword listopts parameter (or the t:HTTPoison.Request/0Keyword listoptions parameter if calling Telepoison.Request/1 directly). These are prefixed with :ot_.

If the value is a string or an function with an arity of 1 (the t:HTTPoison.Request/0request) that is used to set the attribute

If :infer is provided, then the function discussed within the Configuration section is used to set the attribute

If the atom :ignore is provided then the http.route attribute is ignored entirely

It is highly recommended to supply the :ot_resource_route explicitly as either a string or a function with an arity of 1 (the t:HTTPoison.Request/0request)

Examples

In the below examples, Telepoison.get!/3 is used for the sake of simplicity but other functions derived from Telepoison.request/1 can be used

config :telepoison,
  ot_attributes: [{"service.name", "users"}]

Telepoison.get!(
  "https://www.example.com/user/list",
  [],
  ot_span_name: "list example users",
  ot_attributes: [{"example.language", "en"}],
  ot_resource_route: :infer
)

In the example above:

Given the above, the service.name attribute will be set to “users” and the http.route attribute will be inferred as /user/:subpath

Telepoison.get!(
  "https://www.example.com/user/list",
  [],
  ot_span_name: "list example users",
  ot_attributes: [{"example.language", "en"}],
  ot_resource_route: :infer
)

In the example above:

Given the above, the http.route attribute will be inferred as /user/:subpath

config :telepoison,
  infer_route: fn 
    %HTTPoison.Request{} = request -> URI.parse(request.url).path
  end

Telepoison.get!(
  "https://www.example.com/user/list",
  [],
  ot_resource_route: :infer
)

In the example above:

Given the above, the http.route attribute will be inferred as /user/list

Telepoison.get!(
  "https://www.example.com/user/list",
  [],
  ot_resource_route: "my secret path"
)

In the example above:

Given the above, the http.route attribute will be set as my secret path

Telepoison.get!(
  "https://www.example.com/user/list",
  [],
  ot_resource_route: :ignore
)

In the example above:

Given the above, the http.route attribute will not be set to any value

How it works

Telepoison, when executing an HTTP request to an external service, creates an OpenTelemetry span, injects the trace context propagation headers in the request headers, and ends the span once the response is received. It automatically sets some of the HTTP span attributes like http.status etc, based on the request and response data.

Telepoison by itself is not particularly useful: it becomes useful when used in conjunction with a “server-side” opentelemetry-instrumented library, e.g. opentelemetry_plug. These do the opposite work: they take the trace context information from the request headers, and they create a SERVER span which becomes the currently active span.

Using the two libraries together, it’s possible to propagate trace information across several microservices and through HTTP “jumps”.

Keep in mind

What’s missing

Copyright and License

Copyright (c) 2020 Prima.it

This work is free. You can redistribute it and/or modify it under the terms of the MIT License. See the LICENSE.md file for more details.