-
Notifications
You must be signed in to change notification settings - Fork 403
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
Resource sdk Implementation #502
Changes from 7 commits
a27a5e4
abe8287
083b169
b61acdd
4540bc5
dfe857c
0ae679e
7673007
d5b389f
9fbe8be
208f231
60034d9
04e9de8
bfdd7e1
2abd049
f71a47c
f7e4909
bc3bebc
48a30d4
d8d015a
48ab9ea
f515165
5b01258
e9745f1
84d5405
01fd510
c60fefc
b023c2a
1586018
9158d71
db2412b
35dbf99
5e67443
adbd86d
ef45994
a272b92
8cd247e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
#pragma once | ||
|
||
#include "opentelemetry/nostd/string_view.h" | ||
#include "opentelemetry/nostd/unique_ptr.h" | ||
#include "opentelemetry/sdk/trace/attribute_utils.h" | ||
#include "opentelemetry/sdk/version/version.h" | ||
#include "opentelemetry/version.h" | ||
|
||
#include <cstdlib> | ||
#include <memory> | ||
#include <sstream> | ||
#include <unordered_map> | ||
|
||
OPENTELEMETRY_BEGIN_NAMESPACE | ||
namespace sdk | ||
{ | ||
namespace resource | ||
{ | ||
|
||
class Resource | ||
{ | ||
public: | ||
Resource(const opentelemetry::common::KeyValueIterable &attributes) noexcept; | ||
|
||
Resource(const opentelemetry::sdk::trace::AttributeMap &attributes) noexcept; | ||
|
||
template <class T, | ||
nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> | ||
Resource(const T &attributes) noexcept : Resource(common::KeyValueIterableView<T>(attributes)) | ||
{} | ||
|
||
Resource(const std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> | ||
attributes) noexcept | ||
: Resource(nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{ | ||
attributes.begin(), attributes.end()}) | ||
{} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's your opinion about replacing those with a single: Resource(const std::map<std::string, opentelemetry::sdk::trace::SpanDataAttributeValue> attributes) noexcept; As resources are an SDK only concept, we don't need to worry about ABI compatibility here. Also, we should move the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, |
||
|
||
const opentelemetry::sdk::trace::AttributeMap &GetAttributes() const noexcept; | ||
|
||
std::unique_ptr<Resource> Merge(const Resource &other); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIt: Here and elsewhere in this file. Can we add method documentation about the expectations of calling this? E.g. for For this review, yes I'm looking it up in the spec, but we should document it here for other maintainers of C++. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. Will add the method documentation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have added the documentation now. |
||
|
||
static std::unique_ptr<Resource> Create( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we have both There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, probably because of creating unique pointers. Should we make the constructors private then, to prevent the creation of unmanaged resources? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is challenge to do this in C++. Ideally, I would like to make constructor as private, and make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. Please ignore above comment. I have now made constructor as protected ( so that it can be used in test cases ), and made |
||
const opentelemetry::common::KeyValueIterable &attributes); | ||
|
||
static std::unique_ptr<Resource> Create( | ||
std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> | ||
attributes) noexcept | ||
{ | ||
return Create(nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{ | ||
attributes.begin(), attributes.end()}); | ||
} | ||
|
||
template <class T, | ||
nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> | ||
static std::unique_ptr<Resource> Create(const T &attributes) noexcept | ||
{ | ||
return Create(common::KeyValueIterableView<T>(attributes)); | ||
} | ||
|
||
static std::unique_ptr<Resource> CreateEmpty(); | ||
|
||
static std::unique_ptr<Resource> Create(const std::string &attributes); | ||
|
||
private: | ||
const opentelemetry::sdk::trace::AttributeMap attribute_map_; | ||
}; | ||
|
||
} // namespace resource | ||
} // namespace sdk | ||
OPENTELEMETRY_END_NAMESPACE |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#pragma once | ||
|
||
#include "opentelemetry/nostd/unique_ptr.h" | ||
#include "opentelemetry/sdk/resource/resource.h" | ||
#include "opentelemetry/version.h" | ||
|
||
OPENTELEMETRY_BEGIN_NAMESPACE | ||
namespace sdk | ||
{ | ||
namespace resource | ||
{ | ||
|
||
class ResourceDetector | ||
{ | ||
public: | ||
virtual std::unique_ptr<opentelemetry::sdk::resource::Resource> Detect() = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason to return a unique_ptr over just using the stack here? Resource is non-virtual class, so it might be a simple API to just return it by-value. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the motivation behind that is to avoid excessive copying of a resource. A resource might be appended to each span. Having a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on suggestion from @jsuereth , |
||
}; | ||
|
||
class OTELResourceDetector : public ResourceDetector | ||
{ | ||
public: | ||
std::unique_ptr<opentelemetry::sdk::resource::Resource> Detect() noexcept override; | ||
}; | ||
|
||
} // namespace resource | ||
} // namespace sdk | ||
OPENTELEMETRY_END_NAMESPACE |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Copyright 2020, 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(default_visibility = ["//visibility:public"]) | ||
|
||
cc_library( | ||
name = "resource", | ||
srcs = glob(["**/*.cc"]), | ||
hdrs = glob(["**/*.h"]), | ||
include_prefix = "src/resource", | ||
deps = [ | ||
"//api", | ||
"//sdk:headers", | ||
], | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
add_library(opentelemetry_resources resource.cc resource_detector.cc) | ||
|
||
set_target_properties(opentelemetry_resources PROPERTIES EXPORT_NAME resources) | ||
|
||
target_link_libraries(opentelemetry_resources opentelemetry_common) | ||
|
||
target_include_directories( | ||
opentelemetry_resources | ||
PUBLIC "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/sdk/include>") | ||
|
||
install( | ||
TARGETS opentelemetry_resources | ||
EXPORT "${PROJECT_NAME}-target" | ||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} | ||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} | ||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#include "opentelemetry/sdk/resource/resource.h" | ||
#include "opentelemetry/nostd/span.h" | ||
#include "opentelemetry/sdk/resource/resource_detector.h" | ||
#include "opentelemetry/version.h" | ||
|
||
OPENTELEMETRY_BEGIN_NAMESPACE | ||
namespace sdk | ||
{ | ||
namespace resource | ||
{ | ||
|
||
const std::string TELEMETRY_SDK_LANGUAGE = "telemetry.sdk.language"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Name the constants like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks. fixed now :) |
||
const std::string TELEMETRY_SDK_NAME = "telemetry.sdk.name"; | ||
const std::string TELEMETRY_SDK_VERSION = "telemetry.sdk.version"; | ||
|
||
Resource::Resource(const opentelemetry::common::KeyValueIterable &attributes) noexcept | ||
: attribute_map_(attributes) | ||
{} | ||
|
||
Resource::Resource(const opentelemetry::sdk::trace::AttributeMap &attributes) noexcept | ||
: attribute_map_(attributes) | ||
{} | ||
|
||
const opentelemetry::sdk::trace::AttributeMap &Resource::GetAttributes() const noexcept | ||
{ | ||
return attribute_map_; | ||
} | ||
|
||
std::unique_ptr<Resource> Resource::Merge(const Resource &other) | ||
{ | ||
opentelemetry::sdk::trace::AttributeMap merged_resource_attributes(other.GetAttributes()); | ||
merged_resource_attributes.AddAttributes(attribute_map_); | ||
return std::unique_ptr<Resource>(new Resource(merged_resource_attributes)); | ||
} | ||
|
||
std::unique_ptr<Resource> Resource::Create( | ||
const opentelemetry::common::KeyValueIterable &attributes) | ||
{ | ||
Resource default_resource({{{TELEMETRY_SDK_LANGUAGE, "cpp"}, | ||
{TELEMETRY_SDK_NAME, "opentelemetry"}, | ||
{TELEMETRY_SDK_VERSION, OPENTELEMETRY_SDK_VERSION}}}); | ||
|
||
if (attributes.size() > 0) | ||
{ | ||
Resource input_resource(attributes); | ||
auto merged_resource = default_resource.Merge(input_resource); | ||
return merged_resource->Merge(*(OTELResourceDetector().Detect())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Would it make sense to have both the OTEL resource + default resource be statics within this function?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, I have changed it accordingly.
and
|
||
} | ||
return default_resource.Merge(*(OTELResourceDetector().Detect())); | ||
} | ||
|
||
std::unique_ptr<Resource> Resource::CreateEmpty() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think when we start to use resources, we have to make them shared pointers. Resources are supposed to be attached to every span. We don't want to have unique pointers there, but share a common resource with a shared pointer. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right. Have changed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. based on suggestion from @jsuereth , |
||
{ | ||
return Create({}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can use a static singleton for the default resource, like Java does: https://github.com/open-telemetry/opentelemetry-java/blob/master/sdk/common/src/main/java/io/opentelemetry/sdk/resources/Resource.java#L53 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. Using static local for |
||
} | ||
|
||
std::unique_ptr<Resource> Resource::Create(const std::string &attributes) | ||
{ | ||
opentelemetry::sdk::trace::AttributeMap resource_attributes; | ||
std::istringstream iss(attributes); | ||
std::string token; | ||
while (std::getline(iss, token, ',')) | ||
{ | ||
size_t pos = token.find('='); | ||
std::string key = token.substr(0, pos); | ||
std::string value = token.substr(pos + 1); | ||
resource_attributes.SetAttribute(key, value); | ||
} | ||
return std::unique_ptr<Resource>(new Resource(resource_attributes)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be better to have this logic in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct. Have changed this accordingly now. |
||
} | ||
|
||
} // namespace resource | ||
} // namespace sdk | ||
OPENTELEMETRY_END_NAMESPACE |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#include "opentelemetry/sdk/resource/resource_detector.h" | ||
#include <cstdlib> | ||
|
||
OPENTELEMETRY_BEGIN_NAMESPACE | ||
namespace sdk | ||
{ | ||
namespace resource | ||
{ | ||
|
||
const char *OTEL_RESOURCE_ATTRIBUTES = "OTEL_RESOURCE_ATTRIBUTES"; | ||
|
||
std::unique_ptr<Resource> OTELResourceDetector::Detect() noexcept | ||
{ | ||
char *resource_attributes_str = std::getenv(OTEL_RESOURCE_ATTRIBUTES); | ||
if (resource_attributes_str == nullptr) | ||
return std::unique_ptr<Resource>(new Resource({})); | ||
return Resource::Create(std::string(resource_attributes_str)); | ||
} | ||
|
||
} // namespace resource | ||
} // namespace sdk | ||
OPENTELEMETRY_END_NAMESPACE |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
cc_test( | ||
name = "resource_test", | ||
srcs = [ | ||
"resource_test.cc", | ||
], | ||
deps = [ | ||
"//api", | ||
"//sdk/src/resource", | ||
"@com_google_googletest//:gtest_main", | ||
], | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
foreach(testname resource_test) | ||
add_executable(${testname} "${testname}.cc") | ||
target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES} | ||
${CMAKE_THREAD_LIBS_INIT} opentelemetry_resources) | ||
gtest_add_tests( | ||
TARGET ${testname} | ||
TEST_PREFIX resources. | ||
TEST_LIST ${testname}) | ||
endforeach() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this include necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we actually need it in
resource.cpp
( to read env variable throughstd::getenv
). Will move it there. Thanks for noticing it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is done now.