text: // 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.
  
  // Defines base class LogReader and its derived classes AuditReader and
  // MessageReader. AuditReader parses SELinux logs from /var/log/audit/audit.log
  // and MessageReader parses other logs from /var/log/messages and
  // /var/log/upstart.log.
  
  #ifndef CRASH_REPORTER_ANOMALY_DETECTOR_LOG_READER_H_
  #define CRASH_REPORTER_ANOMALY_DETECTOR_LOG_READER_H_
  
  #include "crash-reporter/anomaly_detector_text_file_reader.h"
  
  #include <string>
  
  #include <base/files/file_util.h>
  #include <base/time/time.h>
  #include <re2/re2.h>
  
  namespace anomaly {
  
  // First group captures unix timestamp.
  // Second group captures the log message.
  // e.g.
  // `type=AVC msg=audit(1588751099.358:13): avc:  denied  { module_request }`
  // ` for  pid=1795 comm="init" kmod="fs-cgroup2" scontext=u:r:init:s0`
  // ` tcontext=u:r:kernel:s0 tclass=system permissive=0`
  constexpr char kAuditLogPattern[] = R"([^(]+\(([\d\.]+)\S+ (.+))";
  
  // First group captures timestamp in RFC3339 format.
  // Second group captures the tag (i.e. service name).
  // Third group captures the log message.
  // e.g.
  // `2020-05-10T22:45:04.419261-07:00 ERR tpm_managerd[790]: TPM error`
  // ` 0x3011 (Communication failure): Failed to connect context.`
  // e.g.2
  // `2020-05-10T22:45:04.419261-07:00 ERR kernel: [  893.009245]`
  // ` atme1_mxt_ts 3-004b: Status: 00 Config Checksum: 673e89`
  // e.g.3
  // `2020-05-14T19:37:04.202906+09:00 INFO VM(3)[8947]:`
  // ` [devices/src/virtio/balloon.rs:290] ballon config changed`
  constexpr char kMessageLogPattern[] = R"((\S+) \S+ (\S*?)(?:\[\d+\])?:\s+(.+))";
  
  // First group captures timestamp in RFC3339 format.
  // Second group captures the service name.
  // Third group captures the log message.
  // e.g.
  // `2020-05-15T16:34:00.678394+09:00 INFO kernel:`
  // ` [ 1608.687863] init: Connection from private client`
  constexpr char kUpstartLogPattern[] =
      R"((\S+) \S+ \S+: \[\s*\S+\] (\w+):\s+(.+))";
  
  // Describes an entry in log files.
  // tag: name of the service that generated the log.
  // message: content of the log.
  // timestamp: timestamp of the log.
  struct LogEntry {
    std::string tag;
    std::string message;
    base::Time timestamp;
  };
  
  // LogReader parses newline-delimited log entries into structs that can
  // be parsed by log parsers (in anomaly_detector.h) to be analysed for errors.
  // It uses anomaly::TextFileReader for reading lines in the log files and
  // handling log rotations.
  class LogReader {
   public:
    explicit LogReader(const base::FilePath& path);
    virtual ~LogReader() = 0;
  
    // Returns true while there are log entries in the log file. It will update
    // the output parameter 'entry' if one is found.
    bool GetNextEntry(LogEntry* entry);
  
   private:
    const base::FilePath log_file_path_;
  
    // TextFileReader is defined in anomaly_detector_text_file_reader.h.
    TextFileReader log_file_;
  
    // Parses a line from log_file_ to generate LogEntry.
    virtual bool ReadLine(const std::string& line, LogEntry* entry) = 0;
  
    // Moves the position of log_file_ to the beginning.
    // Only used for testing.
    void SeekToBegin();
  
    FRIEND_TEST(AnomalyDetectorLogReaderTest, AuditReaderTest);
    FRIEND_TEST(AnomalyDetectorLogReaderTest, MessageReaderTest);
    FRIEND_TEST(AnomalyDetectorLogReaderTest, UpstartMessageReaderTest);
    DISALLOW_COPY_AND_ASSIGN(LogReader);
  };
  
  // AuditReader specialises in parsing log entries generated by SELinux.
  class AuditReader : public LogReader {
   public:
    explicit AuditReader(const base::FilePath& path, const char* pattern)
        : LogReader(path), pattern_(pattern) {}
  
    // Each line in log file is checked against pattern_ to retrieve relevant
    // info.
    const RE2 pattern_;
  
   private:
    bool ReadLine(const std::string& line, LogEntry* entry) override;
  };
  
  // MessageReader specialises in parsing syslog formatted logs in
  // /var/log/messages and /var/log/upstart.log.
  class MessageReader : public LogReader {
   public:
    explicit MessageReader(const base::FilePath& path, const char* pattern)
        : LogReader(path), pattern_(pattern) {}
  
    // Each line in log file is checked against pattern_ to retrieve relevant
    // info.
    const RE2 pattern_;
  
   private:
    bool ReadLine(const std::string& line, LogEntry* entry) override;
  };
  
  }  // namespace anomaly
  
  #endif  // CRASH_REPORTER_ANOMALY_DETECTOR_LOG_READER_H_
  