java github_GitHub Research:超过50%的Java记录语句写错了

java github

为什么生产日志无法帮助您找到错误的真正根本原因?

询问您是否使用日志文件监视您的应用程序几乎就像询问…您是否喝水。 我们都使用日志,但是我们如何使用它们则是一个完全不同的问题。

在下面的文章中,我们将对日志进行更深入的研究,并了解日志的使用方式和写入的内容。 我们走吧。

我们的研发团队对Aviv Danziger表示了极大的帮助,感谢他为我们提供和处理数据的巨大帮助。

基础

我们寻求答案需要大量数据,因此我们选择了Google BigQuery。 几个月前,我们首次使用它来查看GitHub的顶级Java项目如何使用logs 。

对于我们当前的帖子,我们在GitHub上排名前40万的Java存储库中,按它们在2016年获得的星级排名进行排名。在这些存储库中,我们过滤掉了Android,示例项目和简单的测试器,从而为我们提供了15797个存储库。

然后,我们提取了包含100多个日志记录语句的存储库,这给我们留下了1,463个存储库。 现在,是时候为所有使我们彻夜难眠的问题找到答案的时候了。

TL; DR:主要要点

如果您不喜欢饼图,柱形图或条形图,并且想跳过主要课程而直接进入甜点,那么以下是我们了解的关于日志记录及其实际操作的5个关键点:

1.日志实际上并没有我们想像的那么多,即使它们每天最多可以增加数百GB。 超过50%的语句没有有关应用程序可变状态的信息
2.在生产中,禁用了全部日志记录语句的64%
3.达到生产状态的日志记录语句的变量比平均开发水平的日志记录语句少35% 4. “永远不要发生” 5.有一种更好的方法来解决生产中的错误

现在,让我们用一些数据备份这些点。

1.多少个记录语句实际上包含变量?

我们要检查的第一件事是每个语句中发出了多少个变量。 我们选择在每个存储库中按从0个变量到5个及以上的比例对数据进行切片。 然后,我们对总数进行了统计,并对研究中所有项目的平均细分情况有所了解。

按变量数计算的平均Java项目

如您所见,普通的Java项目不会在其日志记录语句的50%以上记录任何变量。 我们还可以看到,只有0.95%的日志记录语句发出5个或更多变量。

这意味着日志所捕获的有关应用程序的信息有限,而找出实际发生的情况可能就像在日志文件中搜索针头一样。

2.生产中激活了多少个记录语句?

开发和生产环境有所不同,原因有很多,其中之一就是它们与日志记录的关系。 在开发中,所有日志级别均已激活。 但是,在生产中仅会激活ERROR和WARN。 让我们看看这种故障的样子。

生产与开发日志

该图表显示,普通的Java应用程序具有35.5%的唯一日志记录语句,这些语句有可能在生产中被激活(ERROR,WARN),以及64.5%的语句仅在开发中被激活(TRACE,INFO,DEBUG)。

大多数信息丢失。 哎哟。

3.每个日志级别的平均变量数是多少?

因此,开发人员不仅会跳过语句中的变量,而且普通的Java应用程序首先不会向生产日志发送那么多的语句。

现在,我们决定分别查看每个日志级别,并计算相应语句中变量的平均数量。

每个记录语句的平均变量数

平均值表明,TRACE,DEBUG和INFO语句比WARN和ERROR包含更多的变量。 考虑到前三个变量的平均数量为0.78,后两个变量为0.5,“更多”是一个礼貌的单词。

这意味着生产日志记录语句所包含的变量比开发日志记录语句所包含的变量少35%。 另外,正如我们前面所看到的,它们的总数也要低得多。

如果要在日志中搜索有关您的应用程序发生了什么的线索,但空白处–这就是为什么它发生的原因。 不用担心,有更好的方法。

通过OverOps ,您可以查看任何异常,记录的错误或警告背后的变量,而不必依赖实际记录的信息。 您将能够在事件的整个调用堆栈中查看完整的源代码和变量状态。 即使未将其打印到日志文件中。 OverOps还会向您显示在错误之前在生产中记录的250个DEBUG,TRACE和INFO级别的语句,即使它们已关闭并且从未到达日志文件。

