Home | History | Annotate | Download | only in log_private
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/extensions/api/log_private/syslog_parser.h"
      6 
      7 #include <string>
      8 #include <vector>
      9 
     10 #include "base/logging.h"
     11 #include "base/memory/linked_ptr.h"
     12 #include "base/memory/singleton.h"
     13 #include "base/strings/string_number_conversions.h"
     14 #include "base/strings/string_split.h"
     15 #include "base/strings/string_tokenizer.h"
     16 #include "base/time/time.h"
     17 #include "chrome/browser/extensions/api/log_private/filter_handler.h"
     18 #include "chrome/browser/extensions/api/log_private/log_parser.h"
     19 #include "chrome/browser/extensions/api/log_private/log_private_api.h"
     20 #include "chrome/common/extensions/api/log_private.h"
     21 
     22 namespace extensions {
     23 
     24 namespace {
     25 
     26 const int kExpectedTimeTokenNum = 7;
     27 const char kLogEntryDelimiters[] = "-:T";
     28 const char kProcessInfoDelimiters[] = "[]";
     29 
     30 }  // namespace
     31 
     32 SyslogParser::SyslogParser() {}
     33 
     34 SyslogParser::~SyslogParser() {}
     35 
     36 SyslogParser::Error SyslogParser::ParseEntry(
     37     const std::string& input,
     38     std::vector<linked_ptr<api::log_private::LogEntry> >* output,
     39     FilterHandler* filter_handler) const {
     40   linked_ptr<api::log_private::LogEntry> entry(new api::log_private::LogEntry);
     41 
     42   base::StringTokenizer tokenizer(input, " ");
     43   if (!tokenizer.GetNext()) {
     44     LOG(ERROR)
     45         << "Error when parsing data. Expect: At least 3 tokens. Actual: 0";
     46     return TOKENIZE_ERROR;
     47   }
     48   std::string time = tokenizer.token();
     49   if (ParseTime(time, &(entry->timestamp)) != SyslogParser::SUCCESS) {
     50     return SyslogParser::PARSE_ERROR;
     51   }
     52   // Skips "localhost" field.
     53   if (!tokenizer.GetNext()) {
     54     LOG(ERROR)
     55         << "Error when parsing data. Expect: At least 3 tokens. Actual: 1";
     56     return TOKENIZE_ERROR;
     57   }
     58   if (!tokenizer.GetNext()) {
     59     LOG(ERROR)
     60         << "Error when parsing data. Expect: At least 3 tokens. Actual: 2";
     61     return TOKENIZE_ERROR;
     62   }
     63   ParseProcess(tokenizer.token(), entry.get());
     64   ParseLevel(input, entry.get());
     65   entry->full_entry = input;
     66 
     67   if (filter_handler->IsValidLogEntry(*(entry.get()))) {
     68     output->push_back(entry);
     69   }
     70 
     71   return SyslogParser::SUCCESS;
     72 }
     73 
     74 SyslogParser::Error ParseTimeHelper(base::StringTokenizer* tokenizer,
     75                                     std::string* output) {
     76   if (!tokenizer->GetNext()) {
     77     LOG(ERROR) << "Error when parsing time";
     78     return SyslogParser::PARSE_ERROR;
     79   }
     80   *output = tokenizer->token();
     81   return SyslogParser::SUCCESS;
     82 }
     83 
     84 SyslogParser::Error SyslogParser::ParseTime(const std::string& input,
     85                                             double* output) const {
     86   base::StringTokenizer tokenizer(input, kLogEntryDelimiters);
     87   std::string tokens[kExpectedTimeTokenNum];
     88   for (int i = 0; i < kExpectedTimeTokenNum; i++) {
     89     if (ParseTimeHelper(&tokenizer, &(tokens[i])) != SyslogParser::SUCCESS)
     90       return SyslogParser::PARSE_ERROR;
     91   }
     92 
     93   std::string buffer = tokens[1] + '-' + tokens[2] + '-' + tokens[0] + ' ' +
     94                        tokens[3] + ':' + tokens[4] + ":00";
     95 
     96   base::Time parsed_time;
     97   if (!base::Time::FromString(buffer.c_str(), &parsed_time)) {
     98     LOG(ERROR) << "Error when parsing time";
     99     return SyslogParser::PARSE_ERROR;
    100   }
    101 
    102   double seconds;
    103   base::StringToDouble(tokens[5], &seconds);
    104   *output = parsed_time.ToJsTime() +
    105             (seconds * base::Time::kMillisecondsPerSecond);
    106 
    107   return SyslogParser::SUCCESS;
    108 }
    109 
    110 SyslogParser::Error SyslogParser::ParseProcess(
    111     const std::string& input,
    112     api::log_private::LogEntry* entry) const {
    113   base::StringTokenizer tokenizer(input, kProcessInfoDelimiters);
    114   if (!tokenizer.GetNext()) {
    115     LOG(ERROR)
    116         << "Error when parsing data. Expect: At least 1 token. Actual: 0";
    117     return SyslogParser::PARSE_ERROR;
    118   }
    119   entry->process = tokenizer.token();
    120   entry->process_id = "unknown";
    121   if (tokenizer.GetNext()) {
    122     std::string token = tokenizer.token();
    123     int tmp;
    124     if (base::StringToInt(token, &tmp)) {
    125       entry->process_id = token;
    126     }
    127   }
    128   return SyslogParser::SUCCESS;
    129 }
    130 
    131 void SyslogParser::ParseLevel(const std::string& input,
    132                               api::log_private::LogEntry* entry) const {
    133   if (input.find("ERROR") != std::string::npos) {
    134     entry->level = "error";
    135   } else if (input.find("WARN") != std::string::npos) {
    136     entry->level = "warning";
    137   } else if (input.find("INFO") != std::string::npos) {
    138     entry->level = "info";
    139   } else {
    140     entry->level = "unknown";
    141   }
    142 }
    143 
    144 }  // namespace extensions
    145