Files
otel-collector/pkg/metering/v1/metrics.go
zeekay ae0925f365 merge: upstream/main (-X ours, brand preserved)
# Conflicts:
#	processor/o11ylogspipelineprocessor/documentation.md
#	processor/o11ylogspipelineprocessor/internal/metadata/generated_telemetry.go
#	processor/o11ylogspipelineprocessor/internal/metadata/generated_telemetry_test.go
#	processor/o11ylogspipelineprocessor/internal/metadatatest/generated_telemetrytest.go
#	processor/o11ylogspipelineprocessor/internal/metadatatest/generated_telemetrytest_test.go
#	processor/o11ylogspipelineprocessor/pipeline_test.go
#	processor/o11ylogspipelineprocessor/stanza/operator/helper/expr_test.go
#	processor/o11ylogspipelineprocessor/stanza/operator/helper/ilike.go
#	processor/o11ylogspipelineprocessor/stanza/operator/helper/like.go
#	processor/o11ylogspipelineprocessor/stanza/operator/helper/like_test.go
#	processor/o11ylogspipelineprocessor/testdata/pipeline_test_config.yaml
2026-06-02 10:22:06 -07:00

113 lines
3.1 KiB
Go

package v1
import (
"regexp"
"github.com/hanzoai/otel-collector/pkg/metering"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.uber.org/zap"
)
var (
excludeRegex = regexp.MustCompile("^(o11y|otelcol).*")
)
type metrics struct {
Logger *zap.Logger
Sizer metering.Sizer
}
func NewMetrics(logger *zap.Logger) metering.Metrics {
if logger == nil {
logger = zap.NewNop()
}
return &metrics{
Logger: logger,
Sizer: metering.NewJSONSizer(logger),
}
}
func (meter *metrics) Size(md pmetric.Metrics) int {
// Note: We will never use this function unless our billing mechanism changes
// The metrics limits should have been samples count based, however, we rolled out with size
// and many have a guestimated and set the size limits. So we will keep this as pmetric json size for now
bytes, err := (&pmetric.JSONMarshaler{}).MarshalMetrics(md)
if err != nil {
meter.Logger.Error("cannot marshal metrics", zap.Error(err))
return 0
}
return len(bytes)
}
func (meter *metrics) SizePerResource(rmd pmetric.ResourceMetrics) int {
// check what can be done here
return 0
}
func (meter *metrics) Count(md pmetric.Metrics) int {
count := 0
for i := 0; i < md.ResourceMetrics().Len(); i++ {
resourceMetric := md.ResourceMetrics().At(i)
count += meter.CountPerResource(resourceMetric)
}
return count
}
func (meter *metrics) CountPerResource(rmd pmetric.ResourceMetrics) int {
count := 0
for j := 0; j < rmd.ScopeMetrics().Len(); j++ {
scopeMetrics := rmd.ScopeMetrics().At(j)
for k := 0; k < scopeMetrics.Metrics().Len(); k++ {
metric := scopeMetrics.Metrics().At(k)
// if the metric satisifies the excluded regex then skip the metric
if excludeRegex.MatchString(metric.Name()) {
continue
}
switch metric.Type() {
case pmetric.MetricTypeGauge:
count += metric.Gauge().DataPoints().Len()
case pmetric.MetricTypeSum:
count += metric.Sum().DataPoints().Len()
case pmetric.MetricTypeHistogram:
subCount := 0
// each bucket is treated as separate sample
for i := 0; i < metric.Histogram().DataPoints().Len(); i++ {
subCount += metric.Histogram().DataPoints().At(i).BucketCounts().Len()
subCount += 1 // count metric
if metric.Histogram().DataPoints().At(i).HasSum() {
subCount += 1
}
if metric.Histogram().DataPoints().At(i).HasMin() {
subCount += 1
}
if metric.Histogram().DataPoints().At(i).HasMax() {
subCount += 1
}
}
count += subCount
case pmetric.MetricTypeSummary:
subCount := 0
for i := 0; i < metric.Summary().DataPoints().Len(); i++ {
subCount += metric.Summary().DataPoints().At(i).QuantileValues().Len()
subCount += 2 // count,sum metrics
}
count += subCount
case pmetric.MetricTypeExponentialHistogram:
// Intentionally not counted. Exp histograms aren't billable on Cloud yet,
// and counting each bucket as a sample would explode the count.
// Kept consistent with the signozclickhousemetrics exporter's writeExpHist,
// which also does not count these toward usage.
// TODO(srikanthccv): revisit when exp histograms are supported on Cloud.
}
}
}
return count
}