01、记录器的生命周期

Serilog 大多数情况下“只需使用”,并且在创建和处理日志记录器时不需要过多考虑。然而,由于以下原因:

某些接收器(sink)涉及后台进程,特别是那些使用网络的接收器;

一些接收器(尤其是文件和滚动文件接收器)所持有的资源;

因此,某些使用模式在效果和可靠性上表现得更好。

1、在所有应用程序中

使用 Serilog 最简单的方法是通过全局 Log 类:

Log.Logger = new LoggerConfiguration()
.WriteTo.File(@"myapp\log.txt")
.CreateLogger();
Log.Information("Hello!");
// Your application runs, then:
Log.CloseAndFlush();

如果这样做,只需配置一次日志记录器,然后在应用程序的整个生命周期中使用它。

要创建更专业的日志记录器:

调用 Log.ForContext(...) 来接收一个附加了额外属性的 ILogger;这不需要任何特殊的关闭/刷新逻辑,因为这将由父日志记录器处理。

在少数情况下,可以使用单独的 LoggerConfiguration 创建一个额外的 ILogger,并使用 WriteTo.Logger(Log.Logger) 将事件传递到根日志记录器;在这种情况下,必须遵循下面的处置逻辑。

2、不使用 Log

如果您不希望使用静态 Log 类,可以使用 LoggerConfiguration 创建一个 ILogger。

using (var log = new LoggerConfiguration()
.WriteTo.File(@"myapp\log.txt")
.CreateLogger())
{
log.Information("Hello again!");
// Your app runs, then disposal of `log` flushes any buffers
}

在这种情况下,不使用 Log.CloseAndFlush()。相反,当应用程序不再需要日志记录器时,会进行处置。

只有通过 LoggerConfiguration 创建的根日志记录器需要以这种方式处理。从 ForContext() 和类似方法返回的 ILoggers 不需要任何特殊处理。

3、使用 IoC 容器

请参见 Autofac 集成示例,了解如何与 Autofac IoC 容器一起使用可注入的 ILoggers。如果您希望更新此页面以提供其他容器的说明,请提出问题。

02、可靠性

Serilog 认为,综合考虑,日志记录的优先级低于其他应用程序代码,绝不应在可避免的情况下影响正在运行的应用程序的操作。

在实践中,这主要转化为一种处理 Serilog 中异常的策略。在这个过程中会对可用性做出一些妥协。本文档解释了作为 Serilog 库用户您可以期待的内容,以及如果您正在扩展 Serilog,如何编写与其余代码库良好配合的代码。

1、配置

在配置时,即调用 LoggerConfiguration 方法时,错误分为两类。

运行时配置错误

如果由于主机机器的运行时状态无法配置接收器(sink),Serilog 将捕获任何导致的异常并将其写入 SelfLog(参见调试和诊断)。

// X: does not exist, but this is a runtime condition
// so Serilog will not fail here.
Log.Logger = new LoggerConfiguration()
.WriteTo.File("X:\\log.txt")
.CreateLogger();

这种策略可以防止部署环境中的暂时性问题导致原本有效的应用程序失败。

开发时不变性违规

在配置时,对于永远无法有效执行的代码(例如,违反 API 不变性的情况)会做出一定的容忍:

// Null is never acceptable as a filename, so
// Seriog will throw ArgumentNullException here.
Log.Logger = new LoggerConfiguration()
.WriteTo.File(null)
.CreateLogger();

这一决定基于两个原因:

这些错误不太可能通过开发者的工作站或测试环境,因为日志记录配置发生在启动时,并且应该总是以相同的方式失败。

允许无效值或静默忽略它们会导致意外行为,这很难调试,并使库的正确配置更加困难。

如果您愿意,可以将日志记录配置代码包装在 try/catch 结构中,以避免异常传播,但不推荐这样做。

接收器作者: 实现这一点的责任在于接收器的实现本身,因此需要明确考虑/处理。

2、写入日志事件

事件分阶段写入日志记录管道。首先调用记录器,然后构造事件,接下来对其进行丰富,应用过滤器,最后将其传递(“发出”)到配置的接收器。

调用记录器

ILogger 和静态 Log 类上的方法会静默忽略无效参数:

// Safely does nothing
Log.Warning(null);

这样做是因为在执行频率较低的代码路径中的日志记录语句可能不会被测试,因此不应在运行时失败。

构造日志事件

