【问题标题】:iOS crash log catch, debug info.. Catch and send via email to the Dev teamiOS 崩溃日志捕获、调试信息.. 捕获并通过电子邮件发送给开发团队
【发布时间】:2012-01-04 05:24:47
【问题描述】:

最近我们遇到了一种情况,我们希望查看用户在其设备上的应用程序的调试信息。因此,我正在寻找一种在设备上查找日志、将其作为内联文本粘贴到邮件中并允许用户发送的方法。

有什么想法吗?问题又来了。。 1)在设备上查找调试日志 2)打开文件并将文件内容作为内联文本附加到邮件中。 3)允许用户在下次应用启动时通过电子邮件发送给它..

谢谢,

【问题讨论】:

  • iTunes 实际上会自动为您做到这一点。检查您的 iTunes-Connect 帐户。

标签: iphone ios email crash


【解决方案1】:

感谢所有的投入。我将您的解决方案合并为一个可以解决我的问题的解决方案。这就是我所做的。当然我没有编译代码,这是一个半生不熟的代码。但是当我在我的代码中实现它时,我会尽快熨烫它..

NSLog到文件How to NSLog into a fileLOG2FILE

#if TARGET_IPHONE_SIMULATOR == 0    
    NSArray *paths =  
    NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);        
    NSString *documentsDirectory = [paths objectAtIndex:0];    
    NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console.log"];    
    freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
#endif

捕获崩溃并将它们也记录到文件中

首先,创建一个函数来处理错误并将其输出到控制台(以及您想要对其执行的任何其他操作):

void uncaughtExceptionHandler(NSException *exception) {    
    NSLog(@"CRASH: %@", exception);      
    NSLog(@"Stack Trace: %@", [exception callStackSymbols]);    
    // Internal error reporting
}

接下来,将异常处理程序添加到您的应用委托:

-(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:  
(NSDictionary*)launchOptions
{   
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);    // Normal launch stuff
}

在 info.plist 中设置一个名为 Crashed 的变量,然后以这种方式读/写它

- (void)readPlist
 {
      NSString *localizedPath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"plist"];        
      NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:localizedPath];

    NSString *crashed;
    crashed = [plistDict objectForKey:@"Crashed"];
}


- (void)writeToPlist
{
    NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];

    [plistDict setValue:@"YES" forKey:@"Crashed"];
    [plistDict writeToFile:filePath atomically: YES];
}

应用启动后,读取 info.plist 并提示用户提交崩溃日志。

{
    MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init];
    mailComposer.mailComposeDelegate = self;[mailComposer setSubject:@"Crash Log"];
    // Set up recipients
    NSArray *toRecipients = [NSArray arrayWithObject:@"first@example.com"]; 
    [mailComposer setToRecipients:toRecipients];
    // Attach the Crash Log..
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console.log"];
    NSData *myData = [NSData dataWithContentsOfFile:logPath];
    [mailComposer addAttachmentData:myData mimeType:@"Text/XML" fileName:@"Console.log"];
    // Fill out the email body text
    NSString *emailBody = @"Crash Log";
    [mailComposer setMessageBody:emailBody isHTML:NO];
    [self presentModalViewController:mailComposer animated:YES];
}

【讨论】:

  • 效果很好,谢谢。我在一个单独的方法中添加了 Mail 函数代码,并从一个按钮调用它,该按钮允许用户通过电子邮件发送调试日志。您必须在邮件控制器中添加 didFinishWithResult 以关闭模式视图并返回到应用程序。
  • NSString *localizedPath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"plist"]; - 实际上你不能将数据保存到 mainBundle 中的 plist。所以使用文档文件夹
  • 有趣的解决方案。当您可以使用 NSUserDefaults 时,为什么还要尝试写入 plist?
  • 不幸的是,这种方法不能捕获所有类型的崩溃。不会捕获由于调用已释放对象而导致的崩溃。我知道因为它发生在我身上:)
  • @AppvolutionTech 或任何机构都可以将此代码翻译成 Swift :)
【解决方案2】:
  1. 要记录您自己的数据,请使用Cocoalumberjack。它比 NSLog 快得多,并且可以动态打开/关闭。它还提供将数据保存到文件中的选项。 NSLog 将减慢您的应用程序并填充控制台日志。此外,您通常不想记录太多。崩溃发生时,您无法安全地进行日志记录。因此,一旦您弄清楚问题区域在哪里,请在此处添加更多日志记录并尝试重现它,例如通过使用自动化测试框架,如KIF

  2. 要捕获崩溃报告,您应该只使用基于开源框架PLCrashReporter 的解决方案,它可以safely 捕获崩溃,即使您的应用程序已经在应用商店中!不推荐其他人建议的异常捕获,请查看this article了解原因!

    iTunes Connect 也允许您查看一些崩溃报告,但最多需要 2 周才能看到一些,但目前还不是全部,例如由Camera+ developers 指出。所以你最好使用自己的解决方案。

    PLCrashReporter 将向您发送标准 Apple 格式的崩溃报告,准备好进行符号化,以便您了解代码中发生崩溃的位置,包括行号。

    一些基于PLCrashReporter的解决方案有:

    • QuincyKit: 开源客户端 + php 服务器,基本崩溃分组,符号化可以从你的 mac 自动化(我是这个的开发者)
    • HockeyApp:付费服务,使用 QuincyKit 客户端,高级崩溃分组,完全在服务器上完成的符号化(我是这个的开发者之一)
    • Bugsense:免费服务,无符号化
    • AppBlade:如果使用 25 台或更少的设备,则免费服务,没有符号
    • Crashlytics: 内测,未知功能,他们的解决方案似乎是基于 PLCrashReporter
  3. 建议的解决方案要么允许在下次启动时自动发送数据,要么询问用户是否同意发送。

