程序中的log4j、stderr、stdout日志区别

news2024/10/2 16:21:31

使用 databricks 的过程中,发现他将日志分为 log4j、stderr、stdout日志。了解日志是调试程序关键技能。顺着这个思路,我认真学习了一下这几个日志的区别。

image.png

目录

    • Java 中的日志
      • 目录结构
      • 使用log4j记录日志
      • 向标准输出和标准错误输出写信息
      • 运行结果
    • 以python为例
    • 高阶讲解
    • 总结

这些日志文件有不同的用途和记录内容:

  1. log4j-active.log:这是由log4j框架生成的日志文件。log4j是一个用于Java应用程序的日志记录库,能够灵活地控制日志输出的格式和目标(如文件、控制台等)。这个日志文件通常包含应用程序运行时的各种详细信息,包括调试信息、错误消息、警告等。

  2. stderr:标准错误输出日志文件。这个文件通常记录程序运行过程中产生的错误信息和异常。这些错误信息对于调试和解决程序问题非常重要。标准错误输出通常用于分离错误消息和正常的程序输出,便于识别和处理。

  3. stdout:标准输出日志文件。这个文件记录程序的正常输出信息,比如运行结果、状态信息等。标准输出通常显示程序的正常执行流程和结果,用于监控程序的运行状态。

总结起来:

  • log4j-active.log:记录应用程序的详细运行日志,包括调试信息和错误。
  • stderr:记录程序运行过程中的错误和异常。
  • stdout:记录程序的正常输出信息和运行状态。

当然可以,下面是一些Java代码示例,展示如何使用log4j记录日志,以及如何向标准输出和标准错误输出写信息。

Java 中的日志

目录结构

your-project
│
├── src
│   ├── main
│   │   ├── java
│   │   │   └── Log4jExample.java
│   │   └── resources
│   │       └── log4j.properties
│   └── test
│       ├── java
│       └── resources
│
├── pom.xml
└── ...

使用log4j记录日志

首先,需要在项目中引入log4j依赖(如果使用Maven):

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

然后,确保log4j.properties文件放在项目的src/main/resources目录下。如果这个目录不存在,可以手动创建。配置log4j.properties文件:

# 设置日志级别为DEBUG
log4j.rootLogger=DEBUG, file

# 配置文件输出
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=log4j-active.log
log4j.appender.file.MaxFileSize=5MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c - %m%n

最后,编写Java代码使用log4j记录日志:

import org.apache.log4j.Logger;

public class Log4jExample {
    private static final Logger logger = Logger.getLogger(Log4jExample.class);

    public static void main(String[] args) {
        logger.debug("This is a debug message");
        logger.info("This is an info message");
        logger.warn("This is a warn message");
        logger.error("This is an error message");
        logger.fatal("This is a fatal message");
    }
}

目录结构如下:
image.png

运行后日志
image.png

向标准输出和标准错误输出写信息

使用Java的System.out和System.err可以分别向标准输出和标准错误输出写信息:

public class StdOutErrExample {
    public static void main(String[] args) {
        // 向标准输出写信息
        System.out.println("This is a standard output message");

        // 向标准错误输出写信息
        System.err.println("This is a standard error message");

        // 模拟一个错误
        try {
            int result = 10 / 0;
        } catch (ArithmeticException e) {
            System.err.println("Caught an exception: " + e.getMessage());
        }
    }
}

image.png

运行结果

  1. log4j-active.log 文件将包含:

    2024-07-09 10:00:00 [main] DEBUG Log4jExample - This is a debug message
    2024-07-09 10:00:00 [main] INFO  Log4jExample - This is an info message
    2024-07-09 10:00:00 [main] WARN  Log4jExample - This is a warn message
    2024-07-09 10:00:00 [main] ERROR Log4jExample - This is an error message
    2024-07-09 10:00:00 [main] FATAL Log4jExample - This is a fatal message
    
  2. stdout 输出:

    This is a standard output message
    
  3. stderr 输出:

    This is a standard error message
    Caught an exception: / by zero
    

通过这些示例代码,可以看到如何在Java应用程序中使用log4j记录日志,以及如何使用标准输出和标准错误输出来记录不同类型的信息。

以python为例

  1. log4j-active.log (log4j 输出):
    这是使用log4j库记录的应用程序日志。通常用于记录应用程序的运行状态、错误等信息。
import logging
from logging import FileHandler

logger = logging.getLogger('myapp')
logger.setLevel(logging.DEBUG)
handler = FileHandler('log4j-active.log')
logger.addHandler(handler)

logger.info("应用程序启动")
logger.error("发生错误:连接数据库失败")
  1. stderr (标准错误):
    用于输出错误信息和诊断信息。在Python中,可以通过sys.stderr来写入。
