File size: 2,246 Bytes
1c4c66b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package debug

import (
	"bytes"
	"context"
	"fmt"
	"time"

	dto "github.com/prometheus/client_model/go"
	"github.com/prometheus/common/expfmt"
	"google.golang.org/protobuf/proto"
	"google.golang.org/protobuf/types/known/timestamppb"

	"github.com/openmeterio/openmeter/openmeter/streaming"
)

// DebugConnector is a connector for debug metrics.
type DebugConnector interface {
	GetDebugMetrics(ctx context.Context, namespace string) (string, error)
}

// debugConnector is the internal implementation of the DebugConnector interface.
type debugConnector struct {
	streaming streaming.Connector
}

// NewDebugConnector creates a new DebugConnector.
func NewDebugConnector(streaming streaming.Connector) DebugConnector {
	return &debugConnector{
		streaming: streaming,
	}
}

// GetDebugMetrics returns metrics in an OpenMetrics (Prometheus) format for debugging purposes.
// It is useful to monitor the number of events ingested on the vendor side.
func (c *debugConnector) GetDebugMetrics(ctx context.Context, namespace string) (string, error) {
	// Start from the beginning of the day
	queryParams := streaming.CountEventsParams{
		From: time.Now().Truncate(time.Hour * 24).UTC(),
	}

	// Query events counts
	rows, err := c.streaming.CountEvents(ctx, namespace, queryParams)
	if err != nil {
		return "", fmt.Errorf("connector count events: %w", err)
	}

	// Convert to Prometheus metrics
	var metrics []*dto.Metric
	for _, row := range rows {
		metric := &dto.Metric{
			Label: []*dto.LabelPair{
				{
					Name:  proto.String("subject"),
					Value: proto.String(row.Subject),
				},
			},
			Counter: &dto.Counter{
				// We can lose precision here
				Value:            proto.Float64(float64(row.Count)),
				CreatedTimestamp: timestamppb.New(time.Now()),
			},
		}

		metrics = append(metrics, metric)
	}

	family := &dto.MetricFamily{
		Name:   proto.String("openmeter_events_total"),
		Help:   proto.String("Number of ingested events"),
		Type:   dto.MetricType_COUNTER.Enum(),
		Unit:   proto.String("events"),
		Metric: metrics,
	}

	var out bytes.Buffer
	_, err = expfmt.MetricFamilyToOpenMetrics(&out, family)
	if err != nil {
		return "", fmt.Errorf("convert metric family to OpenMetrics: %w", err)
	}

	return out.String(), nil
}