欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java 日志中 Marker 的使用示例詳解

 更新時間:2025年09月23日 14:21:20   作者:catoop  
Marker是SLF4J(以及Logback、Log4j 2)提供的一個接口,它本質(zhì)上是一個命名對象,你可以把它想象成一個可以附加到日志語句上的"標簽"或"戳記",本文給大家介紹Java日志中Marker的使用示例,感興趣的朋友跟隨小編一起看看吧

什么是Marker?

Marker是SLF4J(以及Logback、Log4j 2)提供的一個接口,它本質(zhì)上是一個命名對象。你可以把它想象成一個可以附加到日志語句上的"標簽"或"戳記"。

核心思想:有時,僅憑日志級別(如DEBUG, INFO, ERROR)不足以描述一條日志事件的特定屬性或類別。Marker就是為了滿足這種分類需求而設計的。

為什么使用Marker?

使用Marker的主要優(yōu)勢在于過濾路由。

1. 精細化的過濾

你可以在日志配置中編寫規(guī)則,例如:“將所有帶有SECURITY標記的日志,無論其級別是WARN還是DEBUG,都輸出到一個單獨的安全日志文件security.log中。”

2. 觸發(fā)特定操作

某些Appender(如SMTPAppender)可以被配置為當接收到帶有特定Marker(如NOTIFICATION)的ERROR日志時,立即發(fā)送郵件告警。

3. 更好的上下文信息

它為日志數(shù)據(jù)提供了額外的元數(shù)據(jù),使得在日志管理系統(tǒng)中(如ELK Stack、Splunk)進行搜索和聚合變得更加容易。

如何使用Marker?(代碼示例)

我們以SLF4J + Logback為例。

步驟1:定義Marker

通常,我們會將Marker定義為常量。

import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
// 定義Marker常量
public class AppConstants {
    // 定義一個名為 "SECURITY" 的 Marker
    public static final Marker SECURITY_MARKER = MarkerFactory.getMarker("SECURITY");
    // 定義另一個名為 "DB" 的 Marker
    public static final Marker DB_MARKER = MarkerFactory.getMarker("DB");
    // 可以定義更多...
    public static final Marker IMPORTANT_BUSINESS = MarkerFactory.getMarker("IMPORTANT_BUSINESS");
}

步驟2:在日志語句中使用Marker

SLF4J的Logger接口提供了帶有Marker參數(shù)的重載方法。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyService {
private static final Logger logger = LoggerFactory.getLogger(MyService.class);
	public void login(String username) {
        // ... 業(yè)務邏輯 ...
        if (loginFailed) {
            // 使用Marker:這是一個安全相關的警告日志
        	logger.warn(AppConstants.SECURITY_MARKER, "Failed login attempt for user: {}", username);
        }
    }
    public void queryDatabase() {
        logger.debug(AppConstants.DB_MARKER, "Executing SELECT * FROM users...");
        // ... 執(zhí)行查詢 ...
    }
}

步驟3:配置日志框架以響應Marker(Logback示例)

這是最關鍵的一步,Marker的強大功能在此體現(xiàn)。你需要在logback.xml中進行配置。

場景1:將帶有SECURITY標記的所有日志路由到單獨的文件

<configuration>
    <!-- 常規(guī)日志 Appender -->
    <appender name="FILE-APPENDER" class="ch.qos.logback.core.FileAppender">
        <file>myapp.log</file>
        <encoder>
            <pattern>%date [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 安全日志專用Appender -->
    <appender name="SECURITY-MARKER-APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>security.log</file>
        <filter class="ch.qos.logback.core.filter.MarkerFilter">
            <marker>SECURITY</marker>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder>
            <pattern>%date [%thread] %marker %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="debug">
        <appender-ref ref="FILE-APPENDER"/>
        <appender-ref ref="SECURITY-MARKER-APPENDER"/>
    </root>
</configuration>

場景2:當發(fā)生嚴重錯誤且?guī)в刑囟擞洉r發(fā)送郵件

<appender name="EMAIL" class="ch.qos.logback.classic.net.SMTPAppender">
    <smtpHost>smtp.mycompany.com</smtpHost>
    <to>ops@mycompany.com</to>
    <from>alerts@myapp.com</from>
    <subject>URGENT ERROR: %logger{20} - %m</subject>
    <layout class="ch.qos.logback.classic.PatternLayout">
        <pattern>%date %-5level %logger{35} - %message%n</pattern>
    </layout>
    <!-- 使用復合過濾器 -->
    <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
        <evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
            <!-- 指定 Marker 名稱 -->
            <marker>IMPORTANT_BUSINESS</marker>
        </evaluator>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
    <!-- 加上 LevelFilter 確保只有 ERROR 級別才觸發(fā) -->
    <filter class="ch.qos.logback.core.filter.LevelFilter">
        <level>ERROR</level>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
</appender>

高級用法:Marker繼承

一個Marker可以引用另一個Marker,形成父子關系。這在組織復雜的標記類別時非常有用。

// 創(chuàng)建一個父Marker
Marker parentMarker = MarkerFactory.getMarker("PARENT");
// 創(chuàng)建一個子Marker
Marker childMarker = MarkerFactory.getMarker("CHILD");
// 建立繼承關系
childMarker.add(parentMarker);

在過濾時,如果你在配置中設置了過濾父標記PARENT,那么所有帶有子標記CHILD的日志事件也會被匹配,因為它繼承了父標記的屬性。

