聊聊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…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...