Couchbase C++ SDK 1.3.1 (rev. fb3f860)
Loading...
Searching...
No Matches
otel_meter.hxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright 2021 Couchbase, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#pragma once
19
21
22#include <opentelemetry/context/context.h>
23#include <opentelemetry/metrics/meter.h>
24#include <opentelemetry/metrics/sync_instruments.h>
25
26#include <algorithm>
27#include <memory>
28#include <mutex>
29#include <shared_mutex>
30#include <utility>
31#include <variant>
32
33namespace couchbase::metrics
34{
35template<typename T>
37{
38public:
40 opentelemetry::nostd::shared_ptr<opentelemetry::metrics::Histogram<T>> histogram,
41 const std::map<std::string, std::string>& tags)
42 : histogram_{ std::move(histogram) }
43 , tags_{ tags }
44 {
45 tags_.erase("__unit");
46 }
47
48 void record_value(std::int64_t value) override
49 {
50 if constexpr (std::is_same_v<T, double>) {
51 auto value_in_seconds = static_cast<double>(value) / 1'000'000.0;
52 histogram_->Record(
53 value_in_seconds, opentelemetry::common::KeyValueIterableView{ tags_ }, context_);
54 } else {
55 value = std::max<int64_t>(value, 0);
56 auto uvalue = static_cast<std::uint64_t>(value);
57 histogram_->Record(uvalue, opentelemetry::common::KeyValueIterableView{ tags_ }, context_);
58 }
59 }
60
61private:
62 opentelemetry::nostd::shared_ptr<opentelemetry::metrics::Histogram<T>> histogram_;
63 std::map<std::string, std::string> tags_{};
64 opentelemetry::context::Context context_{};
65 std::mutex mutex_;
66};
67
69{
70public:
71 explicit otel_meter(opentelemetry::nostd::shared_ptr<opentelemetry::metrics::Meter> meter)
72 : meter_{ std::move(meter) }
73 {
74 }
75
76 auto get_value_recorder(const std::string& name, const std::map<std::string, std::string>& tags)
77 -> std::shared_ptr<value_recorder> override
78 {
79 bool in_seconds{ false };
80 if (tags.count("__unit") > 0) {
81 if (tags.at("__unit") == "s") {
82 in_seconds = true;
83 }
84 }
85
86 {
87 // Check if we already have the histogram
88 std::shared_lock lock(mutex_);
89 if (in_seconds) {
90 if (const auto it = double_histograms_.find(name); it != double_histograms_.end()) {
91 return std::make_shared<otel_value_recorder<double>>(it->second, tags);
92 }
93 } else {
94 if (const auto it = uint_histograms_.find(name); it != uint_histograms_.end()) {
95 return std::make_shared<otel_value_recorder<std::uint64_t>>(it->second, tags);
96 }
97 }
98 }
99
100 {
101 // We have to check if we already have the histogram again, before creating it, in case
102 // another thread created it while we were waiting for the exclusive lock
103 std::scoped_lock lock(mutex_);
104 if (in_seconds) {
105 if (const auto it = double_histograms_.find(name); it != double_histograms_.end()) {
106 return std::make_shared<otel_value_recorder<double>>(it->second, tags);
107 }
108 // Not found, we have to create it
109 auto histogram = meter_->CreateDoubleHistogram(name, "", "s");
110 double_histograms_.emplace(name, std::move(histogram));
111 return std::make_shared<otel_value_recorder<double>>(double_histograms_.at(name), tags);
112 } else {
113 if (const auto it = uint_histograms_.find(name); it != uint_histograms_.end()) {
114 return std::make_shared<otel_value_recorder<std::uint64_t>>(it->second, tags);
115 }
116 // Not found, we have to create it
117 auto histogram = meter_->CreateUInt64Histogram(name);
118 uint_histograms_.emplace(name, std::move(histogram));
119 return std::make_shared<otel_value_recorder<std::uint64_t>>(uint_histograms_.at(name),
120 tags);
121 }
122 }
123 }
124
125private:
126 opentelemetry::nostd::shared_ptr<opentelemetry::metrics::Meter> meter_;
127 std::shared_mutex mutex_;
128 std::map<std::string, opentelemetry::nostd::shared_ptr<opentelemetry::metrics::Histogram<double>>>
129 double_histograms_;
130 std::map<std::string,
131 opentelemetry::nostd::shared_ptr<opentelemetry::metrics::Histogram<std::uint64_t>>>
132 uint_histograms_;
133};
134} // namespace couchbase::metrics
Definition meter.hxx:41
auto get_value_recorder(const std::string &name, const std::map< std::string, std::string > &tags) -> std::shared_ptr< value_recorder > override
Definition otel_meter.hxx:76
otel_meter(opentelemetry::nostd::shared_ptr< opentelemetry::metrics::Meter > meter)
Definition otel_meter.hxx:71
void record_value(std::int64_t value) override
Definition otel_meter.hxx:48
otel_value_recorder(opentelemetry::nostd::shared_ptr< opentelemetry::metrics::Histogram< T > > histogram, const std::map< std::string, std::string > &tags)
Definition otel_meter.hxx:39
Definition meter.hxx:28
Definition meter.hxx:26