Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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...
commit 517921140446ef4fef129855c7981fc1f237f301 1 parent 5a32576
pierrezurek pierrezurek authored cyanogen committed
7 include/cutils/logprint.h
@@ -38,6 +38,11 @@ typedef enum {
38 38 FORMAT_LONG,
39 39 } AndroidLogPrintFormat;
40 40
  41 +typedef enum {
  42 + OUTPUT_COLOR_ON = 0,
  43 + OUTPUT_COLOR_OFF,
  44 +} AndroidLogColoredOutput;
  45 +
41 46 typedef struct AndroidLogFormat_t AndroidLogFormat;
42 47
43 48 typedef struct AndroidLogEntry_t {
@@ -58,6 +63,8 @@ void android_log_format_free(AndroidLogFormat *p_format);
58 63 void android_log_setPrintFormat(AndroidLogFormat *p_format,
59 64 AndroidLogPrintFormat format);
60 65
  66 +void android_log_setColoredOutput(AndroidLogFormat *p_format);
  67 +
61 68 /**
62 69 * Returns FORMAT_OFF on invalid string
63 70 */
82 liblog/logprint.c
@@ -17,6 +17,13 @@
17 17
18 18 #define _GNU_SOURCE /* for asprintf */
19 19
  20 +#define COLOR_BLUE 75
  21 +#define COLOR_DEFAULT 231
  22 +#define COLOR_GREEN 40
  23 +#define COLOR_ORANGE 166
  24 +#define COLOR_RED 196
  25 +#define COLOR_YELLOW 226
  26 +
20 27 #include <ctype.h>
21 28 #include <stdio.h>
22 29 #include <errno.h>
@@ -39,6 +46,7 @@ struct AndroidLogFormat_t {
39 46 android_LogPriority global_pri;
40 47 FilterInfo *filters;
41 48 AndroidLogPrintFormat format;
  49 + AndroidLogColoredOutput colored_output;
42 50 };
43 51
44 52 static FilterInfo * filterinfo_new(const char * tag, android_LogPriority pri)
@@ -118,6 +126,23 @@ static char filterPriToChar (android_LogPriority pri)
118 126 }
119 127 }
120 128
  129 +static int colorFromPri (android_LogPriority pri)
  130 +{
  131 + switch (pri) {
  132 + case ANDROID_LOG_VERBOSE: return COLOR_DEFAULT;
  133 + case ANDROID_LOG_DEBUG: return COLOR_BLUE;
  134 + case ANDROID_LOG_INFO: return COLOR_GREEN;
  135 + case ANDROID_LOG_WARN: return COLOR_ORANGE;
  136 + case ANDROID_LOG_ERROR: return COLOR_RED;
  137 + case ANDROID_LOG_FATAL: return COLOR_RED;
  138 + case ANDROID_LOG_SILENT: return COLOR_DEFAULT;
  139 +
  140 + case ANDROID_LOG_DEFAULT:
  141 + case ANDROID_LOG_UNKNOWN:
  142 + default: return COLOR_DEFAULT;
  143 + }
  144 +}
  145 +
121 146 static android_LogPriority filterPriForTag(
122 147 AndroidLogFormat *p_format, const char *tag)
123 148 {
@@ -174,6 +199,7 @@ AndroidLogFormat *android_log_format_new()
174 199
175 200 p_ret->global_pri = ANDROID_LOG_VERBOSE;
176 201 p_ret->format = FORMAT_BRIEF;
  202 + p_ret->colored_output = OUTPUT_COLOR_OFF;
177 203
178 204 return p_ret;
179 205 }
@@ -202,6 +228,11 @@ void android_log_setPrintFormat(AndroidLogFormat *p_format,
202 228 p_format->format=format;
203 229 }
204 230
  231 +void android_log_setColoredOutput(AndroidLogFormat *p_format)
  232 +{
  233 + p_format->colored_output = OUTPUT_COLOR_ON;
  234 +}
  235 +
