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

Unified Diff: talk/app/webrtc/objc/RTCFileLogger.mm

Issue 1217473011: AppRTCDemo file logging. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Rebase 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | talk/app/webrtc/objc/public/RTCFileLogger.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: talk/app/webrtc/objc/RTCFileLogger.mm
diff --git a/talk/app/webrtc/objc/RTCFileLogger.mm b/talk/app/webrtc/objc/RTCFileLogger.mm
new file mode 100644
index 0000000000000000000000000000000000000000..b474d7a5c65dec7f9b0673300998980009e93b4c
--- /dev/null
+++ b/talk/app/webrtc/objc/RTCFileLogger.mm
@@ -0,0 +1,230 @@
+/*
+ * libjingle
+ * Copyright 2015 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "RTCFileLogger.h"
+
+#include "webrtc/base/checks.h"
+#include "webrtc/base/logging.h"
+#include "webrtc/base/scoped_ptr.h"
+#include "webrtc/base/stream.h"
+
+NSString *const kDefaultLogFileName = @"webrtc.log";
+NSUInteger const kDefaultMaxFileSize = 10 * 1024 * 1024; // 10MB.
+
+namespace rtc {
+
+class CircularFileStreamLogSink : public LogSink {
+ public:
+ // Creates a log sink that writes to the given stream. This log sink takes
+ // ownership of |stream|.
+ CircularFileStreamLogSink(CircularFileStream *stream) {
+ DCHECK(stream);
+ _stream.reset(stream);
+ }
+
+ ~CircularFileStreamLogSink() override {}
+
+ void OnLogMessage(const std::string &message) override {
+ if (_stream) {
+ _stream->WriteAll(message.data(), message.size(), nullptr, nullptr);
+ }
+ }
+
+ CircularFileStream *GetStream() { return _stream.get(); }
+
+ private:
+ scoped_ptr<CircularFileStream> _stream;
+};
+
+} // namespace rtc
+
+@implementation RTCFileLogger {
+ BOOL _hasStarted;
+ NSString *_filePath;
+ NSUInteger _maxFileSize;
+ rtc::scoped_ptr<rtc::CircularFileStreamLogSink> _logSink;
+}
+
+@synthesize severity = _severity;
+
+- (instancetype)init {
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(
+ NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString *documentsDirPath = [paths firstObject];
+ NSString *defaultFilePath =
+ [documentsDirPath stringByAppendingPathComponent:kDefaultLogFileName];
+ return [self initWithFilePath:defaultFilePath
+ maxFileSize:kDefaultMaxFileSize];
+}
+
+- (instancetype)initWithFilePath:(NSString *)filePath
+ maxFileSize:(NSUInteger)maxFileSize {
+ NSParameterAssert(filePath.length);
+ NSParameterAssert(maxFileSize);
+ if (self = [super init]) {
+ _filePath = filePath;
+ _maxFileSize = maxFileSize;
+ _severity = kRTCFileLoggerSeverityInfo;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [self stop];
+}
+
+- (void)start {
+ if (_hasStarted) {
+ return;
+ }
+ rtc::scoped_ptr<rtc::CircularFileStream> stream;
+ stream.reset(new rtc::CircularFileStream(_maxFileSize));
+ _logSink.reset(new rtc::CircularFileStreamLogSink(stream.release()));
+ int error = 0;
+ if (!_logSink->GetStream()->Open(_filePath.UTF8String, "wb", &error)) {
+ LOG(LS_ERROR) << "Failed to open log file at path: "
+ << _filePath.UTF8String
+ << " Error: "
+ << error;
+ _logSink.reset();
+ return;
+ }
+ // TODO(tkchin): Log thead info on iOS, currently this doesn't do anything.
henrika_webrtc 2015/07/15 08:36:01 It actually does now :-) Please try it out.
+ rtc::LogMessage::LogThreads(true);
+ rtc::LogMessage::LogTimestamps(true);
+ rtc::LogMessage::AddLogToStream(_logSink.get(), [self rtcSeverity]);
+ _hasStarted = YES;
+}
+
+- (void)stop {
+ if (!_hasStarted) {
+ return;
+ }
+ DCHECK(_logSink);
+ rtc::LogMessage::RemoveLogToStream(_logSink.get());
+ _hasStarted = NO;
+
+ // Read the ordered version of the log.
+ NSData *logData = [self reorderedLogData];
+ NSError *error = nil;
+ // Write the ordered version back to disk.
+ if (![logData writeToFile:_filePath
+ options:NSDataWritingAtomic
+ error:&error]) {
+ LOG(LS_ERROR) << "Failed to rewrite log to disk at path: "
+ << _filePath.UTF8String;
+ if (error) {
+ LOG(LS_ERROR) << "Error: " << error.localizedDescription.UTF8String;
+ }
+ } else {
+ // If we succeeded in writing to disk we don't need to hold on to the
+ // stream anymore.
+ _logSink.reset();
+ }
+}
+
+- (NSData *)logData {
+ if (_hasStarted) {
+ return nil;
+ }
+ if (!_logSink.get()) {
+ // If there isn't a previously used stream just return contents of file.
+ return [[self class] contentsOfFileAtPath:_filePath];
+ }
+ return [self reorderedLogData];
+}
+
+#pragma mark - Private
+
++ (NSData *)contentsOfFileAtPath:(NSString *)path {
+ NSError *error = nil;
+ NSData *contents = [NSData dataWithContentsOfFile:path
+ options:0
+ error:&error];
+ if (error) {
+ LOG(LS_ERROR) << "Failed to read contents of file at path: "
+ << path.UTF8String
+ << " Error: "
+ << error.localizedDescription.UTF8String;
+ return nil;
+ }
+ return contents;
+}
+
+- (NSData *)reorderedLogData {
+ if (_hasStarted || !_logSink.get()) {
+ return nil;
+ }
+ // We have a stream we used for writing in memory and we're not writing. The
+ // stream has a pointer to where the log boundary is so it can reorder the
+ // log correctly. We just need to reopen the file in read mode.
+ int error = 0;
+ rtc::CircularFileStream *stream = _logSink->GetStream();
+ if (!stream->Open(_filePath.UTF8String, "r", &error)) {
+ LOG(LS_ERROR) << "Failed to open log file at path: "
+ << _filePath.UTF8String
+ << " Error: "
+ << error;
+ return nil;
+ }
+ size_t logSize = 0;
+ size_t bytesRead = 0;
+ error = 0;
+ if (!stream->GetSize(&logSize)) {
+ LOG(LS_ERROR) << "Failed to get log file size.";
+ return nil;
+ }
+ // Allocate memory using malloc so we can pass it direcly to NSData without
+ // copying.
+ rtc::scoped_ptr<uint8_t[]> buffer(static_cast<uint8_t*>(malloc(logSize)));
+ if (stream->ReadAll(buffer.get(), logSize, &bytesRead, &error)
+ != rtc::SR_SUCCESS) {
+ LOG(LS_ERROR) << "Failed to read log file at path: "
+ << _filePath.UTF8String
+ << " Error: "
+ << error;
+ }
+ DCHECK_LE(bytesRead, logSize);
+ // NSData takes ownership of the bytes and frees it on dealloc.
+ return [NSData dataWithBytesNoCopy:buffer.release()
+ length:bytesRead];
+}
+
+- (rtc::LoggingSeverity)rtcSeverity {
+ switch (_severity) {
+ case kRTCFileLoggerSeverityVerbose:
+ return rtc::LS_VERBOSE;
+ case kRTCFileLoggerSeverityInfo:
+ return rtc::LS_INFO;
+ case kRTCFileLoggerSeverityWarning:
+ return rtc::LS_WARNING;
+ case kRTCFileLoggerSeverityError:
+ return rtc::LS_ERROR;
+ }
+}
+
+@end
« 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