【问题标题】:Correct way to store logs for iOS为 iOS 存储日志的正确方法
【发布时间】:2015-10-16 10:46:04
【问题描述】:

我有一个 IT 团队将支持的家用应用。 当他们支持桌面应用程序时,他们可能会阅读日志以发现任何问题(例如服务器在同步请求时返回 404)。

我可以在 iOS 上使用 NSLog,但是用户如何在没有 Xcode 的情况下访问它们? 我不能要求任何用户“请给我你的手机来调查发生了什么”。

没有 Xcode 和 Mac 的 IT 人员是否可以使用某种工具来读取 iOS 日志?

【问题讨论】:

  • 使用外包服务器
  • 登录到文件并在您的应用上启用 iTunes 文档共享。

标签: ios logging


【解决方案1】:

没有 Xcode 和 Mac 的 IT 人员是否可以使用某种工具来读取 iOS 日志?

很遗憾没有。过去,您可以在设备上运行一个可以读取控制台日志的应用程序,但 Apple 取消了该功能。我猜他们认为这是安全漏洞。

如果您的用户可以使用运行 Xcode 的 Mac,他们可以直接在 Xcode 中查看控制台日志。

否则,正如其他人所建议的那样,您将不得不在您的应用程序中构建将日志保存在您可以到达的地方的能力。例如,您可以写入文件,然后提供(在应用程序内)将该文件通过电子邮件发送给自己。许多应用在其设置包中都有这样的工具接口。