当构造日志事件时,Serilog 可能会反射任何解构对象的属性。

如果这些属性抛出异常,Serilog 会捕获错误,写入 SelfLog,并在解构对象中包含错误信息而不是属性值。

关于类型加载的说明

如果一个应用程序在没有所需依赖项的情况下部署,加载器可能会无法找到/构造有效类型。这是一个主要的应用程序配置错误,可能在解构过程中或稍后,例如在 JIT 阶段显现出来。这种情况非常罕见。在这种情况下,Serilog 不会做任何事情,允许错误传播。

装饰器

装饰器向日志事件添加属性。装饰器可能会抛出异常:Serilog 会捕获这些异常并写入 SelfLog。

装饰器作者: Serilog 自身实现了这一策略,装饰器在意外失败时应抛出异常(尽管出于性能考虑,避免这种情况是明智的)。

过滤器

过滤器决定哪些事件会被传递到日志记录管道中。过滤器不会抛出异常,而是写入 SelfLog:

// No events will be carried through this pipeline, but no
// errors will be thrown.
Log.Logger = new LoggerConfiguration()
.Filter.ByExcluding(e => { throw new Exception(); })
.WriteTo.ColoredConsole()
.CreateLogger();

过滤器作者: 如果过滤器意外抛出异常,这被视为一个错误——这对性能和功能的影响是显著的。

发出到接收器

Serilog 捕获并将接收器引发的任何异常写入 SelfLog。通常情况下,这些异常是正常使用 Serilog 时发生的绝大多数异常。

接收器作者: 接收器在失败时应抛出异常。Serilog 将一致地捕获和处理这些异常。

关于不可捕获的异常的说明

需要注意的是,仍然存在一类不可捕获的异常,Serilog 被迫传播这些异常,例如 StackOverflowException 等。

3、异步/批处理网络操作

许多 Serilog 接收器使用相同的基础 PeriodicBatchingSink 架构。这些接收器(例如批处理的 Azure 表存储接收器、CouchDB 接收器、RavenDB 接收器和 Seq 接收器(在非持久模式下))会缓存日志事件,从而减少将日志数据传输到远程主机所需的网络往返次数。

Log.Logger = new LoggerConfiguration()
.WriteTo.CouchDB("api/missing")
.CreateLogger()

这些接收器在写入事件时不会失败,但可能会在后台异步发送批次时失败。当批次发送失败时,详细信息将写入 SelfLog。

正在发送的批次将保留在内存中,并会以逐渐增加的时间间隔重试,时间间隔从 5 秒逐步增加到 10 分钟。增加的时间间隔可以保护接收器,在经历一段停机后重新上线时,避免连接洪水。

如果经过 4 次尝试仍无法发送批次,该批次将被丢弃并尝试新的批次。这可以防止接收器拒绝的“坏”事件堵塞日志记录器。后续的成功将允许其他批次正常传输。

如果再有两次尝试失败(总共 6 次失败,通常在 10 分钟左右),等待的日志事件的整个缓冲区将被丢弃。这可以防止在日志事件长时间无法送达时出现内存不足错误。

如果连接仍然中断,缓冲区将每 10 分钟刷新一次,直到重新建立连接。

接收器作者: 通过从 PeriodicBatchingSink 派生,可以默认提供此行为。如果需要不同的行为,则需要实现自定义的 ILogEventSink。

:相关源码都已经上传至代码库,有兴趣的可以看看。https://gitee.com/hugogoos/Planner