【讨论】:

  • BugSense 目前在设备上提供符号化。
  • @Kerni 如何使用 QuincyKit 在您的机器(必须是 Mac)上进行自动符号化?
  • @Roberto 是的,它必须是 Mac。 QuincyKit 捆绑了经过修改的符号化脚本、启动代理等。查看如何设置它的自述文件:github.com/TheRealKerni/QuincyKit/blob/develop/README.markdown
【解决方案3】:

这是一种在发生崩溃时捕获崩溃的解决方案,它提供的代码信息比崩溃日志更易于阅读。它会缺少一些崩溃日志,但正如 Till 所说,无论如何您都应该能够访问这些日志。

来自另一个关于 Xcode 4.2 在崩溃时总是返回到 main 的 SO 问题。那里的答案使用此方法,您可以扩展它以跟踪崩溃。

在 AppDelegate 中实现您自己的异常处理程序

// on load
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);

void uncaughtExceptionHandler(NSException *exception) {
    NSLog(@"CRASH: %@", exception);
    NSLog(@"Stack Trace: %@", [exception callStackSymbols]);
    // Internal error reporting
}

更新 我做了一些回溯,Zane Claes 为问题Xcode 4.2 debug doesn't symbolicate stack call提供了这个解决方案@

他在第二条评论中提供了一个通用解决方案。 “我发现将崩溃日志写入文件并提示用户在下次启动时提交它很有用(仅在发布模式下,不会妨碍调试)。这让我得到了很好的错误报告。 .. 并且用户知道他们的问题正在得到解决”我知道不是每个人都想问这个用户,但是那里有超级用户很乐意提供帮助。

您当然可以包含一个不再向我显示此提示的按钮,这样人们就不会因报告机制而感到沮丧。

或者, 您可以使用信息联系服务器(不确定它是否会在崩溃时工作,但请保存它并偶尔尝试将详细信息发布到服务器)

【讨论】:

  • +1 很高兴知道:-) 但 Jacob 在崩溃前不会获得日志文件内容
【解决方案4】:

Swift 下的日志和分析可以使用 SwiftyBeaver,它是一个功能齐全的日志平台,包括开源 Swift 2 和 Objective-C 框架,加密云存储和 Mac 应用程序。

网址:https://swiftybeaver.com

框架(支持):https://github.com/SwiftyBeaver/SwiftyBeaver

免责声明:我是创始人。

【讨论】:

  • 这个可以用来推送日志到服务器吗?或与谷歌文档集成。?
  • 可以,可以用来推送日志到服务器。它甚至拥有自己的端到端加密日志平台。
  • @sebastian,这是一个非常酷的框架。您能否确认有多少用户(设备)日志可以同步到云端。如果任何商店应用程序使用此框架意味着,该应用程序必须在收集日志数据之前获得用户同意..对吗?最后,我们如何确保将日志同步到云端不会减慢应用速度..?
【解决方案5】:

我一直在使用 Crittercism 为我自动执行此操作。也可用于测试和生产。

【讨论】:

    【解决方案6】:

    BugSense 为 iOS 提供崩溃报告服务。除了提供完全符号化的堆栈跟踪之外,BugSense 还为您的所有应用程序的崩溃提供分析。

    我认为它比电子邮件更好,因为当您的应用程序变得流行时,您将需要手动管理所有这些电子邮件,而 BugSense 会自动执行此操作。但是,BugSense 也是开源的,因此您可以随意修改其内部结构并添加任何附加功能。

    除此之外,您还可以让我们免费为您工作:如果您对希望我们拥有的一项很酷的新功能有任何想法,我们就会去做 - 只要我们认为它也很酷。

    免责声明:我为 BugSense-iOS.framework 编写代码。

    【讨论】:

      【解决方案7】:

      有关 Apple 提供的免费实用程序,请参阅 Ryan 在 How to view NSLog statement from iphone .app file 中的回答。

      但这仍然不是一个方便的解决方案。如果您负担得起新版本,您应该在应用程序中更改您的日志记录。 Jano 在How to NSLog into a file 中对此有一些非常好的想法。尤其是选项 2 应该不需要太多努力。

      一般来说,无论使用什么编程语言,我都会建议在项目开始时将原生日志记录设施隐藏在外观或类似设计的后面。

      【讨论】:

        【解决方案8】:

        如果您将 TestFlight 与他们的 SDK 一起使用,这是自动化的。这是一个非常好的系统。但是,仅适用于测试版本。

        https://testflightapp.com/sdk/

        【讨论】:

        • 这不再可用,因为 Apple 在 2015 年收购了 Testflight。
        【解决方案9】:

        我使用下面的代码来捕获调试日志 - Swift 4.1

        var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        let documentsDirectory = paths[0]
        let fileName = "Logfile.txt"
        let logFilePath = (documentsDirectory as NSString).appendingPathComponent(fileName)
        freopen(logFilePath.cString(using: String.Encoding.ascii)!, "a+", stderr)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-12-16
          • 1970-01-01
          • 2019-09-16
          相关资源
          最近更新 更多