我们很乐意向您展示其工作原理, 请点击此处安排演示 。

4.这永远不会发生

由于我们已经掌握了所有这些记录语句的信息,因此我们决定从中获得一些乐趣。 我们发现有58条提及“这绝不应该发生”。

我们只能说,如果它永远不会发生,则至少要有一个体面才能打印出一个变量或2,因此您将能够看到它为什么仍会发生��

我们是如何做到的?

正如我们提到的,要获取此数据,我们首先必须过滤掉无关的Java存储库,并专注于拥有100多个日志记录语句的存储库,这给我们留下了1,463个可以减少使用的存储库。

然后,我们添加了一些正则表达式魔术,并拔出了所有日志行:

SELECT *FROM [java-log-levels-usage:java_log_level_usage.top_repos_java_contents_lines_no_android_no_arduino]WHERE REGEXP_MATCH(line, r'.*((LOGGER|Logger|logger|LOG|Log|log)[.](trace|info|debug|warn|warning|error|fatal|severe|config|fine|finer|finest)).*')OR REGEXP_MATCH(line, r'.*((Level|Priority)[.](TRACE|TRACE_INT|X_TRACE_INT|INFO|INFO_INT|DEBUG|DEBUG_INT|WARN|WARN_INT|WARNING|WARNING_INT|ERROR|ERROR_INT)).*')OR REGEXP_MATCH(line, r'.*((Level|Priority)[.](FATAL|FATAL_INT|SEVERE|SEVERE_INT|CONFIG|CONFIG_INT|FINE|FINE_INT|FINER|FINER_INT|FINEST|FINEST_INT|ALL|OFF)).*')

现在我们有了数据,我们开始对其进行切片。 首先,我们筛选出每个日志级别的变量数量:

SELECT sample_repo_name,log_level,CASE WHEN parametersCount + concatenationCount = 0  THEN "0"WHEN parametersCount + concatenationCount = 1  THEN "1"WHEN parametersCount + concatenationCount = 2  THEN "2"WHEN parametersCount + concatenationCount = 3  THEN "3"WHEN parametersCount + concatenationCount = 4  THEN "4"WHEN parametersCount + concatenationCount >= 5 THEN "5+"END total_params_tier,SUM(parametersCount + concatenationCount) total_params,SUM(CASE WHEN parametersCount > 0 THEN 1 ELSE 0 END) has_parameters,SUM(CASE WHEN concatenationCount > 0 THEN 1 ELSE 0 END) has_concatenation,SUM(CASE WHEN parametersCount = 0 AND concatenationCount = 0 THEN 1 ELSE 0 END) has_none,SUM(CASE WHEN parametersCount > 0 AND concatenationCount > 0 THEN 1 ELSE 0 END) has_both,COUNT(1) logging_statements,SUM(parametersCount) parameters_count,SUM(concatenationCount) concatenation_count,SUM(CASE WHEN isComment = true THEN 1 ELSE 0 END) comment_count,SUM(CASE WHEN shouldNeverHappen = true THEN 1 ELSE 0 END) should_never_happen_countFROM [java-log-levels-usage:java_log_level_usage.top_repos_java_log_lines_no_android_no_arduino_attributes]  GROUP BY sample_repo_name,log_level,total_params_tier

然后计算每个层的平均使用量。 这就是我们获得总存储库语句的平均百分比的方式。

SELECT total_params_tier,AVG(logging_statements / total_repo_logging_statements) percent_out_of_total_repo_statements,SUM(total_params) total_params,SUM(logging_statements) logging_statements,SUM(has_parameters) has_parameters,SUM(has_concatenation) has_concatenation,SUM(has_none) has_none,SUM(has_both) has_both,SUM(parameters_count) parameters_count,SUM(concatenation_count) concatenation_count,SUM(comment_count) comment_count,SUM(should_never_happen_count) should_never_happen_countFROM (SELECT sample_repo_name,total_params_tier,SUM(total_params) total_params,SUM(logging_statements) logging_statements,SUM(logging_statements) OVER (PARTITION BY sample_repo_name) total_repo_logging_statements,SUM(has_parameters) has_parameters,SUM(has_concatenation) has_concatenation,SUM(has_none) has_none,SUM(has_both) has_both,SUM(parameters_count) parameters_count,SUM(concatenation_count) concatenation_count,SUM(comment_count) comment_count,SUM(should_never_happen_count) should_never_happen_countFROM [java-log-levels-usage:java_log_level_usage.top_repos_java_log_lines_no_android_no_arduino_attributes_counters_with_params_count]GROUP BY sample_repo_name,total_params_tier)WHERE total_repo_logging_statements >= 100GROUP BY total_params_tierORDER BY 1,2

