Erlang/OTP中的日志与事件处理(一)

Erlang/OTP中的日志

Simple Cache真要是在运行过程中出了什么故障该怎么办呢?就当前的设计来看,除非服务整个崩溃,否则你可能根本无法察觉有任何异常。(比如,在我们的设计中,元素存储进程在退出时会自行进行清理,而由于工作进程被设置成temporary型,监督者此时是不会作出任何反应的。)
这套缓存服务不能再这样沉默下去了,Erlang/OTP自带的精良装备可以很好地解决这个问题。这些装备就是日志应用、SASL应用,以及由gen_event行为模式提供的事件处理框架。它们共同构成了一整套强大的用于与外界进行各种信息交换的工具。利用gen_event,你还可以让其他应用接入你的系统。

1.日志概述

Log4j等日志系统(或是log4c、log4r等)。在各种软件开发工具中,日志的地位十分显赫,几乎所有编程语言都提供了一套适用于该语言的、可视为事实标准的日志系统。日志系统一般都设有多个严重级别,用于区分日志的重要程度。日志级别通常可分为五个,分别是: critical(或severe)、error、warning、info和debug。确切名称可能依系统的不同而不同。这几个级别的含义都显而易见,但每个级别的使用场合却没那么容易区分,针对这个问题,我们简单做一个总结。

critical或severe———表示系统遭遇了灾难性故障或者客户已无法访问系统,此时应立即采取人工措施。使用这个级别时应慎之又慎,只有那种有必要在凌晨三点把人从床上拖起来的紧急情况才用得上这个级别的日志。

error一一告知系统运维人员系统中出现了一些不良状况,但并不严重。例如,某个子系统崩溃后重启了一次,或是某个客户会话因数据错误而被中断。这类问题理应立即得到修复,不过拖到明天再处理也无伤大雅。不要滥用这个级别,否则人们会逐渐忽略这些消息。

warn一一告知运维人员系统中出现了某些潜在的负面问题,但暂时无害。你可以选择忽略这个级别的问题,或是暂时绕过留待日后修复,以免捅出别的什么篓子或是给系统平添不必要的负载。

info———表示一条通告性消息,用于将某个事件的发生告知给运维人员。这类事件可能是好消息,比如“备份任务完成";也可能有那么点儿令人沮丧,比如“邮件发送失败,五分钟后重试”。这个级别可以随便用,但也别太离谱,以免把你的运维团队淹没在各种毫无用途的细节之中。

debug———提供各种巨细信息。这个级别基本上是给身为开发者的你准备的,用于协助调试运行中的系统,(在一定限度内) debug日志总是越多越好。除非有人明确地要求,否则一般是不输出debug消息的。

大多数日志系统都允许运维人员根据具体情况设置一个最低严重级别。如果想要把控一切,就调到debug级别,在该级别下你可以看到所有类型的消息。如果希望看到除debug消息以外的所有消息,就调到info级别。如果仅希望在发现问题时得到通知,则可以调到warn级别,以此类推。

日志系统还提供了一些其他功能,比如调整输出格式,给日志消息添加时间戳等。暂且不去关注这些细节,我们先来看看Erlang/OTP的日志功能是怎样运作的。

2.Erlang/OTP内置的日志设施

日志是个极为常用的系统需求,Erlang/OTP的基本发行版便提供了日志功能支持。其主要功能由标准库中kernel应用的error_logger模块提供,供OTP行为模式使用的扩展日志功能则由SASL应用提供。它不仅提供了输出日志的方法,还给出了一套用于实现自定义日志和事件处理的通用框架。

OTP的默认日志格式比较古怪,常用的日志解析工具都拿它没办法。因此你必须权衡是否选用原生的日志系统,如果你的系统需要融入现有的非Erlang的基础架构,那么可能不应该选用其他的日志系统;如果是要基于OTP创建全新的系统,情况则相反。同时,你也应当明了在选择外部日志系统时需要做出哪些妥协。为了做到知己知彼,让我们先来看看日志系统的主要API。

3.标准日志函数

