The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
365 lines
16 KiB
365 lines
16 KiB
// Copyright 2024 The gRPC 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. |
|
|
|
#ifndef GRPC_SRC_CORE_LIB_CHANNEL_METRICS_H |
|
#define GRPC_SRC_CORE_LIB_CHANNEL_METRICS_H |
|
|
|
#include <cstdint> |
|
#include <memory> |
|
#include <vector> |
|
|
|
#include "absl/functional/any_invocable.h" |
|
#include "absl/functional/function_ref.h" |
|
#include "absl/strings/string_view.h" |
|
#include "absl/types/span.h" |
|
|
|
#include <grpc/support/log.h> |
|
#include <grpc/support/metrics.h> |
|
#include <grpc/support/port_platform.h> |
|
|
|
#include "src/core/lib/channel/call_tracer.h" |
|
#include "src/core/lib/channel/channel_args.h" |
|
#include "src/core/lib/channel/context.h" |
|
#include "src/core/lib/gprpp/no_destruct.h" |
|
#include "src/core/lib/gprpp/sync.h" |
|
#include "src/core/lib/gprpp/time.h" |
|
#include "src/core/lib/slice/slice.h" |
|
|
|
namespace grpc_core { |
|
|
|
constexpr absl::string_view kMetricLabelTarget = "grpc.target"; |
|
|
|
// A global registry of instruments(metrics). This API is designed to be used |
|
// to register instruments (Counter, Histogram, and Gauge) as part of program |
|
// startup, before the execution of the main function (during dynamic |
|
// initialization time). Using this API after the main function begins may |
|
// result into missing instruments. This API is thread-unsafe. |
|
class GlobalInstrumentsRegistry { |
|
public: |
|
enum class ValueType { |
|
kUndefined, |
|
kInt64, |
|
kUInt64, |
|
kDouble, |
|
}; |
|
enum class InstrumentType { |
|
kUndefined, |
|
kCounter, |
|
kHistogram, |
|
kCallbackGauge, |
|
}; |
|
using InstrumentID = uint32_t; |
|
struct GlobalInstrumentDescriptor { |
|
ValueType value_type; |
|
InstrumentType instrument_type; |
|
InstrumentID index; |
|
bool enable_by_default; |
|
absl::string_view name; |
|
absl::string_view description; |
|
absl::string_view unit; |
|
std::vector<absl::string_view> label_keys; |
|
std::vector<absl::string_view> optional_label_keys; |
|
}; |
|
struct GlobalInstrumentHandle { |
|
// This is the index for the corresponding registered instrument that |
|
// StatsPlugins can use to uniquely identify an instrument in the current |
|
// process. Though this is not guaranteed to be stable between different |
|
// runs or between different versions. |
|
InstrumentID index; |
|
}; |
|
struct GlobalUInt64CounterHandle : public GlobalInstrumentHandle {}; |
|
struct GlobalDoubleCounterHandle : public GlobalInstrumentHandle {}; |
|
struct GlobalUInt64HistogramHandle : public GlobalInstrumentHandle {}; |
|
struct GlobalDoubleHistogramHandle : public GlobalInstrumentHandle {}; |
|
struct GlobalCallbackInt64GaugeHandle : public GlobalInstrumentHandle {}; |
|
struct GlobalCallbackDoubleGaugeHandle : public GlobalInstrumentHandle {}; |
|
using GlobalCallbackHandle = absl::variant<GlobalCallbackInt64GaugeHandle, |
|
GlobalCallbackDoubleGaugeHandle>; |
|
|
|
// Creates instrument in the GlobalInstrumentsRegistry. |
|
static GlobalUInt64CounterHandle RegisterUInt64Counter( |
|
absl::string_view name, absl::string_view description, |
|
absl::string_view unit, absl::Span<const absl::string_view> label_keys, |
|
absl::Span<const absl::string_view> optional_label_keys, |
|
bool enable_by_default); |
|
static GlobalDoubleCounterHandle RegisterDoubleCounter( |
|
absl::string_view name, absl::string_view description, |
|
absl::string_view unit, absl::Span<const absl::string_view> label_keys, |
|
absl::Span<const absl::string_view> optional_label_keys, |
|
bool enable_by_default); |
|
static GlobalUInt64HistogramHandle RegisterUInt64Histogram( |
|
absl::string_view name, absl::string_view description, |
|
absl::string_view unit, absl::Span<const absl::string_view> label_keys, |
|
absl::Span<const absl::string_view> optional_label_keys, |
|
bool enable_by_default); |
|
static GlobalDoubleHistogramHandle RegisterDoubleHistogram( |
|
absl::string_view name, absl::string_view description, |
|
absl::string_view unit, absl::Span<const absl::string_view> label_keys, |
|
absl::Span<const absl::string_view> optional_label_keys, |
|
bool enable_by_default); |
|
static GlobalCallbackInt64GaugeHandle RegisterCallbackInt64Gauge( |
|
absl::string_view name, absl::string_view description, |
|
absl::string_view unit, absl::Span<const absl::string_view> label_keys, |
|
absl::Span<const absl::string_view> optional_label_keys, |
|
bool enable_by_default); |
|
static GlobalCallbackDoubleGaugeHandle RegisterCallbackDoubleGauge( |
|
absl::string_view name, absl::string_view description, |
|
absl::string_view unit, absl::Span<const absl::string_view> label_keys, |
|
absl::Span<const absl::string_view> optional_label_keys, |
|
bool enable_by_default); |
|
|
|
static void ForEach( |
|
absl::FunctionRef<void(const GlobalInstrumentDescriptor&)> f); |
|
static const GlobalInstrumentDescriptor& GetInstrumentDescriptor( |
|
GlobalInstrumentHandle handle); |
|
|
|
private: |
|
friend class GlobalInstrumentsRegistryTestPeer; |
|
|
|
GlobalInstrumentsRegistry() = delete; |
|
|
|
static std::vector<GlobalInstrumentsRegistry::GlobalInstrumentDescriptor>& |
|
GetInstrumentList(); |
|
}; |
|
|
|
// An interface for implementing callback-style metrics. |
|
// To be implemented by stats plugins. |
|
class CallbackMetricReporter { |
|
public: |
|
virtual ~CallbackMetricReporter() = default; |
|
|
|
virtual void Report( |
|
GlobalInstrumentsRegistry::GlobalCallbackInt64GaugeHandle handle, |
|
int64_t value, absl::Span<const absl::string_view> label_values, |
|
absl::Span<const absl::string_view> optional_values) = 0; |
|
virtual void Report( |
|
GlobalInstrumentsRegistry::GlobalCallbackDoubleGaugeHandle handle, |
|
double value, absl::Span<const absl::string_view> label_values, |
|
absl::Span<const absl::string_view> optional_values) = 0; |
|
}; |
|
|
|
class RegisteredMetricCallback; |
|
|
|
// The StatsPlugin interface. |
|
class StatsPlugin { |
|
public: |
|
// A general-purpose way for stats plugin to store per-channel or per-server |
|
// state. |
|
class ScopeConfig { |
|
public: |
|
virtual ~ScopeConfig() = default; |
|
}; |
|
|
|
virtual ~StatsPlugin() = default; |
|
|
|
// Whether this stats plugin is enabled for the channel specified by \a scope. |
|
// Returns true and a channel-specific ScopeConfig which may then be used to |
|
// configure the ClientCallTracer in GetClientCallTracer(). |
|
virtual std::pair<bool, std::shared_ptr<ScopeConfig>> IsEnabledForChannel( |
|
const experimental::StatsPluginChannelScope& scope) const = 0; |
|
// Whether this stats plugin is enabled for the server specified by \a args. |
|
// Returns true and a server-specific ScopeConfig which may then be used to |
|
// configure the ServerCallTracer in GetServerCallTracer(). |
|
virtual std::pair<bool, std::shared_ptr<ScopeConfig>> IsEnabledForServer( |
|
const ChannelArgs& args) const = 0; |
|
|
|
// Adds \a value to the uint64 counter specified by \a handle. \a label_values |
|
// and \a optional_label_values specify attributes that are associated with |
|
// this measurement and must match with their corresponding keys in |
|
// GlobalInstrumentsRegistry::RegisterUInt64Counter(). |
|
virtual void AddCounter( |
|
GlobalInstrumentsRegistry::GlobalUInt64CounterHandle handle, |
|
uint64_t value, absl::Span<const absl::string_view> label_values, |
|
absl::Span<const absl::string_view> optional_label_values) = 0; |
|
// Adds \a value to the double counter specified by \a handle. \a label_values |
|
// and \a optional_label_values specify attributes that are associated with |
|
// this measurement and must match with their corresponding keys in |
|
// GlobalInstrumentsRegistry::RegisterDoubleCounter(). |
|
virtual void AddCounter( |
|
GlobalInstrumentsRegistry::GlobalDoubleCounterHandle handle, double value, |
|
absl::Span<const absl::string_view> label_values, |
|
absl::Span<const absl::string_view> optional_label_values) = 0; |
|
// Records a uint64 \a value to the histogram specified by \a handle. \a |
|
// label_values and \a optional_label_values specify attributes that are |
|
// associated with this measurement and must match with their corresponding |
|
// keys in GlobalInstrumentsRegistry::RegisterUInt64Histogram(). |
|
virtual void RecordHistogram( |
|
GlobalInstrumentsRegistry::GlobalUInt64HistogramHandle handle, |
|
uint64_t value, absl::Span<const absl::string_view> label_values, |
|
absl::Span<const absl::string_view> optional_label_values) = 0; |
|
// Records a double \a value to the histogram specified by \a handle. \a |
|
// label_values and \a optional_label_values specify attributes that are |
|
// associated with this measurement and must match with their corresponding |
|
// keys in GlobalInstrumentsRegistry::RegisterDoubleHistogram(). |
|
virtual void RecordHistogram( |
|
GlobalInstrumentsRegistry::GlobalDoubleHistogramHandle handle, |
|
double value, absl::Span<const absl::string_view> label_values, |
|
absl::Span<const absl::string_view> optional_label_values) = 0; |
|
// Adds a callback to be invoked when the stats plugin wants to |
|
// populate the corresponding metrics (see callback->metrics() for list). |
|
virtual void AddCallback(RegisteredMetricCallback* callback) = 0; |
|
// Removes a callback previously added via AddCallback(). The stats |
|
// plugin may not use the callback after this method returns. |
|
virtual void RemoveCallback(RegisteredMetricCallback* callback) = 0; |
|
|
|
// Gets a ClientCallTracer associated with this stats plugin which can be used |
|
// in a call. |
|
virtual ClientCallTracer* GetClientCallTracer( |
|
const Slice& path, bool registered_method, |
|
std::shared_ptr<ScopeConfig> scope_config) = 0; |
|
// Gets a ServerCallTracer associated with this stats plugin which can be used |
|
// in a call. |
|
virtual ServerCallTracer* GetServerCallTracer( |
|
std::shared_ptr<ScopeConfig> scope_config) = 0; |
|
|
|
// TODO(yijiem): This is an optimization for the StatsPlugin to create its own |
|
// representation of the label_values and use it multiple times. We would |
|
// change AddCounter and RecordHistogram to take RefCountedPtr<LabelValueSet> |
|
// and also change the StatsPluginsGroup to support this. |
|
// Use the StatsPlugin to get a representation of label values that can be |
|
// saved for multiple uses later. |
|
// virtual RefCountedPtr<LabelValueSet> MakeLabelValueSet( |
|
// absl::Span<absl::string_view> label_values) = 0; |
|
}; |
|
|
|
// A global registry of stats plugins. It has shared ownership to the registered |
|
// stats plugins. This API is supposed to be used during runtime after the main |
|
// function begins. This API is thread-safe. |
|
class GlobalStatsPluginRegistry { |
|
public: |
|
// A stats plugin group object is how the code in gRPC normally interacts with |
|
// stats plugins. They got a stats plugin group which contains all the stats |
|
// plugins for a specific scope and all operations on the stats plugin group |
|
// will be applied to all the stats plugins within the group. |
|
class StatsPluginGroup { |
|
public: |
|
// Adds a stats plugin and a scope config (per-channel or per-server) to the |
|
// group. |
|
void AddStatsPlugin(std::shared_ptr<StatsPlugin> plugin, |
|
std::shared_ptr<StatsPlugin::ScopeConfig> config) { |
|
PluginState plugin_state; |
|
plugin_state.plugin = std::move(plugin); |
|
plugin_state.scope_config = std::move(config); |
|
plugins_state_.push_back(std::move(plugin_state)); |
|
} |
|
// Adds a counter in all stats plugins within the group. See the StatsPlugin |
|
// interface for more documentation and valid types. |
|
template <class HandleType, class ValueType> |
|
void AddCounter(HandleType handle, ValueType value, |
|
absl::Span<const absl::string_view> label_values, |
|
absl::Span<const absl::string_view> optional_values) { |
|
for (auto& state : plugins_state_) { |
|
state.plugin->AddCounter(handle, value, label_values, optional_values); |
|
} |
|
} |
|
// Records a value to a histogram in all stats plugins within the group. See |
|
// the StatsPlugin interface for more documentation and valid types. |
|
template <class HandleType, class ValueType> |
|
void RecordHistogram(HandleType handle, ValueType value, |
|
absl::Span<const absl::string_view> label_values, |
|
absl::Span<const absl::string_view> optional_values) { |
|
for (auto& state : plugins_state_) { |
|
state.plugin->RecordHistogram(handle, value, label_values, |
|
optional_values); |
|
} |
|
} |
|
|
|
// Registers a callback to be used to populate callback metrics. |
|
// The callback will update the specified metrics. The callback |
|
// will be invoked no more often than min_interval. Multiple callbacks may |
|
// be registered for the same metrics, as long as no two callbacks report |
|
// data for the same set of labels in which case the behavior is undefined. |
|
// |
|
// The returned object is a handle that allows the caller to control |
|
// the lifetime of the callback; when the returned object is |
|
// destroyed, the callback is de-registered. The returned object |
|
// must not outlive the StatsPluginGroup object that created it. |
|
GRPC_MUST_USE_RESULT std::unique_ptr<RegisteredMetricCallback> |
|
RegisterCallback( |
|
absl::AnyInvocable<void(CallbackMetricReporter&)> callback, |
|
std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle> metrics, |
|
Duration min_interval = Duration::Seconds(5)); |
|
|
|
// Adds all available client call tracers associated with the stats plugins |
|
// within the group to \a call_context. |
|
void AddClientCallTracers(const Slice& path, bool registered_method, |
|
grpc_call_context_element* call_context); |
|
// Adds all available server call tracers associated with the stats plugins |
|
// within the group to \a call_context. |
|
void AddServerCallTracers(grpc_call_context_element* call_context); |
|
|
|
private: |
|
friend class RegisteredMetricCallback; |
|
|
|
struct PluginState { |
|
std::shared_ptr<StatsPlugin::ScopeConfig> scope_config; |
|
std::shared_ptr<StatsPlugin> plugin; |
|
}; |
|
|
|
std::vector<PluginState> plugins_state_; |
|
}; |
|
|
|
// Registers a stats plugin with the global stats plugin registry. |
|
static void RegisterStatsPlugin(std::shared_ptr<StatsPlugin> plugin); |
|
|
|
// The following functions can be invoked to get a StatsPluginGroup for |
|
// a specified scope. |
|
static StatsPluginGroup GetStatsPluginsForChannel( |
|
const experimental::StatsPluginChannelScope& scope); |
|
static StatsPluginGroup GetStatsPluginsForServer(const ChannelArgs& args); |
|
|
|
private: |
|
friend class GlobalStatsPluginRegistryTestPeer; |
|
|
|
GlobalStatsPluginRegistry() = default; |
|
|
|
static NoDestruct<Mutex> mutex_; |
|
static NoDestruct<std::vector<std::shared_ptr<StatsPlugin>>> plugins_ |
|
ABSL_GUARDED_BY(mutex_); |
|
}; |
|
|
|
// A metric callback that is registered with a stats plugin group. |
|
class RegisteredMetricCallback { |
|
public: |
|
RegisteredMetricCallback( |
|
GlobalStatsPluginRegistry::StatsPluginGroup& stats_plugin_group, |
|
absl::AnyInvocable<void(CallbackMetricReporter&)> callback, |
|
std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle> metrics, |
|
Duration min_interval); |
|
|
|
~RegisteredMetricCallback(); |
|
|
|
// Invokes the callback. The callback will report metric data via reporter. |
|
void Run(CallbackMetricReporter& reporter) { callback_(reporter); } |
|
|
|
// Returns the set of metrics that this callback will modify. |
|
const std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle>& metrics() |
|
const { |
|
return metrics_; |
|
} |
|
|
|
// Returns the minimum interval at which a stats plugin may invoke the |
|
// callback. |
|
Duration min_interval() const { return min_interval_; } |
|
|
|
private: |
|
GlobalStatsPluginRegistry::StatsPluginGroup& stats_plugin_group_; |
|
absl::AnyInvocable<void(CallbackMetricReporter&)> callback_; |
|
std::vector<GlobalInstrumentsRegistry::GlobalCallbackHandle> metrics_; |
|
Duration min_interval_; |
|
}; |
|
|
|
} // namespace grpc_core |
|
|
|
#endif // GRPC_SRC_CORE_LIB_CHANNEL_METRICS_H
|
|
|