Skip to content
Browse files

ADB Logcat colored output.

This patch adds a new '-C' option to logcat so that the output is
colored with colors similar to the ones in DDMS.
Simply type "adb logcat -C" to use it.
Works well with bash in gnome-terminal.

Change-Id: Ie72199ecca0e04f2082c993f5763646bb09da61e
  • Loading branch information...
1 parent 5a32576 commit 517921140446ef4fef129855c7981fc1f237f301 @pierrezurek pierrezurek committed with cyanogen Oct 17, 2010
Showing with 87 additions and 16 deletions.
  1. +7 −0 include/cutils/logprint.h
  2. +68 −14 liblog/logprint.c
  3. +12 −2 logcat/logcat.cpp
View
7 include/cutils/logprint.h
@@ -38,6 +38,11 @@ typedef enum {
FORMAT_LONG,
} AndroidLogPrintFormat;
+typedef enum {
+ OUTPUT_COLOR_ON = 0,
+ OUTPUT_COLOR_OFF,
+} AndroidLogColoredOutput;
+
typedef struct AndroidLogFormat_t AndroidLogFormat;
typedef struct AndroidLogEntry_t {
@@ -58,6 +63,8 @@ void android_log_format_free(AndroidLogFormat *p_format);
void android_log_setPrintFormat(AndroidLogFormat *p_format,
AndroidLogPrintFormat format);
+void android_log_setColoredOutput(AndroidLogFormat *p_format);
+
/**
* Returns FORMAT_OFF on invalid string
*/
View
82 liblog/logprint.c
@@ -17,6 +17,13 @@
#define _GNU_SOURCE /* for asprintf */
+#define COLOR_BLUE 75
+#define COLOR_DEFAULT 231
+#define COLOR_GREEN 40
+#define COLOR_ORANGE 166
+#define COLOR_RED 196
+#define COLOR_YELLOW 226
+
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
@@ -39,6 +46,7 @@ struct AndroidLogFormat_t {
android_LogPriority global_pri;
FilterInfo *filters;
AndroidLogPrintFormat format;
+ AndroidLogColoredOutput colored_output;
};
static FilterInfo * filterinfo_new(const char * tag, android_LogPriority pri)
@@ -118,6 +126,23 @@ static char filterPriToChar (android_LogPriority pri)
}
}
+static int colorFromPri (android_LogPriority pri)
+{
+ switch (pri) {
+ case ANDROID_LOG_VERBOSE: return COLOR_DEFAULT;
+ case ANDROID_LOG_DEBUG: return COLOR_BLUE;
+ case ANDROID_LOG_INFO: return COLOR_GREEN;
+ case ANDROID_LOG_WARN: return COLOR_ORANGE;
+ case ANDROID_LOG_ERROR: return COLOR_RED;
+ case ANDROID_LOG_FATAL: return COLOR_RED;
+ case ANDROID_LOG_SILENT: return COLOR_DEFAULT;
+
+ case ANDROID_LOG_DEFAULT:
+ case ANDROID_LOG_UNKNOWN:
+ default: return COLOR_DEFAULT;
+ }
+}
+
static android_LogPriority filterPriForTag(
AndroidLogFormat *p_format, const char *tag)
{
@@ -174,6 +199,7 @@ AndroidLogFormat *android_log_format_new()
p_ret->global_pri = ANDROID_LOG_VERBOSE;
p_ret->format = FORMAT_BRIEF;
+ p_ret->colored_output = OUTPUT_COLOR_OFF;
return p_ret;
}
@@ -202,6 +228,11 @@ void android_log_setPrintFormat(AndroidLogFormat *p_format,
p_format->format=format;
}
+void android_log_setColoredOutput(AndroidLogFormat *p_format)
+{
+ p_format->colored_output = OUTPUT_COLOR_ON;
+}
+
/**
* Returns FORMAT_OFF on invalid string
*/
@@ -698,20 +729,32 @@ char *android_log_formatLogLine (
*/
size_t prefixLen, suffixLen;
+ size_t prefixColorLen = 0;
+ char * prefixBufTmp = prefixBuf;
+ size_t prefixBufTmpRemainLen = sizeof(prefixBuf);
+
+ if (p_format->colored_output == OUTPUT_COLOR_ON) {
+ prefixColorLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen, "%c[%d;%d;%dm", 0x1B, 38, 5, colorFromPri(entry->priority));
+ if(prefixColorLen >= prefixBufTmpRemainLen)
+ prefixColorLen = prefixBufTmpRemainLen - 1;
+ prefixBufTmp += prefixColorLen;
+ prefixBufTmpRemainLen -= prefixColorLen;
+ }
+
switch (p_format->format) {
case FORMAT_TAG:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
+ prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
"%c/%-8s: ", priChar, entry->tag);
strcpy(suffixBuf, "\n"); suffixLen = 1;
break;
case FORMAT_PROCESS:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
+ prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
"%c(%5d) ", priChar, entry->pid);
suffixLen = snprintf(suffixBuf, sizeof(suffixBuf),
" (%s)\n", entry->tag);
break;
case FORMAT_THREAD:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
+ prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
"%c(%5d:%p) ", priChar, entry->pid, (void*)entry->tid);
strcpy(suffixBuf, "\n");
suffixLen = 1;
@@ -723,21 +766,21 @@ char *android_log_formatLogLine (
suffixLen = 1;
break;
case FORMAT_TIME:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
+ prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
"%s.%03ld %c/%-8s(%5d): ", timeBuf, entry->tv_nsec / 1000000,
priChar, entry->tag, entry->pid);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
case FORMAT_THREADTIME:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
+ prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
"%s.%03ld %5d %5d %c %-8s: ", timeBuf, entry->tv_nsec / 1000000,
(int)entry->pid, (int)entry->tid, priChar, entry->tag);
strcpy(suffixBuf, "\n");
suffixLen = 1;
break;
case FORMAT_LONG:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
+ prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
"[ %s.%03ld %5d:%p %c/%-8s ]\n",
timeBuf, entry->tv_nsec / 1000000, entry->pid,
(void*)entry->tid, priChar, entry->tag);
@@ -747,7 +790,7 @@ char *android_log_formatLogLine (
break;
case FORMAT_BRIEF:
default:
- prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
+ prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
"%c/%-8s(%5d): ", priChar, entry->tag, entry->pid);
strcpy(suffixBuf, "\n");
suffixLen = 1;
@@ -759,11 +802,22 @@ char *android_log_formatLogLine (
* possibly causing heap corruption. To avoid this we double check and
* set the length at the maximum (size minus null byte)
*/
- if(prefixLen >= sizeof(prefixBuf))
- prefixLen = sizeof(prefixBuf) - 1;
+ if(prefixLen >= prefixBufTmpRemainLen)
+ prefixLen = prefixBufTmpRemainLen - 1;
if(suffixLen >= sizeof(suffixBuf))
suffixLen = sizeof(suffixBuf) - 1;
+ size_t suffixColorLen = 0;
+ char * suffixBufTmp = suffixBuf + suffixLen;
+ size_t suffixBufTmpRemainLen = sizeof(suffixBuf) - suffixLen;
+
+ if (p_format->colored_output == OUTPUT_COLOR_ON) {
+ suffixColorLen = snprintf(suffixBufTmp, suffixBufTmpRemainLen, "%c[%dm", 0x1B, 0);
+ if(suffixColorLen >= suffixBufTmpRemainLen)
+ suffixColorLen = suffixBufTmpRemainLen - 1;
+ }
+
+
/* the following code is tragically unreadable */
size_t numLines;
@@ -790,7 +844,7 @@ char *android_log_formatLogLine (
// this is an upper bound--newlines in message may be counted
// extraneously
- bufferSize = (numLines * (prefixLen + suffixLen)) + entry->messageLen + 1;
+ bufferSize = (numLines * (prefixColorLen + prefixLen + suffixLen + suffixColorLen)) + entry->messageLen + 1;
if (defaultBufferSize >= bufferSize) {
ret = defaultBuffer;
@@ -809,11 +863,11 @@ char *android_log_formatLogLine (
if (prefixSuffixIsHeaderFooter) {
strcat(p, prefixBuf);
- p += prefixLen;
+ p += prefixColorLen + prefixLen;
strncat(p, entry->message, entry->messageLen);
p += entry->messageLen;
strcat(p, suffixBuf);
- p += suffixLen;
+ p += suffixLen + suffixColorLen;
} else {
while(pm < (entry->message + entry->messageLen)) {
const char *lineStart;
@@ -827,11 +881,11 @@ char *android_log_formatLogLine (
lineLen = pm - lineStart;
strcat(p, prefixBuf);
- p += prefixLen;
+ p += prefixColorLen + prefixLen;
strncat(p, lineStart, lineLen);
p += lineLen;
strcat(p, suffixBuf);
- p += suffixLen;
+ p += suffixLen + suffixColorLen;
if (*pm == '\n') pm++;
}
View
14 logcat/logcat.cpp
@@ -404,7 +404,8 @@ static void show_help(const char *cmd)
" -g get the size of the log's ring buffer and exit\n"
" -b <buffer> request alternate ring buffer\n"
" ('main' (default), 'radio', 'events')\n"
- " -B output the log in binary");
+ " -B output the log in binary\n"
+ " -C colored output");
fprintf(stderr,"\nfilterspecs are a series of \n"
@@ -446,6 +447,11 @@ static int setLogFormat(const char * formatString)
return 0;
}
+static void setColoredOutput()
+{
+ android_log_setColoredOutput(g_logformat);
+}
+
extern "C" void logprint_run_tests(void);
int main(int argc, char **argv)
@@ -475,7 +481,7 @@ int main(int argc, char **argv)
for (;;) {
int ret;
- ret = getopt(argc, argv, "cdt:gsQf:r::n:v:b:B");
+ ret = getopt(argc, argv, "cdt:gsQf:r::n:v:b:BC");
if (ret < 0) {
break;
@@ -505,6 +511,10 @@ int main(int argc, char **argv)
getLogSize = 1;
break;
+ case 'C':
+ setColoredOutput();
+ break;
+
case 'b': {
char* buf = (char*) malloc(strlen(LOG_FILE_DIR) + strlen(optarg) + 1);
strcpy(buf, LOG_FILE_DIR);

0 comments on commit 5179211

Please sign in to comment.
Something went wrong with that request. Please try again.