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

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

Issue 1217473011: AppRTCDemo file logging. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Cleanup 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') | webrtc/base/stream.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * libjingle
3 * Copyright 2015 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
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,
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
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #import "RTCFileLogger.h"
29
30 #include "webrtc/base/checks.h"
31 #include "webrtc/base/logging.h"
32 #include "webrtc/base/scoped_ptr.h"
33 #include "webrtc/base/stream.h"
34
35 NSString *const kDefaultLogFileName = @"webrtc.log";
36 NSUInteger const kDefaultMaxFileSize = 10 * 1024 * 1024; // 10MB.
37
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 {
66 BOOL _hasStarted;
67 NSString *_filePath;
68 NSUInteger _maxFileSize;
69 rtc::scoped_ptr<rtc::CircularFileStreamLogSink> _logSink;
70 }
71
72 @synthesize severity = _severity;
73
74 - (instancetype)init {
75 NSArray *paths = NSSearchPathForDirectoriesInDomains(
76 NSDocumentDirectory, NSUserDomainMask, YES);
77 NSString *documentsDirPath = [paths firstObject];
78 NSString *defaultFilePath =
79 [documentsDirPath stringByAppendingPathComponent:kDefaultLogFileName];
80 return [self initWithFilePath:defaultFilePath
81 maxFileSize:kDefaultMaxFileSize];
82 }
83
84 - (instancetype)initWithFilePath:(NSString *)filePath
85 maxFileSize:(NSUInteger)maxFileSize {
86 NSParameterAssert(filePath.length);
87 NSParameterAssert(maxFileSize);
88 if (self = [super init]) {
89 _filePath = filePath;
90 _maxFileSize = maxFileSize;
91 }
92 return self;
93 }
94
95 - (void)dealloc {
96 [self stop];
97 }
98
99 - (void)start {
100 if (_hasStarted) {
101 return;
102 }
103 rtc::scoped_ptr<rtc::CircularFileStream> stream;
104 stream.reset(new rtc::CircularFileStream(_maxFileSize));
105 _logSink.reset(new rtc::CircularFileStreamLogSink(stream.release()));
106 int error = 0;
107 if (!_logSink->GetStream()->Open(_filePath.UTF8String, "wb", &error)) {
108 LOG(LS_ERROR) << "Failed to open log file at path: "
109 << _filePath.UTF8String
110 << " Error: "
111 << error;
112 _logSink.reset();
113 return;
114 }
115 // TODO(tkchin): Log thead info on iOS, currently this doesn't do anything.
116 rtc::LogMessage::LogThreads(true);
117 rtc::LogMessage::LogTimestamps(true);
118 rtc::LogMessage::AddLogToStream(_logSink.get(), [self rtcSeverity]);
119 _hasStarted = YES;
120 }
121
122 - (void)stop {
123 if (!_hasStarted) {
124 return;
125 }
126 DCHECK(_logSink);
127 rtc::LogMessage::RemoveLogToStream(_logSink.get());
128 _hasStarted = NO;
129
130 // Read the ordered version of the log.
131 NSData *logData = [self reorderedLogData];
132 NSError *error = nil;
133 // Write the ordered version back to disk.
134 if (![logData writeToFile:_filePath
135 options:NSDataWritingAtomic
136 error:&error]) {
137 LOG(LS_ERROR) << "Failed to rewrite log to disk at path: "
138 << _filePath.UTF8String;
139 if (error) {
140 LOG(LS_ERROR) << "Error: " << error.localizedDescription.UTF8String;
141 }
142 } else {
143 // If we succeeded in writing to disk we don't need to hold on to the
144 // stream anymore.
145 _logSink.reset();
146 }
147 }
148
149 - (NSData *)logData {
150 if (_hasStarted) {
151 return nil;
152 }
153 if (!_logSink.get()) {
154 // If there isn't a previously used stream just return contents of file.
155 return [[self class] contentsOfFileAtPath:_filePath];
156 }
157 return [self reorderedLogData];
158 }
159
160 #pragma mark - Private
161
162 + (NSData *)contentsOfFileAtPath:(NSString *)path {
163 NSError *error = nil;
164 NSData *contents = [NSData dataWithContentsOfFile:path
165 options:0
166 error:&error];
167 if (error) {
168 LOG(LS_ERROR) << "Failed to read contents of file at path: "
169 << path.UTF8String
170 << " Error: "
171 << error.localizedDescription.UTF8String;
172 return nil;
173 }
174 return contents;
175 }
176
177 - (NSData *)reorderedLogData {
178 if (_hasStarted || !_logSink.get()) {
179 return nil;
180 }
181 // We have a stream we used for writing in memory and we're not writing. The
182 // stream has a pointer to where the log boundary is so it can reorder the
183 // log correctly. We just need to reopen the file in read mode.
184 int error = 0;
185 rtc::CircularFileStream *stream = _logSink->GetStream();
186 if (!stream->Open(_filePath.UTF8String, "r", &error)) {
187 LOG(LS_ERROR) << "Failed to open log file at path: "
188 << _filePath.UTF8String
189 << " Error: "
190 << error;
191 return nil;
192 }
193 size_t logSize = 0;
194 size_t bytesRead = 0;
195 error = 0;
196 if (!stream->GetSize(&logSize)) {
197 LOG(LS_ERROR) << "Failed to get log file size.";
198 return nil;
199 }
200 // Allocate memory using malloc so we can pass it direcly to NSData without
201 // copying.
202 rtc::scoped_ptr<uint8_t[]> buffer(static_cast<uint8_t*>(malloc(logSize)));
203 if (stream->ReadAll(buffer.get(), logSize, &bytesRead, &error)
204 != rtc::SR_SUCCESS) {
205 LOG(LS_ERROR) << "Failed to read log file at path: "
206 << _filePath.UTF8String
207 << " Error: "
208 << error;
209 }
210 DCHECK_LE(bytesRead, logSize);
211 // NSData takes ownership of the bytes and frees it on dealloc.
212 return [NSData dataWithBytesNoCopy:buffer.release()
213 length:bytesRead];
214 }
215
216 - (rtc::LoggingSeverity)rtcSeverity {
217 switch (_severity) {
218 case kRTCFileLoggerSeverityVerbose:
219 return rtc::LS_VERBOSE;
220 case kRTCFileLoggerSeverityInfo:
221 return rtc::LS_INFO;
222 case kRTCFileLoggerSeverityWarning:
223 return rtc::LS_WARNING;
224 case kRTCFileLoggerSeverityError:
225 return rtc::LS_ERROR;
226 }
227 }
228
229 @end
OLDNEW
« no previous file with comments | « no previous file | talk/app/webrtc/objc/public/RTCFileLogger.h » ('j') | webrtc/base/stream.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698