123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- package monitoring
- import (
- "context"
- "errors"
- "net/http"
- "github.com/imgproxy/imgproxy/v3/monitoring/cloudwatch"
- "github.com/imgproxy/imgproxy/v3/monitoring/datadog"
- "github.com/imgproxy/imgproxy/v3/monitoring/newrelic"
- "github.com/imgproxy/imgproxy/v3/monitoring/otel"
- "github.com/imgproxy/imgproxy/v3/monitoring/prometheus"
- "github.com/imgproxy/imgproxy/v3/monitoring/stats"
- )
- // Monitoring holds all monitoring service instances
- type Monitoring struct {
- config *Config
- stats *stats.Stats
- prometheus *prometheus.Prometheus
- newrelic *newrelic.NewRelic
- datadog *datadog.DataDog
- otel *otel.Otel
- cloudwatch *cloudwatch.CloudWatch
- }
- // New creates a new Monitoring instance
- func New(ctx context.Context, config *Config, workersNumber int) (*Monitoring, error) {
- if err := config.Validate(); err != nil {
- return nil, err
- }
- m := &Monitoring{
- config: config,
- stats: stats.New(workersNumber),
- }
- var prErr, nlErr, ddErr, otelErr, cwErr error
- m.prometheus, prErr = prometheus.New(&config.Prometheus, m.stats)
- m.newrelic, nlErr = newrelic.New(&config.NewRelic, m.stats)
- m.datadog, ddErr = datadog.New(&config.DataDog, m.stats)
- m.otel, otelErr = otel.New(&config.OpenTelemetry, m.stats)
- m.cloudwatch, cwErr = cloudwatch.New(ctx, &config.CloudWatch, m.stats)
- err := errors.Join(prErr, nlErr, ddErr, otelErr, cwErr)
- return m, err
- }
- // Enabled returns true if at least one monitoring service is enabled
- func (m *Monitoring) Enabled() bool {
- return m.prometheus.Enabled() ||
- m.newrelic.Enabled() ||
- m.datadog.Enabled() ||
- m.otel.Enabled() ||
- m.cloudwatch.Enabled()
- }
- // Stats returns the stats instance
- func (m *Monitoring) Stats() *stats.Stats {
- return m.stats
- }
- // Stop stops all monitoring services
- func (m *Monitoring) Stop(ctx context.Context) {
- m.newrelic.Stop(ctx)
- m.datadog.Stop()
- m.otel.Stop(ctx)
- m.cloudwatch.Stop()
- }
- // StartPrometheus starts the Prometheus metrics server
- func (m *Monitoring) StartPrometheus(cancel context.CancelFunc) error {
- return m.prometheus.StartServer(cancel)
- }
- func (m *Monitoring) StartRequest(ctx context.Context, rw http.ResponseWriter, r *http.Request) (context.Context, context.CancelFunc, http.ResponseWriter) {
- promCancel, rw := m.prometheus.StartRequest(rw)
- ctx, nrCancel, rw := m.newrelic.StartTransaction(ctx, rw, r)
- ctx, ddCancel, rw := m.datadog.StartRootSpan(ctx, rw, r)
- ctx, otelCancel, rw := m.otel.StartRootSpan(ctx, rw, r)
- cancel := func() {
- promCancel()
- nrCancel()
- ddCancel()
- otelCancel()
- }
- return ctx, cancel, rw
- }
- func (m *Monitoring) SetMetadata(ctx context.Context, meta Meta) {
- for key, value := range meta {
- m.newrelic.SetMetadata(ctx, key, value)
- m.datadog.SetMetadata(ctx, key, value)
- m.otel.SetMetadata(ctx, key, value)
- }
- }
- func (m *Monitoring) StartQueueSegment(ctx context.Context) context.CancelFunc {
- promCancel := m.prometheus.StartQueueSegment()
- nrCancel := m.newrelic.StartSegment(ctx, "Queue", nil)
- ddCancel := m.datadog.StartSpan(ctx, "queue", nil)
- otelCancel := m.otel.StartSpan(ctx, "queue", nil)
- cancel := func() {
- promCancel()
- nrCancel()
- ddCancel()
- otelCancel()
- }
- return cancel
- }
- func (m *Monitoring) StartDownloadingSegment(ctx context.Context, meta Meta) context.CancelFunc {
- promCancel := m.prometheus.StartDownloadingSegment()
- nrCancel := m.newrelic.StartSegment(ctx, "Downloading image", meta)
- ddCancel := m.datadog.StartSpan(ctx, "downloading_image", meta)
- otelCancel := m.otel.StartSpan(ctx, "downloading_image", meta)
- cancel := func() {
- promCancel()
- nrCancel()
- ddCancel()
- otelCancel()
- }
- return cancel
- }
- func (m *Monitoring) StartProcessingSegment(ctx context.Context, meta Meta) context.CancelFunc {
- promCancel := m.prometheus.StartProcessingSegment()
- nrCancel := m.newrelic.StartSegment(ctx, "Processing image", meta)
- ddCancel := m.datadog.StartSpan(ctx, "processing_image", meta)
- otelCancel := m.otel.StartSpan(ctx, "processing_image", meta)
- cancel := func() {
- promCancel()
- nrCancel()
- ddCancel()
- otelCancel()
- }
- return cancel
- }
- func (m *Monitoring) StartStreamingSegment(ctx context.Context) context.CancelFunc {
- promCancel := m.prometheus.StartStreamingSegment()
- nrCancel := m.newrelic.StartSegment(ctx, "Streaming image", nil)
- ddCancel := m.datadog.StartSpan(ctx, "streaming_image", nil)
- otelCancel := m.otel.StartSpan(ctx, "streaming_image", nil)
- cancel := func() {
- promCancel()
- nrCancel()
- ddCancel()
- otelCancel()
- }
- return cancel
- }
- func (m *Monitoring) SendError(ctx context.Context, errType string, err error) {
- m.prometheus.IncrementErrorsTotal(errType)
- m.newrelic.SendError(ctx, errType, err)
- m.datadog.SendError(ctx, errType, err)
- m.otel.SendError(ctx, errType, err)
- }
|