用于投递日志消息的标准API比较简单,但该API仅支持3个日志级别:error、warning和info。很快你便会发现,这根本算不上什么限制,因为报首尖型N事PTL理m即ror四r蕴地(付干Fkernel于初学者而言,还是先将就一下吧。日志投递相关的API函数可以在error_logger模块(位于kernel应用中)中找到。以下是最基本的几个函数:

error logger:error_msg ( Format) -> ok.
error_logger:error_msg ( Format, Data) -> ok.
error_logger:warning_msg (Format) -> ok
error_logger:warning_msg (Format,Data) -> ok.
error_logger:info_msg (Format) ->ok.
error_logger:info_msg (Format, Data) -> ok.

这几个函数的接口与标准库函数io:format/1和io:format/2相同:第一个参数是格式字符串,其中可以包含由波浪号(~)开头的转义码,如~w,第二个参数则是与转义码对应的值的列表。

我们先来打印几条日志看看。使用下列方法你可以通过调用info_msg/1来输出简单字符串:

2>error_logger:info_msg("This is a message~n") .
=INFO REPORT==== 16-Jan-2024::22:21:32 ===
This is a message
ok

这样便向日志记录器发送了一条info消息,日志记录器会对该消息进行格式化,并给它加上一个含有严重级别和时间戳的标题。默认情况下,日志消息是直接输出到终端的,你也可以对系统进行配置,将日志输出到文件或将日志关闭。(示例中的ok是函数调用返回给shell的返回值,并非消息的一部分)

使用info_msg/2可以在日志消息中掺入数据:

3>error_logger:info_msg("This is an ~s message~n",["info"]).
=INFO REPORT==== 16-Jan-2024::22:24:24 ===
This is an info message
ok

转义码~s用于在格式字符串中插人其他字符串。有关格式字符串的详情请参阅io:format/2的文档,你只需记住第二个参数一定是个项式列表就可以了。一般来说,列表中的元素应该与格式字符串中的格式指示符一一对应(表示换行符的~n除外)。
这几个函数的容错性要优于io:format(...)。即便格式规范有误,消息也能输出,而不至于引起崩溃。例如,如果第二个参数中的元素数目不对,你将得到以下报告:

4> error_logger:info_msg ( "This is an ~s message~n", ["info",this_is_an_unused_atom]).
=INFO REPORT==== 16-Jan-2024::22:28:18 ===
ERROR: "This is an ~s message~n" - ["info",this_is_an_unused_atom]
ok

如此一来即便在写代码时不小心搞错了日志消息格式也不至于丢失潜在的关键信息。这个特性看似没什么大不了的,但却非常重要。
让我们来考察一些更为实用的日志消息吧:

5>error_logger:info_msg("Invalid reply ~p from ~s ~n",[<<"quux">>,"stockholm"]).
=INFO REPORT==== 16-Jan-2024::22:33:28 ===
Invalid reply <<"quux">>from stockholm
ok

当然,实际系统中的数据总是通过变量传入的,不会像这样硬编码在代码中。请注意~p:这个格式指示符特别有用。它可以将给定的值格式化成更易于人类阅读的格式—-在处理包含字符数据的列表或二进制串时尤为有用。

除了info_msg,请再分别尝试一下error_msg和warning_msg,并注意其中的区别。你会发现warning消息和error消息实际上是一样的;这是因为,在默认情况下, warning被直接映射至error。(出于历史原因,实际上只存在info和error两种消息。在启动Erlang时给erl加上+Ww参数可以取消warning到error的映射)
 

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

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

相关文章

十五、CSS3DObject和CSS2DObject的区别

在3d场景中我们会遇到很多标签,主要分为三种,css3dobject、css2dobject、css3dsprite三种,今天主要说说css3dobject和css2dobject的相似点和区别。 Threejs版本:0.138.3 下面看实现的效果: 相似点 使用方法都是差不多的,下面讲解下css2dobject的使用方法在index.html增…

[ACM学习] 动态规划基础之一二三维dp

课内学习的动态规划 有记忆的迭代 优化解的结构&#xff1a;原始问题的一部分解是子问题的解 三要素&#xff1a;1.子问题 2.状态的定义 3.状态转移方程 定义 线性dp的一道例题 dp[i]表示以位置 i 结尾的方案总数&#xff0c;dp[4]2&#xff0c;因为&#xff1a;首先只放一…

【驱动】TI AM437x(内核调试-06):网卡(PHY和MAC)、七层OSI

1、网络基础知识 1.1 七层OSI 第一层:物理层。 1)需求: 两个电脑之间如何进行通信? 具体就是一台发比特流,另一台能够收到。于是就有了物理层:主要是定义设备标准,如网线的额接口类型、管线的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流,就是从1/0…

【GitHub项目推荐--一行命令下载全网视频】【转载】

项目地址&#xff1a;https://github.com/soimort/you-get 首先声明&#xff0c;请不要使用该项目从事违法活动哦~仅供学习使用&#xff01; 解决痛点 如果你上网的时候看了一些东西不错&#xff0c;想下载下来&#xff0c;或者在线观看喜欢的视频&#xff0c;但是没有找到网…

xilinxi mulitboot 启动

xilinix在线更新有两种方式&#xff0c;一种是使用ICAP原语&#xff0c;另一中是在xdc中约束&#xff0c;根据应用的场景不同&#xff0c;选用不同的启动方式&#xff0c;第二种更为简单。 可参考官方提供的手册和实例 XAPP1247 链接&#xff1a; XAPP1247 golden和updata.b…

python期末考试:基本数据的表示

1. 关于 Python 的数字类型&#xff0c;以下选项中描述错误的是( )。 A. Python 整数类型提供了 4 种进制表示&#xff1a;十进制、二进制、八进制和十六进制 B. Python 语言要求所有浮点数必须带有小数部分 C. Python 语言中&#xff0c;复数类型中实数部分和虚数部分的数…

【零基础入门Python数据分析】Anaconda3 JupyterNotebookseaborn版

