Monolog SocketHandler 实战指南:通过 TCP、UDP 与 Unix Socket 发送日志
后端【免费下载链接】monologSends your logs to files, sockets, inboxes, databases and various web services项目地址https://gitcode.com/gh_mirrors/mo/monolog点击查看免费下载Monolog 的SocketHandler允许你通过fsockopen()或pfsockopen()将日志直接写入任意 socket 端点是构建集中式日志收集、接入 syslog-ng / Fluentd / rsyslog 等日志服务时最常用的网络日志通道。本文以 doc/sockets.md 为主线结合 SocketHandler.php 源码与 SocketHandlerTest.php 测试用例完整讲解协议选择、持久连接、超时控制与写入原理读完即可在真实项目中落地可复用的 socket 日志方案。SocketHandler 能做什么SocketHandler是 Monolog 中面向「网络化日志」的通用处理器官方文档将其定位为「Logs records to sockets, use this for UNIX and TCP sockets」见 02-handlers-formatters-processors.md。它解决的核心问题是把日志记录从本地应用进程发送到另一个进程或远端服务器例如发送给本机/远程的syslog-ng、rsyslog、Fluentd等日志守护进程写入 Unix domain socket供同机其他服务消费通过 UDP 向日志收集端投递如 SyslogUdpHandler 基于 UDP 实现远程 syslog。从源码结构看SocketHandler继承自AbstractProcessingHandler因此它天然具备 Monolog 处理器栈的完整能力级别过滤isHandling、处理器级 processor、以及 formatter 格式化详见 AbstractProcessingHandler.php。每一条被处理的记录都会先被 formatter 格式化为字符串再通过 socket 写出。支持的连接协议TCP、UDP 与 Unix SocketSocketHandler默认使用TCP连接通过连接字符串前缀可以切换协议前缀协议连接字符串示例无前缀TCP默认localhost:514、tcp://127.0.0.1:9000unix://Unix domain socketunix:///var/log/httpd_app_log.socketudp://UDPudp://logs.example.com:12201这一设计对应源码中fsockopen($this-connectionString, -1, ...)与pfsockopen(...)的调用方式见 SocketHandler.phpPHP 的fsockopen原生支持在地址前加unix://打开 Unix socket、加udp://打开 UDP socketMonolog 直接复用了这套语法。由于 UDP 无连接语义官方提示 UDP 在isConnected()检查时可能看似已连接、写时才失败排障时需注意这一特性。基础示例写入 Unix Socket以下完整示例来自 doc/sockets.md创建一个向 Unix socket 写日志的 logger?php use Monolog\Logger; use Monolog\Handler\SocketHandler; // Create the logger $logger new Logger(my_logger); // Create the handler $handler new SocketHandler(unix:///var/log/httpd_app_log.socket); $handler-setPersistent(true); // Now add the handler $logger-pushHandler($handler, Level::Debug); // You can now use your logger $logger-info(My logger is now ready);提示Level::Debug是处理器的最小触发级别现代 Monolog 更推荐在构造函数中直接传入级别例如new SocketHandler(unix:///var/log/httpd_app_log.socket, Level::Debug)等价于调用setLevel()。pushHandler()只负责把处理器压入栈顶。使用 syslog-ng 作为接收端时你在日志服务器上应能看到如下记录cweb1 [2012-02-26 00:12:03] my_logger.INFO: My logger is now ready [] []其中my_logger是 channel 名INFO是级别名末尾的[] []分别是空的 context 与 extra。该行格式来自默认的LineFormatter可通过 setFormatter 替换为 JSON、GELF 或 Fluentd 协议格式见下文「与 FluentdFormatter 组合」。构造函数参数与全部配置项SocketHandler的构造函数签名及默认值如下见 SocketHandler.phppublic function __construct( string $connectionString, // socket 连接串如 tcp://127.0.0.1:514 或 unix:///path/to.sock $level Level::Debug, // 最小日志级别 bool $bubble true, // 记录处理后是否继续向下冒泡给栈中其他 handler bool $persistent false, // 是否使用持久连接pfsockopen float $timeout 0.0, // 传输超时秒0 表示不限制 float $writingTimeout 10.0, // 写超时秒0 表示不限制 ?float $connectionTimeout null, // 连接超时秒null 时取 ini 的 default_socket_timeout ?int $chunkSize null // fwrite 写入块大小字节null 表示不设置 )此外每个参数都有对应的 getter/setter支持运行时动态调整validateTimeout()会拒绝负数并抛出InvalidArgumentException见 SocketHandler.php方法作用生效时机setPersistent(bool)/isPersistent()开关持久连接仅在连接建立前生效setConnectionTimeout(float)/getConnectionTimeout()连接建立超时仅在连接前生效setTimeout(float)/getTimeout()数据读取超时作用于整个流的stream_set_timeout仅在连接前生效setWritingTimeout(float)/getWritingTimeout()写入停滞超时防止写不出去时死循环连接后的写入阶段setChunkSize(int)/getChunkSize()设置stream_set_chunk_size的块大小连接后的写入阶段getConnectionString()读取当前连接串—持久连接persistent的意义文档明确指出持久 socket 主要在 Web 环境下有价值——每个 PHP-FPM 请求结束时关闭连接、下一个请求又重新建连的开销可以省去连接可跨请求复用。源码中的体现是close()方法的逻辑public function close(): void { if (!$this-isPersistent()) { $this-closeSocket(); } }即只有非持久连接才在close()时真正fclose()持久连接交由 PHP 进程生命周期管理见 SocketHandler.php。测试testCloseDoesNotClosePersistentSocket专门验证了这一点持久模式下close()后资源仍然存活见 SocketHandlerTest.php。持久连接由pfsockopen()建立SocketHandler.php普通连接则走fsockopen()。写入流程与底层原理SocketHandler继承自AbstractProcessingHandler一条日志的完整调用链是Logger::addRecord()生成LogRecordAbstractProcessingHandler::handle()先做级别过滤isHandling再运行处理器级 processors然后用 formatter 生成$record-formatted见 AbstractProcessingHandler.php调用SocketHandler::write($record)connectIfNotConnected()若isConnected()为假资源不存在或feof()已到 EOF说明对端关闭了连接则执行connect()connect()依次完成createSocketResource()fsockopen/pfsockopen→setSocketTimeout()stream_set_timeout→setStreamChunkSize()可选generateDataStream($record)返回(string) $record-formatted即 formatter 输出writeToSocket($data)循环写入。以上流程见 SocketHandler.php 与 SocketHandler.php。断线重连与可靠写入writeToSocket()是一个「边写边检」的循环每次fwrite后检查流元数据中的timed_out标志一旦超时立即抛RuntimeException(Write timed-out)如果写出的字节数持续不增长且超过了writingTimeout则主动closeSocket()并抛异常避免在写不出去的对端上无限循环见 SocketHandler.php。测试testAvoidInfiniteLoopWhenNoDataIsWrittenForAWritingTimeoutSeconds专门用fwrite返回 0 的 mock 验证了该防护见 SocketHandlerTest.php。值得注意的健壮性设计连接失败fsockopen返回false抛UnexpectedValueException错误信息包含errno: errstr流超时设置失败、块大小设置失败同样抛UnexpectedValueExceptionfwrite返回false或写入中途对端 EOF均抛RuntimeException这些场景在测试套件中均有对应用例testExceptionIsThrownOnFsockopenError、testExceptionIsThrownOnPfsockopenError、testWriteFailsOnIfFwriteReturnsFalse、testWriteFailsIfStreamTimesOut、testWriteFailsOnIncompleteWrite等见 SocketHandlerTest.php。这带来的工程含义是当远端日志服务短暂不可用时socket 写日志会抛出异常并可能中断当前请求。如果不想让日志故障拖垮业务可以配合WhatFailureGroupHandler或FallbackGroupHandler包装见 02-handlers-formatters-processors.md 中关于远程 TCP 连接死亡的讨论。与 FluentdFormatter 组合接入 Fluentd 日志管道SocketHandler是接入 Fluentdtd-agent的推荐通道。仓库中的 FluentdFormatter.php 专门负责把LogRecord序列化为 Fluentd 的 unix socket 协议消息[tag, timestamp, message]三段式 JSON其类注释给出了完整的配套配置$logger new Monolog\Logger(fluent.tag); $fluentHandler new Monolog\Handler\SocketHandler(unix:///var/run/td-agent/td-agent.sock); $fluentHandler-setFormatter(new Monolog\Formatter\FluentdFormatter()); $logger-pushHandler($fluentHandler);对应的 Fluentd 端配置为source type unix path /var/run/td-agent/td-agent.sock /sourceFluentdFormatter构造参数$levelTag决定是否把日志级别拼进 tag如fluent.tag.warning关闭时则把level与level_name放入消息体见 FluentdFormatter.php。这也是 SocketHandler「通用 socket 通道 专用 formatter」组合能力的典型示范。UDP 场景SyslogUdpHandler 与 UdpSocket如果你需要的是标准的远程 syslogUDP 514Monolog 提供了更专业的 SyslogUdpHandler它内部使用 UdpSocketsocket_createsocket_sendto支持 RFC3164、RFC5424、RFC5424e 三种报文格式并且必须安装 PHP 的sockets扩展否则抛MissingExtensionException。一个容易被忽略的实战参数是$maxLengthUDP 数据报理论最大载荷为 65023 字节UdpSocket::DATAGRAM_MAX_LENGTH但如此大的报文会在 IP 层分片而很多路由器/防火墙会丢弃分片报文导致日志被静默丢弃。文档与源码注释建议按路径 MTU 设置如 1024UdpSocket会按maxLength - 头部长度截断消息见 UdpSocket.php相关截断行为由 UdpSocketTest.php 验证。排障要点小结验证连接串语法garbage://here这类非法地址会在首次写入时抛UnexpectedValueExceptiontestInvalidHostname用例确认接收端协议匹配TCP 用tcp://或裸 host:portUnix socket 必须加unix://前缀UDP 加udp://前缀检查超时配置负超时值会直接抛InvalidArgumentExceptionwritingTimeout建议保持默认 10 秒或调大防止大消息、慢对端场景下误判断线持久连接只影响连接生命周期setPersistent(true)必须在首次连接前调用且不会改变消息格式与超时行为。延伸阅读处理器/格式化器/处理器的完整清单02-handlers-formatters-processors.mdLogger 基本用法、channel 与处理器栈模型01-usage.mdSocketHandler 完整源码SocketHandler.phpSocketHandler 测试用例SocketHandlerTest.phpUDP syslog 实现SyslogUdpHandler.php 与 UdpSocket.phpFluentd 协议 formatterFluentdFormatter.php赞分享后端【免费下载链接】monologSends your logs to files, sockets, inboxes, databases and various web services项目地址https://gitcode.com/gh_mirrors/mo/monolog点击查看免费下载相关推荐Vector Socket Source 深度指南TCP、UDP 与 Unix Domain Socket 日志采集实战Vector Socket Source 深度指南TCP、UDP 与 Unix Domain Socket 日志采集实战 socket 是 Vector 内置可观测性数据工程数据集成日志分析Telegraf Socket Writer 输出插件完全指南通过 TCP/UDP/Unix Socket 发送指标数据Telegraf Socket Writer 输出插件完全指南通过 TCP/UDP/Unix Socket 发送指标数据 Socket Writer 是 Te可观测性指标监控运维Vector Socket Sink 深入解析通过 TCP、UDP 与 Unix 域套接字交付日志与指标Vector Socket Sink 深入解析通过 TCP、UDP 与 Unix 域套接字交付日志与指标 Vector 的 socket sink 是一个稳定可观测性数据工程数据集成日志分析上一篇开源监控利器Open-Falcon Agent下一篇推荐开源项目React-Component/Upload - 简洁高效的文件上传组件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

