Skip to content

Logger: Propagating resources through LoggerProvider - #1154

Merged
ThomsonTan merged 11 commits into
open-telemetry:mainfrom
owent:propagating_resource_through_logger_provider
Jan 12, 2022
Merged

Logger: Propagating resources through LoggerProvider#1154
ThomsonTan merged 11 commits into
open-telemetry:mainfrom
owent:propagating_resource_through_logger_provider

Conversation

@owent

@owent owent commented Dec 20, 2021

Copy link
Copy Markdown
Member

Signed-off-by: owentou owentou@tencent.com

Fixes #1086

Changes

  • Add logs::LoggerContext, logs::MultiLogProcessor, logs::MultiRecordable
  • Remove resource from Logger::Log
  • Remove TracerProvider::GetProcessor (Without implementation before.)
  • [BREAK CHANGES] Change the declaration of sdk::logs::Recordable::SetResource
  • [BREAK CHANGES] Change the LoggerProvider::SetProcessor to LoggerProvider::AddProcessor
  • Share LoggerContext between loggers
  • Add api/include/opentelemetry/common/macros.h to provide OPENTELEMETRY_DEPRECATED, OPENTELEMETRY_DEPRECATED_MESSAGE and OPENTELEMETRY_MAYBE_UNUSED

Is there any way to convert opentelemetry::sdk::common::OwnedAttributeValue into opentelemetry::common::AttributeValue ?
It's difficult to reuse and dump data from opentelemetry::sdk::common::OwnedAttributeValue.

For significant contributions please make sure you have completed the following items:

  • CHANGELOG.md updated for non-trivial changes
  • Unit tests have been added
  • Changes in public API reviewed

@owent
owent requested a review from a team December 20, 2021 16:30
@codecov

codecov Bot commented Dec 20, 2021

Copy link
Copy Markdown

Codecov Report

Merging #1154 (c53bfd1) into main (f20f72f) will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #1154   +/-   ##
=======================================
  Coverage   93.29%   93.29%           
=======================================
  Files         174      174           
  Lines        6402     6402           
=======================================
  Hits         5972     5972           
  Misses        430      430           
Impacted Files Coverage Δ
...nclude/opentelemetry/sdk/common/empty_attributes.h 100.00% <ø> (ø)

@lalitb

lalitb commented Dec 20, 2021

Copy link
Copy Markdown
Member

Is there any way to convert opentelemetry::sdk::common::OwnedAttributeValue into opentelemetry::common::AttributeValue ?
It's difficult to reuse and dump data from opentelemetry::sdk::common::OwnedAttributeValue.

Where do you see its usage? We can possibly create a converter similar to AttributeValue to OwnedAttributeValue -

@owent

owent commented Dec 21, 2021

Copy link
Copy Markdown
Member Author

Is there any way to convert opentelemetry::sdk::common::OwnedAttributeValue into opentelemetry::common::AttributeValue ?
It's difficult to reuse and dump data from opentelemetry::sdk::common::OwnedAttributeValue.

Where do you see its usage? We can possibly create a converter similar to AttributeValue to OwnedAttributeValue -

I have wrote a example to share resource between logs before.And the codes is like these:

class KeyValueIterableViewForResourceAttributes final : public opentelemetry::common::KeyValueIterable {
 public:
  explicit KeyValueIterableViewForResourceAttributes(
      const opentelemetry::sdk::resource::ResourceAttributes& container) noexcept
      : container_{&container} {}

  // KeyValueIterable
  bool ForEachKeyValue(
      opentelemetry::nostd::function_ref<bool(nostd::string_view, opentelemetry::common::AttributeValue)> callback)
      const noexcept override {
    auto iter = std::begin(*container_);
    auto last = std::end(*container_);
    for (; iter != last; ++iter) {
      if (!callback(iter->first, ConvertOwnedAttribute(iter->second))) {
        return false;
      }
    }
    return true;
  }

  size_t size() const noexcept override { return nostd::size(*container_); }