205 236 /**
206 237 * Returns FORMAT_OFF on invalid string
207 238 */
@@ -698,20 +729,32 @@ char *android_log_formatLogLine (
698 729 */
699 730 size_t prefixLen, suffixLen;
700 731
  732 + size_t prefixColorLen = 0;
  733 + char * prefixBufTmp = prefixBuf;
  734 + size_t prefixBufTmpRemainLen = sizeof(prefixBuf);
  735 +
  736 + if (p_format->colored_output == OUTPUT_COLOR_ON) {
  737 + prefixColorLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen, "%c[%d;%d;%dm", 0x1B, 38, 5, colorFromPri(entry->priority));
  738 + if(prefixColorLen >= prefixBufTmpRemainLen)
  739 + prefixColorLen = prefixBufTmpRemainLen - 1;
  740 + prefixBufTmp += prefixColorLen;
  741 + prefixBufTmpRemainLen -= prefixColorLen;
  742 + }
  743 +
701 744 switch (p_format->format) {
702 745 case FORMAT_TAG:
703   - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
  746 + prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
704 747 "%c/%-8s: ", priChar, entry->tag);
705 748 strcpy(suffixBuf, "\n"); suffixLen = 1;
706 749 break;
707 750 case FORMAT_PROCESS:
708   - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
  751 + prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
709 752 "%c(%5d) ", priChar, entry->pid);
710 753 suffixLen = snprintf(suffixBuf, sizeof(suffixBuf),
711 754 " (%s)\n", entry->tag);
712 755 break;
713 756 case FORMAT_THREAD:
714   - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
  757 + prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
715 758 "%c(%5d:%p) ", priChar, entry->pid, (void*)entry->tid);
716 759 strcpy(suffixBuf, "\n");
717 760 suffixLen = 1;
@@ -723,21 +766,21 @@ char *android_log_formatLogLine (
723 766 suffixLen = 1;
724 767 break;
725 768 case FORMAT_TIME:
726   - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
  769 + prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
727 770 "%s.%03ld %c/%-8s(%5d): ", timeBuf, entry->tv_nsec / 1000000,
728 771 priChar, entry->tag, entry->pid);
729 772 strcpy(suffixBuf, "\n");
730 773 suffixLen = 1;
731 774 break;
732 775 case FORMAT_THREADTIME:
733   - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
  776 + prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
734 777 "%s.%03ld %5d %5d %c %-8s: ", timeBuf, entry->tv_nsec / 1000000,
735 778 (int)entry->pid, (int)entry->tid, priChar, entry->tag);
736 779 strcpy(suffixBuf, "\n");
737 780 suffixLen = 1;
738 781 break;
739 782 case FORMAT_LONG:
740   - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
  783 + prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
