Add handling of a +TIMESTAMP flag in the SAL_LOG environment variable

Change-Id: I9bdcd8b2d7b46a087d7f5461b6f7c3d9f02ec084
This commit is contained in:
Tor Lillqvist
2016-08-18 14:07:00 +03:00
parent f8ba7ff1e5
commit fb00c725bb
2 changed files with 73 additions and 13 deletions

View File

@@ -228,15 +228,21 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) {
with with
@verbatim @verbatim
<switch> ::= <sense><level>("."<area>)? <switch> ::= <sense><item>
<sense> ::= "+"|"-" <sense> ::= "+"|"-"
<item> ::= <flag>|<level>("."<area>)?
<flag> ::= "TIMESTAMP"
<level> ::= "INFO"|"WARN" <level> ::= "INFO"|"WARN"
@endverbatim @endverbatim
If the environment variable is unset, "+WARN" is used instead (which results If the environment variable is unset, or contains no level, the level
in all warnings being output but no infos). If the given value does not setting "+WARN" is assumed instead (which results in all warnings being
match the regular expression, "+INFO+WARN" is used instead (which in turn output but no infos). If the given value does not match the regular
results in everything being output). expression, "+INFO+WARN" is used instead (which in turn results in
everything being output).
The "+TIMESTAMP" flag causes each output line (as selected by the level
switch(es)) to be prefixed by a timestamp like 2016-08-18:14:04:43.672.
A given macro call's level (INFO or WARN) and area is matched against the A given macro call's level (INFO or WARN) and area is matched against the
given switches as follows: Only those switches for which the level matches given switches as follows: Only those switches for which the level matches
@@ -251,12 +257,12 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) {
SAL_INFO("other", ...) generate output, while calls like SAL_INFO("other", ...) generate output, while calls like
SAL_INFO("foo", ...) or SAL_INFO("foo.barzzz", ...) do not. SAL_INFO("foo", ...) or SAL_INFO("foo.barzzz", ...) do not.
The generated log output consists of the given level ("info" or "warn"), the The generated log output consists of the optinal timestamp, the given level
given area, the process ID, the thread ID, the source file, and the source ("info" or "warn"), the given area, the process ID, the thread ID, the
line number, each followed by a colon, followed by a space, the given source file, and the source line number, each followed by a colon, followed
message, and a newline. The precise format of the log output is subject to by a space, the given message, and a newline. The precise format of the log
change. The log output is printed to stderr without further text encoding output is subject to change. The log output is printed to stderr without
conversion. further text encoding conversion.
@see @ref sal_log_areas @see @ref sal_log_areas

View File

@@ -105,6 +105,55 @@ char const * getEnvironmentVariable() {
return env; return env;
} }
void maybeOutputTimestamp(std::ostringstream &s) {
char const * env = getEnvironmentVariable();
if (env == nullptr)
return;
for (char const * p = env;;) {
switch (*p++) {
case '\0':
return;
case '+':
{
char const * p1 = p;
while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') {
++p1;
}
if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("TIMESTAMP"))) {
char ts[100];
TimeValue systemTime;
osl_getSystemTime(&systemTime);
TimeValue localTime;
osl_getLocalTimeFromSystemTime(&systemTime, &localTime);
oslDateTime dateTime;
osl_getDateTimeFromTimeValue(&localTime, &dateTime);
struct tm tm;
tm.tm_sec = dateTime.Seconds;
tm.tm_min = dateTime.Minutes;
tm.tm_hour = dateTime.Hours;
tm.tm_mday = dateTime.Day;
tm.tm_mon = dateTime.Month - 1;
tm.tm_year = dateTime.Year - 1900;
strftime(ts, sizeof(ts), "%Y-%m-%d:%H:%M:%S", &tm);
char milliSecs[10];
sprintf(milliSecs, "%03d", dateTime.NanoSeconds/1000000);
s << ts << '.' << milliSecs << ':';
return;
}
char const * p2 = p1;
while (*p2 != '+' && *p2 != '-' && *p2 != '\0') {
++p2;
}
p = p2;
}
break;
default:
; // nothing
}
}
return;
}
#endif #endif
namespace { namespace {
@@ -119,7 +168,7 @@ bool report(sal_detail_LogLevel level, char const * area) {
return true; return true;
assert(area != nullptr); assert(area != nullptr);
char const * env = getEnvironmentVariable(); char const * env = getEnvironmentVariable();
if (env == nullptr) { if (env == nullptr || strcmp(env, "+TIMESTAMP") == 0) {
env = "+WARN"; env = "+WARN";
} }
std::size_t areaLen = std::strlen(area); std::size_t areaLen = std::strlen(area);
@@ -156,6 +205,10 @@ bool report(sal_detail_LogLevel level, char const * area) {
} else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("WARN"))) } else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("WARN")))
{ {
match = level == SAL_DETAIL_LOG_LEVEL_WARN; match = level == SAL_DETAIL_LOG_LEVEL_WARN;
} else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("TIMESTAMP")))
{
// handled later
match = false;
} else { } else {
return true; return true;
// upon an illegal SAL_LOG value, everything is considered // upon an illegal SAL_LOG value, everything is considered
@@ -190,8 +243,9 @@ void log(
std::ostringstream s; std::ostringstream s;
#if !defined ANDROID #if !defined ANDROID
// On Android, the area will be used as the "tag," and log info already // On Android, the area will be used as the "tag," and log info already
// contains the PID // contains timestamp and PID.
if (!sal_use_syslog) { if (!sal_use_syslog) {
maybeOutputTimestamp(s);
s << toString(level) << ':'; s << toString(level) << ':';
} }
if (!isDebug(level)) { if (!isDebug(level)) {