OLD | NEW |
| (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/filerotatingstream.h" | |
32 #include "webrtc/base/logging.h" | |
33 #include "webrtc/base/logsinks.h" | |
34 #include "webrtc/base/scoped_ptr.h" | |
35 | |
36 NSString *const kDefaultLogDirName = @"webrtc_logs"; | |
37 NSUInteger const kDefaultMaxFileSize = 10 * 1024 * 1024; // 10MB. | |
38 const char *kRTCFileLoggerRotatingLogPrefix = "rotating_log"; | |
39 | |
40 @implementation RTCFileLogger { | |
41 BOOL _hasStarted; | |
42 NSString *_dirPath; | |
43 NSUInteger _maxFileSize; | |
44 rtc::scoped_ptr<rtc::FileRotatingLogSink> _logSink; | |
45 } | |
46 | |
47 @synthesize severity = _severity; | |
48 @synthesize rotationType = _rotationType; | |
49 @synthesize shouldDisableBuffering = _shouldDisableBuffering; | |
50 | |
51 - (instancetype)init { | |
52 NSArray *paths = NSSearchPathForDirectoriesInDomains( | |
53 NSDocumentDirectory, NSUserDomainMask, YES); | |
54 NSString *documentsDirPath = [paths firstObject]; | |
55 NSString *defaultDirPath = | |
56 [documentsDirPath stringByAppendingPathComponent:kDefaultLogDirName]; | |
57 return [self initWithDirPath:defaultDirPath | |
58 maxFileSize:kDefaultMaxFileSize]; | |
59 } | |
60 | |
61 - (instancetype)initWithDirPath:(NSString *)dirPath | |
62 maxFileSize:(NSUInteger)maxFileSize { | |
63 return [self initWithDirPath:dirPath | |
64 maxFileSize:maxFileSize | |
65 rotationType:kRTCFileLoggerTypeCall]; | |
66 } | |
67 | |
68 - (instancetype)initWithDirPath:(NSString *)dirPath | |
69 maxFileSize:(NSUInteger)maxFileSize | |
70 rotationType:(RTCFileLoggerRotationType)rotationType { | |
71 NSParameterAssert(dirPath.length); | |
72 NSParameterAssert(maxFileSize); | |
73 if (self = [super init]) { | |
74 BOOL isDir = NO; | |
75 NSFileManager *fileManager = [NSFileManager defaultManager]; | |
76 if ([fileManager fileExistsAtPath:dirPath isDirectory:&isDir]) { | |
77 if (!isDir) { | |
78 // Bail if something already exists there. | |
79 return nil; | |
80 } | |
81 } else { | |
82 if (![fileManager createDirectoryAtPath:dirPath | |
83 withIntermediateDirectories:NO | |
84 attributes:nil | |
85 error:nil]) { | |
86 // Bail if we failed to create a directory. | |
87 return nil; | |
88 } | |
89 } | |
90 _dirPath = dirPath; | |
91 _maxFileSize = maxFileSize; | |
92 _severity = kRTCFileLoggerSeverityInfo; | |
93 } | |
94 return self; | |
95 } | |
96 | |
97 - (void)dealloc { | |
98 [self stop]; | |
99 } | |
100 | |
101 - (void)start { | |
102 if (_hasStarted) { | |
103 return; | |
104 } | |
105 switch (_rotationType) { | |
106 case kRTCFileLoggerTypeApp: | |
107 _logSink.reset( | |
108 new rtc::FileRotatingLogSink(_dirPath.UTF8String, | |
109 kRTCFileLoggerRotatingLogPrefix, | |
110 _maxFileSize, | |
111 _maxFileSize / 10)); | |
112 break; | |
113 case kRTCFileLoggerTypeCall: | |
114 _logSink.reset( | |
115 new rtc::CallSessionFileRotatingLogSink(_dirPath.UTF8String, | |
116 _maxFileSize)); | |
117 break; | |
118 } | |
119 if (!_logSink->Init()) { | |
120 LOG(LS_ERROR) << "Failed to open log files at path: " | |
121 << _dirPath.UTF8String; | |
122 _logSink.reset(); | |
123 return; | |
124 } | |
125 if (_shouldDisableBuffering) { | |
126 _logSink->DisableBuffering(); | |
127 } | |
128 rtc::LogMessage::LogThreads(true); | |
129 rtc::LogMessage::LogTimestamps(true); | |
130 rtc::LogMessage::AddLogToStream(_logSink.get(), [self rtcSeverity]); | |
131 _hasStarted = YES; | |
132 } | |
133 | |
134 - (void)stop { | |
135 if (!_hasStarted) { | |
136 return; | |
137 } | |
138 RTC_DCHECK(_logSink); | |
139 rtc::LogMessage::RemoveLogToStream(_logSink.get()); | |
140 _hasStarted = NO; | |
141 _logSink.reset(); | |
142 } | |
143 | |
144 - (NSData *)logData { | |
145 if (_hasStarted) { | |
146 return nil; | |
147 } | |
148 NSMutableData* logData = [NSMutableData data]; | |
149 rtc::scoped_ptr<rtc::FileRotatingStream> stream; | |
150 switch(_rotationType) { | |
151 case kRTCFileLoggerTypeApp: | |
152 stream.reset( | |
153 new rtc::FileRotatingStream(_dirPath.UTF8String, | |
154 kRTCFileLoggerRotatingLogPrefix)); | |
155 break; | |
156 case kRTCFileLoggerTypeCall: | |
157 stream.reset(new rtc::CallSessionFileRotatingStream(_dirPath.UTF8String)); | |
158 break; | |
159 } | |
160 if (!stream->Open()) { | |
161 return logData; | |
162 } | |
163 size_t bufferSize = 0; | |
164 if (!stream->GetSize(&bufferSize) || bufferSize == 0) { | |
165 return logData; | |
166 } | |
167 size_t read = 0; | |
168 // Allocate memory using malloc so we can pass it direcly to NSData without | |
169 // copying. | |
170 rtc::scoped_ptr<uint8_t[]> buffer(static_cast<uint8_t*>(malloc(bufferSize))); | |
171 stream->ReadAll(buffer.get(), bufferSize, &read, nullptr); | |
172 logData = [[NSMutableData alloc] initWithBytesNoCopy:buffer.release() | |
173 length:read]; | |
174 return logData; | |
175 } | |
176 | |
177 #pragma mark - Private | |
178 | |
179 - (rtc::LoggingSeverity)rtcSeverity { | |
180 switch (_severity) { | |
181 case kRTCFileLoggerSeverityVerbose: | |
182 return rtc::LS_VERBOSE; | |
183 case kRTCFileLoggerSeverityInfo: | |
184 return rtc::LS_INFO; | |
185 case kRTCFileLoggerSeverityWarning: | |
186 return rtc::LS_WARNING; | |
187 case kRTCFileLoggerSeverityError: | |
188 return rtc::LS_ERROR; | |
189 } | |
190 } | |
191 | |
192 @end | |
OLD | NEW |