blob: b66e30378e24a2fb0b79fdadd80774b2ba685de5 [file] [log] [blame]
Christopher Wiley5781aa42012-07-30 14:42:23 -07001// Copyright (c) 2012 The Chromium OS 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#ifndef SHILL_MEMORY_LOG_H_
6#define SHILL_MEMORY_LOG_H_
7
8#include <deque>
9#include <string>
10#include <sstream>
Han Shenafb5b5a2012-08-13 11:43:28 -070011#include <unistd.h>
Christopher Wiley5781aa42012-07-30 14:42:23 -070012
13#include <base/basictypes.h>
14#include <base/lazy_instance.h>
15#include <base/logging.h>
16#include <gtest/gtest_prod.h>
17
Christopher Wiley3e7635e2012-08-15 09:46:17 -070018class FilePath;
19
Christopher Wiley5781aa42012-07-30 14:42:23 -070020// MemoryLog is nothing but a memory buffer of the most recent messages, capped
21// by a configurable limit of how many message bytes to remember at a time.
22// When a new message comes in, we add it to the buffer, then drop the oldest
23// messages until the size of the buffer is under the byte limit. The number of
24// bytes in the buffer does not include std::string overhead, nor overhead from
25// the buffer implementation. Only bytes in messages are counted.
26//
27// When something 'interesting' happens (e.g. connectivity event or crash), the
28// logic reacting to that event can dump the contents of the MemoryLog to disk.
29// This gives us a verbose log of the most recent events up until the event,
30// which may be useful for further debugging.
31
32namespace shill {
33
Christopher Wiley5781aa42012-07-30 14:42:23 -070034class MemoryLog {
35 public:
36 // Returns a singleton of this class.
37 static MemoryLog *GetInstance();
38
Christopher Wiley5781aa42012-07-30 14:42:23 -070039 ~MemoryLog();
40 // Appends this message to the log, dropping the oldest messages until the log
41 // is under the byte limit.
42 void Append(const std::string &msg);
43 // Removes all messages from the log.
44 void Clear();
Christopher Wiley5781aa42012-07-30 14:42:23 -070045 // Sets the maximum size for the log and drops messages until we get under it.
46 void SetMaximumSize(size_t size_in_bytes);
Christopher Wiley3e7635e2012-08-15 09:46:17 -070047 // See FlushToDiskImpl().
48 void FlushToDisk();
Christopher Wiley5781aa42012-07-30 14:42:23 -070049
50 size_t maximum_size_bytes() const { return maximum_size_bytes_; }
51 size_t current_size_bytes() const { return current_size_bytes_; }
52
53 private:
54 friend class MemoryLogTest;
Christopher Wileyf11cebb2012-08-08 12:22:20 -070055 // Required for constructing LazyInstance<MemoryLog>.
56 friend struct base::DefaultLazyInstanceTraits<MemoryLog>;
Christopher Wiley3e7635e2012-08-15 09:46:17 -070057 FRIEND_TEST(ManagerTest, PopProfileShouldClearMemoryLog);
58 FRIEND_TEST(MemoryLogTest, MemoryLogFlushToDiskCannotCreateFile);
59 FRIEND_TEST(MemoryLogTest, MemoryLogFlushToDiskRotateWorks);
Christopher Wiley5781aa42012-07-30 14:42:23 -070060 FRIEND_TEST(MemoryLogTest, MemoryLogFlushToDiskWorks);
Christopher Wiley3e7635e2012-08-15 09:46:17 -070061 FRIEND_TEST(MemoryLogTest, MemoryLogFlushToFileWorks);
Christopher Wiley5781aa42012-07-30 14:42:23 -070062 FRIEND_TEST(MemoryLogTest, MemoryLogIsLogging);
63 FRIEND_TEST(MemoryLogTest, MemoryLogLimitingWorks);
Christopher Wileyf11cebb2012-08-08 12:22:20 -070064 FRIEND_TEST(MemoryLogTest, MemoryLogMessageInterceptorWorks);
Christopher Wiley5781aa42012-07-30 14:42:23 -070065
66 // Arbitrary default verbose log capacity is an even megabyte.
67 static const size_t kDefaultMaximumMemoryLogSizeInBytes = 1 << 20;
Christopher Wiley3e7635e2012-08-15 09:46:17 -070068 // Default log dump path used with FlushToDisk() when a user is logged in.
69 static const char kDefaultLoggedInDumpPath[];
70 // Default log dump path used when no user is logged in.
71 static const char kDefaultLoggedOutDumpPath[];
72 // If this file exists, then we say that a user is logged in
73 static const char kLoggedInTokenPath[];
74 // The on disk log file may only be this big before we'll forcibly rotate it.
75 // This means we may have this number * 2 bytes on disk at any time.
76 static const size_t kDefaultMaxDiskLogSizeInBytes =
77 kDefaultMaximumMemoryLogSizeInBytes * 20;
Christopher Wiley5781aa42012-07-30 14:42:23 -070078
79 std::deque<std::string> log_;
80
81 void ShrinkToTargetSize(size_t number_bytes);
82 size_t TestGetNumberMessages() { return log_.size(); }
Christopher Wiley3e7635e2012-08-15 09:46:17 -070083 bool TestContainsMessageWithText(const char *msg);
84 void TestSetMaxDiskLogSize(size_t number_bytes) {
85 maximum_disk_log_size_bytes_ = number_bytes;
86 }
87 // Appends the current contents of the memory buffer to a specified file on
88 // disk. Returns the number of bytes written to disk, or -1 on failure. -1 is
89 // returned on failure even if some bytes have already made it to disk.
90 // Attempts to create the parent directories of |file_path| if it does not
91 // already exist. If the resulting log file is too large (> kMaxDiskLogSize),
92 // tries to rotate logs.
93 ssize_t FlushToFile(const FilePath &file_path);
94 // Flushes the log to disk via FlushToFile, then clears the log, and tries to
95 // rotate our logs if |file_path| is larger than
96 // |maximum_disk_log_size_bytes_|.
97 //
98 // We rotate here rather than through logrotate because we fear situations
99 // where we experience a lot of connectivity problems in a short span of time
100 // before logrotate has a chance to run.
101 void FlushToDiskImpl(const FilePath &file_path);
Christopher Wiley5781aa42012-07-30 14:42:23 -0700102
103 size_t maximum_size_bytes_;
104 size_t current_size_bytes_;
Christopher Wiley3e7635e2012-08-15 09:46:17 -0700105 size_t maximum_disk_log_size_bytes_;
Christopher Wiley5781aa42012-07-30 14:42:23 -0700106
Christopher Wileyf11cebb2012-08-08 12:22:20 -0700107 DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryLog);
Christopher Wiley5781aa42012-07-30 14:42:23 -0700108};
109
110class MemoryLogMessage {
111 public:
112 MemoryLogMessage(const char *file,
113 int line,
114 logging::LogSeverity severity,
115 bool propagate_down);
116 ~MemoryLogMessage();
117
118 std::ostream &stream() { return stream_; }
119
120 private:
Christopher Wiley5781aa42012-07-30 14:42:23 -0700121 const char *file_;
122 const int line_;
123 const logging::LogSeverity severity_;
124 bool propagate_down_;
125 std::ostringstream stream_;
126 size_t message_start_;
127
128 void Init();
129
130 DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryLogMessage);
131};
132
133} // namespace shill
134
135#endif // SHILL_MEMORY_LOG_H_