最佳實踐和注意事項

  1. 重用Marker對象:將Marker定義為靜態(tài)常量并重用。創(chuàng)建Marker是有開銷的,不應該在每次日志調(diào)用時都創(chuàng)建。
  2. 保持名稱唯一且有意義:Marker的名稱應該清晰、一致,并能準確描述它所代表的類別。
  3. 謹慎使用:不要過度使用Marker。如果日志級別已經(jīng)足夠清晰,就不需要再引入Marker。
  4. 性能:雖然開銷很小,但檢查Marker的過濾操作確實會增加一點成本。
  5. 并非所有Appender都支持:確保你使用的Appender和Filter支持Marker。

總結

特性描述
是什么一個可以附加到日志事件上的命名標簽(Marker對象)
為什么提供比日志級別更豐富的分類方式,實現(xiàn)精細化過濾和路由
怎么用1. 定義Marker常量 2. 在日志API中傳入Marker 3. 在配置文件中使用MarkerFilter進行匹配和路由
高級特性支持繼承(父子關系)
關鍵點1.Marker不是給人看的 - 它不是為了讓開發(fā)者在閱讀日志時獲得更多信息,Marker不體現(xiàn)在日志內(nèi)容中
2.Marker是給日志系統(tǒng)用的 - 它是程序可讀的日志元數(shù)據(jù),用于自動化的日志處理
3.價值體現(xiàn)在配置中 - Marker的真正價值和意義,在于能夠在配置文件中定義如何處理帶有特定標記的日志
4.實現(xiàn)關注點分離 - 從開發(fā)角度,編碼時負責標記日志。從運維角度,日志運維人員負責配置具體Marker的處理方式,兩者解耦互不干擾。一個Marker 一般要有對應的處理場景才有意義。

到此這篇關于Java 日志中 Marker 的使用示例詳解的文章就介紹到這了,更多相關Java 日志 Marker 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 使用Java編寫控制JDBC連接、執(zhí)行及關閉的工具類

    使用Java編寫控制JDBC連接、執(zhí)行及關閉的工具類

    這篇文章主要介紹了如何使用Java來編寫控制JDBC連接、執(zhí)行及關閉的程序,包括一個針對各種數(shù)據(jù)庫通用的釋放資源的工具類的寫法,需要的朋友可以參考下
    2016-03-03
  • 為IntelliJ IDEA配置JVM參數(shù)的兩種方法

    為IntelliJ IDEA配置JVM參數(shù)的兩種方法

    在使用IntelliJ IDEA進行Java開發(fā)時,合理配置JVM參數(shù)對于優(yōu)化項目性能和資源管理至關重要,IntelliJ IDEA提供了兩種方便的方式來設置JVM參數(shù),本文將詳細介紹這兩種方法:通過工具欄編輯配置和通過服務編輯配置,需要的朋友可以參考下
    2024-12-12
  • SpringBoot使用TraceId進行日志鏈路追蹤的實現(xiàn)步驟

    SpringBoot使用TraceId進行日志鏈路追蹤的實現(xiàn)步驟

    有時候一個業(yè)務調(diào)用鏈場景,很長,調(diào)了各種各樣的方法,看日志的時候,各個接口的日志穿插,確實讓人頭大,所以為了解決這個問題,本文給大家介紹了SpringBoot使用TraceId進行日志鏈路追蹤的實現(xiàn)步驟,需要的朋友可以參考下
    2024-11-11
  • java stream中Collectors的用法實例精講

    java stream中Collectors的用法實例精講

    這篇文章主要為大家介紹了java stream中Collectors的用法實例精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • Java?Scanner?類最佳實踐

    Java?Scanner?類最佳實踐

    本文將深入解析Scanner類的核心功能、使用場景及最佳實踐,幫助開發(fā)者高效處理控制臺輸入、文件讀取等場景,感興趣的朋友一起看看吧
    2025-07-07
  • Springboot內(nèi)置的工具類之CollectionUtils示例講解

    Springboot內(nèi)置的工具類之CollectionUtils示例講解

    這篇文章主要介紹了Springboot內(nèi)置的工具類之CollectionUtils,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12
  • Spring之底層架構核心概念Environment及用法詳解

    Spring之底層架構核心概念Environment及用法詳解

    這篇文章主要介紹了Spring之底層架構核心概念-Environment,本文結合示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12
  • java EasyExcel實現(xiàn)動態(tài)列解析和存表

    java EasyExcel實現(xiàn)動態(tài)列解析和存表

    這篇文章主要為大家介紹了java EasyExcel實現(xiàn)動態(tài)列解析和存表示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • JAVA三種異常處理機制的具體使用

    JAVA三種異常處理機制的具體使用

    異常是程序在編譯或執(zhí)行的過程中可能出現(xiàn)的問題,本文主要介紹了JAVA三種異常處理機制的具體使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-06-06
  • Spring?AI集成DeepSeek實現(xiàn)流式輸出的操作方法

    Spring?AI集成DeepSeek實現(xiàn)流式輸出的操作方法

    本文介紹了如何在SpringBoot中使用Sse(Server-SentEvents)技術實現(xiàn)流式輸出,后端使用SpringMVC中的SseEmitter對象,前端使用EventSource對象監(jiān)聽SSE接口并展示數(shù)據(jù)流,通過這種方式可以提升用戶體驗,避免大模型響應速度慢的問題,感興趣的朋友一起看看吧
    2025-03-03

最新評論