目录 一、安装环境 python介绍 anaconda介绍 jupyter notebook介绍 anaconda3 环境安装 解决JuPyter500&#xff1a;Internal Server Error问题-CSDN博客 Jupyter notebook快捷键操作大全 二、Python基础入门 数据类型与变量 数据类型 变量及赋值 布尔类型与逻辑运算…

vue刷新当前页面

我们经常遇到此种情形&#xff0c;当新增编辑完成后&#xff0c;需要重新刷新页面数据&#xff0c;重新调用接口较多时&#xff0c;挨个调用过于繁琐&#xff1b;甚至可能遇到跨组件调用的问题&#xff0c;毫无疑问&#xff0c;处理起来有些许费力&#xff0c;本文就将如何处理…

基于时域有限差分法的FDTD的计算电磁学算法-YEE网格下的更新公式推导

基于时域有限差分法的FDTD的计算电磁学算法&#xff08;含Matlab代码&#xff09;-YEE网格下的更新公式推导 参考书籍&#xff1a;The finite-difference time-domain method for electromagnetics with MATLAB simulations&#xff08;国内翻译版本&#xff1a;MATLAB模拟的电…

【MATLAB】 SSA奇异谱分析信号分解算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 1 基本定义 SSA奇异谱分析&#xff08;Singular Spectrum Analysis&#xff09;是一种处理非线性时间序列数据的方法&#xff0c;可以对时间序列进行分析和预测。 它基于构造在时间序列上的特定矩阵的奇异值分解&#…

C#,入门教程(66)——枚举Enum的高等用法

前言&#xff1a;国内码农与国外优秀程序员的最大区别是&#xff0c;我们的专家、教授喜欢唾沫横飞地&#xff0c;夸夸其谈语言特性、框架、性能&#xff0c;唯一目的是带私货&#xff08;书籍或教程&#xff09;&#xff0c;很少能写出真有用的程序。差距在哪呢&#xff1f;基…

线性代数——行列式相关性质

目录 一、行列式与它的转置列行列式相等 二、对换行列式的两行&#xff08;列&#xff09;&#xff0c;行列式变号 三、行列式某行&#xff08;列&#xff09;有公因子k&#xff0c;则k可以提到行列式外 四、行列式中若两行成比例&#xff0c;则行列式为0 五、行列式的某一行…

Python | 三、函数

函数的形参和实参&#xff08;对应卡码网11题句子缩写&#xff09; 除非实参是可变对象&#xff0c;如列表、字典和集合&#xff0c;则此时形参会复制实参的地址&#xff0c;即此时二者指向同一个地址&#xff0c;因此在函数内对形参的操作会影响到实参除这种情况外&#xff0…

嵌入式应用开发学习建议

学习嵌入式应用开发需要掌握一定的编程语言、操作系统和硬件知识&#xff0c;以下是一些学习嵌入式应用开发的建议: 1&#xff09;学习C/C等编程语言&#xff1a;C/C是嵌入式系统最常用的编程语言之一&#xff0c;掌握这些语言的语法和特性可以帮助开发人员更好地理解嵌入式系…

What is `HttpServletRequestWrapper` does?

HttpServletRequestWrapper 是 Java Servlet API 中的一个类&#xff0c;作为 HttpServletRequest 接口的包装器&#xff08;Decorator&#xff09;实现。 该类设计为装饰者模式&#xff08;Decorator Pattern&#xff09;的一部分&#xff0c;允许开发人员通过包装现有的 Http…

【DP】53.最大子数组和

题目 法1&#xff1a;DP class Solution {public int maxSubArray(int[] nums) {if (nums null || nums.length 0) {return 0;}int n nums.length, res nums[0];int[] dp new int[n];dp[0] nums[0];for (int i 1; i < nums.length; i) {dp[i] Math.max(nums[i], d…

Orchestrator源码解读4-计划内切换

计划内切换 Graceful master promotion 通常因为升级&#xff0c;服务器为何等原因&#xff0c;需要按照计划将主库迁移到其他实例的情况。 计划内切换的拓扑结构改变的流程如下&#xff1a; orchestrator自己选或用户自己指定一个从库实例为新主库orchestrator将其他从库ch…

【江科大STM32合集】day2按键控制LED光敏传感器控制峰鸣器

【STM32合集】day2按键控制LED&光敏传感器控制峰鸣器 电路基础c语言基础main.ckey.c结果 实现一个键开关灯实验结果避坑 电路基础 运算放大器-在江科大51单片机b站视频&#xff08;AD/DA&#xff09;复习 原理&#xff1a;两个极端 同相输入端电压 》反相输入端 电压输出最…

【leetcode题解C++】707.设计链表

你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则还需要属性 prev 以指示链表中的上一个节点…

Git_01_push失败之解决办法

从本地服务器向云端服务器提交代码的过程中&#xff0c;碰到了以下问题&#xff1a; 提示账号没有push权限 rootlocalhost:~/repo/$ git push qnx HEAD:refs/for/develop Counting objects: 29, done. Delta compression using up to 32 threads. Compressing objects: 100% …