Files
doris/be/src/util/debug_points.h

140 lines
5.2 KiB
C++

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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 <atomic>
#include <boost/lexical_cast.hpp>
#include <chrono>
#include <functional>
#include <map>
#include <memory>
#include <thread>
#include <type_traits>
#include "common/compiler_util.h"
#include "common/config.h"
#include "fmt/format.h"
// more usage can see 'util/debug_points_test.cpp'
#define DBUG_EXECUTE_IF(debug_point_name, code) \
if (UNLIKELY(config::enable_debug_points)) { \
auto dp = DebugPoints::instance()->get_debug_point(debug_point_name); \
if (dp) { \
[[maybe_unused]] auto DP_NAME = debug_point_name; \
code; \
} \
}
// define some common debug actions
// usage example: DBUG_EXECUTE_IF("xxx", DBUG_BLOCK);
#define DBUG_BLOCK \
{ \
LOG(INFO) << "start debug block " << DP_NAME; \
while (DebugPoints::instance()->is_enable(DP_NAME)) { \
std::this_thread::sleep_for(std::chrono::milliseconds(10)); \
} \
LOG(INFO) << "end debug block " << DP_NAME; \
}
namespace doris {
struct DebugPoint {
std::atomic<int64_t> execute_num {0};
int64_t execute_limit = -1;
int64_t expire_ms = -1;
std::map<std::string, std::string> params;
template <typename T>
T param(const std::string& key, T default_value = T()) {
auto it = params.find(key);
if (it == params.end()) {
return default_value;
}
if constexpr (std::is_same_v<T, bool>) {
if (it->second == "true") {
return true;
}
if (it->second == "false") {
return false;
}
return boost::lexical_cast<T>(it->second);
} else if constexpr (std::is_arithmetic_v<T>) {
return boost::lexical_cast<T>(it->second);
} else if constexpr (std::is_same_v<T, const char*>) {
return it->second.c_str();
} else {
static_assert(std::is_same_v<T, std::string>);
return it->second;
}
}
};
class DebugPoints {
public:
bool is_enable(const std::string& name);
std::shared_ptr<DebugPoint> get_debug_point(const std::string& name);
void remove(const std::string& name);
void clear();
// if not enable debug point or its params not contains `key`, then return `default_value`
// url: /api/debug_point/add/name?k1=v1&k2=v2&...
template <typename T>
T get_debug_param_or_default(const std::string& name, const std::string& key,
const T& default_value) {
auto debug_point = get_debug_point(name);
return debug_point ? debug_point->param(key, default_value) : default_value;
}
// url: /api/debug_point/add/name?value=v
template <typename T>
T get_debug_param_or_default(const std::string& name, const T& default_value) {
return get_debug_param_or_default(name, "value", default_value);
}
void add(const std::string& name, std::shared_ptr<DebugPoint> debug_point);
// more 'add' functions for convenient use
void add(const std::string& name) { add(name, std::make_shared<DebugPoint>()); }
void add_with_params(const std::string& name,
const std::map<std::string, std::string>& params) {
add(name, std::shared_ptr<DebugPoint>(new DebugPoint {.params = params}));
}
template <typename T>
void add_with_value(const std::string& name, const T& value) {
add_with_params(name, {{"value", fmt::format("{}", value)}});
}
static DebugPoints* instance();
private:
DebugPoints();
using DebugPointMap = std::map<std::string, std::shared_ptr<DebugPoint>>;
// handler(new_debug_points)
void update(std::function<void(DebugPointMap&)>&& handler);
private:
/// TODO: replace atomic_load/store() on shared_ptr (which is deprecated as of C++20) by C++20 std::atomic<std::shared_ptr>.
/// Clang 15 currently does not support it.
std::shared_ptr<const DebugPointMap> _debug_points;
};
} // namespace doris