  static opentelemetry::common::AttributeValue ConvertOwnedAttribute(
      const opentelemetry::sdk::common::OwnedAttributeValue& value) {
    if (nostd::holds_alternative<bool>(value)) {
      return opentelemetry::common::AttributeValue{nostd::get<bool>(value)};
    } else if (nostd::holds_alternative<int32_t>(value)) {
      return opentelemetry::common::AttributeValue{nostd::get<int32_t>(value)};
    } else if (nostd::holds_alternative<int64_t>(value)) {
      return opentelemetry::common::AttributeValue{nostd::get<int64_t>(value)};
    } else if (nostd::holds_alternative<uint32_t>(value)) {
      return opentelemetry::common::AttributeValue{nostd::get<uint32_t>(value)};
    } else if (nostd::holds_alternative<uint64_t>(value)) {
      return opentelemetry::common::AttributeValue{nostd::get<uint64_t>(value)};
    } else if (nostd::holds_alternative<double>(value)) {
      return opentelemetry::common::AttributeValue{nostd::get<double>(value)};
    } else if (nostd::holds_alternative<std::string>(value)) {
      return opentelemetry::common::AttributeValue{nostd::get<std::string>(value)};
    } else if (nostd::holds_alternative<std::vector<bool>>(value)) {
      // TODO: Add support for vector<bool>
      return opentelemetry::common::AttributeValue{};
    } else if (nostd::holds_alternative<std::vector<int32_t>>(value)) {
      return opentelemetry::common::AttributeValue{nostd::get<std::vector<int32_t>>(value)};
    } else if (nostd::holds_alternative<std::vector<uint32_t>>(value)) {
      return opentelemetry::common::AttributeValue{nostd::get<std::vector<uint32_t>>(value)};
    } else if (nostd::holds_alternative<std::vector<int64_t>>(value)) {
      return opentelemetry::common::AttributeValue{nostd::get<std::vector<int64_t>>(value)};
    } else if (nostd::holds_alternative<std::vector<uint64_t>>(value)) {
      return opentelemetry::common::AttributeValue{nostd::get<std::vector<uint64_t>>(value)};
    } else if (nostd::holds_alternative<std::vector<double>>(value)) {
      return opentelemetry::common::AttributeValue{nostd::get<std::vector<double>>(value)};
    } else if (nostd::holds_alternative<std::vector<std::string>>(value)) {
      // TODO: Add support to convert vector<std::string> tp vector<nostd::string_view>
      return opentelemetry::common::AttributeValue{};
    }

    return opentelemetry::common::AttributeValue{};
  }

 private:
  const opentelemetry::sdk::resource::ResourceAttributes* container_;
};

void Report(const opentelemetry::sdk::resource::Resource& shared_resource) {
  auto span = GetTracer()->StartSpan("cpp-test-span-otlp");
  auto ctx = span->GetContext();
  auto logger = GetLogger();
  auto shared_resource_attributes = KeyValueIterableViewForResourceAttributes(shared_resource.GetAttributes());
  using attribute_span = nostd::span<const std::pair<nostd::string_view, opentelemetry::common::AttributeValue>>;
  logger->Log(opentelemetry::logs::Severity::kInfo, "log name", "log body", shared_resource_attributes,
              opentelemetry::common::KeyValueIterableView<attribute_span>{attribute_span{}}, ctx.trace_id(),
              ctx.span_id(), ctx.trace_flags(), std::chrono::system_clock::now());
}

It can not convert all types from OwnedAttributeValue to AttributeValue . Even atfer move resource into provider, I think it's still useful if we want to Recordable::SetAttribute from data with lifetime(I want to reuse OwnedAttributeValue to store complex data structures and use it as attributes of trace or log).

@lalitb

lalitb commented Dec 21, 2021

Copy link
Copy Markdown
Member

It can not convert all types from OwnedAttributeValue to AttributeValue . Even atfer move resource into provider, I think it's still useful if we want to Recordable::SetAttribute from data with lifetime(I want to reuse OwnedAttributeValue to store complex data structures and use it as attributes of trace or log).

