1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-15 01:04:37 +02:00

Improve logging.

Move command begin to C except when it must be called after another command in Perl (e.g. expire after backup). Command begin logs correctly for complex data types like hash and list. Specify which commands will log to file immediately and set the default log level for log messages that are common to all commands. File logging is initiated from C.
This commit is contained in:
David Steele
2018-03-12 10:55:58 -04:00
parent 94494a632f
commit 03f1082e86
34 changed files with 729 additions and 209 deletions

View File

@ -1,6 +1,7 @@
/***********************************************************************************************************************************
Common Command Routines
***********************************************************************************************************************************/
#include <assert.h>
#include <string.h>
#include "common/log.h"
@ -14,53 +15,95 @@ Begin the command
void
cmdBegin()
{
MEM_CONTEXT_TEMP_BEGIN()
// A command must be set
assert(cfgCommand() != cfgCmdNone);
// This is fairly expensive log message to generate so skip it if it won't be output
if (logWill(cfgLogLevelDefault()))
{
// Basic info on command start
String *info = strNewFmt("%s command begin %s:", cfgCommandName(cfgCommand()), PGBACKREST_VERSION);
// Loop though options and add the ones that are interesting
for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
MEM_CONTEXT_TEMP_BEGIN()
{
const Variant *option = cfgOption(optionId);
// Basic info on command start
String *info = strNewFmt("%s command begin %s:", cfgCommandName(cfgCommand()), PGBACKREST_VERSION);
// Skip the option if it is not valid, or default, or not set
if (!cfgOptionValid(optionId) ||
cfgOptionSource(optionId) == cfgSourceDefault ||
(option == NULL && !cfgOptionNegate(optionId)))
// Loop though options and add the ones that are interesting
for (ConfigOption optionId = 0; optionId < CFG_OPTION_TOTAL; optionId++)
{
continue;
}
// Skip the option if it is not valid
if (!cfgOptionValid(optionId))
continue;
// If option was negated
if (cfgOptionNegate(optionId))
strCatFmt(info, " --no-%s", cfgOptionName(optionId));
// Else not negated
else
{
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(optionId);
strCatFmt(info, " --%s", cfgOptionName(optionId));
if (cfgDefOptionType(optionDefId) != cfgDefOptTypeBoolean)
// If option was negated
if (cfgOptionNegate(optionId))
strCatFmt(info, " --no-%s", cfgOptionName(optionId));
// If option was reset
else if (cfgOptionReset(optionId))
strCatFmt(info, " --reset-%s", cfgOptionName(optionId));
// Else set and not default
else if (cfgOptionSource(optionId) != cfgSourceDefault && cfgOptionTest(optionId))
{
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(optionId);
// Don't show redacted options
if (cfgDefOptionSecure(optionDefId))
strCat(info, "=<redacted>");
strCatFmt(info, " --%s=<redacted>", cfgOptionName(optionId));
// Output boolean option
else if (cfgDefOptionType(optionDefId) == cfgDefOptTypeBoolean)
strCatFmt(info, " --%s", cfgOptionName(optionId));
// Output other options
else
{
const String *optionStr = varStrForce(option);
StringList *valueList = NULL;
if (strchr(strPtr(optionStr), ' ') != NULL)
optionStr = strNewFmt("\"%s\"", strPtr(optionStr));
// Generate the values of hash options
if (cfgDefOptionType(optionDefId) == cfgDefOptTypeHash)
{
valueList = strLstNew();
strCatFmt(info, "=%s", strPtr(optionStr));
const KeyValue *optionKv = cfgOptionKv(optionId);
const VariantList *keyList = kvKeyList(optionKv);
for (unsigned int keyIdx = 0; keyIdx < varLstSize(keyList); keyIdx++)
{
strLstAdd(
valueList,
strNewFmt(
"%s=%s", strPtr(varStr(varLstGet(keyList, keyIdx))),
strPtr(varStrForce(kvGet(optionKv, varLstGet(keyList, keyIdx))))));
}
}
// Generate values for list options
else if (cfgDefOptionType(optionDefId) == cfgDefOptTypeList)
{
valueList = strLstNewVarLst(cfgOptionLst(optionId));
}
// Else only one value
else
{
valueList = strLstNew();
strLstAdd(valueList, varStrForce(cfgOption(optionId)));
}
// Output options and values
for (unsigned int valueListIdx = 0; valueListIdx < strLstSize(valueList); valueListIdx++)
{
const String *value = strLstGet(valueList, valueListIdx);
strCatFmt(info, " --%s", cfgOptionName(optionId));
if (strchr(strPtr(value), ' ') != NULL)
value = strNewFmt("\"%s\"", strPtr(value));
strCatFmt(info, "=%s", strPtr(value));
}
}
}
}
}
LOG_INFO(strPtr(info));
LOG_ANY(cfgLogLevelDefault(), 0, strPtr(info));
}
MEM_CONTEXT_TEMP_END();
}
MEM_CONTEXT_TEMP_END();
}
/***********************************************************************************************************************************
@ -69,17 +112,24 @@ End the command
void
cmdEnd(int code)
{
MEM_CONTEXT_TEMP_BEGIN()
// A command must be set
assert(cfgCommand() != cfgCmdNone);
// Skip this log message if it won't be output. It's not too expensive but since we skipped cmdBegin(), may as well.
if (logWill(cfgLogLevelDefault()))
{
// Basic info on command end
String *info = strNewFmt("%s command end: ", cfgCommandName(cfgCommand()));
MEM_CONTEXT_TEMP_BEGIN()
{
// Basic info on command end
String *info = strNewFmt("%s command end: ", cfgCommandName(cfgCommand()));
if (code == 0)
strCat(info, "completed successfully");
else
strCatFmt(info, "aborted with exception [%03d]", code);
if (code == 0)
strCat(info, "completed successfully");
else
strCatFmt(info, "aborted with exception [%03d]", code);
LOG_INFO(strPtr(info));
LOG_ANY(cfgLogLevelDefault(), 0, strPtr(info));
}
MEM_CONTEXT_TEMP_END();
}
MEM_CONTEXT_TEMP_END();
}