如何将应用程序日志写入文件并获取它们

Posted

技术标签:

【中文标题】如何将应用程序日志写入文件并获取它们【英文标题】:How to write Application Logs to File and get them 【发布时间】:2017-11-16 03:43:06 【问题描述】:

我正在 ios 开发中迈出第一步,并正在寻找一种在 iOS 中使用日志记录的方法。

我找到了这些关于使用 swift 3 进行日志记录的文档:https://developer.apple.com/documentation/os/logging#1682426

文档说日志没有保存在磁盘上。获取日志和处理文件的典型方法是什么?

【问题讨论】:

我猜你想像 CrashReporter 一样将日志作为文件获取,对吗?在这种情况下,有几个 pod 可以将其存档。 PLCrashReporter 是我在我的一个项目中使用的一个。它将日志文件打印到一个文件中并生成一个报告,该报告将发送到特定的服务器。 我想像文档中一样使用 os.log 记录参数和运行时行为。在不久的将来,我想收集这些日志并将它们发送到其他地方。但我正在寻找一种简洁的代码方法,而不是一个库。 【参考方案1】:

将此文件放入您的项目中

//
//  log.swift
//  logtest
//

import Foundation

struct Log: TextOutputStream 

    func write(_ string: String) 
        let fm = FileManager.default
        let log = fm.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("log.txt")
        if let handle = try? FileHandle(forWritingTo: log) 
            handle.seekToEndOfFile()
            handle.write(string.data(using: .utf8)!)
            handle.closeFile()
         else 
            try? string.data(using: .utf8)?.write(to: log)
        
    


var logger = Log()

如果您需要记录某些内容,只需使用类似的打印功能

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 
        // Override point for customization after application launch.
        print("started:", Date(), to: &logger)
        return true
    

override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    print(#file, #function, "my own text", 1, [1,2], to: &logger)

在您的应用程序的“文档”文件夹中,您可以找到“log.txt”文件,您可以稍后查看。

两次运行我的测试应用程序时,内容看起来像

started: 2017-06-14 09:58:58 +0000
/Users/ivo_vacek/Documents/logtest/logtest/ViewController.swift viewDidLoad() my own text 1 [1, 2]
started: 2017-06-14 09:59:15 +0000
/Users/ivo_vacek/Documents/logtest/logtest/ViewController.swift viewDidLoad() my own text 1 [1, 2] 

如果您不喜欢“全局”,请将 Log 定义为单音类

class Log: TextOutputStream 

    func write(_ string: String) 
        let fm = FileManager.default
        let log = fm.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("log.txt")
        if let handle = try? FileHandle(forWritingTo: log) 
            handle.seekToEndOfFile()
            handle.write(string.data(using: .utf8)!)
            handle.closeFile()
         else 
            try? string.data(using: .utf8)?.write(to: log)
        
    
    static var log: Log = Log()
    private init()  // we are sure, nobody else could create it

并像使用它

print("started:", Date(), to: &Log.log)

【讨论】:

好吧,是的。这是一种方法,但为什么我不能使用 os.log 框架?我的意思是它包含一个 LogLevel 等等。我有一个未解决的问题 Log.log 前面的“&”是什么意思? @Offset OSLog 仅适用于 iOS 10.0+、macOS 10.12+、tvOS 10.0+、watchOS 3.0+、未知 SDK 8.0+。 & 作为输入输出,使变量成为输入输出参数。使用 OSLog 将操作系统导入文件 好吧,只是说清楚。 OSLog 仅用于调试?我无法写入文件或可以用作文件?我认为它非常混乱。甚至还有一个适用于所有版本的 NSLog。所以总结一下:要么我编写自己的记录器(如上),要么使用第三方库? @Offset 由你决定 :-),没有足够的信息(至少我没有)来有效地使用 OSLog。使用 NSLog/ NSLogv 见'man 3 asl'。如果您想将输出定向到其他地方,则需要使用自定义日志记录工具。 是否可以简单地使用通过调用os_log 创建的日志并将它们压缩并通过电子邮件发送?目前我只知道 sysdiagnose 方法...【参考方案2】:

Swift 3.0 版本

在您的项目中创建一个新的 swift 文件“TextLog.swift”

import Foundation

