Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(296)

Side by Side Diff: talk/app/webrtc/objc/RTCFileLogger.mm

Issue 1245143005: Remove CircularFileStream / replace it with CallSessionFileRotatingStream. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | talk/app/webrtc/objc/public/RTCFileLogger.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * libjingle 2 * libjingle
3 * Copyright 2015 Google Inc. 3 * Copyright 2015 Google Inc.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright notice, 8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer. 9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, 10 * 2. Redistributions in binary form must reproduce the above copyright notice,
(...skipping 10 matching lines...) Expand all
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28 #import "RTCFileLogger.h" 28 #import "RTCFileLogger.h"
29 29
30 #include "webrtc/base/checks.h" 30 #include "webrtc/base/checks.h"
31 #include "webrtc/base/filerotatingstream.h"
31 #include "webrtc/base/logging.h" 32 #include "webrtc/base/logging.h"
33 #include "webrtc/base/logsinks.h"
32 #include "webrtc/base/scoped_ptr.h" 34 #include "webrtc/base/scoped_ptr.h"
33 #include "webrtc/base/stream.h"
34 35
35 NSString *const kDefaultLogFileName = @"webrtc.log"; 36 NSString *const kDefaultLogDirName = @"webrtc_logs";
36 NSUInteger const kDefaultMaxFileSize = 10 * 1024 * 1024; // 10MB. 37 NSUInteger const kDefaultMaxFileSize = 10 * 1024 * 1024; // 10MB.
37 38
38 namespace rtc {
39
40 class CircularFileStreamLogSink : public LogSink {
41 public:
42 // Creates a log sink that writes to the given stream. This log sink takes
43 // ownership of |stream|.
44 CircularFileStreamLogSink(CircularFileStream *stream) {
45 DCHECK(stream);
46 _stream.reset(stream);
47 }
48
49 ~CircularFileStreamLogSink() override {}
50
51 void OnLogMessage(const std::string &message) override {
52 if (_stream) {
53 _stream->WriteAll(message.data(), message.size(), nullptr, nullptr);
54 }
55 }
56
57 CircularFileStream *GetStream() { return _stream.get(); }
58
59 private:
60 scoped_ptr<CircularFileStream> _stream;
61 };
62
63 } // namespace rtc
64
65 @implementation RTCFileLogger { 39 @implementation RTCFileLogger {
66 BOOL _hasStarted; 40 BOOL _hasStarted;
67 NSString *_filePath; 41 NSString *_dirPath;
68 NSUInteger _maxFileSize; 42 NSUInteger _maxFileSize;
69 rtc::scoped_ptr<rtc::CircularFileStreamLogSink> _logSink; 43 rtc::scoped_ptr<rtc::CallSessionFileRotatingLogSink> _logSink;
70 } 44 }
71 45
72 @synthesize severity = _severity; 46 @synthesize severity = _severity;
73 47
74 - (instancetype)init { 48 - (instancetype)init {
75 NSArray *paths = NSSearchPathForDirectoriesInDomains( 49 NSArray *paths = NSSearchPathForDirectoriesInDomains(
76 NSDocumentDirectory, NSUserDomainMask, YES); 50 NSDocumentDirectory, NSUserDomainMask, YES);
77 NSString *documentsDirPath = [paths firstObject]; 51 NSString *documentsDirPath = [paths firstObject];
78 NSString *defaultFilePath = 52 NSString *defaultDirPath =
79 [documentsDirPath stringByAppendingPathComponent:kDefaultLogFileName]; 53 [documentsDirPath stringByAppendingPathComponent:kDefaultLogDirName];
80 return [self initWithFilePath:defaultFilePath 54 return [self initWithDirPath:defaultDirPath
81 maxFileSize:kDefaultMaxFileSize]; 55 maxFileSize:kDefaultMaxFileSize];
82 } 56 }
83 57
84 - (instancetype)initWithFilePath:(NSString *)filePath 58 - (instancetype)initWithDirPath:(NSString *)dirPath
85 maxFileSize:(NSUInteger)maxFileSize { 59 maxFileSize:(NSUInteger)maxFileSize {
86 NSParameterAssert(filePath.length); 60 NSParameterAssert(dirPath.length);
87 NSParameterAssert(maxFileSize); 61 NSParameterAssert(maxFileSize);
88 if (self = [super init]) { 62 if (self = [super init]) {
89 _filePath = filePath; 63 BOOL isDir = NO;
64 NSFileManager *fileManager = [NSFileManager defaultManager];
65 if ([fileManager fileExistsAtPath:dirPath isDirectory:&isDir]) {
66 if (!isDir) {
67 // Bail if something already exists there.
68 return nil;
69 }
70 } else {
71 if (![fileManager createDirectoryAtPath:dirPath
72 withIntermediateDirectories:NO
73 attributes:nil
74 error:nil]) {
75 // Bail if we failed to create a directory.
76 return nil;
77 }
78 }
79 _dirPath = dirPath;
90 _maxFileSize = maxFileSize; 80 _maxFileSize = maxFileSize;
91 _severity = kRTCFileLoggerSeverityInfo; 81 _severity = kRTCFileLoggerSeverityInfo;
92 } 82 }
93 return self; 83 return self;
94 } 84 }
95 85
96 - (void)dealloc { 86 - (void)dealloc {
97 [self stop]; 87 [self stop];
98 } 88 }
99 89
100 - (void)start { 90 - (void)start {
101 if (_hasStarted) { 91 if (_hasStarted) {
102 return; 92 return;
103 } 93 }
104 rtc::scoped_ptr<rtc::CircularFileStream> stream; 94 _logSink.reset(new rtc::CallSessionFileRotatingLogSink(_dirPath.UTF8String,
105 stream.reset(new rtc::CircularFileStream(_maxFileSize)); 95 _maxFileSize));
106 _logSink.reset(new rtc::CircularFileStreamLogSink(stream.release())); 96 if (!_logSink->Init()) {
107 int error = 0; 97 LOG(LS_ERROR) << "Failed to open log files at path: "
108 if (!_logSink->GetStream()->Open(_filePath.UTF8String, "wb", &error)) { 98 << _dirPath.UTF8String;
109 LOG(LS_ERROR) << "Failed to open log file at path: "
110 << _filePath.UTF8String
111 << " Error: "
112 << error;
113 _logSink.reset(); 99 _logSink.reset();
114 return; 100 return;
115 } 101 }
116 // TODO(tkchin): Log thead info on iOS, currently this doesn't do anything.
117 rtc::LogMessage::LogThreads(true); 102 rtc::LogMessage::LogThreads(true);
118 rtc::LogMessage::LogTimestamps(true); 103 rtc::LogMessage::LogTimestamps(true);
119 rtc::LogMessage::AddLogToStream(_logSink.get(), [self rtcSeverity]); 104 rtc::LogMessage::AddLogToStream(_logSink.get(), [self rtcSeverity]);
120 _hasStarted = YES; 105 _hasStarted = YES;
121 } 106 }
122 107
123 - (void)stop { 108 - (void)stop {
124 if (!_hasStarted) { 109 if (!_hasStarted) {
125 return; 110 return;
126 } 111 }
127 DCHECK(_logSink); 112 DCHECK(_logSink);
128 rtc::LogMessage::RemoveLogToStream(_logSink.get()); 113 rtc::LogMessage::RemoveLogToStream(_logSink.get());
129 _hasStarted = NO; 114 _hasStarted = NO;
130 115 _logSink.reset();
131 // Read the ordered version of the log.
132 NSData *logData = [self reorderedLogData];
133 NSError *error = nil;
134 // Write the ordered version back to disk.
135 if (![logData writeToFile:_filePath
136 options:NSDataWritingAtomic
137 error:&error]) {
138 LOG(LS_ERROR) << "Failed to rewrite log to disk at path: "
139 << _filePath.UTF8String;
140 if (error) {
141 LOG(LS_ERROR) << "Error: " << error.localizedDescription.UTF8String;
142 }
143 } else {
144 // If we succeeded in writing to disk we don't need to hold on to the
145 // stream anymore.
146 _logSink.reset();
147 }
148 } 116 }
149 117
150 - (NSData *)logData { 118 - (NSData *)logData {
151 if (_hasStarted) { 119 if (_hasStarted) {
152 return nil; 120 return nil;
153 } 121 }
154 if (!_logSink.get()) { 122 NSMutableData* logData = [NSMutableData data];
155 // If there isn't a previously used stream just return contents of file. 123 rtc::scoped_ptr<rtc::CallSessionFileRotatingStream> stream(
156 return [[self class] contentsOfFileAtPath:_filePath]; 124 new rtc::CallSessionFileRotatingStream(_dirPath.UTF8String));
125 if (!stream->Open()) {
126 return logData;
157 } 127 }
158 return [self reorderedLogData]; 128 const size_t bufferSize = 1024;
129 size_t read = 0;
130 rtc::scoped_ptr<uint8_t[]> buffer(new uint8_t[bufferSize]);
131 do {
132 stream->ReadAll(buffer.get(), bufferSize, &read, nullptr);
133 [logData appendBytes:buffer.get() length:read];
134 } while (read > 0);
jiayl2 2015/07/22 21:17:33 Do we need the loop because ReadAll may exit when
tkchin_webrtc 2015/07/22 23:01:39 No, it's because the buffer may be too big or too
jiayl2 2015/07/22 23:35:01 Ah, I see. I think this is fine.
135 return logData;
159 } 136 }
160 137
161 #pragma mark - Private 138 #pragma mark - Private
162 139
163 + (NSData *)contentsOfFileAtPath:(NSString *)path {
164 NSError *error = nil;
165 NSData *contents = [NSData dataWithContentsOfFile:path
166 options:0
167 error:&error];
168 if (error) {
169 LOG(LS_ERROR) << "Failed to read contents of file at path: "
170 << path.UTF8String
171 << " Error: "
172 << error.localizedDescription.UTF8String;
173 return nil;
174 }
175 return contents;
176 }
177
178 - (NSData *)reorderedLogData {
179 if (_hasStarted || !_logSink.get()) {
180 return nil;
181 }
182 // We have a stream we used for writing in memory and we're not writing. The
183 // stream has a pointer to where the log boundary is so it can reorder the
184 // log correctly. We just need to reopen the file in read mode.
185 int error = 0;
186 rtc::CircularFileStream *stream = _logSink->GetStream();
187 if (!stream->Open(_filePath.UTF8String, "r", &error)) {
188 LOG(LS_ERROR) << "Failed to open log file at path: "
189 << _filePath.UTF8String
190 << " Error: "
191 << error;
192 return nil;
193 }
194 size_t logSize = 0;
195 size_t bytesRead = 0;
196 error = 0;
197 if (!stream->GetSize(&logSize)) {
198 LOG(LS_ERROR) << "Failed to get log file size.";
199 return nil;
200 }
201 // Allocate memory using malloc so we can pass it direcly to NSData without
202 // copying.
203 rtc::scoped_ptr<uint8_t[]> buffer(static_cast<uint8_t*>(malloc(logSize)));
204 if (stream->ReadAll(buffer.get(), logSize, &bytesRead, &error)
205 != rtc::SR_SUCCESS) {
206 LOG(LS_ERROR) << "Failed to read log file at path: "
207 << _filePath.UTF8String
208 << " Error: "
209 << error;
210 }
211 DCHECK_LE(bytesRead, logSize);
212 // NSData takes ownership of the bytes and frees it on dealloc.
213 return [NSData dataWithBytesNoCopy:buffer.release()
214 length:bytesRead];
215 }
216
217 - (rtc::LoggingSeverity)rtcSeverity { 140 - (rtc::LoggingSeverity)rtcSeverity {
218 switch (_severity) { 141 switch (_severity) {
219 case kRTCFileLoggerSeverityVerbose: 142 case kRTCFileLoggerSeverityVerbose:
220 return rtc::LS_VERBOSE; 143 return rtc::LS_VERBOSE;
221 case kRTCFileLoggerSeverityInfo: 144 case kRTCFileLoggerSeverityInfo:
222 return rtc::LS_INFO; 145 return rtc::LS_INFO;
223 case kRTCFileLoggerSeverityWarning: 146 case kRTCFileLoggerSeverityWarning:
224 return rtc::LS_WARNING; 147 return rtc::LS_WARNING;
225 case kRTCFileLoggerSeverityError: 148 case kRTCFileLoggerSeverityError:
226 return rtc::LS_ERROR; 149 return rtc::LS_ERROR;
227 } 150 }
228 } 151 }
229 152
230 @end 153 @end
OLDNEW
« no previous file with comments | « no previous file | talk/app/webrtc/objc/public/RTCFileLogger.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698