import sys

def divide(a, b):
    if b == 0:
        print("错误:除数不能为零", file=sys.stderr)
        return None
    return a / b

result = divide(10, 0)
  1. stdout (标准输出):
    用于输出程序的正常信息。在Python中,print()函数默认输出到stdout。
print("这是标准输出信息")

# 也可以显式地使用sys.stdout
import sys
sys.stdout.write("另一种写入标准输出的方式\n")

主要区别:

  • log4j-active.log: 专门的日志文件,可配置级别,便于长期存储和分析。
  • stderr: 用于即时的错误报告,通常显示在控制台。
  • stdout: 用于常规程序输出,也通常显示在控制台。

在实际应用中,stderr和stdout经常被重定向到文件中进行日志记录。log4j提供了更灵活的日志管理功能。

高阶讲解

  1. Log4j 详解

Log4j 提供了更复杂的日志管理功能,包括不同的日志级别和灵活的输出配置。

import org.apache.log4j.*;

public class AdvancedLog4jExample {
    private static final Logger logger = Logger.getLogger(AdvancedLog4jExample.class);

    public static void main(String[] args) {
        // 配置 Log4j
        configureLog4j();

        // 使用不同级别的日志
        logger.trace("这是一个 TRACE 级别的消息");
        logger.debug("这是一个 DEBUG 级别的消息");
        logger.info("这是一个 INFO 级别的消息");
        logger.warn("这是一个 WARN 级别的消息");
        logger.error("这是一个 ERROR 级别的消息");
        logger.fatal("这是一个 FATAL 级别的消息");

        // 记录异常
        try {
            throw new RuntimeException("模拟的异常");
        } catch (RuntimeException e) {
            logger.error("捕获到异常", e);
        }
    }

