Skip to content

Commit

Permalink
Erlang Sampler and Resource documentation (#2556)
Browse files Browse the repository at this point in the history
Co-authored-by: Patrice Chalin <[email protected]>
Co-authored-by: Fred Hebert <[email protected]>
Co-authored-by: Maciej Szlosarczyk <[email protected]>
  • Loading branch information
4 people authored Apr 19, 2023
1 parent 3f3b9f3 commit 5df8876
Show file tree
Hide file tree
Showing 4 changed files with 328 additions and 1 deletion.
2 changes: 1 addition & 1 deletion content/en/docs/instrumentation/erlang/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Configuration is done through the
[Application environment](https://erlang.org/doc/design_principles/applications.html#configuring-an-application)
or [OS Environment Variables]({{< relref
"/docs/reference/specification/sdk-environment-variables" >}}). The SDK (`opentelemetry`
Application) uses the configuration to initialize a [Tracer Provider](https://hexdocs.pm/opentelemetry_api/otel_tracer_provider.html),
Application) uses the configuration to initialize a [Tracer Provider](https://hexdocs.pm/opentelemetry/otel_tracer_server.html),
its [Span Processors](https://hexdocs.pm/opentelemetry/otel_span_processor.html)
and the [Exporter](https://hexdocs.pm/opentelemetry/otel_exporter.html).

Expand Down
98 changes: 98 additions & 0 deletions content/en/docs/instrumentation/erlang/resources.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
title: Resources
weight: 36
---

A [resource](/docs/reference/specification/overview/#resources) represents an
entity producing telemetry as attributes. For example, an OTP Release producing
telemetry that is running in a container on Kubernetes has an OTP Release name,
a Pod name, a namespace, and possibly a deployment name. All four of these
attributes can be included in the resource.

In your observability backend, you can use resource information to better
investigate interesting behavior. For example, if your trace or metrics data
indicate latency in your system, you can narrow it down to a specific container,
pod, or Kubernetes deployment.

## Using resource detectors

Resource detectors fetch resource attributes from various sources. The default
detectors use the OS environment variable `OTEL_RESOURCE_ATTRIBUTES` and the
`opentelemetry` OTP Application environment variable `resource`.

The detectors to use is a list of module names and can be configured in the
Application configuration:

<!-- prettier-ignore-start -->
{{< tabpane langEqualsHeader=true >}}

{{< tab Erlang >}}
%% sys.config
{resource_detectors, [otel_resource_env_var, otel_resource_app_env]}
{{< /tab >}}

{{< tab Elixir >}}
## runtime.exs
resource_detectors: [:otel_resource_env_var, :otel_resource_app_env]
{{< /tab >}}

{{< /tabpane >}}
<!-- prettier-ignore-end -->

Or through the environment variable `OTEL_RESOURCE_DETECTORS`:

```sh
OTEL_RESOURCE_DETECTORS=otel_resource_env_var,otel_resource_app_env
```

All resources detectors are protected with a timeout, in milliseconds, after
which they return an empty value. This allows for resource detectors to do
things like hit the network without potentially hanging the entire program
indefinitely. The default is 5000 milliseconds and can be set with environment
variable `OTEL_RESOURCE_DETECTOR_TIMEOUT` or Application variable
`otel_resource_detector_timeout`.

## Adding resources with OS and Application environment variables

With the two default resource detectors enabled you can set resource attributes
either with the OS environment variable `OTEL_RESOURCE_ATTRIBUTES`:

```sh
OTEL_RESOURCE_ATTRIBUTES="deployment.environment=development"
```

Alternatively, use the `resource` Application environment under the
`opentelemetry` Application configuration of `sys.config` or `runtime.exs`:

<!-- prettier-ignore-start -->
{{< tabpane langEqualsHeader=true >}}

{{< tab Erlang >}}
%% sys.config
{resource, #{deployment => #{environment => <<"development">>}}
{{< /tab >}}

{{< tab Elixir >}}
## runtime.exs
resource: %{deployment: %{environment: "development" }}
{{< /tab >}}

{{< /tabpane >}}
<!-- prettier-ignore-end -->

Resource attributes in the `resource` Application environment variable are
flattened and combined with `.`, so
`#{deployment => #{environment => <<"development">> }` is the same as
`#{'deployment.environment' => <<"development">>}`.

## Custom resource detectors

Custom resource detectors can be created by implementing the
[`otel_resource_detector` behaviour](https://hexdocs.pm/opentelemetry/1.3.0/otel_resource_detector.html#callbacks)
which contains a single callback `get_resource/1` that returns an
[`otel_resource`](https://hexdocs.pm/opentelemetry/1.3.0/otel_resource.html).

Note that there are
[semantic conventions](/docs/reference/specification/resource/semantic_conventions/)
defined for `resource` that should be followed if they apply when adding new
resource attributes.
213 changes: 213 additions & 0 deletions content/en/docs/instrumentation/erlang/sampling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
---
title: Sampling
weight: 37
---

[Sampling](/docs/concepts/sampling/) is a process that restricts the amount of
traces that are generated by a system. The Erlang SDK offers several
[head samplers](/docs/concepts/sampling#head-sampling).

## Default behavior

By default, all spans are sampled, and thus, 100% of traces are sampled. If you
do not need to manage data volume, you do not need to configure a sampler.

## ParentBasedSampler

When sampling, the `ParentBasedSampler` is most often used for
[head sampling](/docs/concepts/sampling/#head-sampling). It uses the sampling
decision of the Span's parent, or the fact that there is no parent, to know
which secondary sampler to use.

The sampler can be configured with the environment variables
`OTEL_TRACES_SAMPLER` and `OTEL_TRACES_SAMPLER_ARG` or using the Application
configuration allows you to configure each of the 5 potential states of a Span's
parent:

- `root` - No parent
- `remote_parent_sampled` - Parent is from a remote Span that is sampled
- `remote_parent_not_sampled` - Parent is from a remote Span that is not sampled
- `local_parent_sampled` - Parent is from a local Span that is sampled
- `local_parent_not_sampled` - Parent is from a local Span that is not sampled

### TraceIdRatioBasedSampler

Within the `ParentBasedSampler` the most common is the
`TraceIdRatioBasedSampler`. It deterministically samples a percentage of traces
that you pass in as a parameter.

#### Environment Variables

You can configure the `TraceIdRatioBasedSampler` with environment variables:

```shell
export OTEL_TRACES_SAMPLER="parentbased_traceidratio"
export OTEL_TRACES_SAMPLER_ARG="0.1"
```

This tells the SDK to sample spans such that only 10% of Traces get created.

#### Application configuration

Example in the Application configuration with a root sampler for sampling 10% of
Traces and using the parent decision in the other cases:

<!-- prettier-ignore-start -->
{{< tabpane langEqualsHeader=true >}}

{{< tab Erlang >}}
%% config/sys.config.src
{sampler, {parent_based, #{root => {trace_id_ratio_based, 0.10},
remote_parent_sampled => always_on,
remote_parent_not_sampled => always_off,
local_parent_sampled => always_on,
local_parent_not_sampled => always_off}}}
{{< /tab >}}

{{< tab Elixir >}}
# config/runtime.exs
sampler: {:parent_based, %{root: {:trace_id_ratio_based, 0.10},
remote_parent_sampled: :always_on,
remote_parent_not_sampled: :always_off,
local_parent_sampled: :always_on,
local_parent_not_sampled: :always_off}}

{{< /tab >}}

{{< /tabpane >}}
<!-- prettier-ignore-end -->

### AlwaysOn and AlwaysOff Sampler

The other two built-in samplers are the `AlwaysOnSampler` and the
`AlwaysOffSampler`.

#### Environment Variables

You can configure the `ParentBasedSampler` to use either the `AlwaysOnSampler`
or `AlwaysOffSampler` with the environment variable `OTEL_TRACES_SAMPLER`:

```shell
export OTEL_TRACES_SAMPLER="parentbased_always_on"
```

And for the `AlwaysOffSampler`:

```shell
export OTEL_TRACES_SAMPLER="parentbased_always_off"
```

#### Application configuration

Here's an example in the Application configuration with a root sampler that
always samples and using the parent decision in the other cases:

<!-- prettier-ignore-start -->
{{< tabpane langEqualsHeader=true >}}

{{< tab Erlang >}}
%% config/sys.config.src
{sampler, {parent_based, #{root => always_on,
remote_parent_sampled => always_on,
remote_parent_not_sampled => always_off,
local_parent_sampled => always_on,
local_parent_not_sampled => always_off}}}
{{< /tab >}}

{{< tab Elixir >}}
# config/runtime.exs
sampler: {:parent_based, %{root: :always_on,
remote_parent_sampled: :always_on,
remote_parent_not_sampled: :always_off,
local_parent_sampled: :always_on,
local_parent_not_sampled: :always_off}}

{{< /tab >}}

{{< /tabpane >}}
<!-- prettier-ignore-end -->

## Custom Sampler

Custom samplers can be created by implementing the
[`otel_sampler` behaviour](https://hexdocs.pm/opentelemetry/1.3.0/otel_sampler.html#callbacks).
This example sampler:

<!-- prettier-ignore-start -->
{{< tabpane langEqualsHeader=true >}}

{{< tab Erlang >}}
-module(attribute_sampler).

-behavior(otel_sampler).

-export([description/1,
setup/1,
should_sample/7]).

-include("otel_sampler.hrl").

setup(Attributes) when is_map(Attributes) ->
Attributes;
setup(_) ->
#{}.

description(_) ->
<<"AttributeSampler">>.

should_sample(_Ctx, _TraceId, _Links, _SpanName, _SpanKind, Attributes, ConfigAttributes) ->
case maps:intersect(Attributes, ConfigAttributes) of
Map when map_size(Map) > 0 ->
{?DROP, [], []};
_ ->
{?RECORD_AND_SAMPLE, [], []}
end.
{{< /tab >}}

{{< tab Elixir >}}
defmodule AttributesSampler do
def setup(attributes) when is_map(attributes) do
attributes
end

def setup(_) do
%{}
end

def description(_) do
"ExampleSampler"
end

def should_sample(_ctx, _trace_id, _links, _span_name, _span_kind, attributes, config_attributes) do
case :maps.intersect(attributes, config_attributes) do
map when map_size(map) > 0 ->
{:drop, [], []}
_ ->
{:record_and_sample, [], []}
end
end
end
{{< /tab >}}

{{< /tabpane >}}
<!-- prettier-ignore-end -->

Will sample Spans that do not have any attributes that match the attributes
passed as the sampler's configuration.

Example configuration to not sample any Span with an attribute specifying the
URL requested is `/healthcheck`:

<!-- prettier-ignore-start -->
{{< tabpane langEqualsHeader=true >}}

{{< tab Erlang >}}
{sampler, {attributes_sampler, #{'http.target' => <<"/healthcheck">>}}}
{{< /tab >}}

{{< tab Elixir >}}
sampler: {AttributesSampler, %{"http.target": "/healthcheck"}}
{{< /tab >}}

{{< /tabpane >}}
<!-- prettier-ignore-end -->
16 changes: 16 additions & 0 deletions static/refcache.json
Original file line number Diff line number Diff line change
Expand Up @@ -2815,6 +2815,18 @@
"StatusCode": 206,
"LastSeen": "2023-02-15T21:47:40.349021-05:00"
},
"https://hexdocs.pm/opentelemetry/1.3.0/otel_resource.html": {
"StatusCode": 206,
"LastSeen": "2023-04-18T17:53:22.687849481-06:00"
},
"https://hexdocs.pm/opentelemetry/1.3.0/otel_resource_detector.html#callbacks": {
"StatusCode": 206,
"LastSeen": "2023-04-18T17:53:22.515854627-06:00"
},
"https://hexdocs.pm/opentelemetry/1.3.0/otel_sampler.html#callbacks": {
"StatusCode": 206,
"LastSeen": "2023-04-18T17:53:22.862761088-06:00"
},
"https://hexdocs.pm/opentelemetry/otel_exporter.html": {
"StatusCode": 206,
"LastSeen": "2023-02-15T21:47:34.984079-05:00"
Expand All @@ -2823,6 +2835,10 @@
"StatusCode": 206,
"LastSeen": "2023-02-15T21:45:24.525812-05:00"
},
"https://hexdocs.pm/opentelemetry/otel_tracer_server.html": {
"StatusCode": 206,
"LastSeen": "2023-04-18T17:53:23.082563624-06:00"
},
"https://hexdocs.pm/opentelemetry_api/otel_tracer_provider.html": {
"StatusCode": 206,
"LastSeen": "2023-02-15T21:47:29.620967-05:00"
Expand Down

0 comments on commit 5df8876

Please sign in to comment.