Thanks for the explanation with a nicely written example. As you correctly mentioned, the scenario for resource is no more relevant once we start sharing resources through the provider. And passing resource as argument through Logger::log() should be removed. This is a breaking change, but acceptable as Logs Signal is still in preview. For log attributes, it would be better to pass them as KeyValueIterableView. Let me know if I am missing something here.

@owent

owent commented Dec 21, 2021

Copy link
Copy Markdown
Member Author

It can not convert all types from OwnedAttributeValue to AttributeValue . Even atfer move resource into provider, I think it's still useful if we want to Recordable::SetAttribute from data with lifetime(I want to reuse OwnedAttributeValue to store complex data structures and use it as attributes of trace or log).

For log attributes, it would be better to pass them as KeyValueIterableView. Let me know if I am missing something here.

Yes, this is what I mean, and my question is how to create KeyValueIterableView of OwnedAttributeValue ?

@lalitb

lalitb commented Dec 21, 2021

Copy link
Copy Markdown
Member

Yes, this is what I mean, and my question is how to create KeyValueIterableView of OwnedAttributeValue ?

I am still thinking why should this be under the scope of otel-cpp. Isn't this the responsibility of the library developer to ensure to call Span::AddEvent(name, attributes), Logger::Log(..., attributes,...) correctly? They may choose to use SDK::common::AttributMap as storage, or something as simple as std::map<std::string, std::string>. As long as it is converted into Key

Yes, this is what I mean, and my question is how to create KeyValueIterableView of OwnedAttributeValue ?

Which conversion is a problem in your above example - vector<std::string> to span<nostd::string_view> ? I think vector<bool> to span<bool> should be implicitly possible.

@owent

owent commented Dec 21, 2021

Copy link
Copy Markdown
Member Author

Yes, this is what I mean, and my question is how to create KeyValueIterableView of OwnedAttributeValue ?

I am still thinking why should this be under the scope of otel-cpp. Isn't this the responsibility of the library developer to ensure to call Span::AddEvent(name, attributes), Logger::Log(..., attributes,...) correctly? They may choose to use SDK::common::AttributMap as storage, or something as simple as std::map<std::string, std::string>. As long as it is converted into Key

Yes, this is what I mean, and my question is how to create KeyValueIterableView of OwnedAttributeValue ?

Which conversion is a problem in your above example - vector<std::string> to span<nostd::string_view> ? I think vector<bool> to span<bool> should be implicitly possible.

vector<bool> has a special implementation, it is more likely a bitset and the elements in it have no unique address. span<bool> need contiguouse addresses for every element to initialize.

@lalitb

lalitb commented Dec 21, 2021

Copy link
Copy Markdown
Member

vector<bool> has a special implementation, it is more likely a bitset and the elements in it have no unique address. span<bool> need contiguous addresses for every element to initialize.

yes agree, I see a problem with conversion for both vector<bool> and vector<string>, don't have a solution for now. Let me think about this. Now I also vaguely remember discussing this with @maxgolov during ETW implementation here.

@owent
owent force-pushed the propagating_resource_through_logger_provider branch from 9387847 to de2ebed Compare December 22, 2021 06:41
@owent owent changed the title [WIP] Logger: Propagating resources through LoggerProvider Logger: Propagating resources through LoggerProvider Dec 23, 2021
@owent

owent commented Dec 23, 2021

Copy link
Copy Markdown
Member Author

@lalitb This PR is almost finished. Could you please review the changes some time later?

@owent
owent force-pushed the propagating_resource_through_logger_provider branch from 19b3c7f to cfbb5f4 Compare January 4, 2022 02:17

@lalitb lalitb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the PR. Changes are nicely done. have added initial comments. It's a large PR, will have another scan on the multi-processor, multi-recordable part.

Comment thread api/include/opentelemetry/logs/logger.h Outdated