struct TextLog: TextOutputStream 

    /// Appends the given string to the stream.
    mutating func write(_ string: String) 
        let paths = FileManager.default.urls(for: .documentDirectory, in: .allDomainsMask)
        let documentDirectoryPath = paths.first!
        let log = documentDirectoryPath.appendingPathComponent("log.txt")

        do 
            let handle = try FileHandle(forWritingTo: log)
            handle.seekToEndOfFile()
            handle.write(string.data(using: .utf8)!)
            handle.closeFile()
         catch 
            print(error.localizedDescription)
            do 
                try string.data(using: .utf8)?.write(to: log)
             catch 
                print(error.localizedDescription)
            
        

    


在 AppDelegate.swift 文件的底部初始化记录器

var textLog = TextLog()

在应用程序的任何地方使用它,如下所示

textLog.write("hello")

【讨论】:

在我们的设备中哪里可以看到这个日志文件? @AnupGupta,你可以在这里找到它~/Library/Containers/YOU_APP_BUNDLE_ID/Data/Documents /Users/pradeepkumar/Library/Containers/YOU_APP_BUNDLE_ID/Data/Documents/Qandle/ 我很难找到它,但这对我有帮助:***.com/q/6121613/1759443【参考方案3】:

文档说日志没有保存在磁盘上。获取日志和处理文件的典型方法是什么?

我不确定这在某些时候是否属实并已更改,但the current documentation you linked to 确实说日志保存在磁盘上:

该系统将日志数据集中存储在内存和磁盘中,而不是将这些数据写入基于文本的日志文件。

具体可以在a recommended article找到这张表:

您可以使用工具或自定义配置文件覆盖每个日志级别的默认存储行为。有关如何执行此操作的更多信息,请参阅Customizing Logging Behavior While Debugging

这里是an example in the article如何使用记录器(swift):

if #available(OSX 11.0, *) 
   // Log a message to the default log and default log level.
   let defaultLog = Logger()
   defaultLog.log("This is a default message.")
            
   // Log a message to the default log and debug log level
   defaultLog.debug("This is a debug message.")


   // Log an error to a custom log object.
   let customLog = Logger(subsystem: "com.your_company.your_subsystem", 
          category: "your_category_name")
   customLog.error("An error occurred!")
 else 
   // Log a message to the default log and default log level.
   os_log("This is a default message.")
            
   // Log a message to the default log and debug log level
   os_log("This is a debug message.", log: OSLog.default, type: .debug)
            
   // Log an error to a custom log object.
   let customLog = OSLog(subsystem: "com.your_company.your_subsystem", 
            category: "your_category_name")
   os_log("An error occurred!", log: customLog, type: .error)

据我所知,没有必要使用其他答案(不再?)

【讨论】:

OP 也在询问“如何获得它们”。如果您也讨论 OSLogStore 和 Sysdiagnose,您的回答会受益更多 @Honey 你的评论帮助了我,因为我也一直在努力解决这个问题。文档说统一日志系统对于“当您无法将调试器附加到应用程序时,例如当您在用户机器上诊断问题时”很有用,但据我所知,并没有在任何地方解释这个怎么做。我将研究这两个概念并更新我的答案。 @Honey 我已经搜索了整整一个小时,但我无法弄清楚如何使用 OSLogStore。我发现的信息最丰富的是这篇文章:steipete.com/posts/logging-in-swift,但我在阅读后仍然不知道如何使用 OSLogStore,也不明白你为什么需要:我上面链接的文档没有在任何地方提到它,如该表所示,它仍然记录到磁盘。 单击任何说明以查看来自here 的触发器 sysdiagnose 文档。虽然我推荐this 方式。我没有使用过 OSLogStore,但它的好处是 1. 您可以使用某些谓词来查询它们,而不是使用 sysdiagnose 来查询所有应用程序的所有 oslog。 2. 我相信你可以将它们保存到磁盘上,或者要求用户通过电子邮件发送它。 3. 文档为here 我以前用过oslog/Logger。而且你永远不会指定它应该登录到哪里。所以我的假设是,是的,它神奇地记录和检索

以上是关于如何将应用程序日志写入文件并获取它们的主要内容,如果未能解决你的问题,请参考以下文章

JVM崩溃。如何获取错误日志或核心转储

如何检测文本文件的实时变化?

如何在不将文件写入光盘的情况下创建文件并压缩它们?

如何将帧写入视频文件?

如何在shell 中将sql语句执行结果写入日志中

Linux查看日志文件写入速度的4种方法