// Copyright 2023 PingCAP, Inc. // // 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. #pragma once #include #include #include #include #include /** Allows to count number of simultaneously happening processes or current value of some metric. * - for high-level profiling. * * See also ProfileEvents.h * ProfileEvents counts number of happened events - for example, how many times queries was executed. * CurrentMetrics counts number of simultaneously happening events - for example, number of currently executing queries, right now, * or just current value of some metric - for example, replica delay in seconds. * * CurrentMetrics are updated instantly and are correct for any point in time. * For periodically (asynchronously) updated metrics, see AsynchronousMetrics.h */ namespace CurrentMetrics { /// Metric identifier (index in array). using Metric = size_t; using Value = DB::Int64; /// Get text description of metric by identifier. Returns statically allocated string. const char * getDescription(Metric event); /// Metric identifier -> current value of metric. extern std::atomic values[]; /// Get index just after last metric identifier. Metric end(); /// Set value of specified metric. inline void set(Metric metric, Value value) { values[metric].store(value, std::memory_order_relaxed); } /// Get value of specified metric. inline Value get(Metric metric) { return values[metric]; } /// Add value for specified metric. You must subtract value later; or see class Increment below. inline void add(Metric metric, Value value = 1) { values[metric].fetch_add(value, std::memory_order_relaxed); } inline void sub(Metric metric, Value value = 1) { add(metric, -value); } /// For lifetime of object, add amount for specified metric. Then subtract. class Increment { private: std::atomic * what; Value amount; Increment(std::atomic * what, Value amount) : what(what) , amount(amount) { *what += amount; } public: explicit Increment(Metric metric, Value amount = 1) : Increment(&values[metric], amount) {} ~Increment() { if (what) what->fetch_sub(amount, std::memory_order_relaxed); } Increment(Increment && old) { *this = std::move(old); } Increment & operator=(Increment && old) { what = old.what; amount = old.amount; old.what = nullptr; return *this; } void changeTo(Value new_amount) { what->fetch_add(new_amount - amount, std::memory_order_relaxed); amount = new_amount; } /// Subtract value before destructor. void destroy() { what->fetch_sub(amount, std::memory_order_relaxed); what = nullptr; } }; } // namespace CurrentMetrics