network_event_log.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 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 "chromeos/network/network_event_log.h"
6
7#include "base/i18n/time_formatting.h"
8#include "base/logging.h"
9#include "base/memory/scoped_ptr.h"
10#include "base/stringprintf.h"
11#include "base/utf_string_conversions.h"
12
13namespace chromeos {
14
15namespace network_event_log {
16
17namespace {
18
19struct LogEntry {
20  LogEntry(const std::string& module,
21           const std::string& event,
22           const std::string& description);
23
24  std::string ToString() const;
25
26  bool ContentEquals(const LogEntry& other) const;
27
28  std::string module;
29  std::string event;
30  std::string description;
31  base::Time time;
32  int count;
33};
34
35LogEntry::LogEntry(const std::string& module,
36                   const std::string& event,
37                   const std::string& description)
38    : module(module),
39      event(event),
40      description(description),
41      time(base::Time::Now()),
42      count(1) {
43}
44
45std::string LogEntry::ToString() const {
46  std::string line;
47  line += "[" + UTF16ToUTF8(base::TimeFormatShortDateAndTime(time)) + "]";
48  line += " " + module + ":" + event;
49  if (!description.empty())
50    line += ": " + description;
51  if (count > 1)
52    line += base::StringPrintf(" (%d)", count);
53  line += "\n";
54  return line;
55}
56
57bool LogEntry::ContentEquals(const LogEntry& other) const {
58  return module == other.module &&
59      event == other.event &&
60      description == other.description;
61}
62
63typedef std::deque<LogEntry> LogEntryList;
64
65class NetworkEventLog {
66 public:
67  NetworkEventLog() {}
68  ~NetworkEventLog() {}
69
70  void AddEntry(const LogEntry& entry);
71
72  std::string GetAsString(StringOrder order,
73                          size_t max_events);
74
75 private:
76  LogEntryList entries_;
77
78  DISALLOW_COPY_AND_ASSIGN(NetworkEventLog);
79};
80
81void NetworkEventLog::AddEntry(const LogEntry& entry) {
82  if (!entries_.empty()) {
83    LogEntry& last = entries_.back();
84    if (last.ContentEquals(entry)) {
85      // Update count and time for identical events to avoid log spam.
86      ++last.count;
87      last.time = base::Time::Now();
88      return;
89    }
90  }
91  if (entries_.size() >= kMaxNetworkEventLogEntries)
92    entries_.pop_front();
93  entries_.push_back(entry);
94  VLOG(2) << entry.ToString();
95}
96
97std::string NetworkEventLog::GetAsString(StringOrder order,
98                                         size_t max_events) {
99  if (entries_.empty())
100    return "No Log Entries.";
101
102  std::string result;
103  if (order == OLDEST_FIRST) {
104    size_t offset = 0;
105    if (max_events > 0 && max_events < entries_.size())
106      offset = entries_.size() - max_events;
107    for (LogEntryList::const_iterator iter = entries_.begin() + offset;
108         iter != entries_.end(); ++iter) {
109      result += (*iter).ToString();
110    }
111  } else {
112    size_t nlines = 0;
113    // Iterate backwards through the list to show the most recent entries first.
114    for (LogEntryList::const_reverse_iterator riter = entries_.rbegin();
115         riter != entries_.rend(); ++riter) {
116      result += (*riter).ToString();
117      if (max_events > 0 && ++nlines >= max_events)
118        break;
119    }
120  }
121  return result;
122}
123
124}  // namespace
125
126NetworkEventLog* g_network_event_log = NULL;
127const size_t kMaxNetworkEventLogEntries = 1000;
128
129void Initialize() {
130  if (g_network_event_log)
131    delete g_network_event_log;  // reset log
132  g_network_event_log = new NetworkEventLog();
133}
134
135void Shutdown() {
136  delete g_network_event_log;
137  g_network_event_log = NULL;
138}
139
140bool IsInitialized() {
141  return g_network_event_log != NULL;
142}
143
144void AddEntry(const std::string& module,
145              const std::string& event,
146              const std::string& description) {
147  LogEntry entry(module, event, description);
148  if (!g_network_event_log) {
149    VLOG(2) << entry.ToString();
150    return;
151  }
152  g_network_event_log->AddEntry(entry);
153}
154
155std::string GetAsString(StringOrder order, size_t max_events) {
156  if (!g_network_event_log)
157    return "NetworkEventLog not intitialized.";
158  return g_network_event_log->GetAsString(order, max_events);
159}
160
161}  // namespace network_event_log
162
163}  // namespace chromeos
164