Skip to content

Commit e3f8ef0

Browse files
authored
Adding the Resource API (#61)
Design Decisions include: The API package should be minimal, and example implementations should live in SDK when possible. The precedent that exists is to name both the interface and the implementation in the sdk the same. This avoids the generally unhelpful "Default" prefix. opentelemetry-python is standardizing on Google style docstrings. As such resolving formatting that is inconsistent with the style guilde.
1 parent 7c5e018 commit e3f8ef0

File tree

4 files changed

+116
-0
lines changed

4 files changed

+116
-0
lines changed

opentelemetry-api/src/opentelemetry/resources/__init__.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,42 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
15+
import abc
16+
import typing
17+
18+
19+
class Resource(abc.ABC):
20+
"""The interface that resources must implement."""
21+
@staticmethod
22+
@abc.abstractmethod
23+
def create(labels: typing.Dict[str, str]) -> "Resource":
24+
"""Create a new resource.
25+
26+
Args:
27+
labels: the labels that define the resource
28+
29+
Returns:
30+
The resource with the labels in question
31+
32+
"""
33+
@property
34+
@abc.abstractmethod
35+
def labels(self) -> typing.Dict[str, str]:
36+
"""Return the label dictionary associated with this resource.
37+
38+
Returns:
39+
A dictionary with the labels of the resource
40+
41+
"""
42+
@abc.abstractmethod
43+
def merge(self, other: typing.Optional["Resource"]) -> "Resource":
44+
"""Return a resource with the union of labels for both resources.
45+
46+
Labels that exist in the main Resource take precedence unless the
47+
label value is the empty string.
48+
49+
Args:
50+
other: The resource to merge in
51+
52+
"""
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright 2019, 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+
import opentelemetry.resources as resources
16+
17+
18+
class Resource(resources.Resource):
19+
def __init__(self, labels):
20+
self._labels = labels
21+
22+
@staticmethod
23+
def create(labels):
24+
return Resource(labels)
25+
26+
@property
27+
def labels(self):
28+
return self._labels
29+
30+
def merge(self, other):
31+
if other is None:
32+
return self
33+
if not self._labels:
34+
return other
35+
merged_labels = self.labels.copy()
36+
for key, value in other.labels.items():
37+
if key not in merged_labels or merged_labels[key] == "":
38+
merged_labels[key] = value
39+
return Resource(merged_labels)
40+
41+
def __eq__(self, other: object) -> bool:
42+
if not isinstance(other, Resource):
43+
return False
44+
return self.labels == other.labels

opentelemetry-sdk/tests/resources/__init__.py

Whitespace-only changes.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import unittest
2+
from opentelemetry.sdk import resources
3+
4+
5+
class TestResources(unittest.TestCase):
6+
def test_resource_merge(self):
7+
left = resources.Resource({"service": "ui"})
8+
right = resources.Resource({"host": "service-host"})
9+
self.assertEqual(
10+
left.merge(right),
11+
resources.Resource({
12+
"service": "ui",
13+
"host": "service-host"
14+
}))
15+
16+
def test_resource_merge_empty_string(self):
17+
"""Verify Resource.merge behavior with the empty string.
18+
19+
Labels from the source Resource take precedence, with
20+
the exception of the empty string.
21+
22+
"""
23+
left = resources.Resource({"service": "ui", "host": ""})
24+
right = resources.Resource({
25+
"host": "service-host",
26+
"service": "not-ui"
27+
})
28+
self.assertEqual(
29+
left.merge(right),
30+
resources.Resource({
31+
"service": "ui",
32+
"host": "service-host"
33+
}))

0 commit comments

Comments
 (0)