12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/network/network_event_log.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <list>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/files/file_path.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/i18n/time_formatting.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/json/json_writer.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/strings/string_tokenizer.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/values.h"
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/base/escape.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace chromeos {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace network_event_log {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class NetworkEventLog;
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)NetworkEventLog* g_network_event_log = NULL;
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochsize_t g_max_network_event_log_entries = 4000;
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct LogEntry {
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LogEntry(const std::string& file,
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           int file_line,
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           LogLevel log_level,
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           const std::string& event,
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           const std::string& description);
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string ToString(bool show_time,
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       bool show_file,
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       bool show_desc,
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       bool format_html) const;
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string GetNormalText(bool show_desc) const;
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string GetHtmlText(bool show_desc) const;
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void SendToVLogOrErrorLog() const;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ContentEquals(const LogEntry& other) const;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string file;
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int file_line;
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LogLevel log_level;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string event;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string description;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Time time;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int count;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)LogEntry::LogEntry(const std::string& file,
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                   int file_line,
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                   LogLevel log_level,
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   const std::string& event,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   const std::string& description)
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : file(file),
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      file_line(file_line),
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      log_level(log_level),
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      event(event),
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      description(description),
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      time(base::Time::Now()),
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      count(1) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string LogEntry::ToString(bool show_time,
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               bool show_file,
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               bool show_desc,
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               bool format_html) const {
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string line;
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (show_time)
777c720b7466665b17575e0fd6976f9321c6bff489Torne (Richard Coles)    line += "[" + UTF16ToUTF8(base::TimeFormatTimeOfDay(time)) + "] ";
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (show_file) {
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::string filestr = format_html ? net::EscapeForHTML(file) : file;
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    line += base::StringPrintf("%s:%d ", filestr.c_str(), file_line);
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  line += format_html ? GetHtmlText(show_desc) : GetNormalText(show_desc);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (count > 1)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    line += base::StringPrintf(" (%d)", count);
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return line;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string LogEntry::GetNormalText(bool show_desc) const {
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string text = event;
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (show_desc && !description.empty())
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    text += ": " + description;
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return text;
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string LogEntry::GetHtmlText(bool show_desc) const {
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string text;
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (log_level == LOG_LEVEL_DEBUG)
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    text += "<i>";
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  else if (log_level == LOG_LEVEL_USER)
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    text += "<b>";
101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  else if (log_level == LOG_LEVEL_ERROR)
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    text += "<b><i>";
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  text += event;
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (show_desc && !description.empty())
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    text += ": " + net::EscapeForHTML(description);
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (log_level == LOG_LEVEL_DEBUG)
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    text += "</i>";
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  else if (log_level == LOG_LEVEL_USER)
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    text += "</b>";
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  else if (log_level == LOG_LEVEL_ERROR)
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    text += "</i></b>";
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return text;
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void LogEntry::SendToVLogOrErrorLog() const {
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool show_time = true;
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool show_file = true;
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool show_desc = true;
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const bool format_html = false;
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string output = ToString(show_time, show_file, show_desc, format_html);
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (log_level == LOG_LEVEL_ERROR)
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << output;
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    VLOG(1) << output;
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LogEntry::ContentEquals(const LogEntry& other) const {
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return file == other.file &&
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      file_line == other.file_line &&
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      event == other.event &&
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      description == other.description;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void GetFormat(const std::string& format_string,
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               bool* show_time,
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               bool* show_file,
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               bool* show_desc,
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               bool* format_html) {
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::StringTokenizer tokens(format_string, ",");
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *show_time = false;
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *show_file = false;
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *show_desc = false;
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *format_html = false;
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (tokens.GetNext()) {
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::string tok(tokens.token());
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (tok == "time")
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *show_time = true;
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (tok == "file")
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *show_file = true;
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (tok == "desc")
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *show_desc = true;
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (tok == "html")
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      *format_html = true;
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)typedef std::list<LogEntry> LogEntryList;
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class NetworkEventLog {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NetworkEventLog() {}
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~NetworkEventLog() {}
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void AddLogEntry(const LogEntry& entry);
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string GetAsString(StringOrder order,
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          const std::string& format,
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          LogLevel max_level,
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          size_t max_events);
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LogEntryList& entries() { return entries_; }
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LogEntryList entries_;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NetworkEventLog);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NetworkEventLog::AddLogEntry(const LogEntry& entry) {
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!entries_.empty()) {
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LogEntry& last = entries_.back();
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (last.ContentEquals(entry)) {
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Update count and time for identical events to avoid log spam.
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ++last.count;
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      last.log_level = std::min(last.log_level, entry.log_level);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      last.time = base::Time::Now();
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (entries_.size() >= g_max_network_event_log_entries) {
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const size_t max_error_entries = g_max_network_event_log_entries / 2;
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Remove the first (oldest) non-error entry, or the oldest entry if more
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // than half the entries are errors.
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    size_t error_count = 0;
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (LogEntryList::iterator iter = entries_.begin();
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         iter != entries_.end(); ++iter) {
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (iter->log_level != LOG_LEVEL_ERROR) {
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        entries_.erase(iter);
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (++error_count > max_error_entries) {
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Too many error entries, remove the oldest entry.
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        entries_.pop_front();
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break;
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  entries_.push_back(entry);
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  entry.SendToVLogOrErrorLog();
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string NetworkEventLog::GetAsString(StringOrder order,
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         const std::string& format,
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         LogLevel max_level,
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         size_t max_events) {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (entries_.empty())
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return "No Log Entries.";
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool show_time, show_file, show_desc, format_html;
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GetFormat(format, &show_time, &show_file, &show_desc, &format_html);
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string result;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (order == OLDEST_FIRST) {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t offset = 0;
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (max_events > 0 && max_events < entries_.size()) {
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Iterate backwards through the list skipping uninteresting entries to
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // determine the first entry to include.
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      size_t shown_events = 0;
23190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      size_t num_entries = 0;
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      for (LogEntryList::const_reverse_iterator riter = entries_.rbegin();
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           riter != entries_.rend(); ++riter) {
23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        ++num_entries;
23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (riter->log_level > max_level)
23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          continue;
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        if (++shown_events >= max_events)
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          break;
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      offset = entries_.size() - num_entries;
24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (LogEntryList::const_iterator iter = entries_.begin();
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         iter != entries_.end(); ++iter) {
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (offset > 0) {
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        --offset;
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        continue;
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (iter->log_level > max_level)
24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        continue;
25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      result += (*iter).ToString(show_time, show_file, show_desc, format_html);
251558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      result += "\n";
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t nlines = 0;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Iterate backwards through the list to show the most recent entries first.
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (LogEntryList::const_reverse_iterator riter = entries_.rbegin();
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         riter != entries_.rend(); ++riter) {
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (riter->log_level > max_level)
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        continue;
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      result += (*riter).ToString(show_time, show_file, show_desc, format_html);
261558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      result += "\n";
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (max_events > 0 && ++nlines >= max_events)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return result;
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const LogLevel kDefaultLogLevel = LOG_LEVEL_EVENT;
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Initialize() {
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (g_network_event_log)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete g_network_event_log;  // reset log
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_network_event_log = new NetworkEventLog();
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Shutdown() {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete g_network_event_log;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_network_event_log = NULL;
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsInitialized() {
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return g_network_event_log != NULL;
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace internal {
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t GetMaxLogEntries() {
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return g_max_network_event_log_entries;
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SetMaxLogEntries(size_t max_entries) {
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  g_max_network_event_log_entries = max_entries;
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!g_network_event_log)
29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  while (g_network_event_log->entries().size() > max_entries)
29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    g_network_event_log->entries().pop_front();
30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void AddEntry(const char* file,
30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)              int file_line,
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)              LogLevel log_level,
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              const std::string& event,
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              const std::string& description) {
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string filestr;
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (file)
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    filestr = base::FilePath(std::string(file)).BaseName().value();
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LogEntry entry(filestr, file_line, log_level, event, description);
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!g_network_event_log) {
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    entry.SendToVLogOrErrorLog();
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  g_network_event_log->AddLogEntry(entry);
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace internal
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string GetAsString(StringOrder order,
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                        const std::string& format,
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                        LogLevel max_level,
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                        size_t max_events) {
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!g_network_event_log)
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return "NetworkEventLog not initialized.";
32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return g_network_event_log->GetAsString(order, format, max_level, max_events);
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)std::string ValueAsString(const base::Value& value) {
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string vstr;
33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::JSONWriter::WriteWithOptions(
33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      &value, base::JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &vstr);
33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return vstr.empty() ? "''" : vstr;
33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace network_event_log
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace chromeos
338