将日志输出同时记录到文件和系统日志中 [英] Log output to file and system log at the same time

查看:156
本文介绍了将日志输出同时记录到文件和系统日志中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试诊断我编写的应用程序中的问题.该问题是偶发性的,仅在实际情况下会发生:在现场,远离我的PC以及当我处于其他状况时,没有足够的资源可用于立即调试.因此,我最好的选择是收集和分析日志数据.

I am trying to diagnose an issue in an app I have written. The issue is a sporadic one, and occurs only under real-world conditions: in the field, away from my PC, and when I’m in the middle of something else, with no resources to spare for immediate debugging. Therefore, my best bet is collecting and analyzing log data.

不幸的是,当我意识到问题再次出现并进行调试时,所有日志数据已经从Android日志中移出,因为我经常同时运行其他聊天应用程序.增大日志缓冲区的大小无济于事(Android对此不满意,或者其他应用仍然过于健谈),所以我放弃了这条路线.

Unfortunately, by the time I realize the issue has struck again and get around to debugging it, any log data has already rotated out of the Android log as I frequently have other chatty apps running at the same time. Increasing the size of the log buffer has not helped (either Android does not honor it or other apps are still too chatty) so I have abandoned this route.

由于这个原因,我现在正在考虑将我的应用程序日志记录到除常规日志之外的单独的文本文件中.

For this reason, I am now considering having my app log to a separate text file in addition to the regular log.

现在我可以轻松地将每个通话加倍

Now I could easily double every call like

Log.i(TAG, "something happened");

添加另一个将相同内容写入日志文件的调用-但这对我来说似乎不太好.

adding another call that writes the same thing to the log file—but that does not seem very elegant to me.

另一种选择是用包装器替换对Log的所有调用,该包装器将事件均写入Android日志和日志文件.

Another option would be to replace all calls to Log with a wrapper that writes the event both to the Android log and the log file.

问题:Android API是否为此提供了内置机制,即告诉Log将其数据同时写入默认日志和文本文件?还是我需要自己编写代码?

Question: Does the Android API provide a built-in mechanism for this, i.e. telling Log to write its data to the default log and a text file at the same time? Or do I need to code this by myself?

假设:

  • 我知道我需要在代码中的何处生成日志输出(可能发生在任何地方,可能涉及或可能不涉及异常),以及要写入日志的内容.
  • 从设备到PC的日志数据也不是问题(单人秀,我只是将手机插入PC并传输日志文件).

如果您知道当前的Android API没有内置机制可以实现我想要的功能,那么不,Android不支持此功能"是一个完全可以接受的答案.在那种情况下,解决方案很明确-我将退回到包装器功能.我特别不是在寻找解决此问题的其他方法.

If you know the current Android API has no built-in mechanism to achieve what I want, then "no, Android does not support this" is a perfectly acceptable answer. In that case the solution is clear—I would fall back to the wrapper function. I am specifically not looking for a different approach to the problem.

推荐答案

进行了更多研究后,似乎Android API没有提供执行此操作的标准方法.有两种可能的解决方法:

After doing some more research, it seems the Android API does not provide a standard way to do this. There are two possible workarounds:

  • System.outSystem.err输出写入台式机系统中的控制台,并写入Android上的日志.可以将这两个重定向到您选择的任何PrintStream中,这将为您提供所有Java控制台输出.您可以将PrintStream子类化以复制其输入,将其输入到默认流以及您选择的文件中.
  • 创建一个类,该类提供与android.util.Log相同的方法.在每种方法中,调用各自的android.util.Log方法,并将数据另外记录到文件中.如果您调用类Log(但使用不同的包名称,例如org.example.Log),那么您要做的就是用类的导入替换android.util.Log的导入,任何Log方法调用将去上课.
  • System.out and System.err output, which is written to the console in desktop systems, writes to the log on Android. These two can be redirected into any PrintStream of your choice, which would give you all Java console output. You can subclass PrintStream to duplicate its input, feeding it into the default stream as well as into a file of your choice.
  • Create a class which exposes the same methods as android.util.Log. In each method, call through to the respective android.util.Log method and additionally log the data to a file. If you call your class Log (but with a different package name, e.g. org.example.Log), then all you need to do is replace imports of android.util.Log with an import of your class, and any Log method calls will go to your class.