    private static void configureLog4j() {
        // 创建控制台附加器
        ConsoleAppender consoleAppender = new ConsoleAppender();
        consoleAppender.setLayout(new PatternLayout("%d [%t] %-5p %c - %m%n"));
        consoleAppender.setThreshold(Level.INFO);
        consoleAppender.activateOptions();
        Logger.getRootLogger().addAppender(consoleAppender);

        // 创建文件附加器
        try {
            FileAppender fileAppender = new FileAppender(
                new PatternLayout("%d %-5p [%c{1}] %m%n"), 
                "log4j-active.log", 
                true);
            fileAppender.setThreshold(Level.DEBUG);
            Logger.getRootLogger().addAppender(fileAppender);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  1. System.err 和 System.out 的高级用法

虽然 System.err 和 System.out 相对简单,但它们也有一些高级用法:

import java.io.*;

public class AdvancedSystemIOExample {
    public static void main(String[] args) throws IOException {
        // 重定向 System.out 到文件
        PrintStream outFile = new PrintStream(new FileOutputStream("stdout.log"));
        System.setOut(outFile);

        // 重定向 System.err 到文件
        PrintStream errFile = new PrintStream(new FileOutputStream("stderr.log"));
        System.setErr(errFile);

        // 现在标准输出会被写入 stdout.log
        System.out.println("这条消息会被写入 stdout.log 文件");

        // 标准错误会被写入 stderr.log
        System.err.println("这条错误消息会被写入 stderr.log 文件");

        // 使用自定义的 PrintStream
        PrintStream customOut = new PrintStream(System.out) {
            @Override
            public void println(String x) {
                super.println("自定义前缀: " + x);
            }
        };

        System.setOut(customOut);
        System.out.println("这条消息会有自定义前缀");

        // 恢复原始的标准输出和错误流
        System.setOut(System.out);
        System.setErr(System.err);
    }
}
  1. 日志使用的最佳实践
  • 使用适当的日志级别:TRACE 用于非常详细的信息,DEBUG 用于调试,INFO 用于一般信息,WARN 用于警告,ERROR 用于错误,FATAL 用于严重错误。
  • 避免在生产环境中使用 System.out 和 System.err,而应该使用成熟的日志框架。
  • 在记录异常时,同时记录异常消息和堆栈跟踪。
  • 使用参数化日志消息来提高性能:
    logger.debug("User {} logged in from IP {}", username, ipAddress);
    
  • 定期归档和轮转日志文件以管理磁盘空间。
  • 在多线程环境中使用线程安全的日志框架(如 Log4j)。
  1. 日志与应用程序性能

过度的日志记录可能会影响应用程序的性能。应该权衡日志的详细程度和应用程序的性能需求。在性能关键的部分,可以使用条件日志记录:

if (logger.isDebugEnabled()) {
    logger.debug("Complex object state: " + expensiveToStringMethod());
}

这样可以避免在日志级别不够的情况下执行昂贵的字符串操作。

总结

  1. log4j-active.log (Log4j 输出):
    这就像是一本详细的日记本。你可以在里面记录各种重要程度的信息,从小事到大事都有。它很灵活,你可以决定记录什么,怎么记,记到哪里。比如,你可以只记录重要的事,或者把所有细节都记下来。这本日记可以保存很久,方便以后查阅。

  2. stderr (标准错误):
    想象这是一个紧急警报系统。当出现严重问题时,它会立即发出警报。就像火警警报器,它的目的是立刻引起注意。通常,这些警报会直接显示在屏幕上,让你能立即看到。

  3. stdout (标准输出):
    这更像是一个普通的广播系统。它用来传达程序正常运行时的信息,就像商场里的广播。它不像警报那么紧急,但仍然是传递信息的重要渠道。

总的来说:

  • Log4j 就像一个全面的日志系统,可以记录各种级别的信息,便于长期存储和分析。
  • stderr 是用来报告紧急问题的,就像警报器。
  • stdout 用于日常的信息输出,像普通广播。

在实际使用中:

  • 专业的开发者通常更喜欢用 Log4j 这样的系统,因为它更强大,可以更好地管理所有类型的日志。
  • stderr 和 stdout 更简单,常用于快速输出或者在简单的程序中。

记住,好的日志习惯就像是给未来的自己或其他开发者留下清晰的"路标",帮助理解和解决问题。选择合适的日志方式,可以让程序更容易维护和调试。

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

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

相关文章

前端八股文 闭包的理解

什么是闭包 闭包是指有权访问另一个函数作用域中的变量的函数 ——《JavaScript高级程序设计》 &#xff08;闭包 内层函数 引用的外层函数的变量&#xff09; 下面就是一个简单的闭包 闭包不一定必须有 return 闭包不一定有内存泄漏 闭包 什么时候用到 return 就是 外部…

Flutter-实现物理小球碰撞效果

效果 引言 在Flutter应用中实现物理动画效果,可以大大提升用户体验。本文将详细介绍如何在Flutter中创建一个模拟物理碰撞的动画小球界面,主要代码实现基于集成sensors_plus插件来获取设备的加速度传感器数据。 准备工作 在开始之前,请确保在pubspec.yaml文件中添加senso…

中职网络安全Server2216

任务环境说明&#xff1a;✓ 服务器场景&#xff1a;Server2216&#xff08;开放链接&#xff09;✓ 用户名:root密码&#xff1a;1234561.黑客通过网络攻入本地服务器,通过特殊手段在系统中建立了多个异常进程找出启动异常进程的脚本&#xff0c;并将其绝对路径作为Flag值提交…

2.17分一区文献精读:机器学习:乳腺癌预后预测的统计和机器学习模型的开发及内外部验证:队列研究-摘要

#精医求精&#xff0c;文献阅读 大家好&#xff0c;我是蔡老师&#xff0c;一个立志学会所有医学大数据分析模型的女子 今天我们从文献阅读开始 这篇文章的影响因子为17分&#xff0c;全文名称为《Development and internal-external validation of statistical and machine l…

Tensorflow之损失函数与交叉熵

损失函数&#xff1a;预测值与已知答案之间的差距 NN优化目标&#xff1a;loss最小{mse&#xff0c; 自定义&#xff0c; ce) 均方误差tensorflow实现&#xff0c;loss_mse tf.reduce_mean(tf.sqrue(y_-y) 预测酸奶日销量&#xff0c;y&#xff0c;x1, x2是影响日销量的因素…

什么是RPC?有哪些RPC框架?

定义 RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;是一种允许运行在一台计算机上的程序调用另一台计算机上子程序的技术。这种技术屏蔽了底层的网络通信细节&#xff0c;使得程序间的远程通信如同本地调用一样简单。RPC机制使得开发者能够构建分…

leetcode--恢复二叉搜索树

leetcode地址&#xff1a;恢复二叉搜索树 给你二叉搜索树的根节点 root &#xff0c;该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下&#xff0c;恢复这棵树 。 示例 1&#xff1a; 输入&#xff1a;root [1,3,null,null,2] 输出&#xff1a;[3,1,null…

Mac下flutter运行iOS模拟器

上篇flutter环境安装&#xff08;Macvscode&#xff09;已经将vscode和xcode等开发环境都搭建起来了&#xff0c;vscode新建工程还是比较方便的&#xff0c;那么&#xff0c;建立好了之后&#xff0c;我们怎么看效果呢&#xff1f; 1. vscode新建项目 通过 vscode的命令命板(…

Collection 和 Collections 的区别与用法

Collection 和 Collections 的区别与用法 1、Collection 接口1.1 主要特点1.2 常见方法 2、 Collections 工具类2.1 主要特点2.2 常见方法 3、示例代码3.1 使用 Collection 接口3.2 使用 Collections 工具类 4、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收…

JAVA从入门到精通之入门初阶(一)

1. 认识变量 一、 首先变量名要遵循如下命名规则&#xff1a; 1. 变量名只能由字母、数字和下划线组成 2. 变量名必须以字母或下划线开头 3. 变量名大小写敏感 4. 变量名不能使用关键字&#xff0c;如const、static等 5. 变量名应具有描述性&#xff0c;以便于代码的可读性…

三级_网络技术_12_路由设计技术基础

1.R1、R2是一个自治系统中采用RIP路由协议的两个相邻路由器&#xff0c;R1的路由表如下图(a)所示&#xff0c;当R1收到R2发送的如下图(b)的(V.D)报文后&#xff0c;R1更新的4个路由表项中距离值从上到下依次为0、3、3、4 那么&#xff0c;①②③④可能的取值依次为()。 0、4、…

240709_昇思学习打卡-Day21-文本解码原理--以MindNLP为例

240709_昇思学习打卡-Day21-文本解码原理–以MindNLP为例 今天做根据前文预测下一个单词&#xff0c;仅作简单记录及注释。 一个文本序列的概率分布可以分解为每个词基于其上文的条件概率的乘积 &#x1d44a;_0:初始上下文单词序列&#x1d447;: 时间步当生成EOS标签时&a…

使用OpenCV的absdiff函数报错

1.absdiff用法 absdiff函数用于计算两个输入图像之间每个像素的差异&#xff0c;并返回结果图像。 void cv::absdiff ( InputArray src1,InputArray src2,OutputArray dst ) //eg&#xff1a;比较两图像的差异 /*cv::Mat diff;cv::absdiff(depLeft32, imDepth, diff…

Spring MVC深入理解之源码实现

1、SpringMVC的理解 1&#xff09;谈谈对Spring MVC的了解 MVC 是模型(Model)、视图(View)、控制器(Controller)的简写&#xff0c;其核心思想是通过将业务逻辑、数据、显示分离来组织代码。 Model&#xff1a;数据模型&#xff0c;JavaBean的类&#xff0c;用来进行数据封装…

CLion学习笔记-cmake编译和多main函数编译

这里就不讲怎么配置clion了 项目名字 pcl_kdtree_search 1.新建一个工程名字自己取&#xff0c;我这里用自己学习pcl的&#xff0c;加一个main函数&#xff0c;这个时候Cmake里边就是这样的。 #声明要求的cmake最低版本 cmake_minimum_required(VERSION 3.19) #声明一个工程…

【每日一练】python基础入门实例

""" 幼儿园加法练习题 题数不限 每满100分奖励10个棒棒糖 要求&#xff1a; 1.使用三目运算符与基础运算的对比 2.随机数字相加 3.调用函数 4.循环执行练习题 5.有计算分数 6.有时间停止休眠 """ #导入随机模块 import random #导入时间模块 imp…

华为乾崑智驾加持:深蓝S07首次亮相

最近&#xff0c;特斯拉FSD即将入华的消息&#xff0c;让智能驾驶成为了汽车行业热议的焦点&#xff0c;而当新能源汽车的代表企业深蓝汽车&#xff0c;与全球领先的华为乾崑智驾强强联手&#xff0c;一场颠覆性的智能出行变革也已蓄势待发。 7月8日&#xff0c;深蓝汽车携其最…

uniapp自动升级

一、创建云服务空间&#xff08;https://unicloud.dcloud.net.cn&#xff09; 云空间用于关联需要版本控制升级的项目&#xff0c;如果已拥有云空间则省略此步骤。 二、搭建 uni升级中心 - 后台管理系统&#xff08;升级中心 uni-upgrade-center - Admin&#xff09; uni-adm…

DDR3 SO-DIMM 内存条硬件总结(一)

最近在使用fpga读写DDR3&#xff0c;板子上的DDR3有两种形式与fpga相连&#xff0c;一种是直接用ddr3内存颗粒&#xff0c;另一种是通过内存条的形式与fpga相连。这里我们正好记录下和ddr3相关的知识&#xff0c;先从DDR3 SO-DIMM 内存条开始。 1.先看内存条的版本 从JEDEC下载…

Elasticsearch:深度学习与机器学习:了解差异

作者&#xff1a;来自 Elastic Elastic Platform Team 近年来&#xff0c;两项突破性技术一直站在创新的最前沿 —— 机器学习 (machine learning - ML) 和深度学习 (deep learning - DL)。人工智能 (AI) 的这些子集远不止是流行语。它们是推动医疗保健、金融等各行业进步的关键…