Skip to content

Commit 635c5bc

Browse files
authored
Add prometheus bridge (#4227)
1 parent b39f96e commit 635c5bc

12 files changed

+773
-0
lines changed

.github/dependabot.yml

+9
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ updates:
100100
schedule:
101101
interval: weekly
102102
day: sunday
103+
- package-ecosystem: gomod
104+
directory: /bridges/prometheus
105+
labels:
106+
- dependencies
107+
- go
108+
- Skip Changelog
109+
schedule:
110+
interval: weekly
111+
day: sunday
103112
- package-ecosystem: gomod
104113
directory: /detectors/aws/ec2
105114
labels:

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
1313
- Add the new `go.opentelemetry.io/contrib/instrgen` package to provide auto-generated source code instrumentation. (#3068, #3108)
1414
- Set the description for the `rpc.server.duration` metric in `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc`. (#4302)
1515
- Add `NewServerHandler` and `NewClientHandler` that return a `grpc.StatsHandler` used for gRPC instrumentation in `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc`. (#3002)
16+
- Add new Prometheus bridge module in `go.opentelemetry.io/contrib/bridges/prometheus`. (#4227)
1617

1718
### Changed
1819

CODEOWNERS

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222

2323
CODEOWNERS @MrAlias @MadVikingGod @pellared
2424

25+
bridges/prometheus/ @open-telemetry/go-approvers @dashpole
26+
2527
detectors/aws/ @open-telemetry/go-approvers @Aneurysm9
2628
detectors/gcp/ @open-telemetry/go-approvers @dashpole
2729

bridges/prometheus/README.md

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Prometheus Bridge
2+
3+
Status: Experimental
4+
5+
The Prometheus Bridge allows using the Prometheus Golang client library
6+
(github.com/prometheus/client_golang) with the OpenTelemetry SDK.
7+
8+
## Usage
9+
10+
```golang
11+
// Make a Promethes bridge "Metric Producer" that adds metrics from the
12+
// Prometheus DefaultGatherer. Add the WithGatherer(registry) option to add
13+
// metrics from other registries.
14+
bridge := prometheus.NewMetricProducer()
15+
// Make a Periodic Reader to periodically gather metrics from the bridge, and
16+
// push to an OpenTelemetry exporter.
17+
reader := metric.NewPeriodicReader(otelExporter, metric.WithProducer(bridge))
18+
// Create an OTel MeterProvider with our reader. Metrics from OpenTelemetry
19+
// instruments are combined with metrics from Prometheus instruments in
20+
// exported batches of metrics.
21+
mp := metric.NewMeterProvider(metric.WithReader(reader))
22+
```
23+
24+
## Limitations
25+
26+
* Summary metrics are dropped by the bridge.
27+
* Start times for histograms and counters are set to the process start time.
28+
* It does not currently support exponential histograms.

bridges/prometheus/config.go

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package prometheus // import "go.opentelemetry.io/contrib/bridges/prometheus"
16+
17+
import (
18+
"github.com/prometheus/client_golang/prometheus"
19+
)
20+
21+
// config contains options for the producer.
22+
type config struct {
23+
gatherers []prometheus.Gatherer
24+
}
25+
26+
// newConfig creates a validated config configured with options.
27+
func newConfig(opts ...Option) config {
28+
cfg := config{}
29+
for _, opt := range opts {
30+
cfg = opt.apply(cfg)
31+
}
32+
33+
if len(cfg.gatherers) == 0 {
34+
cfg.gatherers = []prometheus.Gatherer{prometheus.DefaultGatherer}
35+
}
36+
37+
return cfg
38+
}
39+
40+
// Option sets producer option values.
41+
type Option interface {
42+
apply(config) config
43+
}
44+
45+
type optionFunc func(config) config
46+
47+
func (fn optionFunc) apply(cfg config) config {
48+
return fn(cfg)
49+
}
50+
51+
// WithGatherer configures which prometheus Gatherer the Bridge will gather
52+
// from. If no registerer is used the prometheus DefaultGatherer is used.
53+
func WithGatherer(gatherer prometheus.Gatherer) Option {
54+
return optionFunc(func(cfg config) config {
55+
cfg.gatherers = append(cfg.gatherers, gatherer)
56+
return cfg
57+
})
58+
}

bridges/prometheus/config_test.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package prometheus // import "go.opentelemetry.io/contrib/bridges/prometheus"
16+
17+
import (
18+
"testing"
19+
20+
"github.com/prometheus/client_golang/prometheus"
21+
"github.com/stretchr/testify/assert"
22+
)
23+
24+
func TestNewConfig(t *testing.T) {
25+
otherRegistry := prometheus.NewRegistry()
26+
27+
testCases := []struct {
28+
name string
29+
options []Option
30+
wantConfig config
31+
}{
32+
{
33+
name: "Default",
34+
options: nil,
35+
wantConfig: config{
36+
gatherers: []prometheus.Gatherer{prometheus.DefaultGatherer},
37+
},
38+
},
39+
{
40+
name: "With a different gatherer",
41+
options: []Option{WithGatherer(otherRegistry)},
42+
wantConfig: config{
43+
gatherers: []prometheus.Gatherer{otherRegistry},
44+
},
45+
},
46+
{
47+
name: "Multiple gatherers",
48+
options: []Option{WithGatherer(otherRegistry), WithGatherer(prometheus.DefaultGatherer)},
49+
wantConfig: config{
50+
gatherers: []prometheus.Gatherer{otherRegistry, prometheus.DefaultGatherer},
51+
},
52+
},
53+
}
54+
for _, tt := range testCases {
55+
t.Run(tt.name, func(t *testing.T) {
56+
cfg := newConfig(tt.options...)
57+
assert.Equal(t, tt.wantConfig, cfg)
58+
})
59+
}
60+
}

bridges/prometheus/doc.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Package prometheus provides a bridge from Prometheus to OpenTelemetry.
16+
package prometheus // import "go.opentelemetry.io/contrib/bridges/prometheus"

bridges/prometheus/go.mod

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
module go.opentelemetry.io/contrib/bridges/prometheus
2+
3+
go 1.19
4+
5+
require (
6+
github.com/prometheus/client_golang v1.16.0
7+
github.com/prometheus/client_model v0.4.1-0.20230719122841-95a0733b38a0
8+
github.com/stretchr/testify v1.8.4
9+
go.opentelemetry.io/otel v1.16.0
10+
go.opentelemetry.io/otel/sdk v1.16.0
11+
go.opentelemetry.io/otel/sdk/metric v0.39.0
12+
)
13+
14+
require (
15+
github.com/beorn7/perks v1.0.1 // indirect
16+
github.com/cespare/xxhash/v2 v2.2.0 // indirect
17+
github.com/davecgh/go-spew v1.1.1 // indirect
18+
github.com/go-logr/logr v1.2.4 // indirect
19+
github.com/go-logr/stdr v1.2.2 // indirect
20+
github.com/golang/protobuf v1.5.3 // indirect
21+
github.com/kr/text v0.2.0 // indirect
22+
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
23+
github.com/pmezard/go-difflib v1.0.0 // indirect
24+
github.com/prometheus/common v0.42.0 // indirect
25+
github.com/prometheus/procfs v0.10.1 // indirect
26+
github.com/rogpeppe/go-internal v1.11.0 // indirect
27+
go.opentelemetry.io/otel/metric v1.16.0 // indirect
28+
go.opentelemetry.io/otel/trace v1.16.0 // indirect
29+
golang.org/x/sys v0.10.0 // indirect
30+
google.golang.org/protobuf v1.30.0 // indirect
31+
gopkg.in/yaml.v3 v3.0.1 // indirect
32+
)

bridges/prometheus/go.sum

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
2+
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
3+
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
4+
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
5+
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
6+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
7+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8+
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
9+
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
10+
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
11+
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
12+
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
13+
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
14+
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
15+
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
16+
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
17+
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
18+
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
19+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
20+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
21+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
22+
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
23+
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
24+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
25+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
26+
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
27+
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
28+
github.com/prometheus/client_model v0.4.1-0.20230719122841-95a0733b38a0 h1:0+/NUBQSANv2NUdj4G9gW+2gy10v89mZB5WMa9/fWPs=
29+
github.com/prometheus/client_model v0.4.1-0.20230719122841-95a0733b38a0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
30+
github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM=
31+
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
32+
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
33+
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
34+
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
35+
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
36+
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
37+
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
38+
go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
39+
go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
40+
go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
41+
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
42+
go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE=
43+
go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4=
44+
go.opentelemetry.io/otel/sdk/metric v0.39.0 h1:Kun8i1eYf48kHH83RucG93ffz0zGV1sh46FAScOTuDI=
45+
go.opentelemetry.io/otel/sdk/metric v0.39.0/go.mod h1:piDIRgjcK7u0HCL5pCA4e74qpK/jk3NiUoAHATVAmiI=
46+
go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
47+
go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
48+
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
49+
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
50+
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
51+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
52+
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
53+
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
54+
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
55+
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
56+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
57+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
58+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
59+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)