mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 02:03:04 +01:00
Improvements
CORE-5475 : Provide ability to filter out info and warnings from trace log, and CORE-4486 : Trace: provide filter to INCLUDE / EXCLUDE errors by their mnemonical names Also, fix text alignment issue in detailed per-table perf stats
This commit is contained in:
parent
7d345af44d
commit
800baa6f44
@ -33,6 +33,7 @@
|
||||
#include "PluginLogWriter.h"
|
||||
#include "os/platform.h"
|
||||
#include "consts_pub.h"
|
||||
#include "codetext.h"
|
||||
#include "../../common/isc_f_proto.h"
|
||||
#include "../../jrd/RuntimeStatistics.h"
|
||||
#include "../../common/dsc.h"
|
||||
@ -97,7 +98,9 @@ TracePluginImpl::TracePluginImpl(IPluginBase* plugin,
|
||||
transactions(getDefaultMemoryPool()),
|
||||
statements(getDefaultMemoryPool()),
|
||||
services(getDefaultMemoryPool()),
|
||||
unicodeCollation(*getDefaultMemoryPool())
|
||||
unicodeCollation(*getDefaultMemoryPool()),
|
||||
include_codes(*getDefaultMemoryPool()),
|
||||
exclude_codes(*getDefaultMemoryPool())
|
||||
{
|
||||
const char* ses_name = initInfo->getTraceSessionName();
|
||||
session_name = ses_name && *ses_name ? ses_name : " ";
|
||||
@ -163,6 +166,13 @@ TracePluginImpl::TracePluginImpl(IPluginBase* plugin,
|
||||
}
|
||||
}
|
||||
|
||||
// parse filters for gds error codes
|
||||
if (!config.include_gds_codes.isEmpty())
|
||||
str2Array(config.include_gds_codes, include_codes);
|
||||
|
||||
if (!config.exclude_gds_codes.isEmpty())
|
||||
str2Array(config.exclude_gds_codes, exclude_codes);
|
||||
|
||||
operational = true;
|
||||
log_init();
|
||||
}
|
||||
@ -496,18 +506,30 @@ void TracePluginImpl::appendTableCounts(const PerformanceInfo *info)
|
||||
if (!config.print_perf || info->pin_count == 0)
|
||||
return;
|
||||
|
||||
record.append(NEWLINE
|
||||
"Table Natural Index Update Insert Delete Backout Purge Expunge" NEWLINE
|
||||
"***************************************************************************************************************" NEWLINE );
|
||||
const TraceCounts* trc = info->pin_tables;
|
||||
const TraceCounts* trc_end = trc + info->pin_count;
|
||||
|
||||
const TraceCounts* trc;
|
||||
const TraceCounts* trc_end;
|
||||
FB_SIZE_T max_len = 0;
|
||||
for (; trc < trc_end; trc++)
|
||||
{
|
||||
FB_SIZE_T len = fb_strlen(trc->trc_relation_name);
|
||||
if (max_len < len)
|
||||
max_len = len;
|
||||
};
|
||||
if (max_len < 32)
|
||||
max_len = 32;
|
||||
|
||||
record.append(NEWLINE"Table");
|
||||
record.append(max_len - 5, ' ');
|
||||
record.append(" Natural Index Update Insert Delete Backout Purge Expunge" NEWLINE);
|
||||
record.append(max_len + 80, '*');
|
||||
record.append(NEWLINE);
|
||||
|
||||
string temp;
|
||||
for (trc = info->pin_tables, trc_end = trc + info->pin_count; trc < trc_end; trc++)
|
||||
for (trc = info->pin_tables; trc < trc_end; trc++)
|
||||
{
|
||||
record.append(trc->trc_relation_name);
|
||||
record.append(MAX_SQL_IDENTIFIER_LEN - fb_strlen(trc->trc_relation_name), ' ');
|
||||
record.append(max_len - fb_strlen(trc->trc_relation_name), ' ');
|
||||
for (int j = 0; j < DBB_max_rel_count; j++)
|
||||
{
|
||||
if (trc->trc_counters[j] == 0)
|
||||
@ -548,6 +570,101 @@ void TracePluginImpl::formatStringArgument(string& result, const UCHAR* str, siz
|
||||
}
|
||||
|
||||
|
||||
bool TracePluginImpl::filterStatus(const ISC_STATUS* status, GdsCodesArray& arr)
|
||||
{
|
||||
FB_SIZE_T pos;
|
||||
while (*status != isc_arg_end)
|
||||
{
|
||||
const ISC_STATUS s = *status;
|
||||
switch (s)
|
||||
{
|
||||
case isc_arg_gds:
|
||||
case isc_arg_warning:
|
||||
if (arr.find(status[1], pos))
|
||||
return true;
|
||||
status += 2;
|
||||
break;
|
||||
|
||||
case isc_arg_cstring:
|
||||
status += 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
status += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
class GdsName2CodeMap
|
||||
{
|
||||
public:
|
||||
GdsName2CodeMap(MemoryPool& pool) :
|
||||
m_map(pool)
|
||||
{
|
||||
for (int i = 0; codes[i].code_string; i++)
|
||||
m_map.put(codes[i].code_string, codes[i].code_number);
|
||||
}
|
||||
|
||||
bool find(const char* name, ISC_STATUS& code) const
|
||||
{
|
||||
return m_map.get(name, code);
|
||||
}
|
||||
|
||||
private:
|
||||
class NocaseCmp
|
||||
{
|
||||
public:
|
||||
static bool greaterThan(const char* i1, const char* i2)
|
||||
{
|
||||
return fb_utils::stricmp(i1, i2) > 0;
|
||||
}
|
||||
};
|
||||
|
||||
GenericMap<Pair<NonPooled<const char*, ISC_STATUS> >, NocaseCmp > m_map;
|
||||
};
|
||||
|
||||
static InitInstance<GdsName2CodeMap> gdsNamesMap;
|
||||
|
||||
void TracePluginImpl::str2Array(const Firebird::string& str, GdsCodesArray& arr)
|
||||
{
|
||||
// input: string with comma-delimited list of gds codes values and\or gds codes names
|
||||
// output: sorted array of gds codes values
|
||||
|
||||
const char *sep = " ,";
|
||||
|
||||
FB_SIZE_T p1 = 0, p2 = 0;
|
||||
while (p2 < str.length())
|
||||
{
|
||||
p2 = str.find_first_of(sep, p1);
|
||||
if (p2 == string::npos)
|
||||
p2 = str.length();
|
||||
|
||||
string s = str.substr(p1, p2 - p1);
|
||||
|
||||
ISC_STATUS code = atol(s.c_str());
|
||||
|
||||
if (!code && !gdsNamesMap().find(s.c_str(), code))
|
||||
fatal_exception::raiseFmt(
|
||||
"Error parsing error codes filter: \n"
|
||||
"\t%s\n"
|
||||
"\tbad item is: %s, at position: %d",
|
||||
str.c_str(), s.c_str(), p1 + 1);
|
||||
|
||||
// avoid duplicates
|
||||
|
||||
FB_SIZE_T ins_pos;
|
||||
if (!arr.find(code, ins_pos))
|
||||
arr.insert(ins_pos, code);
|
||||
|
||||
p1 = str.find_first_not_of(sep, p2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TracePluginImpl::appendParams(ITraceParams* params)
|
||||
{
|
||||
const FB_SIZE_T paramcount = params->getCount();
|
||||
@ -931,14 +1048,20 @@ void TracePluginImpl::appendServiceQueryParams(size_t send_item_length,
|
||||
|
||||
void TracePluginImpl::log_init()
|
||||
{
|
||||
record.printf("\tSESSION_%d %s" NEWLINE "\t%s" NEWLINE, session_id, session_name.c_str(), config.db_filename.c_str());
|
||||
logRecord("TRACE_INIT");
|
||||
if (config.log_initfini)
|
||||
{
|
||||
record.printf("\tSESSION_%d %s" NEWLINE "\t%s" NEWLINE, session_id, session_name.c_str(), config.db_filename.c_str());
|
||||
logRecord("TRACE_INIT");
|
||||
}
|
||||
}
|
||||
|
||||
void TracePluginImpl::log_finalize()
|
||||
{
|
||||
record.printf("\tSESSION_%d %s" NEWLINE "\t%s" NEWLINE, session_id, session_name.c_str(), config.db_filename.c_str());
|
||||
logRecord("TRACE_FINI");
|
||||
if (config.log_initfini)
|
||||
{
|
||||
record.printf("\tSESSION_%d %s" NEWLINE "\t%s" NEWLINE, session_id, session_name.c_str(), config.db_filename.c_str());
|
||||
logRecord("TRACE_FINI");
|
||||
}
|
||||
|
||||
logWriter->release();
|
||||
logWriter = NULL;
|
||||
@ -2037,14 +2160,31 @@ void TracePluginImpl::log_event_trigger_execute(ITraceDatabaseConnection* connec
|
||||
void TracePluginImpl::log_event_error(ITraceConnection* connection, ITraceStatusVector* status,
|
||||
const char* function)
|
||||
{
|
||||
if (!config.log_errors)
|
||||
return;
|
||||
|
||||
string event_type;
|
||||
if (status->hasError())
|
||||
if (config.log_errors && status->hasError())
|
||||
{
|
||||
const ISC_STATUS* errs = status->getStatus()->getErrors();
|
||||
|
||||
if (!include_codes.isEmpty() && !filterStatus(errs, include_codes))
|
||||
return;
|
||||
|
||||
if (!exclude_codes.isEmpty() && filterStatus(errs, exclude_codes))
|
||||
return;
|
||||
|
||||
event_type.printf("ERROR AT %s", function);
|
||||
else if (status->hasWarning())
|
||||
}
|
||||
else if (config.log_warnings && status->hasWarning())
|
||||
{
|
||||
const ISC_STATUS* warns = status->getStatus()->getWarnings();
|
||||
|
||||
if (!include_codes.isEmpty() && !filterStatus(warns, include_codes))
|
||||
return;
|
||||
|
||||
if (!exclude_codes.isEmpty() && filterStatus(warns, exclude_codes))
|
||||
return;
|
||||
|
||||
event_type.printf("WARNING AT %s", function);
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
|
@ -172,12 +172,19 @@ private:
|
||||
Firebird::AutoPtr<Firebird::SimilarToMatcher<UCHAR, Jrd::UpcaseConverter<> > >
|
||||
include_matcher, exclude_matcher;
|
||||
|
||||
// Filters for gds error codes
|
||||
typedef Firebird::SortedArray<ISC_STATUS> GdsCodesArray;
|
||||
GdsCodesArray include_codes;
|
||||
GdsCodesArray exclude_codes;
|
||||
|
||||
void appendGlobalCounts(const PerformanceInfo* info);
|
||||
void appendTableCounts(const PerformanceInfo* info);
|
||||
void appendParams(Firebird::ITraceParams* params);
|
||||
void appendServiceQueryParams(size_t send_item_length, const ntrace_byte_t* send_items,
|
||||
size_t recv_item_length, const ntrace_byte_t* recv_items);
|
||||
void formatStringArgument(Firebird::string& result, const UCHAR* str, size_t len);
|
||||
bool filterStatus(const ISC_STATUS* status, GdsCodesArray& arr);
|
||||
void str2Array(const Firebird::string& str, GdsCodesArray& arr);
|
||||
|
||||
// register various objects
|
||||
void register_connection(Firebird::ITraceDatabaseConnection* connection);
|
||||
|
@ -95,6 +95,24 @@ database
|
||||
# Put errors happened
|
||||
#log_errors = false
|
||||
|
||||
# Put warnings
|
||||
#log_warnings = false
|
||||
|
||||
# Filters for errors and warnings GDS codes.
|
||||
# Comma separated list of GDS codes values and\or names.
|
||||
# For example: deadlock, req_sync, 335544321
|
||||
|
||||
# Include filter. If empty, trace all errors\warnings events.
|
||||
# Else trace event if any code from list is found in status-vector.
|
||||
#include_gds_codes
|
||||
|
||||
# Exclude filter. If empty, trace all errors\warnings events.
|
||||
# Else trace event if no code from list is found in status-vector.
|
||||
#exclude_gds_codes
|
||||
|
||||
# Put trace session init and finish messages
|
||||
#log_initfini = true
|
||||
|
||||
# Sweep activity
|
||||
#log_sweep = false
|
||||
|
||||
@ -199,6 +217,24 @@ services
|
||||
|
||||
# Put errors happened
|
||||
#log_errors = false
|
||||
|
||||
# Put warnings
|
||||
#log_warnings = false
|
||||
|
||||
# Filters for errors and warnings GDS codes.
|
||||
# Comma separated list of GDS codes values and\or names.
|
||||
# For example: deadlock, req_sync, 335544321
|
||||
|
||||
# Include filter. If empty, trace all errors\warnings events.
|
||||
# Else trace event if any code from list is found in status-vector.
|
||||
#include_gds_codes
|
||||
|
||||
# Exclude filter. If empty, trace all errors\warnings events.
|
||||
# Else trace event if no code from list is found in status-vector.
|
||||
#exclude_gds_codes
|
||||
|
||||
# Put trace session init and finish messages
|
||||
#log_initfini = true
|
||||
}
|
||||
|
||||
|
||||
|
@ -36,6 +36,10 @@ STR_PARAMETER(include_filter, "")
|
||||
STR_PARAMETER(exclude_filter, "")
|
||||
PATH_PARAMETER(log_filename, "")
|
||||
BOOL_PARAMETER(log_errors, false)
|
||||
BOOL_PARAMETER(log_warnings, false)
|
||||
STR_PARAMETER(include_gds_codes, "")
|
||||
STR_PARAMETER(exclude_gds_codes, "")
|
||||
BOOL_PARAMETER(log_initfini, true)
|
||||
BOOL_PARAMETER(enabled, false)
|
||||
UINT_PARAMETER(max_log_size, 0)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user