Skip to content

Commit

Permalink
receiver/prometheus/internal: add createNodeAndResourcePdata for Prom…
Browse files Browse the repository at this point in the history
…etheus->OTLP Pdata

Starts the progressive effort to convert directly from
    Prometheus->OTLPPdata

directly instead of

    Prometheus->OpenCensusProto->OTLPPdata

by adding a converter for node+resource -> pdata.Resource.

Updates #3137
  • Loading branch information
odeke-em committed May 12, 2021
1 parent fed888c commit 122cc14
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 0 deletions.
39 changes: 39 additions & 0 deletions receiver/prometheusreceiver/internal/prom_to_otlp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package internal

import (
"net"

"go.opentelemetry.io/collector/consumer/pdata"
"go.opentelemetry.io/collector/translator/conventions"
)

func createNodeAndResourcePdata(job, instance, scheme string) pdata.Resource {
host, port, err := net.SplitHostPort(instance)
if err != nil {
host = instance
}
resource := pdata.NewResource()
attrs := resource.Attributes()
attrs.UpsertString(conventions.AttributeServiceName, job)
attrs.UpsertString(conventions.AttributeHostName, host)
attrs.UpsertString(jobAttr, job)
attrs.UpsertString(instanceAttr, instance)
attrs.UpsertString(portAttr, port)
attrs.UpsertString(schemeAttr, scheme)

return resource
}
74 changes: 74 additions & 0 deletions receiver/prometheusreceiver/internal/prom_to_otlp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package internal

import (
"sort"
"testing"
"unsafe"

metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1"
"github.com/google/go-cmp/cmp"
"google.golang.org/protobuf/testing/protocmp"

"go.opentelemetry.io/collector/consumer/pdata"
otlpresource "go.opentelemetry.io/collector/internal/data/protogen/resource/v1"
"go.opentelemetry.io/collector/translator/internaldata"
)

func TestCreateNodeAndResourceConversion(t *testing.T) {
job, instance, scheme := "converter", "ocmetrics", "http"
ocNode, ocResource := createNodeAndResource(job, instance, scheme)
mdFromOC := internaldata.OCToMetrics(internaldata.MetricsData{
Node: ocNode,
Resource: ocResource,
// We need to pass in a dummy set of metrics
// just to populate and allow for full conversion.
Metrics: []*metricspb.Metric{
{
MetricDescriptor: &metricspb.MetricDescriptor{
Name: "m1",
Description: "d1",
Unit: "By",
},
},
},
})

fromOCResource := protoResource(mdFromOC.ResourceMetrics().At(0).Resource())
byDirectOTLPResource := protoResource(createNodeAndResourcePdata(job, instance, scheme))

if diff := cmp.Diff(byDirectOTLPResource, fromOCResource, protocmp.Transform()); diff != "" {
t.Fatalf("Resource mismatch: got: - want: +\n%s", diff)
}
}

// Unfortunately pdata doesn't expose a way for us to retrieve the underlying resource,
// yet we need to compare the resources which are hidden by an unexported value.
func protoResource(presource pdata.Resource) *otlpresource.Resource {
type extract struct {
orig *otlpresource.Resource
}
extracted := (*extract)(unsafe.Pointer(&presource))
if extracted == nil {
return nil
}
// Ensure that the attributes are sorted so that we can properly compare the raw values.
resource := extracted.orig
sort.Slice(resource.Attributes, func(i, j int) bool {
return resource.Attributes[i].Key < resource.Attributes[j].Key
})
return resource
}

0 comments on commit 122cc14

Please sign in to comment.