blob: 441321b99d981041c1fd32ba18a2adf8b93165d3 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CRASH_REPORTER_CRASH_REPORTER_PARSER_H_
#define CRASH_REPORTER_CRASH_REPORTER_PARSER_H_
#include <memory>
#include <string>
#include <vector>
#include <base/time/clock.h>
#include <base/time/time.h>
#include <metrics/metrics_library.h>
#include "crash-reporter/anomaly_detector.h"
namespace anomaly {
// Anomaly_detector's collector for syslog entries from our own crash_reporter.
// Unlike other anomaly_detector collectors, this doesn't actually ever create
// crash reports -- ParseLogEntry always returns nullopt. Instead, it produces
// UMA metrics that track how well Chrome's crash handlers (breakpad or
// crashpad) are working. If Chrome gets a segfault or such, its internal crash
// handler should invoke crash_reporter directly. Once the internal crash
// handler is done, the kernel should also invoke crash_reporter via the normal
// core pattern file. Both of these produce distinct log entries. By matching
// these up, we can detect how often the internal crash handler is failing to
// invoke crash_reporter. In particular, if we see an invoked-by-kernel message
// without a corresponding invoking-directly message, Chrome's crash handler
// failed. We record the number of unmatched invoked-by-kernel messages, and,
// for a denominator, we record the total number of invoked-by-kernel messages.
//
// (There are some cases -- "dump without crashing" -- in which Chrome will
// invoke crash_reporter but will not actually crash, and so will not produce
// an invoked-by-kernel message. This is why we go to the trouble of actually
// matching up messages from the log, instead of just counting the number of
// invoked-directly and invoked-from-kernel events. The "dump without crashing"
// events will overcount the number of successes and hide the true number of
// failures. Therefore, we ignore "dump without crashing" crashes by not
// counting the number of invoked-by-Chrome messages we see, and not reporting
// the number of unmatched invoked-by-Chrome messages.)
class CrashReporterParser : public Parser {
public:
// We hold on to unmatched messages for at least this long before reporting
// them as unmatched.
static constexpr base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(30);
explicit CrashReporterParser(
std::unique_ptr<base::Clock> clock,
std::unique_ptr<MetricsLibraryInterface> metrics_lib);
MaybeCrashReport ParseLogEntry(const std::string& line) override;
void PeriodicUpdate() override;
private:
enum class Collector {
// Log entry was from ChromeCollector.
CHROME,
// Log entry was from UserCollector.
USER
};
struct UnmatchedCrash {
int pid;
base::Time timestamp;
Collector collector;
};
std::unique_ptr<base::Clock> clock_;
std::unique_ptr<MetricsLibraryInterface> metrics_lib_;
std::vector<UnmatchedCrash> unmatched_crashes_;
};
} // namespace anomaly
#endif // CRASH_REPORTER_CRASH_REPORTER_PARSER_H_