Serilog文档翻译系列(八) - 记录器的生命周期、可靠性的更多相关文章

  1. 【微信小程序开发•系列文章六】生命周期和路由

    这篇文章理论的知识比较多一些,都是个人观点,描述有失妥当的地方希望读者指出. [微信小程序开发•系列文章一]入门 [微信小程序开发•系列文章二]视图层 [微信小程序开发•系列文章三]数据层 [微信小程 ...

  2. Unity3D实践系列04, 脚本的生命周期

    Unity3D脚本生命周期是指从脚本的最初唤醒到脚本最终销毁的整个过程.生命周期的各个方法被封装到了MonoBehaviour类中.具体来说如下: 1.In Editor Mode 编辑模式 当在编辑 ...

  3. 死磕 java线程系列之线程的生命周期

    (手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 简介 大家都知道线程是有生命周期,但是彤哥可以认真负责地告诉你网上几乎没有一篇文章讲得是完全正确的. 常见的错 ...

  4. Spring学习记录(八)---Bean的生命周期

    之前说过,在调用下面时,就创建了容器和对象 ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml&quo ...

  5. Vue系列之 => 钩子函数生命周期

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. 八、spring生命周期之BeanPostProcessor

    BeanPostProcessor我们一般称为Bean的后置处理器,它与我们前面介绍的InitialingBean.init-method等一样,都是在bean的初始化时被调用,具体的用法我们在举例中 ...

  7. Vue系列(二):发送Ajax、JSONP请求、Vue生命周期及实例属性和方法、自定义指令与过渡

    上一篇:Vue系列(一):简介.起步.常用指令.事件和属性.模板.过滤器 一. 发送AJAX请求 1. 简介 vue本身不支持发送AJAX请求,需要使用vue-resource.axios等插件实现 ...

  8. Android Studio 单刷《第一行代码》系列 06 —— Fragment 生命周期

    前情提要(Previously) 本系列将使用 Android Studio 将<第一行代码>(书中讲解案例使用Eclipse)刷一遍,旨在为想入坑 Android 开发,并选择 Andr ...

  9. iOS系列 基础篇 03 探究应用生命周期

    iOS系列 基础篇 03 探究应用生命周期 目录: 1. 非运行状态 - 应用启动场景 2. 点击Home键 - 应用退出场景 3. 挂起重新运行场景 4. 内存清除 - 应用终止场景 5. 结尾 本 ...

  10. iOS系列 基础篇 04 探究视图生命周期

    iOS系列 基础篇 04 探究视图生命周期 视图是应用的一个重要的组成部份,功能的实现与其息息相关,而视图控制器控制着视图,其重要性在整个应用中不言而喻. 以视图的四种状态为基础,我们来系统了解一下视 ...

随机推荐

  1. Java解压rar5兼容rar4

    RAR文件格式由WinRAR开发,广泛用于文件压缩和归档.随着技术的发展,RAR5作为更新的版本,引入了多项改进以提高压缩效率和数据安全性. 压缩效率:RAR5通过增大字典大小至32MB,相较于RAR ...

  2. 【SpringMVC】01 快速上手

    环境搭建 EvBuild 环境组成: - JDK 1.8 + - IDEA 2018 + - Maven 3.0 + - Tomcat 8.0 + 搭建步骤: 1.创建Maven - SpringMV ...

  3. 【转载】大模型时代的PDF解析工具

    本文来自博客园,作者:叶伟民,转载请注明原文链接:https://www.cnblogs.com/adalovelacer/p/18092208/pdf-tools-for-large-languag ...

  4. vscode下如何把缩进为2个空格的python项目改为4个空格的缩进

    最近在看老项目的代码,是python2.7年代的项目,那个时候很多的python项目都是使用2个空格,不过现在估计大多数人写python项目都是使用4个空格的了,而我看这两个空格的项目代码也是感觉十分 ...

  5. 多线程之深入理解park与unpark

    1.背景 面试官问,如何暂停一个线程勒..... 说说你对park的理解....... 2.代码 package com.ldp.demo01; import com.common.MyThreadU ...

  6. 《最新出炉》系列初窥篇-Python+Playwright自动化测试-64 - Canvas和SVG元素推拽

    1.简介 今天宏哥分享的在实际测试工作中很少遇到,比较生僻,如果突然遇到我们可能会脑大.懵逼,一时之间不知道怎么办?所以宏哥这里提供一种思路供大家学习和参考. 2.SVG简介 svg也是html5新增 ...

  7. Java如何防御XSS攻击?

    Q1.什么是XSS攻击? 定义很多,这里我找一个比较详细的解释 https://www.cnblogs.com/csnd/p/11807592.html Q2.为什么会有XSS攻击 也看上面的链接 Q ...

  8. abc366-cnblog

    [E](E - Manhattan Multifocal Ellipse (atcoder.jp)) 解题思路 这题求的是满足\(\sum^n_{i=1}(|x-x_i|+|y-y_i|)\leq D ...

  9. AtCoder Beginner Contest 328

    AtCoder Beginner Contest 328 A - Not Too Hard (atcoder.jp) #include <bits/stdc++.h> #define de ...

  10. Linux input 子系统详解

    1. 模块概述 1.1.相关资料和代码研究 drivers/input/ include/uapi/linux/input-event-codes.h 2. 模块功能 linux核心的输入框架 3. ...