blob: 26ae6a3e0e2e5fa3c2ddb94b47fd125d9714f1a5 [file] [log] [blame]
Joe Onorato5dcbc6c2017-08-29 15:13:58 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Joe Onorato9fc9edf2017-10-15 20:08:52 -070017#include "logd/LogReader.h"
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070018
Yao Chen884c8c12018-01-26 10:36:25 -080019#include "guardrail/StatsdStats.h"
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070020
21#include <time.h>
22#include <unistd.h>
Yao Chen884c8c12018-01-26 10:36:25 -080023#include <utils/Errors.h>
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070024
25using namespace android;
26using namespace std;
27
Bookatz906a35c2017-09-20 15:26:44 -070028namespace android {
29namespace os {
30namespace statsd {
31
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070032#define SNOOZE_INITIAL_MS 100
Yao Chenef99c4f2017-09-22 16:26:54 -070033#define SNOOZE_MAX_MS (10 * 60 * 1000) // Ten minutes
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070034
Joe Onorato9fc9edf2017-10-15 20:08:52 -070035LogReader::LogReader(const sp<LogListener>& listener) : mListener(listener) {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070036}
37
Yao Chenef99c4f2017-09-22 16:26:54 -070038LogReader::~LogReader() {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070039}
40
Yao Chenef99c4f2017-09-22 16:26:54 -070041void LogReader::Run() {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070042 int nextSnoozeMs = SNOOZE_INITIAL_MS;
43
44 // In an ideal world, this outer loop will only ever run one iteration, but it
45 // exists to handle crashes in logd. The inner loop inside connect_and_read()
46 // reads from logd forever, but if that read fails, we fall out to the outer
47 // loop, do the backoff (resetting the backoff timeout if we successfully read
48 // something), and then try again.
49 while (true) {
50 // Connect and read
51 int lineCount = connect_and_read();
52
53 // Figure out how long to sleep.
54 if (lineCount > 0) {
55 // If we managed to read at least one line, reset the backoff
56 nextSnoozeMs = SNOOZE_INITIAL_MS;
57 } else {
58 // Otherwise, expontial backoff
59 nextSnoozeMs *= 1.5f;
60 if (nextSnoozeMs > 10 * 60 * 1000) {
61 // Don't wait for toooo long.
62 nextSnoozeMs = SNOOZE_MAX_MS;
63 }
64 }
65
66 // Sleep
67 timespec ts;
68 timespec rem;
69 ts.tv_sec = nextSnoozeMs / 1000;
70 ts.tv_nsec = (nextSnoozeMs % 1000) * 1000000L;
71 while (nanosleep(&ts, &rem) == -1) {
72 if (errno == EINTR) {
73 ts = rem;
74 }
75 // other errors are basically impossible
76 }
77 }
78}
79
Yao Chenef99c4f2017-09-22 16:26:54 -070080int LogReader::connect_and_read() {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070081 int lineCount = 0;
82 status_t err;
83 logger_list* loggers;
84 logger* eventLogger;
85
86 // Prepare the logging context
87 loggers = android_logger_list_alloc(ANDROID_LOG_RDONLY,
Yao Chenef99c4f2017-09-22 16:26:54 -070088 /* don't stop after N lines */ 0,
89 /* no pid restriction */ 0);
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070090
91 // Open the buffer(s)
Chenjie Yu7ca2e822017-09-07 13:02:47 -070092 eventLogger = android_logger_open(loggers, LOG_ID_STATS);
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070093
94 // Read forever
95 if (eventLogger) {
Yao Chen884c8c12018-01-26 10:36:25 -080096 log_msg msg;
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070097 while (true) {
Joe Onorato5dcbc6c2017-08-29 15:13:58 -070098 // Read a message
99 err = android_logger_list_read(loggers, &msg);
Yao Chen2ee43712018-01-22 14:36:52 -0800100 // err = 0 - no content, unexpected connection drop or EOF.
101 // err = +ive number - size of retrieved data from logger
102 // err = -ive number, OS supplied error _except_ for -EAGAIN
103 if (err <= 0) {
Yao Chen884c8c12018-01-26 10:36:25 -0800104 StatsdStats::getInstance().noteLoggerError(err);
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700105 fprintf(stderr, "logcat read failure: %s\n", strerror(err));
106 break;
107 }
108
109 // Record that we read one (used above to know how to snooze).
110 lineCount++;
111
Joe Onoratoc4dfae52017-10-17 23:38:21 -0700112 // Wrap it in a LogEvent object
113 LogEvent event(msg);
114
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700115 // Call the listener
Yao Chen163d2602018-04-10 10:39:53 -0700116 mListener->OnLogEvent(&event,
117 lineCount == 1 /* indicate whether it's a new connection */);
Joe Onorato5dcbc6c2017-08-29 15:13:58 -0700118 }
119 }
120
121 // Free the logger list and close the individual loggers
122 android_logger_list_free(loggers);
123
124 return lineCount;
125}
126
Yao Chenef99c4f2017-09-22 16:26:54 -0700127} // namespace statsd
128} // namespace os
129} // namespace android