您可以在我们的原始数据文件中查看计算结果 。

最后的想法

我们都使用日志文件,但是似乎大多数人都认为它们是理所当然的。 有了众多的日志管理工具,我们忘记了控制我们自己的代码-并使它对于我们理解,调试和修复很有意义。

翻译自: https://www.javacodegeeks.com/2017/02/github-research-50-java-logging-statements-written-wrong.html

java github

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/334966.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

yolov5论文_YOLOv5的妙用:学习手语,帮助听力障碍群体

编辑:魔王、杜伟计算机视觉可以学习美式手语,进而帮助听力障碍群体吗?数据科学家 David Lee 用一个项目给出了答案。如果听不到了,你会怎么办?如果只能用手语交流呢?当对方无法理解你时,即使像订…

python制作系统程序与html交互_python+html语音人物交互_flask后台与前端(html)交互的两种方法...

基于python flask框架搭建webflask后台与前端(html)交互的两种方法:方法1 使用flask-wtf 提供的表单用常见的登录为例:// An highlighted blockfrom flask_wtf import Formclass LoginForm(Form): # 登录表单ROLE SelectField(角色, choices[(s, 管理员…

Java 程序执行过程的内存流程图(结合类加载器 ClassLoader 讲解)

Student s new Student(); s.play(); Student s2 new Student();以上代码的执行流程如下: JVM 作为操作系统的一个迚程在系统中执行,那么系统会为 JVM 分配一块内存空间,这块内存空 间被 JVM 分为 3 大块(栈区、堆区、方法区) 一般而言&a…

java javap_javap的用途不断发展:您的Java类文件中隐藏了什么?

java javap什么是Javap,如何使用它以及何时要反汇编类文件? 作为Java开发工具包(JDK)的一部分,我们可以使用许多工具,这些工具有助于更好地理解Java代码。 这些工具之一是javap命令,它使我们能…

虚拟内存越大越好吗_手机的运行内存真的是越大越好吗?6GB和8GB到底又该如何选择?...

许多人买手机,除了看处理器、外观以外,关注最多的莫过于手机的运行内存了。选择一个合适的运行内存几乎关系到整个手机使用寿命和命脉。那么我们现在买手机选择多大的运行内存合适呢?真的是越大越好吗?下面我们就来一起看看吧。选…

Adobe PhotoShop(PS) for Windows 快捷键/PS快捷键

文章目录一、工具栏二、文件操作三、选择功能四、视图操作五、编辑操作六、图像调整七、图层操作一、工具栏 功能说明快捷键备注移动工具V矩形、椭圆选框工具M套索、多边形套索、磁性套索L快速选择工具、魔棒工具W裁剪、透视裁剪、切片、切片选择工具C吸管、颜色取样器、标尺、…

kafka和storm集成_Storm和Kafka集成的重要生产错误和修复