10分钟做出可用的OpenCore EFI:OpCore Simplify快速上手指南

10分钟做出可用的OpenCore EFI:OpCore Simplify快速上手指南

10分钟做出可用的OpenCore EFI:OpCore Simplify快速上手指南 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 手动配黑苹果 EFI&#xff0c…

2026/9/20 12:57:54 阅读更多 →
Erlang 应用接入 CAT 监控:erlcat 客户端安装、配置与埋点 API 实战指南

Erlang 应用接入 CAT 监控:erlcat 客户端安装、配置与埋点 API 实战指南

Erlang 应用接入 CAT 监控:erlcat 客户端安装、配置与埋点 API 实战指南 【免费下载链接】cat CAT 作为服务端项目基础组件,提供了 Java, C/C, Node.js, Python, Go 等多语言客户端,已经在美团点评的基础架构中间件框架(MVC框架&a…

2026/9/20 12:57:54 阅读更多 →
在 Flipper Zero 上复刻拓麻歌子:Tama P1 模拟器从 ROM 到源码的完整指南

在 Flipper Zero 上复刻拓麻歌子:Tama P1 模拟器从 ROM 到源码的完整指南

在 Flipper Zero 上复刻拓麻歌子:Tama P1 模拟器从 ROM 到源码的完整指南 【免费下载链接】Flipper Playground (and dump) of stuff I make or modify for the Flipper Zero 项目地址: https://gitcode.com/GitHub_Trending/fl/Flipper 在一台口袋设备里复刻…

2026/9/20 12:57:54 阅读更多 →

最新新闻

React Native 加密数据库实战:用 RxDB Encryption 插件保护移动端本地数据

React Native 加密数据库实战:用 RxDB Encryption 插件保护移动端本地数据

React Native 加密数据库实战:用 RxDB Encryption 插件保护移动端本地数据 【免费下载链接】rxdb The local-first database that runs on every JS runtime and replicates with your existing backend - no vendor, no lock-in - https://rxdb.info/ 项目地址: …

2026/9/20 13:43:28 阅读更多 →
AlphaFold结果解读:pLDDT、PAE、pTM与ipTM指标全解析

AlphaFold结果解读:pLDDT、PAE、pTM与ipTM指标全解析

拿到AlphaFold预测结果之后,你的第一反应是什么?说实话,我以前也干过这种事:先打开pLDDT,别的指标一概不看,颜色鲜亮就长出一口气,看到大段红橙就开始怀疑人生。直到有一次,一个蛋白…

2026/9/20 13:43:28 阅读更多 →
@eggjs/cluster 集群管理器全解析:Egg 多进程架构演进、启动模式与配置实战

@eggjs/cluster 集群管理器全解析:Egg 多进程架构演进、启动模式与配置实战

后端Web框架 【免费下载链接】egg 🥚🥚🥚🥚 Born to build better enterprise frameworks and apps with Node.js & Koa. https://307.run/eggcode 项目地址: https://gitcode.com/gh_mirrors/eg/egg 点击查看 免费…

2026/9/20 13:43:28 阅读更多 →
Voyager 的 Image Refinement:Gemini 生成图片水印的像素级无损去除方案

Voyager 的 Image Refinement:Gemini 生成图片水印的像素级无损去除方案

Voyager 的 Image Refinement:Gemini 生成图片水印的像素级无损去除方案 【免费下载链接】voyager Enhancement suite for Gemini, AI Studio, Claude & ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Stu…

2026/9/20 13:43:28 阅读更多 →
POPGENE遗传多样性分析实战:从数据格式到结果解读

POPGENE遗传多样性分析实战:从数据格式到结果解读

简介:POPGENE是一款基于Windows的免费物种遗传分析软件,这份图文版中文使用教程正是为它而写的,适合从事群体遗传学、分子生态学研究的科研人员和研究生快速上手。内容依托软件实际界面展开,系统介绍了POPGENE的窗口构成、八大菜单…

2026/9/20 13:43:28 阅读更多 →
OpenToonz 快速上手:3 步免费做出第一部 2D 动画

OpenToonz 快速上手:3 步免费做出第一部 2D 动画

OpenToonz 快速上手:3 步免费做出第一部 2D 动画 【免费下载链接】opentoonz OpenToonz - An open-source full-featured 2D animation creation software 项目地址: https://gitcode.com/GitHub_Trending/op/opentoonz OpenToonz 是一款开源、免费的 2D 动画…

2026/9/20 13:42:28 阅读更多 →

日新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/19 23:01:36 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/19 17:50:38 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →