Merge "liblog: logcat: Add year and zone to date on each line"

This commit is contained in:
Mark Salyzyn 2015-09-30 18:56:48 +00:00 committed by Gerrit Code Review
commit 447356ddb4
4 changed files with 162 additions and 17 deletions

View file

@ -36,10 +36,12 @@ typedef enum {
FORMAT_TIME, FORMAT_TIME,
FORMAT_THREADTIME, FORMAT_THREADTIME,
FORMAT_LONG, FORMAT_LONG,
/* The following three are modifiers to above formats */ /* The following are modifiers to above formats */
FORMAT_MODIFIER_COLOR, /* converts priority to color */ FORMAT_MODIFIER_COLOR, /* converts priority to color */
FORMAT_MODIFIER_TIME_USEC, /* switches from msec to usec time precision */ FORMAT_MODIFIER_TIME_USEC, /* switches from msec to usec time precision */
FORMAT_MODIFIER_PRINTABLE, /* converts non-printable to printable escapes */ FORMAT_MODIFIER_PRINTABLE, /* converts non-printable to printable escapes */
FORMAT_MODIFIER_YEAR, /* Adds year to date */
FORMAT_MODIFIER_ZONE, /* Adds zone to date */
} AndroidLogPrintFormat; } AndroidLogPrintFormat;
typedef struct AndroidLogFormat_t AndroidLogFormat; typedef struct AndroidLogFormat_t AndroidLogFormat;

View file