kafka和storm集成我将在此处描述Storm和Kafka集成模块的一些细节,一些您应该意识到的重要错误以及如何克服其中的一些错误(尤其是对于生产安装)。 我在生产安装中大量使用Apache Storm,并将Kafka作为主要输入源(Spout…

显微镜自动聚焦原理是什么_什么是共聚焦显微镜?你了解过共聚焦显微镜吗?...

更出色的表面分析ZEISS Smartproof 5产品表面粗糙度质量控制ZEISS Smartproof 5是一款集成式转盘共聚焦显微镜,依托孔径关联技术将传统共聚焦显微镜的高分辨率与转盘系统的高速采集相结合,能够高速、准确地采集表面3D数据。二维测量:距离、高…

java string args_java – 语法“final String … args”是什么意思/做什么?

Java中参数的省略号表示类型的vararg.因此,在您的情况下,…意味着您可以将任意数量的String参数传递给doInBackground方法.因此,您可以调用此方法doInBackground(“String1”,“String2”,“String3”)或doInBackground(“String1”)或doInBackground(“String1”,“String3”,…

Java 程序执行过程的内存流程图(手写稿)

操作系统会分配一定的内存空间给JVM,空间大小可以在JVM里面设置,JVM会将内存分为三个区域:栈、堆、方法区。

unsafe jdk9_JDK 9清单:Project Jigsaw,sun.misc.Unsafe,G1,REPL等

unsafe jdk9Java 9距离(希望)数月了,现在该回顾一下即将发生的变化以及您应该采取的措施 Java 9即将来临(我们正在计算到达的日子 ),其中包含一系列新功能和改进功能。 这就是为什么我们决定创建一份清单来…

DAO 学习笔记

文章目录什么是 DAO?如何写 DAO?示例代码什么是 DAO? Data Access Object(DAO),数据访问对象/数据存取对象。DAO 是封装数据库访问逻辑的组件/类 。 定义一个类,这个类中的方法封装了数据库访问逻辑,要访问数据库时,只要调用…

dc/os_DC / OS中具有Java和数据库应用程序的服务发现

dc/os该博客将展示一个简单的Java应用程序如何使用DC / OS中的服务发现与数据库进行对话。 为什么要进行服务发现? 应用程序通常由多个组件组成,例如应用程序服务器,数据库,Web服务器,缓存和消息传递服务器。 通常&am…

python进阶项目设计_Python进阶循环设计

之前在“循环”一节,我们已经讨论了Python最基本的循环语法。这一节,我们将接触更加灵活的循环方式。1. 利用range(), 得到下标在Python中,for循环后的in跟随一个序列的话,循环每次使用的序列元素,而不是序列的下标。之…

python调试器入门教程_PyCharm入门第一步(二)——调试第一个Python应用|python基础教程|python入门|python教程...

https://www.xin3721.com/eschool/pythonxin3721/第2步:调试您的第一个Python应用程序找出问题的根源PyCharm报告运行时错误:a ZeroDivisionError。深入研究一下代码,找出问题所在。这里可以使用PyCharm调试器来查看代码中发生了什么。要开始…

Struts2请求处理的内部流程图/结构图/原理图(版本二)

文章目录请求处理流程图流程说明请求处理流程图 流程说明 第 1 步: 客户端初始化一个指向 Servlet 容器(例如 Tomcat)的请求,例如:在浏览器中输入 http:localhost:8080/Struts2/helloworld/helloworldAction.action …

jboss 配置上下文路径_为单个Web应用程序配置多个上下文根– JBoss

jboss 配置上下文路径有时&#xff0c;我们通过在jboss-web.xm l中定义一个来对应用程序进行更改&#xff0c;以支持利用JBoss功能的多个上下文根&#xff0c;如下所示&#xff1a; webapp / WEB-INF / jboss-web.xml&#xff1a; <?xml version"1.0" encoding…

xampp mysql 查询很慢_如何开启mysql的慢查询机制

1 在mysql中默认是不会开启慢查询日志功能的&#xff0c;我们可以使用show variables like ‘%slow%‘来查看一下。结果如下&#xff1a;参数说明&#xff1a;log_slow_queries表示服务器端是否开启慢查询日志记录功能&#xff0c;slow_query_log表示mysql监测满查询的功能是否…

python3.7打包exe坑_[求助]入坑学习python 需要装pyinstaller打包成exe

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼E:\Python>pyinstaller -F E:\Python\123.py142 INFO: PyInstaller: 3.2.1142 INFO: Python: 3.5.3142 INFO: Platform: Windows-7-6.1.7601-SP1143 INFO: wrote E:\Python\123.spec144 INFO: UPX is not available.146 INFO: E…

uaa 授权_使用UAA OAuth2授权服务器–客户端和资源

uaa 授权在上一篇文章中&#xff0c;我介绍了如何使用Cloud Foundry UAA项目启动OAuth2授权服务器&#xff0c;以及如何使用OAuth2授权代码流程中涉及的一些参与者来填充它。 我在Digital Ocean网站上发现这篇文章在描述OAuth2授权代码流方面做得很好&#xff0c;因此&#xf…