python timber_如何使用Timber更有效地记录日志
python timber
by Ayusch Jain
通过Ayusch Jain
如何使用Timber更有效地记录日志 (How to log more efficiently with Timber)
Logging is one of the most used utilities in the Android framework. It is really helpful in debugging your code when debugging by break-point just won't work.
日志记录是Android框架中最常用的实用程序之一。 当无法通过断点进行调试时,这对调试代码非常有帮助。
It is generally a good practice to place Log statements in your code. These statements help you keep a track of flow control in your application. Similarly, it is not recommended to have log statements in your release ready code, since those log statements can be read by anyone who connects their phone to a PC. So, when releasing your application to the play store, it is recommended to remove all the log statements from your code.
通常,将Log语句放置在您的代码中是一个好习惯。 这些语句可帮助您跟踪应用程序中的流控制。 同样,不建议在发布准备就绪的代码中包含日志语句,因为将电话连接到PC的任何人都可以读取这些日志语句。 因此,在将应用程序发布到Play商店时,建议从代码中删除所有日志语句。
But this can be a real pain. There are so many log statements all over your code. Now you have to find each one and remove it from your code for the release version.
但这可能是一个真正的痛苦。 您的代码中有太多的日志语句。 现在,您必须找到每个版本,并将其从发行版本的代码中删除。
Another problem with the default logging mechanism is that you need to pass the TAG every time you write a log statement.
默认日志记录机制的另一个问题是,每次编写日志语句时都需要传递TAG。
Wouldn’t it be wonderful if the log statements would automatically disable themselves when in production? Wouldn’t it be great if the Log statements automatically picked up the TAG/classname while logging and you could just focus on writing better code?
如果日志语句在生产中会自动禁用自身,那将不是很好吗? 如果Log语句在记录时自动选择TAG / classname并只专注于编写更好的代码,那不是很好吗?
Well, problems such as these and many more are solved by a better logging library in android, called Timber (by Jake Wharton).
好吧,诸如此类的问题以及更多的问题都可以通过Android中更好的日志记录库Timber (由Jake Wharton编写)解决。
It is a light-weight, easy to use library. It takes care of most of the maintenance you need to do while logging so that you can focus more on writing great code and less on the maintenance stuff.
它是一个轻巧,易于使用的库。 它可以处理您在记录日志时需要执行的大部分维护工作,因此您可以将更多精力放在编写出色的代码上,而将精力放在维护工作上。
Let’s go ahead and create a sample application to see how you can include Timber in your android application and make your logging life easier.
让我们继续创建一个示例应用程序,以了解如何将Timber包含在android应用程序中 ,并使记录工作变得更轻松。
入门 (Getting Started)
We will be creating a simple Android application with 4 buttons. Each button would print out different priority log statement on the console.
我们将创建一个带有4个按钮的简单Android应用程序。 每个按钮将在控制台上打印出不同的优先级日志语句。
Create a new project in Android and add a dependency for Timber in your app level build.gradle file. At the time of this writing, this is the latest dependency version for timber:
在Android中创建一个新项目,并在您的应用程序级别build.gradle文件中添加Timber的依赖项。 在撰写本文时,这是木材的最新依赖版本:
implementation 'com.jakewharton.timber:timber:4.7.1'
初始化木材 (Initializing Timber)
With the dependency downloaded, now it’s time to initialize the timber library. The best place to initialize timber is in the Application class which will be active during the entire lifetime of the application. So, let’s create a custom application class and initialize our Timber library in it:
下载依赖项后,现在该初始化木材库了。 初始化木材的最佳位置是在Application类中,它将在应用程序的整个生命周期内处于活动状态。 因此,让我们创建一个自定义应用程序类并在其中初始化我们的Timber库 :
class MainApplication : Application() { override fun onCreate() { super.onCreate() if(BuildConfig.DEBUG){ Timber.plant(Timber.DebugTree()) } }}
创建MainActivity (Creating MainActivity)
Let’s now create our MainActivity by adding 4 buttons and setting on click listeners to each of them. Here is my activity_main.xml file. I’m using ConstraintLayout as my root layout and including 4 buttons each for different logging levels.
现在,我们通过添加4个按钮并在每个按钮上设置点击监听器来创建MainActivity。 这是我的activity_main.xml文件。 我使用ConstraintLayout作为我的根布局,并分别包含4个用于不同日志记录级别的按钮。
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
<Button android:text="Error Log" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn_error" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp" android:layout_marginTop="108dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintHorizontal_bias="0.498"/> <Button android:text="Info Log" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn_info" android:layout_marginTop="64dp" app:layout_constraintTop_toBottomOf="@+id/btn_error" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp" app:layout_constraintHorizontal_bias="0.498"/> <Button android:text="Debug Log" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn_debug" android:layout_marginTop="72dp" app:layout_constraintTop_toBottomOf="@+id/btn_info" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp" /> <Button android:text="Verbose Log" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn_verbose" android:layout_marginTop="68dp" app:layout_constraintTop_toBottomOf="@+id/btn_debug" app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="8dp" app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintVertical_bias="0.061"/></android.support.constraint.ConstraintLayout>
Now it’s time to set click listeners to these buttons and print a log statement every time a button is clicked. I’m using kotlin’s synthetic bindings instead of regular findViewById calls or Butterknife. Here is my MainActivity.kt file:
现在是时候将单击侦听器设置为这些按钮,并在每次单击按钮时打印一条日志语句。 我使用的是kotlin的合成绑定,而不是常规的findViewById调用或Butterknife。 这是我的MainActivity.kt文件:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main)
btn_error.setOnClickListener { onClickedError() }
btn_info.setOnClickListener { onInfoClicked() }
btn_debug.setOnClickListener { onDebugClicked() }
btn_verbose.setOnClickListener { onVerboseClicked() } }
private fun onVerboseClicked() { Timber.v("On Verbose Clicked") }
private fun onDebugClicked() { Timber.d("On Debug Clicked.") }
private fun onInfoClicked() { Timber.i("On Info clicked.") }
private fun onClickedError() { Timber.e("On Error Clicked.") }
}
Notice how we didn’t need to initialize any TAG variable in our class, Timber does it automatically for you.
请注意,我们无需在类中初始化任何TAG变量,Timber会自动为您完成。
自定义木材以进行调试和发布 (Customizing Timber for Debug and Release)
Now, this is where Timber really shines. What we’ve done till now was nothing great, just printing the log statements on button clicks. But as you know, logging in production is not a good idea. We will write code to disable the logs for production while keeping them enabled during debug mode.
现在, 这是Timber真正发光的地方。 到目前为止,我们所做的一切都还不错,只是在单击按钮时打印日志语句。 但是,正如您所知,登录生产并不是一个好主意。 我们将编写代码以禁用生产日志,同时在调试模式下保持启用状态。
We’ll write an if block to check if our app is in debug mode and enable logging for that. If not, then we want to initialize Timber using a custom tree.
我们将编写一个if块来检查我们的应用程序是否处于调试模式,并为此启用日志记录。 如果不是,那么我们要使用自定义树来初始化Timber 。
Here’s the modified MainApplication.kt class:
这是修改后的MainApplication.kt类:
class MainApplication : Application() { override fun onCreate() { super.onCreate() if (BuildConfig.DEBUG) { Timber.plant(object : Timber.DebugTree() { override fun createStackElementTag(element: StackTraceElement): String? { return String.format( "Class:%s: Line: %s, Method: %s", super.createStackElementTag(element), element.lineNumber, element.methodName ) } }) } else { Timber.plant(ReleaseTree()) } }}
As you can see, we’ve initialized timber using a custom ReleaseTree when in release mode. Now let’s go ahead and create our own release tree.
如您所见,在发布模式下,我们使用自定义的ReleaseTree初始化了木材。 现在,让我们继续创建自己的发行树。
创建一个自定义树 (Creating a Custom Tree)
Creating a release tree is fairly simple. Create a new Kotlin class and extend it from Timber.Tree. Implement all the abstract functions and you’re good to go.
创建发行树非常简单。 创建一个新的Kotlin类,并从Timber.Tree扩展它。 实现所有抽象功能,您就很好了。
Here’s my ReleaseTree.kt:
这是我的ReleaseTree.kt :
class ReleaseTree : @NotNull Timber.Tree() { override fun log(priority: Int, tag: String?, message: String, t: Throwable?) { if (priority == Log.ERROR || priority == Log.WARN){ //SEND ERROR REPORTS TO YOUR Crashlytics. } }
}
As you can see, whenever there is an error, we can send the log to an online service such as Firebase CrashAnalytics or Crashlytics and not logging out on production.
如您所见,每当发生错误时,我们都可以将日志发送到诸如Firebase CrashAnalytics或Crashlytics之类的在线服务,而不会注销生产。
结果 (Result)
使用Timber与Android Logging的好处 (Benefits of using Timber vs Android Logging)
Let’s look at some of the benefits of using Timber library instead of the default Log utility by android sdk.
让我们看一下使用Timber库代替android sdk的默认Log实用程序的一些好处。
No need to worry about TAGS: Timber generates the TAGs automatically for you so you don’t have to worry about including a global TAG in every class.
无需担心 TAG:Timber会自动为您生成TAG,因此您不必担心在每个课程中都包含全局TAG。
No need to manually remove Log statements: As already shown, it’s really easy to disable Logging for release apps. Hence, you no longer have to go through your entire code and manually remove all the logs.
无需手动删除Log语句 :如已显示,禁用发行版应用程序的日志记录确实很容易。 因此,您不再需要遍历整个代码并手动删除所有日志。
Customized behavior on production: In production versions, you don’t want to log, although you definitely want to log any crashes that might occur. You can implement this by using a custom debug tree (as shown above) which instead of logging to the logcat, sends the logs to your crashlytics service.
生产中的自定义行为 :在生产版本中,尽管您确实想记录可能发生的崩溃,但您不想记录。 您可以使用自定义调试树(如上所示)实现此目的,该树不会将日志记录到logcat,而是将日志发送到您的crashlytics服务。
Customized Meta-Data: You can include customized metadata with your log statements. For example, I’ve added class name, line number and method name from which the log statement is getting printed in the implementation above. Having this data at your disposal can make debugging easier.
自定义的元数据 :您可以在日志语句中包含自定义的元数据。 例如,在上面的实现中,我添加了类名,行号和方法名,日志语句从这些类名,行号和方法名中打印出来。 拥有这些数据可简化调试。
Lightweight: Does not increase your app size/method count by much. Really lightweight library as it is just a wrapper over the already existing log utility.
轻量级 :不会大幅增加您的应用大小/方法数量。 真正的轻量级库,因为它只是对现有日志实用程序的包装。
结论 (Conclusion)
For a long time I had ignored the use of log statements and printing out better logs. As my code got bigger and problems got more complex, I realized I needed to adopt better and more efficient debugging routines. Hence, using Timber is one step in the right direction.
很长时间以来,我一直忽略使用日志语句并打印出更好的日志。 随着我的代码越来越大,问题也越来越复杂,我意识到我需要采用更好,更高效的调试例程。 因此,使用Timber是朝正确方向迈出的一步。
*Important*: I’ve created a SLACK workspace for mobile developers where we can share our learnings about everything latest in Tech, especially in Android Development, RxJava, Kotlin, Flutter, and overall mobile development in general.
*重要* :我为移动开发人员创建了一个SLACK工作区,在这里我们可以分享我们对最新技术的了解,特别是在Android开发,RxJava,Kotlin,Flutter和总体上整体移动开发方面 。
Click on this link to join the slack workspace. It’s absolutely free!
单击此链接以加入松弛工作空间。 完全免费!
This article was originally posted at https://ayusch.com/timber-for-android
本文最初发布在https://ayusch.com/timber-for-android
Like what you read? Don’t forget to share this post on Facebook, Whatsapp, and LinkedIn.
喜欢你读的书吗? 不要忘记在Facebook , Whatsapp和LinkedIn上分享此帖子。
You can follow me on LinkedIn, Quora, Twitter, and Instagram where I answer questions related to Mobile Development, especially Android and Flutter.
您可以在LinkedIn , Quora , Twitter和Instagram上关注我,在那里我回答与移动开发(尤其是Android和Flutter)有关的问题 。
翻译自: https://www.freecodecamp.org/news/how-to-log-more-efficiently-with-timber-a3f41b193940/
python timber
相关文章:

node 实现blog博客
https://cnodejs.org/topic/581b0c4ebb9452c9052e7acb转载于:https://www.cnblogs.com/zhangshuda/p/7640363.html

小程序输入框导致界面上移,在输入的时候固定住页面的解决代码
效果: 代码: <view class"comment" style"bottom:{{bottom}}px"><view class"emoji_block" wx:if{{emoji_block_show}}><view wx:for{{connectemoji}} catchtap"add_biaoqing" id"{{item}}…

react中纯函数_如何在纯React中创建电子邮件芯片
react中纯函数by Andreas Remdt由Andreas Remdt 如何在纯React中创建电子邮件芯片 (How to create email chips in pure React) Imagine that you, the good-looking developer (yes, I’m talking to you!), want to build an invitation form where users can add one or mo…
servlet程序HTTP Status 500 - Error instantiating servlet class 解决
一、项目存放路径问题(最常见) 在安装Tomcat时,运行程序都正常,但却打不开http://localhost:8080/,在Tomcat目录webapps下也找不到自己做的项目,这时因为你做的项目没有部署到webapps目录下,倒霉的时候就会遇到报错HTT…

ASP.NET将原始图片按照指定尺寸等比例缩放显示图片
网站上可能会有很多图片,比如产品图片等,而且他们可能大小不一,宽度和高度也不一定一样,有的很大有的很小。如果放在一张网页上,可能会破坏版面,但是如果强制让他们按照指定的宽度和高度显示,因…

前端开发框架选择
Vue Vant 适用场景:开发移动端 (vue) 上手难度:1 Vant是一款很好用的移动端UI框架,非常轻便,适合小型项目 https://vant-contrib.gitee.io/vant/#/zh-CN/ 微信小程序 适用场景:微信小程序(小程序原生框架…

anki_Anki如何挽救我的工程生涯
ankiby Jeffrey Shek通过Jeffrey Shek Anki如何挽救我的工程生涯 (How Anki saved my Engineering Career) I was burned out and my software career was stalling just three years in. My memory sucked. Was my poor memory from stress, lack of sleep or was it always …

信息安全系统设计基础期末总结
【博客汇总】 一、每周读书笔记链接汇总 •[第二周读书笔记] http://www.cnblogs.com/20135302wei/p/4842480.html •[第三周读书笔记] http://www.cnblogs.com/20135302wei/p/4858760.html •[第四周读书笔记] http://www.cnblogs.com/20135302wei/p/4870113.html •[第五周读…

方法 retrun 异步的值,创建一个变量直接等于一个异步方法返回的值
需求:我想创建一个变量,他的值是一个openid, openid 从 getOpenid (封装的一个异步方法) 里面返回,通常调用 getOpenid ,会返回一个Promise 对象,.then 之后才能得到值,例如: //模拟一个异步方…

ps混合模式glsl代码
https://github.com/jamieowen/glsl-blend 转载于:https://www.cnblogs.com/guochen/p/7645227.html

应用程序启动器 标记为信任_为什么您今天不能信任应用程序-以及如何解决它...
应用程序启动器 标记为信任亲爱的每家高科技公司,请窃取这个想法 (Dear Every Single Tech Company, Please Steal This Idea) When you send a photo to someone, your messaging app actually first sends the photo to an app’s server, which then sends the p…

小程序客服自动回复图片,云开发的实现
小程序先开通云开发,创建一个文件夹,并配置为云函数的目录 小程序客服自动回复图片实现步骤: 1.云函数接收消息推送 第一步:开发者工具云开发控制台中增加配置 打开云开发控制台,到设置 tab 中选择全局设置 - 添加消…

ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务解决
方法1: a、通过oracle 工具 Net Configuration Assistant 重新配置监听,注意如果有双网卡请配置第一块网上IP。如何知道哪一块是一块网卡,可以通过ipconfig命令查看最上面的ip就是一块网卡的 b、通过Net Configuration Assistant 工具配置 “…

r语言 编辑 d3.js_d3.js的语言介绍
r语言 编辑 d3.jsby Matt Oxley由马特奥克斯利(Matt Oxley) d3.js的语言介绍 (A linguistic introduction to d3.js) 如何从一个试探者变成一个自信的用户 (How to go from a tentative to a confident user) d3.js is a fantastic library — but I can honestly tell you th…

【Luogu3041】视频游戏的连击(AC自动机,动态规划)
题面链接 题解 首先构建出AC自动机 然后在AC自动机上面跑DP 转移很显然从Trie树的节点跳到他的儿子节点 但是要注意一个问题, 在计算的时候,每一个节点加入后能够 造成的贡献 要加上他的子串的贡献 至于DP: 设f[i][j]表示已经使用了i个字母 当…

拥抱高效、拥抱 Bugtags 之来自用户的声音(三)
小编按:这是一篇 Bugtags 用户来稿,主要是介绍了使用 Bugtags 前后对测试及解决 Bug 所带来的变化,感谢山西农业大学 - 高正炎同学对 Bugtags 的信赖和支持。小编在这里诚邀各位热心用户向我们投稿,说出你使用 Bugtags 的故事。 0…

小程序打开文档标题乱码处理
先下载,自定义临时文件目录名称,然后再打开就可以了。 wx.downloadFile({url: https://xxx.cn/sfxy.docx, //仅为示例,并非真实的资源filePath: wx.env.USER_DATA_PATH /这是自定义标题.docx,success(res) {console.log(0, res)wx.openDocum…

我是“真正的”软件工程师吗?
by Sun-Li Beatteay通过孙丽贝蒂 我是“真正的”软件工程师吗? (Am I a “real” Software Engineer yet?) Am I a “real” Software Engineer yet?我是“真正的”软件工程师吗? This question has haunted me for years. And it seems I’m not al…

ntpdate[31915]: the NTP socket is in use, exiting
[rootmaster local]# ntpdate cn.pool.ntp.org 10 Oct 13:24:36 ntpdate[31915]: the NTP socket is in use, exitingcron 作业中运行 ntpdate,以便大约每隔一小时就设置一次本地时间。最近,我每次运行该命令时都会收到下列错误消息。 ntpdate[31915]: t…

小程序云开发更新数组的指定对象的值
云开发,在小程序实现 代码说明‘: 在这里,数据集合 groupList 中的 userList 是一个用户列表数组,我要更新数组中,openid 等于我的openid 的在线状态为 true。 先查询条件,集合里面的 _id 等于我传的id&a…
Unreal Engine 4 RenderTarget制作Live Camera效果
Unreal Engine 4 RenderTarget制作Live Camera效果 先上效果: Live Camera我不知道怎么翻译。反正意思就是将一个摄影机的Image渲染到一个2D平面上。 以下介绍下详细的实现方法: 1.创建一个Scene Capture 2D对象 将这个对象拖动到合适的地方。2.创建Re…

领导让我重构代码_领导不是由代码构成
领导让我重构代码The team leader is a key figure in a team of developers. It is a difficult role, involving both technical and social skills. This is the reason why not everyone is tailored for it.团队负责人是开发人员团队中的关键人物。 这是一项艰巨的任务&am…

Spring学习-理解IOC和依赖注入
最近刚买了一本介绍ssm框架的书,里面主要对Mybatis、spring、springmvc和redis做了很多的讲解,个人觉得虽然有的内容我看不懂,但是整体上还是不错的。最近正在学习中,一边学习一边做一些总结,现在我对这些思想技术还没…

windows server2012怎样关机怎样重启-详细教程
|浏览:1991|更新:2014-12-15 17:33123456分步阅读百度经验:jingyan.baidu.com windows server2012和以往有些不同,关机/重启按钮不是在左边,甚至左边的“开始”都不见了,那怎样关机/重启呢?这里开始演示&am…

封装 localStorage 缓存,兼容网页,微信小程序,uni-app
封装的缓存功能,兼容网页,微信小程序,uni-app 使用,支持设置缓存,获取缓存,移除缓存,清空缓存,设置缓存时间,分组缓存设置。 把最下面的 Str4.js 代码拷贝到项目内可以直…

考csp所需算法_CSP vs RxJS:您所不知道的。
考csp所需算法by Kevin Ghadyani通过凯文加迪亚尼(Kevin Ghadyani) CSP vs RxJS:您所不知道的。 (CSP vs RxJS: what you don’t know.) CSP发生了什么? (What happened to CSP?) You probably clicked this article thinking “what is CSP?” It’s…

iOS蓝牙4.0开发例子
1建立中心角色 123#import <CoreBluetooth/CoreBluetooth.h> CBCentralManager *manager; manager [[CBCentralManager alloc] initWithDelegate:self queue:nil]; 2扫描外设(discover) [manager scanForPeripheralsWithServices:nil options:…
Spark Shuffle原理解析
Spark Shuffle原理解析 一:到底什么是Shuffle? Shuffle中文翻译为“洗牌”,需要Shuffle的关键性原因是某种具有共同特征的数据需要最终汇聚到一个计算节点上进行计算。 二:Shuffle可能面临的问题?运行Task的时候才会产…

云开发使用 got 的 get/post 传参请求示例代码
使用 got 进行网络请求的步骤: 1.创建云函数,并在终端执行云函数 2.执行 npm 安装 got ,命令:cnpm install --save got 3.在云函数中使用 示例代码: // 云函数入口文件 const cloud require(wx-server-sdk) cons…

JavaScript词法作用域的简单介绍
by Michael McMillan迈克尔麦克米兰(Michael McMillan) JavaScript词法作用域的简单介绍 (An easy intro to Lexical Scoping in JavaScript) Lexical scoping is a topic that frightens many programmers. One of the best explanations of lexical scoping can be found in…