741 784 "[ %s.%03ld %5d:%p %c/%-8s ]\n",
742 785 timeBuf, entry->tv_nsec / 1000000, entry->pid,
743 786 (void*)entry->tid, priChar, entry->tag);
@@ -747,7 +790,7 @@ char *android_log_formatLogLine (
747 790 break;
748 791 case FORMAT_BRIEF:
749 792 default:
750   - prefixLen = snprintf(prefixBuf, sizeof(prefixBuf),
  793 + prefixLen = snprintf(prefixBufTmp, prefixBufTmpRemainLen,
751 794 "%c/%-8s(%5d): ", priChar, entry->tag, entry->pid);
752 795 strcpy(suffixBuf, "\n");
753 796 suffixLen = 1;
@@ -759,11 +802,22 @@ char *android_log_formatLogLine (
759 802 * possibly causing heap corruption. To avoid this we double check and
760 803 * set the length at the maximum (size minus null byte)
761 804 */
762   - if(prefixLen >= sizeof(prefixBuf))
763   - prefixLen = sizeof(prefixBuf) - 1;
  805 + if(prefixLen >= prefixBufTmpRemainLen)
  806 + prefixLen = prefixBufTmpRemainLen - 1;
764 807 if(suffixLen >= sizeof(suffixBuf))
765 808 suffixLen = sizeof(suffixBuf) - 1;
766 809
  810 + size_t suffixColorLen = 0;
  811 + char * suffixBufTmp = suffixBuf + suffixLen;
  812 + size_t suffixBufTmpRemainLen = sizeof(suffixBuf) - suffixLen;
  813 +
  814 + if (p_format->colored_output == OUTPUT_COLOR_ON) {
  815 + suffixColorLen = snprintf(suffixBufTmp, suffixBufTmpRemainLen, "%c[%dm", 0x1B, 0);
  816 + if(suffixColorLen >= suffixBufTmpRemainLen)
  817 + suffixColorLen = suffixBufTmpRemainLen - 1;
  818 + }
  819 +
  820 +
767 821 /* the following code is tragically unreadable */
768 822
769 823 size_t numLines;
@@ -790,7 +844,7 @@ char *android_log_formatLogLine (
790 844
791 845 // this is an upper bound--newlines in message may be counted
792 846 // extraneously
793   - bufferSize = (numLines * (prefixLen + suffixLen)) + entry->messageLen + 1;
  847 + bufferSize = (numLines * (prefixColorLen + prefixLen + suffixLen + suffixColorLen)) + entry->messageLen + 1;
794 848
795 849 if (defaultBufferSize >= bufferSize) {
796 850 ret = defaultBuffer;
@@ -809,11 +863,11 @@ char *android_log_formatLogLine (
809 863
810 864 if (prefixSuffixIsHeaderFooter) {
811 865 strcat(p, prefixBuf);
812   - p += prefixLen;
  866 + p += prefixColorLen + prefixLen;
813 867 strncat(p, entry->message, entry->messageLen);
814 868 p += entry->messageLen;
815 869 strcat(p, suffixBuf);
816   - p += suffixLen;
  870 + p += suffixLen + suffixColorLen;
817 871 } else {
818 872 while(pm < (entry->message + entry->messageLen)) {
819 873 const char *lineStart;
@@ -827,11 +881,11 @@ char *android_log_formatLogLine (
827 881 lineLen = pm - lineStart;
828 882
829 883 strcat(p, prefixBuf);
830   - p += prefixLen;
  884 + p += prefixColorLen + prefixLen;
831 885 strncat(p, lineStart, lineLen);
832 886 p += lineLen;
833 887 strcat(p, suffixBuf);
834   - p += suffixLen;
  888 + p += suffixLen + suffixColorLen;
835 889
836 890 if (*pm == '\n') pm++;
837 891 }
14 logcat/logcat.cpp
@@ -404,7 +404,8 @@ static void show_help(const char *cmd)
404 404 " -g get the size of the log's ring buffer and exit\n"
405 405 " -b <buffer> request alternate ring buffer\n"
406 406 " ('main' (default), 'radio', 'events')\n"
407   - " -B output the log in binary");
  407 + " -B output the log in binary\n"
  408 + " -C colored output");
408 409
409 410
410 411 fprintf(stderr,"\nfilterspecs are a series of \n"
@@ -446,6 +447,11 @@ static int setLogFormat(const char * formatString)
446 447 return 0;
447 448 }
448 449
  450 +static void setColoredOutput()
  451 +{
  452 + android_log_setColoredOutput(g_logformat);
  453 +}
  454 +
449 455 extern "C" void logprint_run_tests(void);
450 456
451 457 int main(int argc, char **argv)
@@ -475,7 +481,7 @@ int main(int argc, char **argv)
475 481 for (;;) {
476 482 int ret;
477 483
478   - ret = getopt(argc, argv, "cdt:gsQf:r::n:v:b:B");
  484 + ret = getopt(argc, argv, "cdt:gsQf:r::n:v:b:BC");
479 485
480 486 if (ret < 0) {
481 487 break;
@@ -505,6 +511,10 @@ int main(int argc, char **argv)
505 511 getLogSize = 1;
506 512 break;
507 513
  514 + case 'C':
  515 + setColoredOutput();
  516 + break;
  517 +
508 518 case 'b': {
509 519 char* buf = (char*) malloc(strlen(LOG_FILE_DIR) + strlen(optarg) + 1);
510 520 strcpy(buf, LOG_FILE_DIR);

0 comments on commit 5179211

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