【讨论】:

    【解决方案2】:

    我在工作中一直在使用CocoaLumberjackAntennaDDAntennalogger 的组合进行远程日志记录。基本上,您必须在服务器上设置一个端点,Antenna 将用于远程发送日志。

    这是在我的项目中配置它时的参考: Remote logging using CocoaLumberjack, Antenna & DDAntennaLogger

    【讨论】:

      【解决方案3】:

      你可以这样做:

      步骤 1: 将您的 NSLog 语句重定向到文件系统中的文本文件。您可以对特定的用户操作执行此操作,或者始终启用它并定期删除它。

      第 2 步:拥有一个网络服务,可让您将保存的日志上传到文件系统中。您可以在用户操作时触发此操作,也可以是基于计时器的作业。

      第 3 步:上传成功后从文件系统中删除日志。

      以下是此类自定义记录器的示例:

      #import "MyCustomLogging.h"
      
      #define kMyCustomLoggingFile @"NSLogging.txt"
      
      static NSString *const kMyDeviceLogUploadURL = @"uploadDeviceLogURL";
      
      @interface MyCustomLogging ()
      
      @property (nonatomic, strong) MyRequestHandler *requestHandler;
      @property (nonatomic, assign, getter = isNsLogRedirected) BOOL nsLogRedirected;
      @property (nonatomic, assign) BOOL shouldStopLogging;
      @property (nonatomic, strong) NSString *pathForLogging;
      
      @end
      
      
      @implementation MyCustomLogging
      
      static int savedStdErr = 0;
      static MyCustomLogging *sharedMyCustomLogging = nil;
      
      
      + (MyCustomLogging *)sharedMyCustomLogging {
          static dispatch_once_t pred = 0;
      
          dispatch_once(&pred, ^{
              sharedMyCustomLogging = [[self alloc] init];
          });
      
          return sharedMyCustomLogging;
      }
      
      
      #pragma mark -
      #pragma mark Start Method
      
      - (void)startLogging {
          // Starting the Redirection of the Logs
          if (!self.isNsLogRedirected) {
              [self nsLogRedirectedToFile];
          }
      }
      
      
      #pragma mark -
      #pragma mark Stop Method
      
      - (void)stopLogging {
          NSLog(@"Stopping the logging");
          NSString *aLoggingPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
          self.pathForLogging = [aLoggingPath stringByAppendingPathComponent:kMyCustomLoggingFile];
      
          // If file already exists & logging was not redirected then directly upload the logs::A Possible case of app quit/crash without uploading previous logs
          if ([self isLogFilePresent] && !self.nsLogRedirected) {
              [self uploadLogs];
          } else if (self.isNsLogRedirected) { //Check for Successive  Stop Notifications
              self.shouldStopLogging = YES;
              [self restoreNSLog];
          } else {
              NSDictionary *anUserInfo = @{kMyDeviceLogUplodStatusKey: kMyValueOne};
              [[NSNotificationCenter defaultCenter] postNotificationName:kMyDeviceLogsUploadNotification object:nil userInfo:anUserInfo];
          }
      }
      
      
      #pragma mark -
      #pragma mark Private Method
      
      - (void)nsLogRedirectedToFile {
          if (!self.isNsLogRedirected) {
              NSLog(@"Redirecting NSLogs to a file.....");
              self.nsLogRedirected = YES;
              savedStdErr = dup(STDERR_FILENO);
      
              NSString *aLoggingPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
              self.pathForLogging = [aLoggingPath stringByAppendingPathComponent:kMyCustomLoggingFile];
              NSLog(@"Logging Path: %@", self.pathForLogging);
              freopen([self.pathForLogging cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
              NSLog(@"NSLog Redirected to a file Succesfully");
              [MySessionObject setLoggingOn:YES];
          }
      }
      
      
      - (void)restoreNSLog {
          if (self.isNsLogRedirected) {
              [MySessionObject setLoggingOn:NO];
              NSLog(@"NSLog Will be Restored now....");
              self.nsLogRedirected = NO;
              fflush(stderr);
      
              dup2(savedStdErr, STDERR_FILENO);
              close(savedStdErr);
              savedStdErr = 0;
          }
      
          [self uploadLogs];
          NSLog(@"NSLog Restored Successfully");
      }
      
      
      - (void)uploadLogs {
          NSLog(@"Now uploading files");
      
          // Disable logging before files are uploading
          MySessionObject.enableLogging = NO;
      
          NSError *anError = nil;
          NSData *aLogData = [NSData dataWithContentsOfFile:self.pathForLogging options:NSDataReadingUncached error:&anError];
      
          //Converting to String
          NSString *aLogString = [[NSString alloc] initWithData:aLogData encoding:NSUTF8StringEncoding];
      
          NSMutableDictionary *aPostBody = [[NSMutableDictionary alloc] initWithCapacity:3];
          [aPostBody setValue:aLogString forKey:@"logData"];
          [aPostBody setValue:MySessionObject.wifiMACAddress forKey:@"deviceMACAddress"];
          [aPostBody setValue:MySessionObject.deviceToken forKey:@"deviceID"];
      
          __weak MyCustomLogging *aBlockSelf = self;
      
          self.requestHandler = [[MyRequestHandler alloc] initWithEndPoint:@"/uploadLogs" body:aPostBody container:nil loadingOverlayTitle:nil successHandler:^(NSDictionary *iResponse) {
              if (iResponse) {
                  //Remove the File From the Path
                  NSError *aFileError = nil;
                  BOOL aFileRemoveSuccess = [[NSFileManager defaultManager] removeItemAtPath:self.pathForLogging error:&aFileError];
      
                  if (!aFileRemoveSuccess) {
                      //Tracking the Event
                      NSString *aDescription = [NSString stringWithFormat:@"Error Code:%ld Error Description:%@", (long)[aFileError code], [aFileError localizedDescription]];
                      NSLog(@"Error occured while deleting log file:%@", aDescription);
                  }
      
                  // Clearing all
                  aBlockSelf.pathForLogging = nil;
                  NSDictionary *anUserInfo = @{kMyDeviceLogUplodStatusKey: kMyValueOne};
                  [[NSNotificationCenter defaultCenter] postNotificationName:kMyDeviceLogsUploadNotification object:nil userInfo:anUserInfo];
              }
          } andErrorHandler:^(NSString *iMessage, NSString *iKey, NSInteger iErrorCode, BOOL iIsNetworkError) {
              NSDictionary *anUserInfo = @{kMyDeviceLogUplodStatusKey: kMyValueZero};
              [[NSNotificationCenter defaultCenter] postNotificationName:kMyDeviceLogsUploadNotification object:nil userInfo:anUserInfo];
          }];
      
          [self.requestHandler executeRequest];
      }
      
      
      - (BOOL)isLogFilePresent {
          NSFileManager *aFileManager = [[NSFileManager alloc] init];
          BOOL aFilePresent = [aFileManager fileExistsAtPath:self.pathForLogging];
          return aFilePresent;
      }
      
      
      @end
      

      【讨论】:

        猜你喜欢
        • 2021-05-01
        • 2016-11-24
        • 2016-02-21
        • 2015-09-28
        • 1970-01-01
        • 1970-01-01
        • 2016-06-07
        • 2013-05-08
        • 1970-01-01
        相关资源
        最近更新 更多