@lalitb lalitb Jan 4, 2022

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion here, but Logger implementation is in preview and should be fine to have breaking changes without explicit deprecating first, and have cleaner code. Also for tracing implementation, specs are already stable, which means there won't be any further breaking changes required for it. Just thinking about whether we need to really add deprecated support.
Whatever we decide need to also be done for the instrumentation library cc @esigo

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's helpful for users to have some time to upgrade the usage of Log API instead of just compile error.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With logs in experimental, I think breaking changes should be acceptable and users should be prepared for it. This will keep the API much cleaner. We should definitely mention this as a breaking change in the Release description.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I can remove these later, should I keep api/include/opentelemetry/common/macros.h ? Maybe it's useful in the future?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove macros for now, can add them back later if required. Thanks.

Comment thread bazel/repository.bzl Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - we also need to update the benchmark submodule used by cmake, and version in the ./third_party_release file ( we can raise an issue, and do it in separate PR).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing this.

Comment thread sdk/include/opentelemetry/sdk/logs/logger.h Outdated
@owent
owent force-pushed the propagating_resource_through_logger_provider branch 2 times, most recently from 32bbbf1 to ce61fda Compare January 4, 2022 06:20
Comment thread sdk/src/logs/multi_log_processor.cc Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are we trying to achieve here - to ensure that the total time taken by all the processors shouldn't exceed timeout ? For traces, logic is a bit different, as the same timeout is used for all processors. This looks good too to me.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think it may confuse ther users if they set timeout to some value, but actually take a more longer time.

E.g. when closing a service process, we may force to flush data, wait a limited time and then force to exit no matter it's done or not.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes agree.

@lalitb lalitb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once we remove the deprecated functionality.

@owent

owent commented Jan 5, 2022

Copy link
Copy Markdown
Member Author

LGTM once we remove the deprecated functionality.

Done. I keep the OPENTELEMETRY_MAYBE_UNUSED and it's used in sdk/include/opentelemetry/sdk/common/empty_attributes.h . Some compiler will warning unused static function when it's included(maybe included by recordable.h) by source file and do not use it.

@lalitb

lalitb commented Jan 6, 2022

Copy link
Copy Markdown
Member

LGTM once we remove the deprecated functionality.

Done. I keep the OPENTELEMETRY_MAYBE_UNUSED and it's used in sdk/include/opentelemetry/sdk/common/empty_attributes.h . Some compiler will warning unused static function when it's included(maybe included by recordable.h) by source file and do not use it.

Thanks. Probably all unused functionality can be removed separately some other time. Changes look good now. Thanks for working on this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why check vs2012 here? Seems the only valid case here is _MSVC_LANG >= 201703L. Also if this is true, should this be covered by the first check of __cplusplus >= 201703L?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's duplicated, I have removed it.Thanks.

@lalitb

lalitb commented Jan 12, 2022

Copy link
Copy Markdown
Member

@ThomsonTan - Is it good to merge?

owent added 8 commits January 12, 2022 15:10
Signed-off-by: owentou <owentou@tencent.com>
+ [BREAK CHANGES] Change the declaration of `sdk::logs::Recordable::SetResource`
+ [BREAK CHANGES] Change the `LoggerProvider::SetProcessor` into `LoggerProvider::AddProcessor`
+ Share `LoggerContext` between loggers

Signed-off-by: owentou <owentou@tencent.com>
Signed-off-by: owentou <owentou@tencent.com>
Signed-off-by: owentou <owentou@tencent.com>
Signed-off-by: owentou <owentou@tencent.com>
+ Fix multi log processor
+ Fix crash problem when log with invalid severity

Signed-off-by: owentou <owentou@tencent.com>
Signed-off-by: owentou <owentou@tencent.com>
Signed-off-by: owentou <owentou@tencent.com>
owent added 3 commits January 12, 2022 15:10
Signed-off-by: owentou <owentou@tencent.com>
Signed-off-by: owentou <owentou@tencent.com>
Signed-off-by: owentou <owentou@tencent.com>
@owent
owent force-pushed the propagating_resource_through_logger_provider branch from 6d72128 to c53bfd1 Compare January 12, 2022 07:11
@owent

owent commented Jan 12, 2022

Copy link
Copy Markdown
Member Author

Rebase on main again

@ThomsonTan
ThomsonTan merged commit d206b50 into open-telemetry:main Jan 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Logger: Propagating resources through LoggerProvider

3 participants