注意事项::这只会为您提供代码明确记录的数据(即您拥有源文件的数据)以及进入System.outSystem.err的所有内容.它不包括JAR库的日志输出(如果您不能修改其源代码),也不包括系统生成的任何输出(例如来自默认异常处理程序的堆栈跟踪)或其他进程(其中一些可能是系统进程和报告)与您的过程有关的条件.

Caveats: This will only give you data explicitly logged by your code (i.e. for which you have the source files), as well as anything that goes to System.out or System.err. It will not include log output from JAR libraries (if you cannot modify their source code), nor any output generated by the system (such as stack traces from default exception handlers) or by other processes (some of which may be system processes and report conditions related to your process).

本文说明了如何从Android内部读取日志.简而言之:

This article explains how to read the logs from within Android. In a nutshell:

  • Android在设备上包括一个名为logcat的命令行实用程序,它将为您连续提供日志消息,直到停止. (尝试通过adb shell进入设备并运行它.它具有许多命令行选项来控制其行为.不过,不确定是否在所有发行版中都存在它.)
  • 通过Runtime.getRuntime().exec("logcat")启动此命令,然后获取返回的进程的输入流.这将为您提供日志消息的输入流.
  • 根据该文章,您的应用需要android.permission.READ_LOGS权限才能读取日志.
  • Android includes a command line utility called logcat on the device, which will give you a continuous feed of log messages until stopped. (Try it by adb shelling into your device and running it. It has a bunch of command-line options to control its behavior. Not sure if it is present on all distributions, though.)
  • Launch this command via Runtime.getRuntime().exec("logcat"), then obtain the input stream of the process returned. This will give you an input stream of log messages.
  • According to the article, your app needs the android.permission.READ_LOGS permission to read logs.

我已阅读声明,但某些版本的Android(提到了4.2)不允许将此权限授予非系统应用程序.根据我自己的测试,没有此权限的行为会有所不同:Anbox将返回完整的logcat,而LineageOS(在15.1上进行测试)将仅显示来自调用它的应用程序的日志条目(包括以前的实例,大概是与同一Linux用户关联的所有内容) ).这可能是一个限制,也可能是受欢迎的过滤器功能. YMMV.

I have read statements that certain versions of Android (4.2 was mentioned) do not allow this permission to be granted to non-system apps, though. According to my own tests, behavior without this permissions differ: Anbox will return the full logcat, while LineageOS (tested on 15.1) will only show log entries from the app which called it (including previous instances, presumably everything associated with the same Linux user). This can be a limitation or a welcome filter feature. YMMV.

logcat方便地具有命令行选项-f,用于指定输出文件.我尝试过

logcat conveniently has a command line option, -f, to specify an output file. I tried

Runtime.getRuntime().exec("logcat -f " + absolutePathToLogFile);

和logcat会在应用程序运行期间一直记录日志.杀死应用程序(通过单击Anbox标题栏中的X)显然也终止了子进程.

and logcat keeps logging as long as the app’s process runs. Killing the app (by clicking the X in the title bar on Anbox) apparently also terminated the child process.

现在,您可以在应用启动时运行此代码,也可以将此功能转换为单独的应用,该应用在启动时启动并连续收集所有应用的日志.

Now you can either run this code when your app starts up, or you can turn this functionality into a separate app which starts on boot and continuously collects logs for all apps.

注意事项::如果您正在运行一些健谈的应用程序,这可能会很快填满您的存储空间(这就是为什么条目首先迅速移出logcat的原因).建议使日志镜像可配置(例如通过首选项)和/或确保定期删除旧文件.另外,如果在您的应用终止之前一直保持logcat进程运行,则您将无法通过MTP访问该文件,因为没有简便的方法来运行媒体扫描仪(如果您在文件仍被写入时对其进行扫描) ,它将在MTP上被截断,直到再次进行媒体扫描为止.

Caveats: This may fill up your storage space quickly if you have some chatty apps running (which is why entries rotate out of the logcat so quickly in the first place). It is recommended to make log mirroring configurable (e.g. via Preferences) and/or ensure old files are deleted regularly. Also, if you keep the logcat process running until your app terminates, you will not be able to access the file over MTP as there is no easy way to run the media scanner (if you scan the file while it is still written to, it will appear truncated over MTP until another media scan runs).

这篇关于将日志输出同时记录到文件和系统日志中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