Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to otel-contrib-col v0.51.0 #796

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/configschema/go.mod
Expand Up @@ -404,7 +404,7 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/pquerna/cachecontrol v0.1.0 // indirect
github.com/prometheus/client_golang v1.12.1 // indirect
github.com/prometheus/client_golang v1.12.2-0.20220318110013-3bc8f2c651ff // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.34.0 // indirect
github.com/prometheus/common/sigv4 v0.1.0 // indirect
Expand Down
3 changes: 2 additions & 1 deletion cmd/configschema/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions exporter/prometheusexporter/collector.go
Expand Up @@ -20,6 +20,7 @@ import (

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/model"
"go.opentelemetry.io/collector/model/pdata"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
conventions "go.opentelemetry.io/collector/semconv/v1.6.1"
Expand Down Expand Up @@ -194,6 +195,7 @@ func (c *collector) convertDoubleHistogram(metric pmetric.Metric, resourceAttrs

indicesMap := make(map[float64]int)
buckets := make([]float64, 0, len(ip.MBucketCounts()))

for index, bucket := range ip.MExplicitBounds() {
if _, added := indicesMap[bucket]; !added {
indicesMap[bucket] = index
Expand All @@ -215,11 +217,36 @@ func (c *collector) convertDoubleHistogram(metric pmetric.Metric, resourceAttrs
points[bucket] = cumCount
}

arrLen := ip.Exemplars().Len()
exemplars := make([]prometheus.Exemplar, arrLen)
for i := 0; i < arrLen; i++ {
e := ip.Exemplars().At(i)

labels := make(prometheus.Labels, e.FilteredAttributes().Len())
e.FilteredAttributes().Range(func(k string, v pdata.Value) bool {
labels[k] = v.AsString()
return true
})

exemplars[i] = prometheus.Exemplar{
Value: e.DoubleVal(),
Labels: labels,
Timestamp: e.Timestamp().AsTime(),
}
}

m, err := prometheus.NewConstHistogram(desc, ip.Count(), ip.Sum(), points, attributes...)
if err != nil {
return nil, err
}

if arrLen > 0 {
m, err = prometheus.NewMetricWithExemplars(m, exemplars...)
if err != nil {
return nil, err
}
}

if c.sendTimestamps {
return prometheus.NewMetricWithTimestamp(ip.Timestamp().AsTime(), m), nil
}
Expand Down
79 changes: 79 additions & 0 deletions exporter/prometheusexporter/collector_test.go
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/prometheus/client_golang/prometheus"
io_prometheus_client "github.com/prometheus/client_model/go"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/model/pdata"
"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
conventions "go.opentelemetry.io/collector/semconv/v1.6.1"
Expand Down Expand Up @@ -96,6 +97,84 @@ func TestConvertInvalidMetric(t *testing.T) {
}
}

func TestConvertDoubleHistogramExemplar(t *testing.T) {
// initialize empty histogram
metric := pdata.NewMetric()
metric.SetDataType(pmetric.MetricDataTypeHistogram)
metric.SetName("test_metric")
metric.SetDescription("this is test metric")
metric.SetUnit("T")

// initialize empty datapoint
hd := metric.Histogram().DataPoints().AppendEmpty()

bounds := []float64{5, 25, 90}
hd.SetExplicitBounds(bounds)
bc := []uint64{2, 35, 70}
hd.SetBucketCounts(bc)

exemplarTs, _ := time.Parse("unix", "Mon Jan _2 15:04:05 MST 2006")
exemplars := []prometheus.Exemplar{
{
Timestamp: exemplarTs,
Value: 3,
Labels: prometheus.Labels{"test_label_0": "label_value_0"},
},
{
Timestamp: exemplarTs,
Value: 50,
Labels: prometheus.Labels{"test_label_1": "label_value_1"},
},
{
Timestamp: exemplarTs,
Value: 78,
Labels: prometheus.Labels{"test_label_2": "label_value_2"},
},
}

// add each exemplar value to the metric
for _, e := range exemplars {
pde := hd.Exemplars().AppendEmpty()
pde.SetDoubleVal(e.Value)
for k, v := range e.Labels {
pde.FilteredAttributes().InsertString(k, v)
}
pde.SetTimestamp(pdata.NewTimestampFromTime(e.Timestamp))
}

c := collector{
accumulator: &mockAccumulator{
[]pdata.Metric{metric},
pcommon.NewMap(),
},
logger: zap.NewNop(),
}

pbMetric, _ := c.convertDoubleHistogram(metric, pcommon.NewMap())
m := io_prometheus_client.Metric{}
require.NoError(t, pbMetric.Write(&m))

buckets := m.GetHistogram().GetBucket()

require.Equal(t, 3, len(buckets))

require.Equal(t, 3.0, buckets[0].GetExemplar().GetValue())
require.Equal(t, int32(128654848), buckets[0].GetExemplar().GetTimestamp().GetNanos())
require.Equal(t, 1, len(buckets[0].GetExemplar().GetLabel()))
require.Equal(t, "test_label_0", buckets[0].GetExemplar().GetLabel()[0].GetName())
require.Equal(t, "label_value_0", buckets[0].GetExemplar().GetLabel()[0].GetValue())

require.Equal(t, 0.0, buckets[1].GetExemplar().GetValue())
require.Equal(t, int32(0), buckets[1].GetExemplar().GetTimestamp().GetNanos())
require.Equal(t, 0, len(buckets[1].GetExemplar().GetLabel()))

require.Equal(t, 78.0, buckets[2].GetExemplar().GetValue())
require.Equal(t, int32(128654848), buckets[2].GetExemplar().GetTimestamp().GetNanos())
require.Equal(t, 1, len(buckets[2].GetExemplar().GetLabel()))
require.Equal(t, "test_label_2", buckets[2].GetExemplar().GetLabel()[0].GetName())
require.Equal(t, "label_value_2", buckets[2].GetExemplar().GetLabel()[0].GetValue())
}

// errorCheckCore keeps track of logged errors
type errorCheckCore struct {
errorMessages []string
Expand Down
3 changes: 3 additions & 0 deletions exporter/prometheusexporter/config.go
Expand Up @@ -46,6 +46,9 @@ type Config struct {
// ResourceToTelemetrySettings defines configuration for converting resource attributes to metric labels.
ResourceToTelemetrySettings resourcetotelemetry.Settings `mapstructure:"resource_to_telemetry_conversion"`

// EnableOpenMetrics enables the use of the OpenMetrics encoding option for the prometheus exporter.
EnableOpenMetrics bool `mapstructure:"enable_open_metrics"`

// skipSanitizeLabel if enabled, labels that start with _ are not sanitized
skipSanitizeLabel bool
}
Expand Down
1 change: 1 addition & 0 deletions exporter/prometheusexporter/factory.go
Expand Up @@ -46,6 +46,7 @@ func createDefaultConfig() config.Exporter {
ConstLabels: map[string]string{},
SendTimestamps: false,
MetricExpiration: time.Minute * 5,
EnableOpenMetrics: false,
skipSanitizeLabel: featuregate.GetRegistry().IsEnabled(dropSanitizationGate.ID),
}
}
Expand Down
3 changes: 2 additions & 1 deletion exporter/prometheusexporter/go.mod
Expand Up @@ -6,12 +6,13 @@ require (
github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.51.0
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/resourcetotelemetry v0.51.0
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/prometheusreceiver v0.51.0
github.com/prometheus/client_golang v1.12.1
github.com/prometheus/client_golang v1.12.2-0.20220318110013-3bc8f2c651ff
github.com/prometheus/client_model v0.2.0
github.com/prometheus/common v0.34.0
github.com/prometheus/prometheus v0.35.1-0.20220503184552-2381d7be5731
github.com/stretchr/testify v1.7.1
go.opentelemetry.io/collector v0.51.0
go.opentelemetry.io/collector/model v0.50.0
go.opentelemetry.io/collector/pdata v0.51.0
go.opentelemetry.io/collector/semconv v0.51.0
go.uber.org/zap v1.21.0
Expand Down
5 changes: 4 additions & 1 deletion exporter/prometheusexporter/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions exporter/prometheusexporter/prometheus.go
Expand Up @@ -56,8 +56,9 @@ func newPrometheusExporter(config *Config, set component.ExporterCreateSettings)
handler: promhttp.HandlerFor(
registry,
promhttp.HandlerOpts{
ErrorHandling: promhttp.ContinueOnError,
ErrorLog: newPromLogger(set.Logger),
ErrorHandling: promhttp.ContinueOnError,
ErrorLog: newPromLogger(set.Logger),
EnableOpenMetrics: config.EnableOpenMetrics,
},
),
}, nil
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -404,7 +404,7 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/pquerna/cachecontrol v0.1.0 // indirect
github.com/prometheus/client_golang v1.12.1 // indirect
github.com/prometheus/client_golang v1.12.2-0.20220318110013-3bc8f2c651ff // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.34.0 // indirect
github.com/prometheus/common/sigv4 v0.1.0 // indirect
Expand Down
3 changes: 2 additions & 1 deletion go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 16 additions & 6 deletions internal/coreinternal/processor/filterconfig/config.go
Expand Up @@ -118,8 +118,18 @@ type MatchProperties struct {
// A match occurs if the span's implementation library matches at least one item in this list.
// This is an optional field.
Libraries []InstrumentationLibrary `mapstructure:"libraries"`

// SpanKinds specify the list of items to match the span kind against.
// A match occurs if the span's span kind matches at least one item in this list.
SpanKinds []string `mapstructure:"span_kinds"`
}

var (
ErrMissingRequiredField = errors.New(`at least one of "attributes", "libraries", or "resources" field must be specified`)
ErrInvalidLogField = errors.New("services, span_names, and span_kinds are not valid for log records")
ErrMissingRequiredLogField = errors.New(`at least one of "log_names", "log_bodies", "log_severity_texts", "attributes", "libraries", "span_kinds", or "resources" field must be specified`)
)

// ValidateForSpans validates properties for spans.
func (mp *MatchProperties) ValidateForSpans() error {
if len(mp.LogBodies) > 0 {
Expand All @@ -131,21 +141,21 @@ func (mp *MatchProperties) ValidateForSpans() error {
}

if len(mp.Services) == 0 && len(mp.SpanNames) == 0 && len(mp.Attributes) == 0 &&
len(mp.Libraries) == 0 && len(mp.Resources) == 0 {
return errors.New(`at least one of "services", "span_names", "attributes", "libraries" or "resources" field must be specified`)
len(mp.Libraries) == 0 && len(mp.Resources) == 0 && len(mp.SpanKinds) == 0 {
return ErrMissingRequiredField
}

return nil
}

// ValidateForLogs validates properties for logs.
func (mp *MatchProperties) ValidateForLogs() error {
if len(mp.SpanNames) > 0 || len(mp.Services) > 0 {
return errors.New("neither services nor span_names should be specified for log records")
if len(mp.SpanNames) > 0 || len(mp.Services) > 0 || len(mp.SpanKinds) > 0 {
return ErrInvalidLogField
}

if len(mp.Attributes) == 0 && len(mp.Libraries) == 0 && len(mp.Resources) == 0 && len(mp.LogBodies) == 0 && len(mp.LogSeverityTexts) == 0 {
return errors.New(`at least one of "attributes", "libraries", "resources", "log_bodies" or "log_severity_texts" field must be specified`)
if len(mp.Attributes) == 0 && len(mp.Libraries) == 0 && len(mp.Resources) == 0 && len(mp.LogBodies) == 0 && len(mp.LogSeverityTexts) == 0 && len(mp.SpanKinds) == 0 {
return ErrMissingRequiredLogField
}

return nil
Expand Down
6 changes: 3 additions & 3 deletions internal/coreinternal/processor/filterlog/filterlog_test.go
Expand Up @@ -41,22 +41,22 @@ func TestLogRecord_validateMatchesConfiguration_InvalidConfig(t *testing.T) {
{
name: "empty_property",
property: filterconfig.MatchProperties{},
errorString: `at least one of "attributes", "libraries", "resources", "log_bodies" or "log_severity_texts" field must be specified`,
errorString: `at least one of "log_names", "log_bodies", "log_severity_texts", "attributes", "libraries", "span_kinds", or "resources" field must be specified`,
},
{
name: "empty_log_bodies_and_attributes",
property: filterconfig.MatchProperties{
LogBodies: []string{},
LogSeverityTexts: []string{},
},
errorString: `at least one of "attributes", "libraries", "resources", "log_bodies" or "log_severity_texts" field must be specified`,
errorString: `at least one of "log_names", "log_bodies", "log_severity_texts", "attributes", "libraries", "span_kinds", or "resources" field must be specified`,
},
{
name: "span_properties",
property: filterconfig.MatchProperties{
SpanNames: []string{"span"},
},
errorString: "neither services nor span_names should be specified for log records",
errorString: "services, span_names, and span_kinds are not valid for log records",
},
{
name: "invalid_match_type",
Expand Down
16 changes: 16 additions & 0 deletions internal/coreinternal/processor/filterspan/filterspan.go
Expand Up @@ -43,6 +43,9 @@ type propertiesMatcher struct {

// Span names to compare to.
nameFilters filterset.FilterSet

// Span kinds to compare to
kindFilters filterset.FilterSet
}

// NewMatcher creates a span Matcher that matches based on the given MatchProperties.
Expand Down Expand Up @@ -76,10 +79,19 @@ func NewMatcher(mp *filterconfig.MatchProperties) (Matcher, error) {
}
}

var kindFS filterset.FilterSet
if len(mp.SpanKinds) > 0 {
kindFS, err = filterset.CreateFilterSet(mp.SpanKinds, &mp.Config)
if err != nil {
return nil, fmt.Errorf("error creating span kind filters: %v", err)
}
}

return &propertiesMatcher{
PropertiesMatcher: rm,
serviceFilters: serviceFS,
nameFilters: nameFS,
kindFilters: kindFS,
}, nil
}

Expand Down Expand Up @@ -122,6 +134,10 @@ func (mp *propertiesMatcher) MatchSpan(span ptrace.Span, resource pcommon.Resour
return false
}

if mp.kindFilters != nil && !mp.kindFilters.Matches(span.Kind().String()) {
return false
}

return mp.PropertiesMatcher.Match(span.Attributes(), resource, library)
}

Expand Down