Add '-t N' flag to logcat, to print only the last N lines of logcat
(to be used in capturing a merged mini logcat for crash reports) Change-Id: I68149eb80f2f79812f43b07d80fbea822476859e
This commit is contained in:
parent
bbf1c64527
commit
d1d3b6dbed
1 changed files with 62 additions and 55 deletions
|
@ -25,6 +25,7 @@
|
|||
|
||||
static AndroidLogFormat * g_logformat;
|
||||
static bool g_nonblock = false;
|
||||
static int g_tail_lines = 0;
|
||||
|
||||
/* logd prefixes records with a length field */
|
||||
#define RECORD_LENGTH_FIELD_SIZE_BYTES sizeof(uint32_t)
|
||||
|
@ -162,19 +163,6 @@ static void processBuffer(log_device_t* dev, struct logger_entry *buf)
|
|||
AndroidLogEntry entry;
|
||||
char binaryMsgBuf[1024];
|
||||
|
||||
if (!dev->printed) {
|
||||
dev->printed = true;
|
||||
if (g_devCount > 1) {
|
||||
snprintf(binaryMsgBuf, sizeof(binaryMsgBuf), "--------- beginning of %s\n",
|
||||
dev->device);
|
||||
bytesWritten = write(g_outFD, binaryMsgBuf, strlen(binaryMsgBuf));
|
||||
if (bytesWritten < 0) {
|
||||
perror("output error");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->binary) {
|
||||
err = android_log_processBinaryLogBuffer(buf, &entry, g_eventTagMap,
|
||||
binaryMsgBuf, sizeof(binaryMsgBuf));
|
||||
|
@ -219,47 +207,51 @@ error:
|
|||
return;
|
||||
}
|
||||
|
||||
static void chooseFirst(log_device_t* dev, log_device_t** firstdev, queued_entry_t** firstentry) {
|
||||
*firstdev = NULL;
|
||||
*firstentry = NULL;
|
||||
int i=0;
|
||||
for (; dev; dev=dev->next) {
|
||||
i++;
|
||||
if (dev->queue) {
|
||||
if ((*firstentry) == NULL || cmp(dev->queue, *firstentry) < 0) {
|
||||
(*firstentry) = dev->queue;
|
||||
*firstdev = dev;
|
||||
static void chooseFirst(log_device_t* dev, log_device_t** firstdev) {
|
||||
for (*firstdev = NULL; dev != NULL; dev = dev->next) {
|
||||
if (dev->queue != NULL && (*firstdev == NULL || cmp(dev->queue, (*firstdev)->queue) < 0)) {
|
||||
*firstdev = dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void maybePrintStart(log_device_t* dev) {
|
||||
if (!dev->printed) {
|
||||
dev->printed = true;
|
||||
if (g_devCount > 1 && !g_printBinary) {
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "--------- beginning of %s\n", dev->device);
|
||||
if (write(g_outFD, buf, strlen(buf)) < 0) {
|
||||
perror("output error");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void printEntry(log_device_t* dev, queued_entry_t* entry) {
|
||||
if (g_printBinary) {
|
||||
printBinary(&entry->entry);
|
||||
} else {
|
||||
processBuffer(dev, &entry->entry);
|
||||
}
|
||||
}
|
||||
|
||||
static void eatEntry(log_device_t* dev, queued_entry_t* entry) {
|
||||
if (dev->queue != entry) {
|
||||
perror("assertion failed: entry isn't first in queue");
|
||||
exit(1);
|
||||
}
|
||||
printEntry(dev, entry);
|
||||
static void skipNextEntry(log_device_t* dev) {
|
||||
maybePrintStart(dev);
|
||||
queued_entry_t* entry = dev->queue;
|
||||
dev->queue = entry->next;
|
||||
delete entry;
|
||||
}
|
||||
|
||||
static void printNextEntry(log_device_t* dev) {
|
||||
maybePrintStart(dev);
|
||||
if (g_printBinary) {
|
||||
printBinary(&dev->queue->entry);
|
||||
} else {
|
||||
processBuffer(dev, &dev->queue->entry);
|
||||
}
|
||||
skipNextEntry(dev);
|
||||
}
|
||||
|
||||
static void readLogLines(log_device_t* devices)
|
||||
{
|
||||
log_device_t* dev;
|
||||
int max = 0;
|
||||
queued_entry_t* entry;
|
||||
queued_entry_t* old;
|
||||
int ret;
|
||||
bool somethingForEveryone;
|
||||
int queued_lines = 0;
|
||||
bool sleep = true;
|
||||
|
||||
int result;
|
||||
|
@ -284,7 +276,7 @@ static void readLogLines(log_device_t* devices)
|
|||
if (result >= 0) {
|
||||
for (dev=devices; dev; dev = dev->next) {
|
||||
if (FD_ISSET(dev->fd, &readset)) {
|
||||
entry = new queued_entry_t;
|
||||
queued_entry_t* entry = new queued_entry_t;
|
||||
/* NOTE: driver guarantees we read exactly one full entry */
|
||||
ret = read(dev->fd, entry->buf, LOGGER_ENTRY_MAX_LEN);
|
||||
if (ret < 0) {
|
||||
|
@ -307,36 +299,45 @@ static void readLogLines(log_device_t* devices)
|
|||
entry->entry.msg[entry->entry.len] = '\0';
|
||||
|
||||
dev->enqueue(entry);
|
||||
++queued_lines;
|
||||
}
|
||||
}
|
||||
|
||||
if (result == 0) {
|
||||
// we did our short timeout trick and there's nothing new
|
||||
// print all that aren't the last in their list
|
||||
// print everything we have and wait for more data
|
||||
sleep = true;
|
||||
while (true) {
|
||||
chooseFirst(devices, &dev, &entry);
|
||||
if (!entry) {
|
||||
chooseFirst(devices, &dev);
|
||||
if (dev == NULL) {
|
||||
break;
|
||||
}
|
||||
eatEntry(dev, entry);
|
||||
if (g_tail_lines == 0 || queued_lines <= g_tail_lines) {
|
||||
printNextEntry(dev);
|
||||
} else {
|
||||
skipNextEntry(dev);
|
||||
}
|
||||
--queued_lines;
|
||||
}
|
||||
// They requested to just dump the log
|
||||
|
||||
// the caller requested to just dump the log and exit
|
||||
if (g_nonblock) {
|
||||
exit(0);
|
||||
}
|
||||
} else {
|
||||
// print all that aren't the last in their list
|
||||
while (true) {
|
||||
chooseFirst(devices, &dev, &entry);
|
||||
if (!entry) {
|
||||
sleep = false;
|
||||
break;
|
||||
} else if (entry->next == NULL) {
|
||||
sleep = false;
|
||||
sleep = false;
|
||||
while (g_tail_lines == 0 || queued_lines > g_tail_lines) {
|
||||
chooseFirst(devices, &dev);
|
||||
if (dev == NULL || dev->queue->next == NULL) {
|
||||
break;
|
||||
}
|
||||
eatEntry(dev, entry);
|
||||
if (g_tail_lines == 0) {
|
||||
printNextEntry(dev);
|
||||
} else {
|
||||
skipNextEntry(dev);
|
||||
}
|
||||
--queued_lines;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -398,6 +399,7 @@ static void show_help(const char *cmd)
|
|||
" brief process tag thread raw time threadtime long\n\n"
|
||||
" -c clear (flush) the entire log and exit\n"
|
||||
" -d dump the log and then exit (don't block)\n"
|
||||
" -t <count> print only the most recent <count> lines (implies -d)\n"
|
||||
" -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"
|
||||
|
@ -472,7 +474,7 @@ int main(int argc, char **argv)
|
|||
for (;;) {
|
||||
int ret;
|
||||
|
||||
ret = getopt(argc, argv, "cdgsQf:r::n:v:b:B");
|
||||
ret = getopt(argc, argv, "cdt:gsQf:r::n:v:b:B");
|
||||
|
||||
if (ret < 0) {
|
||||
break;
|
||||
|
@ -493,6 +495,11 @@ int main(int argc, char **argv)
|
|||
g_nonblock = true;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
g_nonblock = true;
|
||||
g_tail_lines = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
getLogSize = 1;
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue