未验证 提交 977ebe8b 编写于 作者: N Nikolai Kochetov 提交者: GitHub

Merge pull request #22058 from azat/system.errors-trace

Convert system.errors.stack_trace from String into Array(UInt64)
......@@ -9,7 +9,7 @@ Columns:
- `value` ([UInt64](../../sql-reference/data-types/int-uint.md)) — the number of times this error has been happened.
- `last_error_time` ([DateTime](../../sql-reference/data-types/datetime.md)) — time when the last error happened.
- `last_error_message` ([String](../../sql-reference/data-types/string.md)) — message for the last error.
- `last_error_stacktrace` ([String](../../sql-reference/data-types/string.md)) — stacktrace for the last error.
- `last_error_trace` ([Array(UInt64)](../../sql-reference/data-types/array.md)) — A [stack trace](https://en.wikipedia.org/wiki/Stack_trace) which represents a list of physical addresses where the called methods are stored.
- `remote` ([UInt8](../../sql-reference/data-types/int-uint.md)) — remote exception (i.e. received during one of the distributed query).
**Example**
......@@ -25,3 +25,12 @@ LIMIT 1
CANNOT_OPEN_FILE 76 1
└──────────────────┴──────┴───────┘
```
``` sql
WITH arrayMap(x -> demangle(addressToSymbol(x)), last_error_trace) AS all
SELECT name, arrayStringConcat(all, '\n') AS res
FROM system.errors
LIMIT 1
SETTINGS allow_introspection_functions=1\G
```
......@@ -560,7 +560,7 @@ namespace DB
{
namespace ErrorCodes
{
#define M(VALUE, NAME) extern const Value NAME = VALUE;
#define M(VALUE, NAME) extern const ErrorCode NAME = VALUE;
APPLY_FOR_ERROR_CODES(M)
#undef M
......@@ -587,7 +587,7 @@ namespace ErrorCodes
ErrorCode end() { return END + 1; }
void increment(ErrorCode error_code, bool remote, const std::string & message, const std::string & stacktrace)
void increment(ErrorCode error_code, bool remote, const std::string & message, const FramePointers & trace)
{
if (error_code >= end())
{
......@@ -596,10 +596,10 @@ namespace ErrorCodes
error_code = end() - 1;
}
values[error_code].increment(remote, message, stacktrace);
values[error_code].increment(remote, message, trace);
}
void ErrorPairHolder::increment(bool remote, const std::string & message, const std::string & stacktrace)
void ErrorPairHolder::increment(bool remote, const std::string & message, const FramePointers & trace)
{
const auto now = std::chrono::system_clock::now();
......@@ -609,7 +609,7 @@ namespace ErrorCodes
++error.count;
error.message = message;
error.stacktrace = stacktrace;
error.trace = trace;
error.error_time_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
}
ErrorPair ErrorPairHolder::get()
......
#pragma once
#include <stddef.h>
#include <cstddef>
#include <cstdint>
#include <utility>
#include <mutex>
#include <common/types.h>
#include <string_view>
#include <vector>
#include <common/types.h>
/** Allows to count number of simultaneously happening error codes.
* See also Exception.cpp for incrementing part.
......@@ -19,6 +20,7 @@ namespace ErrorCodes
/// ErrorCode identifier (index in array).
using ErrorCode = int;
using Value = size_t;
using FramePointers = std::vector<void *>;
/// Get name of error_code by identifier.
/// Returns statically allocated string.
......@@ -33,7 +35,7 @@ namespace ErrorCodes
/// Message for the last error.
std::string message;
/// Stacktrace for the last error.
std::string stacktrace;
FramePointers trace;
};
struct ErrorPair
{
......@@ -46,7 +48,7 @@ namespace ErrorCodes
{
public:
ErrorPair get();
void increment(bool remote, const std::string & message, const std::string & stacktrace);
void increment(bool remote, const std::string & message, const FramePointers & trace);
private:
ErrorPair value;
......@@ -60,7 +62,7 @@ namespace ErrorCodes
ErrorCode end();
/// Add value for specified error_code.
void increment(ErrorCode error_code, bool remote, const std::string & message, const std::string & stacktrace);
void increment(ErrorCode error_code, bool remote, const std::string & message, const FramePointers & trace);
}
}
......@@ -36,7 +36,7 @@ namespace ErrorCodes
/// - Aborts the process if error code is LOGICAL_ERROR.
/// - Increments error codes statistics.
void handle_error_code([[maybe_unused]] const std::string & msg, const std::string & stacktrace, int code, bool remote)
void handle_error_code([[maybe_unused]] const std::string & msg, int code, bool remote, const Exception::FramePointers & trace)
{
// In debug builds and builds with sanitizers, treat LOGICAL_ERROR as an assertion failure.
// Log the message before we fail.
......@@ -47,20 +47,21 @@ void handle_error_code([[maybe_unused]] const std::string & msg, const std::stri
abort();
}
#endif
ErrorCodes::increment(code, remote, msg, stacktrace);
ErrorCodes::increment(code, remote, msg, trace);
}
Exception::Exception(const std::string & msg, int code, bool remote_)
: Poco::Exception(msg, code)
, remote(remote_)
{
handle_error_code(msg, getStackTraceString(), code, remote);
handle_error_code(msg, code, remote, getStackFramePointers());
}
Exception::Exception(const std::string & msg, const Exception & nested, int code)
: Poco::Exception(msg, nested, code)
{
handle_error_code(msg, getStackTraceString(), code, remote);
handle_error_code(msg, code, remote, getStackFramePointers());
}
Exception::Exception(CreateFromPocoTag, const Poco::Exception & exc)
......@@ -101,6 +102,31 @@ std::string Exception::getStackTraceString() const
#endif
}
Exception::FramePointers Exception::getStackFramePointers() const
{
FramePointers frame_pointers;
#ifdef STD_EXCEPTION_HAS_STACK_TRACE
{
frame_pointers.resize(get_stack_trace_size());
for (size_t i = 0; i < frame_pointers.size(); ++i)
{
frame_pointers[i] = get_stack_trace_frames()[i];
}
}
#else
{
size_t stack_trace_size = trace.getSize();
size_t stack_trace_offset = trace.getOffset();
frame_pointers.reserve(stack_trace_size - stack_trace_offset);
for (size_t i = stack_trace_offset; i < stack_trace_size; ++i)
{
frame_pointers.push_back(trace.getFramePointers()[i]);
}
}
#endif
return frame_pointers;
}
void throwFromErrno(const std::string & s, int code, int the_errno)
{
......
......@@ -24,6 +24,8 @@ namespace DB
class Exception : public Poco::Exception
{
public:
using FramePointers = std::vector<void *>;
Exception() = default;
Exception(const std::string & msg, int code, bool remote_ = false);
Exception(const std::string & msg, const Exception & nested, int code);
......@@ -66,6 +68,8 @@ public:
bool isRemoteException() const { return remote; }
std::string getStackTraceString() const;
/// Used for system.errors
FramePointers getStackFramePointers() const;
private:
#ifndef STD_EXCEPTION_HAS_STACK_TRACE
......
#include <DataTypes/DataTypeString.h>
#include <DataTypes/DataTypesNumber.h>
#include <DataTypes/DataTypeDateTime.h>
#include <DataTypes/DataTypeArray.h>
#include <Storages/System/StorageSystemErrors.h>
#include <Common/ErrorCodes.h>
#include <Interpreters/Context.h>
......@@ -16,7 +17,7 @@ NamesAndTypesList StorageSystemErrors::getNamesAndTypes()
{ "value", std::make_shared<DataTypeUInt64>() },
{ "last_error_time", std::make_shared<DataTypeDateTime>() },
{ "last_error_message", std::make_shared<DataTypeString>() },
{ "last_error_stacktrace", std::make_shared<DataTypeString>() },
{ "last_error_trace", std::make_shared<DataTypeArray>(std::make_shared<DataTypeUInt64>()) },
{ "remote", std::make_shared<DataTypeUInt8>() },
};
}
......@@ -34,7 +35,14 @@ void StorageSystemErrors::fillData(MutableColumns & res_columns, const Context &
res_columns[col_num++]->insert(error.count);
res_columns[col_num++]->insert(error.error_time_ms / 1000);
res_columns[col_num++]->insert(error.message);
res_columns[col_num++]->insert(error.stacktrace);
{
Array trace_array;
trace_array.reserve(error.trace.size());
for (size_t i = 0; i < error.trace.size(); ++i)
trace_array.emplace_back(reinterpret_cast<intptr_t>(error.trace[i]));
res_columns[col_num++]->insert(trace_array);
}
res_columns[col_num++]->insert(remote);
}
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册