@ -48,6 +48,8 @@ struct AndroidLogFormat_t {
bool colored_output; bool colored_output;
bool usec_time_output; bool usec_time_output;
bool printable_output; bool printable_output;
bool year_output;
bool zone_output;
}; };
/* /*
@ -192,6 +194,8 @@ AndroidLogFormat *android_log_format_new()
p_ret->colored_output = false; p_ret->colored_output = false;
p_ret->usec_time_output = false; p_ret->usec_time_output = false;
p_ret->printable_output = false; p_ret->printable_output = false;
p_ret->year_output = false;
p_ret->zone_output = false;
return p_ret; return p_ret;
} }
@ -227,6 +231,12 @@ int android_log_setPrintFormat(AndroidLogFormat *p_format,
case FORMAT_MODIFIER_PRINTABLE: case FORMAT_MODIFIER_PRINTABLE:
p_format->printable_output = true; p_format->printable_output = true;
return 0; return 0;
case FORMAT_MODIFIER_YEAR:
p_format->year_output = true;
return 0;
case FORMAT_MODIFIER_ZONE:
p_format->zone_output = !p_format->zone_output;
return 0;
default: default:
break; break;
} }
@ -234,6 +244,9 @@ int android_log_setPrintFormat(AndroidLogFormat *p_format,
return 1; return 1;
} }
static const char tz[] = "TZ";
static const char utc[] = "UTC";
/** /**
* Returns FORMAT_OFF on invalid string * Returns FORMAT_OFF on invalid string
*/ */
@ -252,7 +265,39 @@ AndroidLogPrintFormat android_log_formatFromString(const char * formatString)
else if (strcmp(formatString, "color") == 0) format = FORMAT_MODIFIER_COLOR; else if (strcmp(formatString, "color") == 0) format = FORMAT_MODIFIER_COLOR;
else if (strcmp(formatString, "usec") == 0) format = FORMAT_MODIFIER_TIME_USEC; else if (strcmp(formatString, "usec") == 0) format = FORMAT_MODIFIER_TIME_USEC;
else if (strcmp(formatString, "printable") == 0) format = FORMAT_MODIFIER_PRINTABLE; else if (strcmp(formatString, "printable") == 0) format = FORMAT_MODIFIER_PRINTABLE;
else format = FORMAT_OFF; else if (strcmp(formatString, "year") == 0) format = FORMAT_MODIFIER_YEAR;
else if (strcmp(formatString, "zone") == 0) format = FORMAT_MODIFIER_ZONE;
else {
extern char *tzname[2];
static const char gmt[] = "GMT";
char *cp = getenv(tz);
if (cp) {
cp = strdup(cp);
}
setenv(tz, formatString, 1);
/*
* Run tzset here to determine if the timezone is legitimate. If the
* zone is GMT, check if that is what was asked for, if not then
* did not match any on the system; report an error to caller.
*/
tzset();
if (!tzname[0]
|| ((!strcmp(tzname[0], utc)
|| !strcmp(tzname[0], gmt)) /* error? */
&& strcasecmp(formatString, utc)
&& strcasecmp(formatString, gmt))) { /* ok */
if (cp) {
setenv(tz, cp, 1);
} else {
unsetenv(tz);
}
tzset();
format = FORMAT_OFF;
} else {
format = FORMAT_MODIFIER_ZONE;
}
free(cp);
}
return format; return format;
} }
@ -887,7 +932,7 @@ char *android_log_formatLogLine (
struct tm tmBuf; struct tm tmBuf;
#endif #endif
struct tm* ptm; struct tm* ptm;
char timeBuf[32]; /* good margin, 23+nul for msec, 26+nul for usec */ char timeBuf[64]; /* good margin, 23+nul for msec, 26+nul for usec */
char prefixBuf[128], suffixBuf[128]; char prefixBuf[128], suffixBuf[128];
char priChar; char priChar;
int prefixSuffixIsHeaderFooter = 0; int prefixSuffixIsHeaderFooter = 0;
@ -905,21 +950,28 @@ char *android_log_formatLogLine (
* For this reason it's very annoying to have regexp meta characters * For this reason it's very annoying to have regexp meta characters
* in the time stamp. Don't use forward slashes, parenthesis, * in the time stamp. Don't use forward slashes, parenthesis,
* brackets, asterisks, or other special chars here. * brackets, asterisks, or other special chars here.
*
* The caller may have affected the timezone environment, this is
* expected to be sensitive to that.
*/ */
#if !defined(_WIN32) #if !defined(_WIN32)
ptm = localtime_r(&(entry->tv_sec), &tmBuf); ptm = localtime_r(&(entry->tv_sec), &tmBuf);
#else #else
ptm = localtime(&(entry->tv_sec)); ptm = localtime(&(entry->tv_sec));
#endif #endif
/* strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ptm); */ strftime(timeBuf, sizeof(timeBuf),
strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm); &"%Y-%m-%d %H:%M:%S"[p_format->year_output ? 0 : 3],
ptm);
len = strlen(timeBuf); len = strlen(timeBuf);
if (p_format->usec_time_output) { if (p_format->usec_time_output) {
snprintf(timeBuf + len, sizeof(timeBuf) - len, len += snprintf(timeBuf + len, sizeof(timeBuf) - len,
".%06ld", entry->tv_nsec / 1000); ".%06ld", entry->tv_nsec / 1000);
} else { } else {
snprintf(timeBuf + len, sizeof(timeBuf) - len, len += snprintf(timeBuf + len, sizeof(timeBuf) - len,
".%03ld", entry->tv_nsec / 1000000); ".%03ld", entry->tv_nsec / 1000000);
}
if (p_format->zone_output) {
strftime(timeBuf + len, sizeof(timeBuf) - len, " %z", ptm);
} }
/* /*

View file

@ -260,7 +260,7 @@ static void show_help(const char *cmd)
" -n <count> Sets max number of rotated logs to <count>, default 4\n" " -n <count> Sets max number of rotated logs to <count>, default 4\n"
" -v <format> Sets the log print format, where <format> is:\n\n" " -v <format> Sets the log print format, where <format> is:\n\n"
" brief color long printable process raw tag thread\n" " brief color long printable process raw tag thread\n"
" threadtime time usec\n\n" " threadtime time usec UTC year zone\n\n"
" -D print dividers between each log buffer\n" " -D print dividers between each log buffer\n"
" -c clear (flush) the entire log and exit\n" " -c clear (flush) the entire log and exit\n"
" -d dump the log and then exit (don't block)\n" " -d dump the log and then exit (don't block)\n"
@ -268,7 +268,8 @@ static void show_help(const char *cmd)
" -t '<time>' print most recent lines since specified time (implies -d)\n" " -t '<time>' print most recent lines since specified time (implies -d)\n"
" -T <count> print only the most recent <count> lines (does not imply -d)\n" " -T <count> print only the most recent <count> lines (does not imply -d)\n"
" -T '<time>' print most recent lines since specified time (not imply -d)\n" " -T '<time>' print most recent lines since specified time (not imply -d)\n"
" count is pure numerical, time is 'MM-DD hh:mm:ss.mmm'\n" " count is pure numerical, time is 'MM-DD hh:mm:ss.mmm...'\n"
" or 'YYYY-MM-DD hh:mm:ss.mmm...' format\n"
" -g get the size of the log's ring buffer and exit\n" " -g get the size of the log's ring buffer and exit\n"
" -L dump logs from prior to last reboot\n" " -L dump logs from prior to last reboot\n"
" -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio',\n" " -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio',\n"
@ -377,7 +378,14 @@ static void logcat_panic(bool showHelp, const char *fmt, ...)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
static const char g_defaultTimeFormat[] = "%m-%d %H:%M:%S.%q"; static char *parseTime(log_time &t, const char *cp) {
char *ep = t.strptime(cp, "%m-%d %H:%M:%S.%q");
if (ep) {
return ep;
}
return t.strptime(cp, "%Y-%m-%d %H:%M:%S.%q");
}
// Find last logged line in gestalt of all matching existing output files // Find last logged line in gestalt of all matching existing output files
static log_time lastLogTime(char *outputFileName) { static log_time lastLogTime(char *outputFileName) {
@ -423,7 +431,7 @@ static log_time lastLogTime(char *outputFileName) {
bool found = false; bool found = false;
for (const auto& line : android::base::Split(file, "\n")) { for (const auto& line : android::base::Split(file, "\n")) {
log_time t(log_time::EPOCH); log_time t(log_time::EPOCH);
char *ep = t.strptime(line.c_str(), g_defaultTimeFormat); char *ep = parseTime(t, line.c_str());
if (!ep || (*ep != ' ')) { if (!ep || (*ep != ' ')) {
continue; continue;
} }
@ -522,11 +530,10 @@ int main(int argc, char **argv)
/* FALLTHRU */ /* FALLTHRU */
case 'T': case 'T':
if (strspn(optarg, "0123456789") != strlen(optarg)) { if (strspn(optarg, "0123456789") != strlen(optarg)) {
char *cp = tail_time.strptime(optarg, g_defaultTimeFormat); char *cp = parseTime(tail_time, optarg);
if (!cp) { if (!cp) {
logcat_panic(false, logcat_panic(false, "-%c \"%s\" not in time format\n",
"-%c \"%s\" not in \"%s\" time format\n", ret, optarg);
ret, optarg, g_defaultTimeFormat);
} }
if (*cp) { if (*cp) {
char c = *cp; char c = *cp;

View file

@ -72,6 +72,90 @@ TEST(logcat, buckets) {
EXPECT_EQ(4, count); EXPECT_EQ(4, count);
} }
TEST(logcat, year) {
FILE *fp;
char needle[32];
time_t now;
time(&now);
struct tm *ptm;
#if !defined(_WIN32)
struct tm tmBuf;
ptm = localtime_r(&now, &tmBuf);
#else
ptm = localtime(&&now);
#endif
strftime(needle, sizeof(needle), "[ %Y-", ptm);
ASSERT_TRUE(NULL != (fp = popen(
"logcat -v long -v year -b all -t 3 2>/dev/null",
"r")));
char buffer[5120];
int count = 0;
while (fgets(buffer, sizeof(buffer), fp)) {
if (!strncmp(buffer, needle, strlen(needle))) {
++count;
}
}
pclose(fp);
ASSERT_EQ(3, count);
}
TEST(logcat, tz) {
FILE *fp;
ASSERT_TRUE(NULL != (fp = popen(
"logcat -v long -v America/Los_Angeles -b all -t 3 2>/dev/null",
"r")));
char buffer[5120];
int count = 0;
while (fgets(buffer, sizeof(buffer), fp)) {
if ((buffer[0] == '[') && (buffer[1] == ' ')
&& isdigit(buffer[2]) && isdigit(buffer[3])
&& (buffer[4] == '-')
&& (strstr(buffer, " -0700 ") || strstr(buffer, " -0800 "))) {
++count;
}
}
pclose(fp);
ASSERT_EQ(3, count);
}
TEST(logcat, ntz) {
FILE *fp;
ASSERT_TRUE(NULL != (fp = popen(
"logcat -v long -v America/Los_Angeles -v zone -b all -t 3 2>/dev/null",
"r")));
char buffer[5120];
int count = 0;
while (fgets(buffer, sizeof(buffer), fp)) {
if ((buffer[0] == '[') && (buffer[1] == ' ')
&& isdigit(buffer[2]) && isdigit(buffer[3])
&& (buffer[4] == '-')
&& (strstr(buffer, " -0700 ") || strstr(buffer, " -0800 "))) {
++count;
}
}
pclose(fp);
ASSERT_EQ(0, count);
}
TEST(logcat, tail_3) { TEST(logcat, tail_3) {
FILE *fp; FILE *fp;