聊聊logback的StatusManager
序
本文主要研究一下logback的StatusManager
StatusManager
ch/qos/logback/core/status/StatusManager.java
public interface StatusManager {/*** Add a new status message.* * @param status*/void add(Status status);/*** Obtain a copy of the status list maintained by this StatusManager.* * @return*/List<Status> getCopyOfStatusList();/*** Return the highest level of all the statii.* * @return*/// int getLevel();/*** Return the number of status entries.* * @return*/int getCount();/*** Add a status listener.* * @param listener*//*** Add a status listener. The StatusManager may decide to skip installation if* an earlier instance was already installed.* * @param listener* @return true if actually added, false if skipped*/boolean add(StatusListener listener);/*** ); Remove a status listener.* * @param listener*/void remove(StatusListener listener);/*** Clear the list of status messages.*/void clear();/*** Obtain a copy of the status listener list maintained by this StatusManager* * @return*/List<StatusListener> getCopyOfStatusListenerList();}
StatusManager接口针对status定义了add、getCopyOfStatusList、getCount、clear方法,针对StatusListener定义了add、remove、getCopyOfStatusListenerList方法
BasicStatusManager
ch/qos/logback/core/BasicStatusManager.java
public class BasicStatusManager implements StatusManager {final protected List<Status> statusList = new ArrayList<Status>();final protected CyclicBuffer<Status> tailBuffer = new CyclicBuffer<Status>(TAIL_SIZE);final protected LogbackLock statusListLock = new LogbackLock();final protected List<StatusListener> statusListenerList = new ArrayList<StatusListener>();final protected LogbackLock statusListenerListLock = new LogbackLock();//......
}
BasicStatusManager实现了StatusManager接口,它使用statusList及statusListLock来操作status,使用statusListenerList及statusListenerListLock来操作StatusListener;另外针对status还提供了tailBuffer
add status
public void add(Status newStatus) {// LBCORE-72: fire event before the count checkfireStatusAddEvent(newStatus);count++;if (newStatus.getLevel() > level) {level = newStatus.getLevel();}synchronized (statusListLock) {if (statusList.size() < MAX_HEADER_COUNT) {statusList.add(newStatus);} else {tailBuffer.add(newStatus);}}}
add方法先加锁,再判断是否超出限制,没有则添加到statusList,超出则添加到tailBuffer
getCopyOfStatusList
public List<Status> getCopyOfStatusList() {synchronized (statusListLock) {List<Status> tList = new ArrayList<Status>(statusList);tList.addAll(tailBuffer.asList());return tList;}}
getCopyOfStatusList则加锁,然后从statusList及tailBuffer获取status
clear
public void clear() {synchronized (statusListLock) {count = 0;statusList.clear();tailBuffer.clear();}}
clear则加锁,重置count,清空statusList及tailBuffer
add listener
public boolean add(StatusListener listener) {synchronized (statusListenerListLock) {if (listener instanceof OnConsoleStatusListener) {boolean alreadyPresent = checkForPresence(statusListenerList, listener.getClass());if (alreadyPresent)return false;}statusListenerList.add(listener);}return true;}private boolean checkForPresence(List<StatusListener> statusListenerList, Class<?> aClass) {for (StatusListener e : statusListenerList) {if (e.getClass() == aClass)return true;}return false;}
add listener方法先加锁,然后判断是否已经存在,不存在则添加到statusListenerList
remove
public void remove(StatusListener listener) {synchronized (statusListenerListLock) {statusListenerList.remove(listener);}}
remove则先加锁,然后从statusListenerList中移除
getCopyOfStatusListenerList
public List<StatusListener> getCopyOfStatusListenerList() {synchronized (statusListenerListLock) {return new ArrayList<StatusListener>(statusListenerList);}}
getCopyOfStatusListenerList则先加锁然后拷贝statusListenerList
Status
ch/qos/logback/core/status/Status.java
public interface Status {int INFO = 0;int WARN = 1;int ERROR = 2;int getLevel();int getEffectiveLevel();Object getOrigin();String getMessage();Throwable getThrowable();/*** @eprecated. Use getTimestamp instead.* @return*/@Deprecateddefault Long getDate() {return getTimestamp();}long getTimestamp();boolean hasChildren();void add(Status child);boolean remove(Status child);Iterator<Status> iterator();}
Status接口定义了getLevel、getEffectiveLevel、getOrigin、getMessage、getThrowable、getTimestamp、hasChildren、add、remove、iterator方法
StatusBase
ch/qos/logback/core/status/StatusBase.java
abstract public class StatusBase implements Status {static private final List<Status> EMPTY_LIST = new ArrayList<Status>(0);int level;final String message;final Object origin;List<Status> childrenList;Throwable throwable;long timestamp;public synchronized void add(Status child) {if (child == null) {throw new NullPointerException("Null values are not valid Status.");}if (childrenList == null) {childrenList = new ArrayList<Status>();}childrenList.add(child);}public synchronized boolean hasChildren() {return ((childrenList != null) && (childrenList.size() > 0));}public synchronized Iterator<Status> iterator() {if (childrenList != null) {return childrenList.iterator();} else {return EMPTY_LIST.iterator();}}public synchronized boolean remove(Status statusToRemove) {if (childrenList == null) {return false;}// TODO also search in childrens' childrenreturn childrenList.remove(statusToRemove);}public synchronized int getEffectiveLevel() {int result = level;int effLevel;Iterator<Status> it = iterator();Status s;while (it.hasNext()) {s = (Status) it.next();effLevel = s.getEffectiveLevel();if (effLevel > result) {result = effLevel;}}return result;}//......}
StatusBase声明实现Status接口,它通过childrenList来存储子status
InfoStatus
ch/qos/logback/core/status/InfoStatus.java
public class InfoStatus extends StatusBase {public InfoStatus(String msg, Object origin) {super(Status.INFO, msg, origin);}public InfoStatus(String msg, Object origin, Throwable t) {super(Status.INFO, msg, origin, t);}}
InfoStatus继承了StatusBase,它的level为Status.INFO
WarnStatus
ch/qos/logback/core/status/WarnStatus.java
public class WarnStatus extends StatusBase {public WarnStatus(String msg, Object origin) {super(Status.WARN, msg, origin);}public WarnStatus(String msg, Object origin, Throwable t) {super(Status.WARN, msg, origin, t);}}
WarnStatus继承了StatusBase,它的level为Status.WARN
ErrorStatus
ch/qos/logback/core/status/ErrorStatus.java
public class ErrorStatus extends StatusBase {public ErrorStatus(String msg, Object origin) {super(Status.ERROR, msg, origin);}public ErrorStatus(String msg, Object origin, Throwable t) {super(Status.ERROR, msg, origin, t);}}
ErrorStatus继承了StatusBase,它的level为Status.ERROR
小结
logback定义了StatusManager用于管理status及其listener,其add方法会回调listener,之后加锁,再判断是否超出限制,没有则添加到statusList,超出则添加到tailBuffer;Status是个接口,它有一个抽象类为StatusBase,而InfoStatus、WarnStatus、ErrorStatus都继承了StatusBase。
相关文章:
聊聊logback的StatusManager
序 本文主要研究一下logback的StatusManager StatusManager ch/qos/logback/core/status/StatusManager.java public interface StatusManager {/*** Add a new status message.* * param status*/void add(Status status);/*** Obtain a copy of the status list maintain…...

[PyTorch][chapter 61][强化学习-免模型学习1]
前言: 在现实的学习任务中,环境 其中的转移概率P,奖赏函数R 是未知的,或者状态X也是未知的 称为免模型学习(model-free learning) 目录: 1: 蒙特卡洛强化学习 2:同策略-蒙特卡洛强化学习 3&am…...
网络运维Day04-补充
文章目录 周期性计划任务周期性计划任务使用案例一案例二 周期性计划任务 在固定时间可以完成相同的任务,被称之为周期性计划任务由crond服务提供需要将定时任务,写到一个文件书写格式如下 分 时 日 月 周 任务(绝对路径)分:0-59时ÿ…...

前端埋点方式
前言: 想要了解用户在系统中所做的操作,从而得出用户在本系统中最常用的模块、在系统中停留的时间。对于了解用户的行为、分析用户的需求有很大的帮助,想实现这种需求可以通过前端埋点的方式。 埋点方式: 1.什么是埋点?…...
iOS导航栏返回按钮
导航栏返回按钮隐藏: override func pushViewController(_ viewController: UIViewController, animated: Bool) {if let vc self.viewControllers.last {let backItem UIBarButtonItem()backItem.title ""vc.navigationItem.backBarButtonItem backI…...

2023中国视频云市场报告:腾讯云音视频解决方案份额连续六次蝉联榜首,加速全球化布局
近日,国际数据公司(IDC)发布了《中国视频云市场跟踪(2023上半年)》报告,腾讯云音视频的解决方案份额连续六次蝉联榜首,并在视频生产创作与媒资管理市场份额中排名第一。同时,在实时音…...
jpa Repository的常用写法总结
一、前言 之前项目在xml中写sql,感觉标签有很多,比较灵活; 最近在写新项目,使用了jpa,只能在java中写sql了,感觉不太灵活,但是也得凑付用。 以下总结下常用入参出参写法。 二、Repository代…...

笔记本电脑 禁用/启用 自带键盘
现在无论办公还是生活 很多人都会选择笔记本电脑 但很多人喜欢机械键盘 或者 用一些外接键盘 但是很多时候我们想操作 会碰到笔记本原来的键盘导致错误操作 那么 我们就需要将笔记本原来的键盘禁用掉 我们先以管理员身份运行命令窗口 然后 有两个命令 禁用默认键盘 sc conf…...

基于 golang 从零到一实现时间轮算法 (三)
引言 本文参考小徐先生的相关博客整理,项目地址为: https://github.com/xiaoxuxiansheng/timewheel/blob/main/redis_time_wheel.go。主要是完善流程以及记录个人学习笔记。 分布式版实现 本章我们讨论一下,如何基于 redis 实现分布式版本的…...

k8s 1.28安装
容器运行时,containerd 按照官方的指导,需要安装runc和cni插件,提示的安装方式,有三种: 二进制安装包源码apt-get 或 dnf安装 我们这里选用第三种,找到docker官方提供的安装方式 ubuntu-containerd # A…...

安装anaconda时控制台conda-version报错
今天根据站内的一篇博客教程博客在此安装anaconda时,检查conda版本时报错如下: >>>>>>>>>>>> ERROR REPORT <<<<<<<<<<<< Traceback (most recent call last): File “D:\An…...

链表(1)
目录 单链表 主函数test.c test1 test2 test3 test4 头文件&函数声明SList.h 函数实现SList.c 打印SLPrint 创建节点CreateNode 尾插SLPushBack 头插SLPushFront 头删SLPopBck 尾删SLPopFront 易错点 本篇开始链表学习。今天主要是单链表&OJ题目。 单链…...

智慧农业:农林牧数据可视化监控平台
数字农业是一种现代农业方式,它将信息作为农业生产的重要元素,并利用现代信息技术进行农业生产过程的实时可视化、数字化设计和信息化管理。能将信息技术与农业生产的各个环节有机融合,对于改造传统农业和改变农业生产方式具有重要意义。 图扑…...

知识注入以对抗大型语言模型(LLM)的幻觉11.6
知识注入以对抗大型语言模型(LLM)的幻觉 摘要1 引言2 问题设置和实验2.1 幻觉2.2 生成响应质量 3 结果和讨论3.1 幻觉3.2 生成响应质量 4 结论和未来工作 摘要 大型语言模型(LLM)内容生成的一个缺点是产生幻觉,即在输…...
机器人物理交互场景及应用的实际意义
机器人物理交互场景是指机器人与物理世界或人类进行实际的物理互动和交互的情境。这些场景涉及机器人在不同环境和应用中使用其物理能力,以执行任务、提供服务或与人类互动。 医疗协助: 外科手术助手:机器人可以用于外科手术,提供…...

Kubernetes Dashboard 用户名密码方式登录
Author:rab 前言 为了 K8s 集群安全,默认情况下 Dashboard 以 Token 的形式登录的,那如果我们想以用户名/密码的方式登录该怎么操作呢?其实只需要我们创建用户并进行 ClusterRoleBinding 绑定即可,接下来是具体的操作…...
Redisson中的对象
Redisson - 是一个高级的分布式协调Redis客服端,能帮助用户在分布式环境中轻松实现一些Java的对象 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, …...

GNU ld链接器 lang_process()(二)
一、ldemul_create_output_section_statements() 位于lang_process()中11行 。 该函数用于创建与目标有关的输出段的语句。这些语句将用于描述输出段的属性和分配。 void ldemul_create_output_section_statements (void) {if (ld_emulation->create_output_section_sta…...

《国产服务器操作系统发展报告(2023)》重磅发布
11月1日,《国产服务器操作系统发展报告(2023)》(以下简称“报告”)在 2023 云栖大会上正式发布,开放原子开源基金会理事长孙文龙、中国信息通信研究院副总工程师石友康、阿里云基础软件部副总裁马涛、浪潮信…...

【PTE-day03 报错注入】
报错注入 1、报错注入 group by count2、报错注入 extractvalue3、报错注入updatexml1、报错注入 group by count http://124.222.124.9:8888/Less-5/?id=-1 union select 1,count(*),concat((select database()),ceil(rand(0)*2)) as a from information_schema.tables grou…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...