xref: /aosp_15_r20/external/webrtc/sdk/objc/api/peerconnection/RTCFileLogger.mm (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker/*
2*d9f75844SAndroid Build Coastguard Worker *  Copyright 2015 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker#import "RTCFileLogger.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker#include <memory>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker#include "rtc_base/checks.h"
16*d9f75844SAndroid Build Coastguard Worker#include "rtc_base/file_rotating_stream.h"
17*d9f75844SAndroid Build Coastguard Worker#include "rtc_base/log_sinks.h"
18*d9f75844SAndroid Build Coastguard Worker#include "rtc_base/logging.h"
19*d9f75844SAndroid Build Coastguard Worker
20*d9f75844SAndroid Build Coastguard WorkerNSString *const kDefaultLogDirName = @"webrtc_logs";
21*d9f75844SAndroid Build Coastguard WorkerNSUInteger const kDefaultMaxFileSize = 10 * 1024 * 1024; // 10MB.
22*d9f75844SAndroid Build Coastguard Workerconst char *kRTCFileLoggerRotatingLogPrefix = "rotating_log";
23*d9f75844SAndroid Build Coastguard Worker
24*d9f75844SAndroid Build Coastguard Worker@implementation RTC_OBJC_TYPE (RTCFileLogger) {
25*d9f75844SAndroid Build Coastguard Worker  BOOL _hasStarted;
26*d9f75844SAndroid Build Coastguard Worker  NSString *_dirPath;
27*d9f75844SAndroid Build Coastguard Worker  NSUInteger _maxFileSize;
28*d9f75844SAndroid Build Coastguard Worker  std::unique_ptr<rtc::FileRotatingLogSink> _logSink;
29*d9f75844SAndroid Build Coastguard Worker}
30*d9f75844SAndroid Build Coastguard Worker
31*d9f75844SAndroid Build Coastguard Worker@synthesize severity = _severity;
32*d9f75844SAndroid Build Coastguard Worker@synthesize rotationType = _rotationType;
33*d9f75844SAndroid Build Coastguard Worker@synthesize shouldDisableBuffering = _shouldDisableBuffering;
34*d9f75844SAndroid Build Coastguard Worker
35*d9f75844SAndroid Build Coastguard Worker- (instancetype)init {
36*d9f75844SAndroid Build Coastguard Worker  NSArray *paths = NSSearchPathForDirectoriesInDomains(
37*d9f75844SAndroid Build Coastguard Worker      NSDocumentDirectory, NSUserDomainMask, YES);
38*d9f75844SAndroid Build Coastguard Worker  NSString *documentsDirPath = [paths firstObject];
39*d9f75844SAndroid Build Coastguard Worker  NSString *defaultDirPath =
40*d9f75844SAndroid Build Coastguard Worker      [documentsDirPath stringByAppendingPathComponent:kDefaultLogDirName];
41*d9f75844SAndroid Build Coastguard Worker  return [self initWithDirPath:defaultDirPath
42*d9f75844SAndroid Build Coastguard Worker                   maxFileSize:kDefaultMaxFileSize];
43*d9f75844SAndroid Build Coastguard Worker}
44*d9f75844SAndroid Build Coastguard Worker
45*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithDirPath:(NSString *)dirPath
46*d9f75844SAndroid Build Coastguard Worker                    maxFileSize:(NSUInteger)maxFileSize {
47*d9f75844SAndroid Build Coastguard Worker  return [self initWithDirPath:dirPath
48*d9f75844SAndroid Build Coastguard Worker                   maxFileSize:maxFileSize
49*d9f75844SAndroid Build Coastguard Worker                  rotationType:RTCFileLoggerTypeCall];
50*d9f75844SAndroid Build Coastguard Worker}
51*d9f75844SAndroid Build Coastguard Worker
52*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithDirPath:(NSString *)dirPath
53*d9f75844SAndroid Build Coastguard Worker                    maxFileSize:(NSUInteger)maxFileSize
54*d9f75844SAndroid Build Coastguard Worker                   rotationType:(RTCFileLoggerRotationType)rotationType {
55*d9f75844SAndroid Build Coastguard Worker  NSParameterAssert(dirPath.length);
56*d9f75844SAndroid Build Coastguard Worker  NSParameterAssert(maxFileSize);
57*d9f75844SAndroid Build Coastguard Worker  if (self = [super init]) {
58*d9f75844SAndroid Build Coastguard Worker    BOOL isDir = NO;
59*d9f75844SAndroid Build Coastguard Worker    NSFileManager *fileManager = [NSFileManager defaultManager];
60*d9f75844SAndroid Build Coastguard Worker    if ([fileManager fileExistsAtPath:dirPath isDirectory:&isDir]) {
61*d9f75844SAndroid Build Coastguard Worker      if (!isDir) {
62*d9f75844SAndroid Build Coastguard Worker        // Bail if something already exists there.
63*d9f75844SAndroid Build Coastguard Worker        return nil;
64*d9f75844SAndroid Build Coastguard Worker      }
65*d9f75844SAndroid Build Coastguard Worker    } else {
66*d9f75844SAndroid Build Coastguard Worker      if (![fileManager createDirectoryAtPath:dirPath
67*d9f75844SAndroid Build Coastguard Worker                  withIntermediateDirectories:NO
68*d9f75844SAndroid Build Coastguard Worker                                   attributes:nil
69*d9f75844SAndroid Build Coastguard Worker                                        error:nil]) {
70*d9f75844SAndroid Build Coastguard Worker        // Bail if we failed to create a directory.
71*d9f75844SAndroid Build Coastguard Worker        return nil;
72*d9f75844SAndroid Build Coastguard Worker      }
73*d9f75844SAndroid Build Coastguard Worker    }
74*d9f75844SAndroid Build Coastguard Worker    _dirPath = dirPath;
75*d9f75844SAndroid Build Coastguard Worker    _maxFileSize = maxFileSize;
76*d9f75844SAndroid Build Coastguard Worker    _severity = RTCFileLoggerSeverityInfo;
77*d9f75844SAndroid Build Coastguard Worker  }
78*d9f75844SAndroid Build Coastguard Worker  return self;
79*d9f75844SAndroid Build Coastguard Worker}
80*d9f75844SAndroid Build Coastguard Worker
81*d9f75844SAndroid Build Coastguard Worker- (void)dealloc {
82*d9f75844SAndroid Build Coastguard Worker  [self stop];
83*d9f75844SAndroid Build Coastguard Worker}
84*d9f75844SAndroid Build Coastguard Worker
85*d9f75844SAndroid Build Coastguard Worker- (void)start {
86*d9f75844SAndroid Build Coastguard Worker  if (_hasStarted) {
87*d9f75844SAndroid Build Coastguard Worker    return;
88*d9f75844SAndroid Build Coastguard Worker  }
89*d9f75844SAndroid Build Coastguard Worker  switch (_rotationType) {
90*d9f75844SAndroid Build Coastguard Worker    case RTCFileLoggerTypeApp:
91*d9f75844SAndroid Build Coastguard Worker      _logSink.reset(
92*d9f75844SAndroid Build Coastguard Worker          new rtc::FileRotatingLogSink(_dirPath.UTF8String,
93*d9f75844SAndroid Build Coastguard Worker                                       kRTCFileLoggerRotatingLogPrefix,
94*d9f75844SAndroid Build Coastguard Worker                                       _maxFileSize,
95*d9f75844SAndroid Build Coastguard Worker                                       _maxFileSize / 10));
96*d9f75844SAndroid Build Coastguard Worker      break;
97*d9f75844SAndroid Build Coastguard Worker    case RTCFileLoggerTypeCall:
98*d9f75844SAndroid Build Coastguard Worker      _logSink.reset(
99*d9f75844SAndroid Build Coastguard Worker          new rtc::CallSessionFileRotatingLogSink(_dirPath.UTF8String,
100*d9f75844SAndroid Build Coastguard Worker                                                  _maxFileSize));
101*d9f75844SAndroid Build Coastguard Worker      break;
102*d9f75844SAndroid Build Coastguard Worker  }
103*d9f75844SAndroid Build Coastguard Worker  if (!_logSink->Init()) {
104*d9f75844SAndroid Build Coastguard Worker    RTC_LOG(LS_ERROR) << "Failed to open log files at path: " << _dirPath.UTF8String;
105*d9f75844SAndroid Build Coastguard Worker    _logSink.reset();
106*d9f75844SAndroid Build Coastguard Worker    return;
107*d9f75844SAndroid Build Coastguard Worker  }
108*d9f75844SAndroid Build Coastguard Worker  if (_shouldDisableBuffering) {
109*d9f75844SAndroid Build Coastguard Worker    _logSink->DisableBuffering();
110*d9f75844SAndroid Build Coastguard Worker  }
111*d9f75844SAndroid Build Coastguard Worker  rtc::LogMessage::LogThreads(true);
112*d9f75844SAndroid Build Coastguard Worker  rtc::LogMessage::LogTimestamps(true);
113*d9f75844SAndroid Build Coastguard Worker  rtc::LogMessage::AddLogToStream(_logSink.get(), [self rtcSeverity]);
114*d9f75844SAndroid Build Coastguard Worker  _hasStarted = YES;
115*d9f75844SAndroid Build Coastguard Worker}
116*d9f75844SAndroid Build Coastguard Worker
117*d9f75844SAndroid Build Coastguard Worker- (void)stop {
118*d9f75844SAndroid Build Coastguard Worker  if (!_hasStarted) {
119*d9f75844SAndroid Build Coastguard Worker    return;
120*d9f75844SAndroid Build Coastguard Worker  }
121*d9f75844SAndroid Build Coastguard Worker  RTC_DCHECK(_logSink);
122*d9f75844SAndroid Build Coastguard Worker  rtc::LogMessage::RemoveLogToStream(_logSink.get());
123*d9f75844SAndroid Build Coastguard Worker  _hasStarted = NO;
124*d9f75844SAndroid Build Coastguard Worker  _logSink.reset();
125*d9f75844SAndroid Build Coastguard Worker}
126*d9f75844SAndroid Build Coastguard Worker
127*d9f75844SAndroid Build Coastguard Worker- (nullable NSData *)logData {
128*d9f75844SAndroid Build Coastguard Worker  if (_hasStarted) {
129*d9f75844SAndroid Build Coastguard Worker    return nil;
130*d9f75844SAndroid Build Coastguard Worker  }
131*d9f75844SAndroid Build Coastguard Worker  NSMutableData* logData = [NSMutableData data];
132*d9f75844SAndroid Build Coastguard Worker  std::unique_ptr<rtc::FileRotatingStreamReader> stream;
133*d9f75844SAndroid Build Coastguard Worker  switch(_rotationType) {
134*d9f75844SAndroid Build Coastguard Worker    case RTCFileLoggerTypeApp:
135*d9f75844SAndroid Build Coastguard Worker      stream = std::make_unique<rtc::FileRotatingStreamReader>(_dirPath.UTF8String,
136*d9f75844SAndroid Build Coastguard Worker                                                               kRTCFileLoggerRotatingLogPrefix);
137*d9f75844SAndroid Build Coastguard Worker      break;
138*d9f75844SAndroid Build Coastguard Worker    case RTCFileLoggerTypeCall:
139*d9f75844SAndroid Build Coastguard Worker      stream = std::make_unique<rtc::CallSessionFileRotatingStreamReader>(_dirPath.UTF8String);
140*d9f75844SAndroid Build Coastguard Worker      break;
141*d9f75844SAndroid Build Coastguard Worker  }
142*d9f75844SAndroid Build Coastguard Worker  size_t bufferSize = stream->GetSize();
143*d9f75844SAndroid Build Coastguard Worker  if (bufferSize == 0) {
144*d9f75844SAndroid Build Coastguard Worker    return logData;
145*d9f75844SAndroid Build Coastguard Worker  }
146*d9f75844SAndroid Build Coastguard Worker  // Allocate memory using malloc so we can pass it direcly to NSData without
147*d9f75844SAndroid Build Coastguard Worker  // copying.
148*d9f75844SAndroid Build Coastguard Worker  std::unique_ptr<uint8_t[]> buffer(static_cast<uint8_t*>(malloc(bufferSize)));
149*d9f75844SAndroid Build Coastguard Worker  size_t read = stream->ReadAll(buffer.get(), bufferSize);
150*d9f75844SAndroid Build Coastguard Worker  logData = [[NSMutableData alloc] initWithBytesNoCopy:buffer.release()
151*d9f75844SAndroid Build Coastguard Worker                                                length:read];
152*d9f75844SAndroid Build Coastguard Worker  return logData;
153*d9f75844SAndroid Build Coastguard Worker}
154*d9f75844SAndroid Build Coastguard Worker
155*d9f75844SAndroid Build Coastguard Worker#pragma mark - Private
156*d9f75844SAndroid Build Coastguard Worker
157*d9f75844SAndroid Build Coastguard Worker- (rtc::LoggingSeverity)rtcSeverity {
158*d9f75844SAndroid Build Coastguard Worker  switch (_severity) {
159*d9f75844SAndroid Build Coastguard Worker    case RTCFileLoggerSeverityVerbose:
160*d9f75844SAndroid Build Coastguard Worker      return rtc::LS_VERBOSE;
161*d9f75844SAndroid Build Coastguard Worker    case RTCFileLoggerSeverityInfo:
162*d9f75844SAndroid Build Coastguard Worker      return rtc::LS_INFO;
163*d9f75844SAndroid Build Coastguard Worker    case RTCFileLoggerSeverityWarning:
164*d9f75844SAndroid Build Coastguard Worker      return rtc::LS_WARNING;
165*d9f75844SAndroid Build Coastguard Worker    case RTCFileLoggerSeverityError:
166*d9f75844SAndroid Build Coastguard Worker      return rtc::LS_ERROR;
167*d9f75844SAndroid Build Coastguard Worker  }
168*d9f75844SAndroid Build Coastguard Worker}
169*d9f75844SAndroid Build Coastguard Worker
170*d9f75844SAndroid Build Coastguard Worker@end
171