@@ -2,187 +2,54 @@ package promotel
22
33import (
44 "context"
5- "time"
65
76 "github.com/prometheus/client_golang/prometheus"
8- "github.com/prometheus/client_golang/prometheus/promauto"
9- "go.opentelemetry.io/collector/consumer"
10- "go.opentelemetry.io/collector/pdata/pmetric"
11- "go.opentelemetry.io/otel/metric"
12- "go.uber.org/zap"
137
148 "github.com/smartcontractkit/chainlink-common/pkg/logger"
159 "github.com/smartcontractkit/chainlink-common/pkg/services"
16- "github.com/smartcontractkit/chainlink-common/pkg/timeutil"
1710
1811 promotelcommon "github.com/smartcontractkit/chainlink-common/pkg/promotel"
1912)
2013
2114const (
22- period = 15 * time .Second
23- heartbeatMetricName = "promotel_heartbeat"
15+ name = "PromOTELForwarder"
2416)
2517
26- type Forwarder struct {
18+ type Options = promotelcommon.ForwarderOptions
19+ type ForwarderService struct {
2720 services.StateMachine
28- lggr logger.Logger
29- gatherer prometheus.Gatherer
30- meterProvider metric.MeterProvider
31- stopCh services.StopChan
32- done chan struct {}
21+ lggr logger.Logger
22+ forwarder * promotelcommon.Forwarder
3323}
3424
35- func NewForwarder (lggr logger.Logger , gatherer prometheus.Gatherer , meterProvider metric.MeterProvider ) * Forwarder {
36- return & Forwarder {
37- lggr : logger .Named (lggr , "PromOTELForwarder" ),
38- gatherer : gatherer ,
39- meterProvider : meterProvider ,
40- stopCh : make (chan struct {}),
41- done : make (chan struct {}),
42- }
43- }
44-
45- func (f * Forwarder ) HealthReport () map [string ]error { return map [string ]error {f .Name (): f .Healthy ()} }
46-
47- func (f * Forwarder ) Name () string { return f .lggr .Name () }
48-
49- func (f * Forwarder ) Start (context.Context ) error {
50- go reportHertbeatMetric (prometheus .DefaultRegisterer , f .lggr , 1 * time .Second )
51-
52- go f .run ()
53- return nil
54- }
55-
56- func (f * Forwarder ) run () {
57-
58- defer close (f .done )
59- ctx , cancel := f .stopCh .NewCtx ()
60- defer cancel ()
61- ticker := timeutil .NewTicker (func () time.Duration { return period })
62- defer ticker .Stop ()
63-
64- go reportHertbeatMetric (prometheus .DefaultRegisterer , f .lggr , 1 * time .Second )
65-
66- exporter := startExporter (ctx , f .lggr )
67-
68- // Fetches metrics from in memory prometheus.Gatherer and converts to OTel format
69- receiver := f .startMetricReceiver (func (ctx context.Context , md pmetric.Metrics ) error {
70- // todo: remove or make configurable
71- f .logOtelMetric (md , f .lggr )
72-
73- // Exports the converted OTel metric
74- return exporter .Consumer ().ConsumeMetrics (ctx , md )
75- })
76- // Close the receiver and exporter when the forwarder is closed
77- defer func () {
78- if err := receiver .Close (); err != nil {
79- f .lggr .Error ("Failed to close scraper" , zap .Error (err ))
80- }
81- if err := exporter .Close (); err != nil {
82- f .lggr .Error ("Failed to close exporter" , zap .Error (err ))
83- }
84- }()
85-
86- for {
87- select {
88- case <- ctx .Done ():
89- return
90- case <- ticker .C :
91- f .forward (ctx )
92- }
93- }
94- }
95-
96- func (f * Forwarder ) forward (ctx context.Context ) {
97- mfs , err := f .gatherer .Gather ()
25+ func NewForwarderService (g prometheus.Gatherer , r prometheus.Registerer , lggr logger.Logger , opts Options ) (* ForwarderService , error ) {
26+ l := logger .Named (lggr , name )
27+ forwarder , err := promotelcommon .NewForwarder (g , r , l , opts )
9828 if err != nil {
99- f .lggr .Errorw ("Failed to gather prometheus metrics" , "err" , err )
100- }
101- for _ , mf := range mfs {
102- for range mf .Metric {
103- if ctx .Err () != nil {
104- return
105- }
106-
107- //TODO f.meterProvider.Meter()
108- }
29+ return nil , err
10930 }
31+ return & ForwarderService {
32+ lggr : l ,
33+ forwarder : forwarder ,
34+ }, nil
11035}
11136
112- func (f * Forwarder ) Close () error {
113- close (f .stopCh )
114- <- f .done
115- return nil
37+ func (f * ForwarderService ) HealthReport () map [string ]error {
38+ return map [string ]error {f .Name (): f .Healthy ()}
11639}
11740
118- func reportHertbeatMetric (reg prometheus.Registerer , lggr logger.Logger , interval time.Duration ) {
119- heartbeat := promauto .With (reg ).NewCounter (prometheus.CounterOpts {
120- Name : heartbeatMetricName ,
121- ConstLabels : prometheus.Labels {
122- "source" : "promotel" ,
123- },
124- })
125- for {
126- heartbeat .Inc ()
127- lggr .Debugw ("Heartbeat promotel" )
128- time .Sleep (interval )
129- }
130- }
41+ func (f * ForwarderService ) Name () string { return f .lggr .Name () }
13142
132- func startExporter (ctx context.Context , logger logger.Logger ) promotelcommon.MetricExporter {
133- expConfig , err := promotelcommon .NewExporterConfig (map [string ]any {
134- "endpoint" : "localhost:4317" ,
135- "tls" : map [string ]any {
136- "insecure" : true ,
137- },
43+ func (f * ForwarderService ) Start (ctx context.Context ) error {
44+ return f .StartOnce (name , func () error {
45+ return f .forwarder .Start (ctx )
13846 })
139- if err != nil {
140- logger .Fatal ("Failed to create exporter config" , zap .Error (err ))
141- }
142- // Sends metrics data in OTLP format to otel-collector endpoint
143- exporter , err := promotelcommon .NewMetricExporter (expConfig , logger )
144- if err != nil {
145- logger .Fatal ("Failed to create metric exporter" , zap .Error (err ))
146- }
147- err = exporter .Start (ctx )
148- if err != nil {
149- logger .Fatal ("Failed to start exporter" , zap .Error (err ))
150- }
151- return exporter
15247}
15348
154- func (f * Forwarder ) startMetricReceiver (next consumer.ConsumeMetricsFunc ) promotelcommon.Runnable {
155- f .lggr .Info ("Starting promotel metric receiver" )
156- config , err := promotelcommon .NewDefaultReceiverConfig ()
157- if err != nil {
158- f .lggr .Fatal ("Failed to create config" , zap .Error (err ))
159- }
160-
161- // Gather metrics via promotel
162- // MetricReceiver fetches metrics from prometheus.Gatherer, then converts it to OTel format and writes formatted metrics to stdout
163- receiver , err := promotelcommon .NewMetricReceiver (config , f .gatherer , next , f .lggr )
164- if err != nil {
165- f .lggr .Fatal ("Failed to create debug metric receiver" , zap .Error (err ))
166- }
167- // Starts the promotel
168- if err := receiver .Start (context .Background ()); err != nil {
169- f .lggr .Fatal ("Failed to start metric receiver" , zap .Error (err ))
170- }
171- return receiver
49+ func (f * ForwarderService ) Close () error {
50+ return f .StopOnce (name , f .forwarder .Close )
17251}
17352
174- func (f * Forwarder ) logOtelMetric (md pmetric.Metrics , logger logger.Logger ) {
175- rms := md .ResourceMetrics ()
176- for i := 0 ; i < rms .Len (); i ++ {
177- rm := rms .At (i )
178- ilms := rm .ScopeMetrics ()
179- for j := 0 ; j < ilms .Len (); j ++ {
180- ilm := ilms .At (j )
181- metrics := ilm .Metrics ()
182- for k := 0 ; k < metrics .Len (); k ++ {
183- metric := metrics .At (k )
184- logger .Debug ("Exporting OTel metric " , zap .Any ("name" , metric .Name ()), zap .Any ("value" , metric .Sum ().DataPoints ().At (0 ).DoubleValue ()))
185- }
186- }
187- }
53+ func DefaultOptions () Options {
54+ return promotelcommon .DefaultForwarderOptions ()
18855}
0 commit comments