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

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

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

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

我们的研发团队对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

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

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

相关文章

matlab rgb2gray的实现

rgb2gray是matlab内部一种处理图像的函数,通过消除图像色调和饱和度信息同时保留亮度实现将将RGB图像或彩色图转换为灰度图像,即灰度化处理的功能,调用这个功能的格式是I rgb2gray(RGB),意思是将真彩色图像RGB转换为灰度强度图像…

8k分辨率需要多大带宽_又一支持8K分辨率的接口标准发布

随着8K显示热潮的兴起,支持8K视频传输和显示的硬件产品越来越多。继之前发布的HDMI2.1标准之后,又一支持8K分辨率视频传输的接口标准DisplayPort 2.0正式发布。视频电子标准协会(VESA)自推出DisplayPort标准之后,历经了多次的修订&#xff0c…

白话解说TCP/IP协议三次握手和四次挥手

白话解说TCP/IP协议三次握手和四次挥手 1、背景 和女朋友异地恋一年多,为了保持感情我提议每天晚上视频聊天一次。 从好上开始,到现在,一年多也算坚持下来了。 1.1、问题 有时候聊天的过程中,我的网络或者她的网络可能会不好&…

matlab 去除pdf文档水印

1用pdf shaper将pdf转为图片; 2用matlab程序去水印代码如下; 3将去除水印的图片通过pdf shaper转为pdf. 1_1.jpg为要去除水印pdf文档 2_1.jpg为空的pdf文档 test_1.jpg为去除水印的图片 img_1 imread(1_1.jpg); img_2 imread(2_1.jpg);img_3 img_2-img_1; img_4 255-i…

音频信号发生器_1957年,DIY的Hi-Fi 电唱机单电子管音频发生器的音质保真度高...

1957年Hi-Fi 电唱机单电子管音频发生器也许你的MP3播放器听起来比62年前这位绅士的高保真转盘听起来要好一些,但我打赌不太可能自己动手DIY一台MP3播放器,就像下面这个家伙那样。在1957年版的《Radio-TV Experimenter》的封面上显示的这个产品是个DIY产品…

tensorflow 启动Session(tf.Session(),tf.InteractivesSession(),tf.train.Supervisor().managed_session() )

(1)tf.Session() 计算图构造完成后, 才能启动图. 启动图的第一步是创建一个 Session 对象。 示例程序: #coding:utf-8 import tensorflow as tf #构造图 a tf.constant(4) b tf.constant(5) c ab#启动图 with tf.Session() as s…

终极Java日志字典:开发人员最常记录的单词是什么?

最终的记录字典,或者:我们记录的最常用单词是什么? 日志文件是调试应用程序的最常用方法,在解决错误时,它们一定可以引导我们朝着正确的方向发展。 但是,大多数日志文件每天都会增加一百万条消息&#xff…

iwrite提交不了作业_iWrite英语写作教学与评阅系统移动端——学生使用手册

通过微信搜索公众号:iWrite爱写作,点击“关注”。一、注册iWrite英语写作教学与评阅系统移动端首页底端显示“登录”按钮。首次关注,点击“登录”按钮,页面跳转至登录/注册界面。点击“注册账号”按钮,即可跳转至注册界…

阻塞IO与非阻塞IO

阻塞IO:操作系统等数据,只发生了一次调用,最大问题:cpu被耽搁了 非阻塞IO:问题:1、发生多次系统调用 2、数据不及时 IO multiplexing model io多路复用,多一个系统调用,但可以建…

matlab的输出(命令窗口、fprint函数、disp函数)

命令窗口直接输出,MATLAB的默认格式是精确到小数点后4位。如果一个数太大或太小,那么将会以科学记数法的形式显示。比如: format stytle 改变默认输出格式要用到format命令,可根据下表改变数据的输出格式 显示数值格式 Stytle …

g2 折线图点与点之间直线_科学网—ggplot2实现散点折线图 - 肖斌的博文

准备的数据:第一列是时间,第二列是样本,第三列是具体数值。横轴标为时间,纵坐标为具体数值,图中不同颜色展示不同样本。具体的代码:library(ggplot2)png("./xyz.png")(保存成png)upsups$date pde…

matlab 字符串处理

% 字符串处理 a a;bb b;ccccc;m % 获取字符串长度length(a) % 连接两个字符串,每个字符串最右边的空格被裁切 dstrcat(a,c) length(d) % 连接多行字符串,每行长度可不等,自动把非最长字符串最右边补空格 % 使与最长字符串相等,会忽略空字符串 est…

【c#基础】泛型

1:减少代码的选项可以是用Object类,也可以使用泛型 但是Object类进行类型传递不是类型安全的。泛型类使用泛型类型保证了类型安全。 泛型类 泛型方法 泛型接口、结构、委托 泛型优点: 1:性能 装箱和拆箱很容易使用,但性能损失比较…

nacos怎么修改服务分组_nacos服务注册如何配置分组?

同问,度娘一番,没找到答案,最终看的代码,大概知道怎么回事了。这个是下面引用源码的版本org.springframework.cloudspring-cloud-starter-alibaba-nacos-discoverycom.alibaba.nacosnacos-client0.2.2.RELEASEcom.alibaba.nacosna…

使用brew,cask和jenv在MacOSX上设置多个Java JRE / JDK

昨天在Java9的Jigsaw HackTheTower事件中,我意识到我需要加强我的游戏并改善我现有的机制,以在我的机器上维护几个不同的JDK。 我曾经手动下载jdk,或使用brew cask安装它们,我会在〜/ bash_profile上设置bash alias来在不同的 JA…

Codeforces - 102222C - Caesar Cipher

https://codeforc.es/gym/102222/my 好像在哪里见过这个东西&#xff1f;字符的左右移还是小心&#xff0c;注意在mod26范围内。 #include<bits/stdc.h> using namespace std; typedef long long ll;inline int read() {int x0;int f0;char c;do {cgetchar();if(c-)f1;} …

python os.path.exists判断文件或文件夹是否存在

import os#判断文件夹是否存在 dir os.path.exists(C:\\Users\\Desktop) print(dir:, dir)#判断文件是否存在 file os.path.exists(C:\\Users\\Desktop\\雍正王朝.txt) print(file:, file)运行结果 显示该文件及文件夹都存在

vue进入页面执行的钩子函数_解决VUE mounted 钩子函数执行时 img 未加载导致页面布局的问题...

项目需求&#xff1a;图片加载时&#xff0c;当鼠标滚动至当前图片进行加载并加上上滑特效&#xff0c;实现这个效果需要对文档文档滚动位置和图片的当前位置进行比较。但是mounted 钩子函数执行时img图片并未加载出来也就是占位为空&#xff0c;导致图片位置计算出问题。解决这…

微服务(Microservices)和服务网格(Service Mesh)架构概念整理

微服务&#xff08;Microservices&#xff09; 在过去的 2016 年和 2017 年&#xff0c;微服务技术迅猛普及&#xff0c;和容器技术一起成为这两年中最吸引眼球的技术热点。而以 Spring Cloud 为代表的传统侵入式开发框架&#xff0c;占据着微服务市场的主流地位。 微服务&…

python os.listdir列举当前文件夹下所有文件及文件夹

import ospath C:\\Users\\Desktop\\test str os.listdir(path) print(str)运行结果&#xff1a;1、2为文件夹&#xff0c;123.txt为文件