Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(telemetry): basic telemetry client and local setup
* Disabled by default, to enable set `WERF_TELEMETRY=1` env var. * werf uses opentelemetry client to send metrics over OTLP. * Send werf runs counter with {OS, arch, version, command, exitCode} labels. * Run `make local-telemtry` to setup local opentelemetry collector with prometheus (using docker compose). Signed-off-by: Timofey Kirillov <timofey.kirillov@flant.com>
- Loading branch information
1 parent
7775193
commit 6dcbd3e
Showing
11 changed files
with
323 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package common | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/werf/logboek" | ||
"github.com/werf/werf/pkg/telemetry" | ||
) | ||
|
||
func InitTelemetry(ctx context.Context) { | ||
// TODO: append error to the ~/.werf/telemetry_errors.log | ||
err := telemetry.Init(ctx) | ||
logboek.Context(ctx).Debug().LogF("Telemetry: init error: %s\n", err) | ||
} | ||
|
||
func ShutdownTelemetry(ctx context.Context, exitCode int) { | ||
telemetry.ChangeMetrics(func(metrics *telemetry.Metrics) { | ||
metrics.ExitCode = exitCode | ||
}) | ||
|
||
// TODO: append error to the ~/.werf/telemetry_errors.log | ||
err := telemetry.Shutdown(ctx) | ||
|
||
logboek.Context(ctx).Debug().LogF("Telemetry: shutdown error: %s\n", err) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package telemetry | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
neturl "net/url" | ||
"time" | ||
|
||
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric" | ||
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" | ||
controller "go.opentelemetry.io/otel/sdk/metric/controller/basic" | ||
processor "go.opentelemetry.io/otel/sdk/metric/processor/basic" | ||
"go.opentelemetry.io/otel/sdk/metric/selector/simple" | ||
) | ||
|
||
var ( | ||
ctrl *controller.Controller | ||
exporter *otlpmetric.Exporter | ||
) | ||
|
||
func SetupController(ctx context.Context, url string) error { | ||
{ | ||
e, err := NewExporter(url) | ||
if err != nil { | ||
return fmt.Errorf("unable to create telemetry exporter: %w", err) | ||
} | ||
exporter = e | ||
} | ||
ctrl = NewController(exporter) | ||
|
||
if err := exporter.Start(ctx); err != nil { | ||
return fmt.Errorf("error starting telemetry exporter: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func NewExporter(url string) (*otlpmetric.Exporter, error) { | ||
urlObj, err := neturl.Parse(url) | ||
if err != nil { | ||
return nil, fmt.Errorf("bad url: %w", err) | ||
} | ||
|
||
var opts []otlpmetrichttp.Option | ||
|
||
if urlObj.Scheme == "http" { | ||
opts = append(opts, otlpmetrichttp.WithInsecure()) | ||
} | ||
|
||
opts = append(opts, | ||
otlpmetrichttp.WithEndpoint(urlObj.Host), | ||
otlpmetrichttp.WithURLPath(urlObj.Path), | ||
otlpmetrichttp.WithRetry(otlpmetrichttp.RetryConfig{Enabled: false}), | ||
otlpmetrichttp.WithTimeout(5*time.Second), | ||
) | ||
|
||
client := otlpmetrichttp.NewClient(opts...) | ||
|
||
return otlpmetric.NewUnstarted(client), nil | ||
} | ||
|
||
func NewController(exporter *otlpmetric.Exporter) *controller.Controller { | ||
checkpointerFactory := processor.NewFactory(simple.NewWithHistogramDistribution(), exporter) | ||
|
||
return controller.New( | ||
checkpointerFactory, | ||
controller.WithExporter(exporter), | ||
controller.WithCollectTimeout(5*time.Second), | ||
controller.WithCollectPeriod(0), | ||
controller.WithPushTimeout(5*time.Second), | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package telemetry | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"go.opentelemetry.io/otel/attribute" | ||
"go.opentelemetry.io/otel/metric" | ||
"go.opentelemetry.io/otel/metric/instrument" | ||
|
||
"github.com/werf/logboek" | ||
) | ||
|
||
type Metrics struct { | ||
Version string | ||
Command string | ||
OS string | ||
Arch string | ||
ExitCode int | ||
} | ||
|
||
func (m *Metrics) WriteOpenTelemetry(ctx context.Context, meter metric.Meter) error { | ||
labels := []attribute.KeyValue{ | ||
attribute.String("version", m.Version), | ||
attribute.String("command", m.Command), | ||
attribute.String("os", m.OS), | ||
attribute.String("arch", m.Arch), | ||
attribute.Int("exit_code", m.ExitCode), | ||
} | ||
|
||
runCounter, err := meter.SyncInt64().Counter("runs", instrument.WithDescription("werf runs counter")) | ||
if err != nil { | ||
return fmt.Errorf("unable to record runs counter: %w", err) | ||
} | ||
runCounter.Add(ctx, 1, labels...) | ||
logboek.Context(ctx).Debug().LogF("Telemetry: incremented runs counter: %#v\n", runCounter) | ||
|
||
return nil | ||
} |
Oops, something went wrong.