1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-12-23 22:11:10 +02:00
Files
imgproxy/monitoring/monitoring.go
2025-10-01 20:05:06 +02:00

173 lines
4.6 KiB
Go

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)
}