Skip to content

Commit 4171b70

Browse files
authored
receiver/prometheus/internal: add createNodeAndResourcePdata for Prometheus->OTLP Pdata (#3139)
* receiver/prometheus/internal: add createNodeAndResourcePdata for Prometheus->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 * Use .Attributes to skip unsafe extraction plus use require.Equal Addresses feedback pointed out by Bogdan, Tigran, Jaana by using Resource.Attributes().Sort() instead and also avoid using go-cmp/cmp and instead opt to using require.Equal. * Add comment and rename parity test check * Add createNodeAndResource unit test
1 parent 4de10a4 commit 4171b70

File tree

2 files changed

+159
-0
lines changed

2 files changed

+159
-0
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package internal
16+
17+
import (
18+
"net"
19+
20+
"go.opentelemetry.io/collector/consumer/pdata"
21+
"go.opentelemetry.io/collector/translator/conventions"
22+
)
23+
24+
func createNodeAndResourcePdata(job, instance, scheme string) pdata.Resource {
25+
host, port, err := net.SplitHostPort(instance)
26+
if err != nil {
27+
host = instance
28+
}
29+
resource := pdata.NewResource()
30+
attrs := resource.Attributes()
31+
attrs.UpsertString(conventions.AttributeServiceName, job)
32+
attrs.UpsertString(conventions.AttributeHostName, host)
33+
attrs.UpsertString(jobAttr, job)
34+
attrs.UpsertString(instanceAttr, instance)
35+
attrs.UpsertString(portAttr, port)
36+
attrs.UpsertString(schemeAttr, scheme)
37+
38+
return resource
39+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package internal
16+
17+
import (
18+
"testing"
19+
20+
metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1"
21+
"github.com/stretchr/testify/require"
22+
23+
"go.opentelemetry.io/collector/consumer/pdata"
24+
"go.opentelemetry.io/collector/translator/internaldata"
25+
)
26+
27+
// Parity test to ensure that createNodeAndResource produces identical results to createNodeAndResourcePdata.
28+
func TestCreateNodeAndResourceEquivalence(t *testing.T) {
29+
job, instance, scheme := "converter", "ocmetrics", "http"
30+
ocNode, ocResource := createNodeAndResource(job, instance, scheme)
31+
mdFromOC := internaldata.OCToMetrics(ocNode, ocResource,
32+
// We need to pass in a dummy set of metrics
33+
// just to populate and allow for full conversion.
34+
[]*metricspb.Metric{
35+
{
36+
MetricDescriptor: &metricspb.MetricDescriptor{
37+
Name: "m1",
38+
Description: "d1",
39+
Unit: "By",
40+
},
41+
},
42+
},
43+
)
44+
45+
fromOCResource := mdFromOC.ResourceMetrics().At(0).Resource().Attributes().Sort()
46+
byDirectOTLPResource := createNodeAndResourcePdata(job, instance, scheme).Attributes().Sort()
47+
48+
require.Equal(t, byDirectOTLPResource, fromOCResource)
49+
}
50+
51+
type jobInstanceDefinition struct {
52+
job, instance, host, scheme, port string
53+
}
54+
55+
func makeResourceWithJobInstanceScheme(def *jobInstanceDefinition) pdata.Resource {
56+
resource := pdata.NewResource()
57+
attrs := resource.Attributes()
58+
// Using hardcoded values to assert on outward expectations so that
59+
// when variables change, these tests will fail and we'll have reports.
60+
attrs.UpsertString("service.name", def.job)
61+
attrs.UpsertString("host.name", def.host)
62+
attrs.UpsertString("job", def.job)
63+
attrs.UpsertString("instance", def.instance)
64+
attrs.UpsertString("port", def.port)
65+
attrs.UpsertString("scheme", def.scheme)
66+
return resource
67+
}
68+
69+
func TestCreateNodeAndResourcePromToOTLP(t *testing.T) {
70+
tests := []struct {
71+
name, job string
72+
instance string
73+
scheme string
74+
want pdata.Resource
75+
}{
76+
{
77+
name: "all attributes proper",
78+
job: "job", instance: "localhost:8888", scheme: "http",
79+
want: makeResourceWithJobInstanceScheme(&jobInstanceDefinition{
80+
"job", "localhost:8888", "localhost", "http", "8888",
81+
}),
82+
},
83+
{
84+
name: "missing port",
85+
job: "job", instance: "myinstance", scheme: "https",
86+
want: makeResourceWithJobInstanceScheme(&jobInstanceDefinition{
87+
"job", "myinstance", "myinstance", "https", "",
88+
}),
89+
},
90+
{
91+
name: "blank scheme",
92+
job: "job", instance: "myinstance:443", scheme: "",
93+
want: makeResourceWithJobInstanceScheme(&jobInstanceDefinition{
94+
"job", "myinstance:443", "myinstance", "", "443",
95+
}),
96+
},
97+
{
98+
name: "blank instance, blank scheme",
99+
job: "job", instance: "", scheme: "",
100+
want: makeResourceWithJobInstanceScheme(&jobInstanceDefinition{
101+
"job", "", "", "", "",
102+
}),
103+
},
104+
{
105+
name: "blank instance, non-blank scheme",
106+
job: "job", instance: "", scheme: "http",
107+
want: makeResourceWithJobInstanceScheme(&jobInstanceDefinition{
108+
"job", "", "", "http", "",
109+
}),
110+
},
111+
}
112+
113+
for _, tt := range tests {
114+
tt := tt
115+
t.Run(tt.name, func(t *testing.T) {
116+
got := createNodeAndResourcePdata(tt.job, tt.instance, tt.scheme)
117+
require.Equal(t, got, tt.want)
118+
})
119+
}
120+
}

0 commit comments

Comments
 (0)