Skip to content

Commit 27c2c68

Browse files
lahsivjarChrsMark
authored andcommitted
[connector/signaltometrics] Add boilerplate for the connector (open-telemetry#36454)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Adds boilerplate code for a new signal to metrics connector. <!-- Issue number (e.g. open-telemetry#1234) or full URL to issue, if applicable. --> #### Link to tracking issue Part of open-telemetry#35930 <!--Describe what testing was performed and which tests were added.--> #### Testing Unit tests provided as required. <!--Describe the documentation added.--> #### Documentation Added basic README. Will add more details with future commits. <!--Please delete paragraphs that you did not use before submitting.--> CC: @ChrsMark --------- Co-authored-by: Christos Markou <[email protected]>
1 parent 933ea73 commit 27c2c68

22 files changed

+926
-0
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: new_component
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: signaltometricsconnector
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: New component for generating metrics from raw signals using user defined OTTL expressions.
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [35930]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: [user]

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ connector/otlpjsonconnector/ @open-telemetry/collector-cont
3434
connector/roundrobinconnector/ @open-telemetry/collector-contrib-approvers @bogdandrutu
3535
connector/routingconnector/ @open-telemetry/collector-contrib-approvers @jpkrohling @mwear
3636
connector/servicegraphconnector/ @open-telemetry/collector-contrib-approvers @jpkrohling @mapno @JaredTan95
37+
connector/signaltometricsconnector/ @open-telemetry/collector-contrib-approvers @ChrsMark @lahsivjar
3738
connector/spanmetricsconnector/ @open-telemetry/collector-contrib-approvers @portertech @Frapschen
3839
connector/sumconnector/ @open-telemetry/collector-contrib-approvers @greatestusername @shalper2 @crobert-1
3940

.github/ISSUE_TEMPLATE/bug_report.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ body:
3535
- connector/roundrobin
3636
- connector/routing
3737
- connector/servicegraph
38+
- connector/signaltometrics
3839
- connector/spanmetrics
3940
- connector/sum
4041
- examples/demo

.github/ISSUE_TEMPLATE/feature_request.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ body:
2929
- connector/roundrobin
3030
- connector/routing
3131
- connector/servicegraph
32+
- connector/signaltometrics
3233
- connector/spanmetrics
3334
- connector/sum
3435
- examples/demo

.github/ISSUE_TEMPLATE/other.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ body:
2929
- connector/roundrobin
3030
- connector/routing
3131
- connector/servicegraph
32+
- connector/signaltometrics
3233
- connector/spanmetrics
3334
- connector/sum
3435
- examples/demo

.github/ISSUE_TEMPLATE/unmaintained.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ body:
3434
- connector/roundrobin
3535
- connector/routing
3636
- connector/servicegraph
37+
- connector/signaltometrics
3738
- connector/spanmetrics
3839
- connector/sum
3940
- examples/demo
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include ../../Makefile.Common
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
# Signal to metrics connector
2+
3+
Signal to metrics connector produces metrics from all signal types (traces,
4+
logs, or metrics).
5+
6+
<!-- status autogenerated section -->
7+
| Status | |
8+
| ------------- |-----------|
9+
| Distributions | [] |
10+
| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aconnector%2Fsignaltometrics%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aconnector%2Fsignaltometrics) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aconnector%2Fsignaltometrics%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aconnector%2Fsignaltometrics) |
11+
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@ChrsMark](https://www.github.com/ChrsMark), [@lahsivjar](https://www.github.com/lahsivjar) |
12+
13+
[development]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#development
14+
15+
## Supported Pipeline Types
16+
17+
| [Exporter Pipeline Type] | [Receiver Pipeline Type] | [Stability Level] |
18+
| ------------------------ | ------------------------ | ----------------- |
19+
| traces | metrics | [development] |
20+
| logs | metrics | [development] |
21+
| metrics | metrics | [development] |
22+
23+
[Exporter Pipeline Type]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md#exporter-pipeline-type
24+
[Receiver Pipeline Type]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/connector/README.md#receiver-pipeline-type
25+
[Stability Level]: https://github.com/open-telemetry/opentelemetry-collector/blob/main/docs/component-stability.md#stability-levels
26+
<!-- end autogenerated section -->
27+
28+
## Configuration
29+
30+
The component can produce metrics from spans, datapoints (for metrics), and logs.
31+
At least one of the metrics for one signal type MUST be specified correctly for
32+
the component to work.
33+
34+
All signal types can be configured to produce metrics with the same configuration
35+
structure. For example, the below configuration will produce delta temporality counters
36+
for counting number of events for each of the configured signals:
37+
38+
```yaml
39+
signaltometrics:
40+
spans:
41+
- name: span.count
42+
description: Count of spans
43+
sum:
44+
value: Int(AbsoluteCount()) # Count of total spans represented by each span
45+
datapoints:
46+
- name: datapoint.count
47+
description: Count of datapoints
48+
sum:
49+
value: "1" # increment by 1 for each datapoint
50+
logs:
51+
- name: logrecord.count
52+
description: Count of log records
53+
sum:
54+
value: "1" # increment by 1 for each log record
55+
```
56+
57+
### Metrics types
58+
59+
`signaltometrics` produces a variety of metric types by utilizing [OTTL](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/pkg/ottl/README.md)
60+
to extract the relevant data for a metric type from the incoming data. The
61+
component can produce the following metric types for each signal types:
62+
63+
- [Sum](https://opentelemetry.io/docs/specs/otel/metrics/data-model/#sums)
64+
- [Histogram](https://opentelemetry.io/docs/specs/otel/metrics/data-model/#histogram)
65+
- [Exponential Histogram](https://opentelemetry.io/docs/specs/otel/metrics/data-model/#exponentialhistogram)
66+
67+
The component does NOT perform any stateful or time based aggregations. The metric
68+
types are aggregated for the payload sent in each `Consume*` call. The final metric
69+
is then sent forward in the pipeline.
70+
71+
#### Sum
72+
73+
Sum metrics have the following configurations:
74+
75+
```yaml
76+
sum:
77+
value: <ottl_value_expression>
78+
```
79+
80+
- [**Required**] `value` represents an OTTL expression to extract a value from the
81+
incoming data. Only OTTL expressions that return a value are accepted. The
82+
returned value determines the value type of the `sum` metric (`int` or `double`).
83+
[OTTL converters](https://pkg.go.dev/github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/ottlfuncs#readme-converters)
84+
can be used to transform the data.
85+
86+
#### Histogram
87+
88+
Histogram metrics have the following configurations:
89+
90+
```yaml
91+
histogram:
92+
buckets: []float64
93+
count: <ottl_value_expression>
94+
value: <ottl_value_expression>
95+
```
96+
97+
- [**Optional**] `buckets` represents the buckets to be used for the histogram.
98+
If no buckets are configured then it defaults to:
99+
100+
```go
101+
[]float64{2, 4, 6, 8, 10, 50, 100, 200, 400, 800, 1000, 1400, 2000, 5000, 10_000, 15_000}
102+
```
103+
104+
- [**Optional**] `count` represents an OTTL expression to extract the count to be
105+
recorded in the histogram from the incoming data. If no expression is provided
106+
then it defaults to the count of the signal i.e. [adjusted count](https://opentelemetry.io/docs/specs/otel/trace/tracestate-probability-sampling-experimental/#adjusted-count)
107+
for spans and count for others. [OTTL converters](https://pkg.go.dev/github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/ottlfuncs#readme-converters)
108+
can be used to transform the data.
109+
- [**Required**] `value` represents an OTTL expression to extract the value to be
110+
recorded in the histogram from the incoming data. [OTTL converters](https://pkg.go.dev/github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/ottlfuncs#readme-converters)
111+
can be used to transform the data.
112+
113+
#### Exponential Histogram
114+
115+
Exponential histogram metrics have the following configurations:
116+
117+
```yaml
118+
exponential_histogram:
119+
max_size: <int64>
120+
count: <ottl_value_expression>
121+
value: <ottl_value_expression>
122+
```
123+
124+
- [**Optional**] `max_size` represents the maximum number of buckets per positive
125+
or negative number range. Defaults to `160`.
126+
- [**Optional**] `count` represents an OTTL expression to extract the count to be
127+
recorded in the exponential histogram from the incoming data. If no expression
128+
is provided then it defaults to the count of the signal i.e. [adjusted count](https://opentelemetry.io/docs/specs/otel/trace/tracestate-probability-sampling-experimental/#adjusted-count)
129+
for spans and count for others.
130+
[OTTL converters](https://pkg.go.dev/github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/ottlfuncs#readme-converters) can be used to transform the data.
131+
- [**Required**] `value` represents an OTTL expression to extract the value to be recorded
132+
in the exponential histogram from the incoming data.
133+
[OTTL converters](https://pkg.go.dev/github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/ottlfuncs#readme-converters) can be used to transform the data.
134+
135+
### Attributes
136+
137+
The component can produce metrics categorized by the attributes (span attributes
138+
for traces, datapoint attributes for datapoints, or log record attributes for logs)
139+
from the incoming data by configuring `attributes` for the configured metrics.
140+
141+
If no `attributes` are configured then the metrics are produced without any attributes.
142+
143+
```yaml
144+
attributes:
145+
- key: datapoint.foo
146+
- key: datapoint.bar
147+
default_value: bar
148+
```
149+
150+
If attributes are specified then a separate metric will be generated for each unique
151+
set of attribute values. Optionally, a `default_value` can be used to always include
152+
the attribute with the value of the attribute defaulting to the value specified in
153+
`default_value` if the incoming data is missing that attribute.
154+
155+
### Conditions
156+
157+
Conditions are an optional list of OTTL conditions that are evaluated on the incoming
158+
data and are ORed together. For example:
159+
160+
```yaml
161+
signaltometrics:
162+
datapoints:
163+
- name: datapoint.bar.sum
164+
description: Count total number of datapoints as per datapoint.bar attribute
165+
conditions:
166+
- resource.attributes["foo"] != nil
167+
- resource.attributes["bar"] != nil
168+
sum:
169+
value: "1"
170+
```
171+
172+
The above configuration will produce sum metrics from datapoints with either `foo`
173+
OR `bar` resource attribute defined.
174+
175+
Conditions can also be ANDed together, for example:
176+
177+
```yaml
178+
signaltometrics:
179+
datapoints:
180+
- name: gauge.to.exphistogram
181+
conditions:
182+
- metric.type == 1 AND resource.attributes["resource.foo"] != nil
183+
exponential_histogram:
184+
count: "1" # 1 count for each datapoint
185+
value: Double(value_int) + value_double # handle both int and double
186+
```
187+
188+
The above configuration produces exponential histogram from gauge metrics with resource
189+
attributes `resource.foo` set.
190+
191+
### Customizing resource attributes
192+
193+
The component allows customizing the resource attributes for the produced metrics
194+
by specifying a list of attributes that should be included in the final metrics.
195+
If no attributes are specified for `include_resource_attributes` then no filtering
196+
is performed i.e. all resource attributes of the incoming data is considered.
197+
198+
```yaml
199+
include_resource_attributes:
200+
- key: resource.foo # Include resource.foo attribute if present
201+
- key: resource.bar # Always include resource.bar attribute, default to bar
202+
default_value: bar
203+
```
204+
205+
With the above configuration the produced metrics would only have the couple of
206+
resource attributes specified in the list:
207+
208+
- `resource.foo` will be present for the produced metrics if the incoming data also
209+
has the attribute defined.
210+
- `resource.bar` will always be present because of the `default_value`. If the incoming
211+
data does not have a resource attribute with name `resource.bar` then the configured
212+
`default_value` of `bar` will be used.
213+
214+
### Single writer
215+
216+
Metrics data streams MUST obey [single-writer](https://opentelemetry.io/docs/specs/otel/metrics/data-model/#single-writer)
217+
principle. However, since `signaltometrics` component produces metrics from all signal
218+
types and also allows customizing the resource attributes, there is a possibility
219+
of violating the single-writer principle. To keep the single-writer principle intact,
220+
the component adds collector instance information as resource attributes. The following
221+
resource attributes are added to each produced metrics:
222+
223+
```yaml
224+
signaltometrics.service.name: <service_name_of_the_otel_collector>
225+
signaltometrics.service.namespace: <service_namespace_of_the_otel_collector>
226+
signaltometrics.service.instance.id: <service_instance_id_of_the_otel_collector>
227+
```
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package config // import "github.com/open-telemetry/opentelemetry-collector-contrib/connector/signaltometricsconnector/config"
5+
6+
import "fmt"
7+
8+
// Config for the connector. Each configuration field describes the metrics
9+
// to produce from a specific signal.
10+
type Config struct {
11+
Spans []MetricInfo `mapstructure:"spans"`
12+
Datapoints []MetricInfo `mapstructure:"datapoints"`
13+
Logs []MetricInfo `mapstructure:"logs"`
14+
}
15+
16+
func (c *Config) Validate() error {
17+
if len(c.Spans) == 0 && len(c.Datapoints) == 0 && len(c.Logs) == 0 {
18+
return fmt.Errorf("no configuration provided, at least one should be specified")
19+
}
20+
return nil
21+
}
22+
23+
// MetricInfo defines the structure of the metric produced by the connector.
24+
type MetricInfo struct {
25+
Name string `mapstructure:"name"`
26+
Description string `mapstructure:"description"`
27+
// Unit, if not-empty, will set the unit associated with the metric.
28+
// See: https://github.com/open-telemetry/opentelemetry-collector/blob/b06236cc794982916cc956f20828b3e18eb33264/pdata/pmetric/generated_metric.go#L72-L81
29+
Unit string `mapstructure:"unit"`
30+
// IncludeResourceAttributes is a list of resource attributes that
31+
// needs to be included in the generated metric. If no resource
32+
// attribute is included in the list then all attributes are included.
33+
IncludeResourceAttributes []Attribute `mapstructure:"include_resource_attributes"`
34+
Attributes []Attribute `mapstructure:"attributes"`
35+
// Conditions are a set of OTTL condtions which are ORed. Data is
36+
// processed into metrics only if the sequence evaluates to true.
37+
Conditions []string `mapstructure:"conditions"`
38+
Histogram *Histogram `mapstructure:"histogram"`
39+
ExponentialHistogram *ExponentialHistogram `mapstructure:"exponential_histogram"`
40+
Sum *Sum `mapstructure:"sum"`
41+
}
42+
43+
type Attribute struct {
44+
Key string `mapstructure:"key"`
45+
DefaultValue any `mapstructure:"default_value"`
46+
}
47+
48+
type Histogram struct {
49+
Buckets []float64 `mapstructure:"buckets"`
50+
Count string `mapstructure:"count"`
51+
Value string `mapstructure:"value"`
52+
}
53+
54+
type ExponentialHistogram struct {
55+
MaxSize int32 `mapstructure:"max_size"`
56+
Count string `mapstructure:"count"`
57+
Value string `mapstructure:"value"`
58+
}
59+
60+
type Sum struct {
61+
Value string `mapstructure:"value"`
62+
}

0 commit comments

Comments
 (0)