在我的公司环境中基于华为昇腾算力通过VLLM Ascend部署了多个大模型包括了Deepseek V4 Flash, GLM 5.2等。在日常运营中我们需要了解用户在调用大模型时是否遇到问题并及时解决但是很多大模型都是采用PD分离方式部署的而且通常都是多个实例进行负载均衡。当遇到问题需要翻查日志时需要去到多个服务器上进行查找十分不便。因此我计划构建一个基于Grafana Loki Fluent-bit的集中日志监控系统可以统一采集各个服务器的日志信息并在Grafana里面进行查询。VLLM部署模型开启日志输出我这边都是通过容器方式运行VLLM需要把VLLM的日志输出到前台保存到宿主机的容器日志目录中。VLLM的日志默认是采用NewLineFormatter格式化它的作用是在多行消息的换行符后添加日志前缀让每一行看起来都“对齐”了。但需要特别注意只有第一行包含完整的时间戳和日志级别后续行虽然也有前缀但时间戳等信息是重复或空缺的。例如一个错误日志可能长这样[10-10 15:20:30] [vllm/engine/llm_engine.py:521] ERROR: CUDA out of memory. Tried to allocate 2048MiB (GPU 0; 23.7GiB total capacity; 20.1GiB already allocated)这种方式虽然方便阅读但是不方便程序进行处理如果逐行采集这些行会被当作独立事件导致告警和分析时无法关联到同一个错误。一个好的处理方式是直接让VLLM输出JSON格式的日志通过环境变VLLM_LOGGING_CONFIG_PATH指定自定义的 JSON 日志配置。在服务器上创建一个配置文件例如vllm-logging.json。以下配置使用了python-json-logger库来格式化输出在VLLM的官方Docker镜像已经包含了这个库了{ version: 1, disable_existing_loggers: false, formatters: { json: { class: pythonjsonlogger.jsonlogger.JsonFormatter, format: %(asctime)s %(levelname)s %(name)s %(message)s } }, handlers: { console: { class: logging.StreamHandler, formatter: json, level: INFO, stream: ext://sys.stdout } }, loggers: { vllm: { handlers: [console], level: INFO, propagate: false } } }然后就可以通过VLLM来启动模型了如以下示例docker run -d \ --gpus all \ --name qwen \ -p 8000:8000 \ -v /path/Qwen3-0.6B:/model \ -v /path/vllm-logging.json:/tmp/vllm-logging.json \ -e VLLM_LOGGING_CONFIG_PATH/tmp/vllm-logging.json \ -e VLLM_LOGGING_LEVELINFO \ vllm/vllm-openai:latest \ /model \ --served-model-name qwen3启动成功之后通过docker logs -f qwen可以看到日志已经是按照json格式输出了如下所示(APIServer pid1) {asctime: 2026-10-03 09:30:36,948, levelname: ERROR, name: vllm.entrypoints.openai.chat_completion.serving, message: Error with model errorErrorInfo(messageThe model /qwen3 does not exist., typeNotFoundError, parammodel, code404)} (APIServer pid1) {asctime: 2026-10-03 09:31:02,088, levelname: INFO, name: vllm.v1.metrics.loggers, message: Engine 000: Avg prompt throughput: 1.5 tokens/s, Avg generation throughput: 12.8 tokens/s, Running: 0 reqs, Waiting: 0 reqs, GPU KV cache usage: 0.0%, Prefix cache hit rate: 0.0%} (APIServer pid1) {asctime: 2026-10-03 09:31:12,089, levelname: INFO, name: vllm.v1.metrics.loggers, message: Engine 000: Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 0.0 tokens/s, Running: 0 reqs, Waiting: 0 reqs, GPU KV cache usage: 0.0%, Prefix cache hit rate: 0.0%}设置Fluent-Bit采集日志信息在运行VLLM的服务器中运行Fluent-Bit容器采集VLLM容器的日志信息。这里我采用的是ghcr.m.daocloud.io/openinsight-proj/fluent-bit:4.0.1这个社区版镜像因为官方镜像的jemalloc内存分配器对系统的内存页大小由严格要求必须是4096。但是在昇腾服务器的麒麟Linux里面默认页大小是65536会出现不匹配的问题。配置fluent-bit.conf[SERVICE] Flush 1 Log_Level info Parsers_File /fluent-bit/etc/parsers.conf [INPUT] Name tail Path /var/lib/docker/containers/*/*-json.log Parser docker Tag docker.* Refresh_Interval 5 Rotate_Wait 30 #Docker_Mode true Path_Key filepath #Read_from_Head true #Ignore_Older 0 DB /fluent-bit/db/flb_tail.db #Docker_Mode true #Docker_Mode_Flush 5 # 只采集运行中的容器 #Interval_Sec 1 [FILTER] Name lua Match docker.* script /fluent-bit/etc/enrich_record.lua call enrich_record [FILTER] Name rewrite_tag Match docker.* Rule $container_name ^(qwen.*)$ vllm.$1 false Rule $container_name ^(apiserver.*)$ apiserver.$1 false Rule $container_name .* other.$1 false [FILTER] Name parser Match vllm.* Key_Name log Parser vllm_prefix Reserve_Data On [FILTER] Name parser Match vllm.* Key_Name payload Parser vllm_payload Reserve_Data On [FILTER] Name modify Match vllm.* Add hostname ${HOSTNAME} Remove filepath [OUTPUT] Name loki Match vllm.* Host 10.135.248.240 Port 3100 Labels jobvllm, instance${HOST_IP}, modelQwen3.6-35B, role$role, index$index, level$levelname #Label_keys $levelname Line_format json [FILTER] Name parser Match apiserver.* Key_Name log Parser apiserver_json Reserve_Data On [FILTER] Name modify Match apiserver.* Add hostname ${HOSTNAME} Remove filepath [OUTPUT] Name loki Match apiserver.* Host 10.135.248.240 Port 3100 Labels jobapiserver, instance${HOST_IP}, level$levelname Line_format json在配置文件里面INPUT后面跟着的第一个lua FILTER是用一个Lua程序对宿主机的容器日志文件按照容器名来过滤并且提取日志中感兴趣的信息。程序如下:function enrich_record(tag, timestamp, record) local log record[log] if not log then return 2, timestamp, record end -- 清洗 ANSI 转义序列 local cleaned string.gsub(log, \27%[[%d;]*m, ) cleaned string.gsub(cleaned, \27%[[%d;]*[A-Za-z], ) cleaned string.gsub(cleaned, \27, ) record[log] cleaned -- 提取 levelname local level string.match(cleaned, levelname%s*:%s*([^])) if not level then level string.match(cleaned, level%s*:%s*([^])) end if level then record[levelname] level end -- 从 filepath 提取容器 ID local path record[filepath] if not path then return 2, timestamp, record end local container_id string.match(path, containers/([^/])/) if not container_id then return 2, timestamp, record end -- 读取 config.v2.json 获取容器名 local config_path /var/lib/docker/containers/ .. container_id .. /config.v2.json local f io.open(config_path, r) if not f then return 2, timestamp, record end local content f:read(*all) f:close() local name string.match(content, Name%s*:%s*/([^])) if not name then return 2, timestamp, record end record[container_name] name -- 解析 role 和 index local role, index string.match(name, _(prefill)_(%d)$) if not role then role, index string.match(name, _(decode)_(%d)$) end if role then record[role] role record[index] index end return 2, timestamp, record end在rewrite_tag FILTER里面定义了几个RULE根据不同的容器名来打上不同的tag。配置文件里面提到的Parser在以下parsers.conf文件中定义[PARSER] Name docker Format json Time_Key time Time_Format %Y-%m-%dT%H:%M:%S.%L Time_Keep On [PARSER] Name vllm_prefix Format regex Regex ^\((?process[^)])\)\s(?payload\{.*) [PARSER] Name vllm_payload Format json [PARSER] Name apiserver_json Format json Time_Key time Time_Format %Y-%m-%dT%H:%M:%S.%L%z Time_Keep On最后运行容器即可docker run -d \ --name fluent-bit \ --user root \ -v /var/lib/docker/containers:/var/lib/docker/containers:ro \ -v /var/run/docker.sock:/var/run/docker.sock:ro \ -v /opt/fluent-bit/db:/fluent-bit/db \ -v /opt/fluent-bit/fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf:ro \ -v /opt/fluent-bit/parsers.conf:/fluent-bit/etc/parsers.conf:ro \ -v /opt/fluent-bit/enrich_record.lua:/fluent-bit/etc/enrich_record.lua:ro \ -e HOSTNAME$(hostname) \ ghcr.m.daocloud.io/openinsight-proj/fluent-bit:4.0.1设置LOKI接收所有Fluent-Bit容器推送的日志docker run -d --name loki \ --restart unless-stopped \ -p 3100:3100 \ -v /data/loki/local-config.yaml:/etc/loki/local-config.yaml:ro \ -v /data/loki/data:/loki \ --config.file/etc/loki/local-config.yaml \ grafana/loki:latestGrafana查询显示Loki日志最后在Grafana里面配置添加数据源输入Loki服务器的IP和端口即可。然后在探索里面就可以对日志进行查询了。如下图
企业数字化 ERP 产品动态
相关推荐
[TC8测试]TCP_CALL_ABORT_03_03 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/6 1:32:11
AI质检(二):VLM检测 目录
三、VLM多模态方案
四、AI质检工作台搭建
1.构建Gradio界面
1)初始化代码
2)创建页签Tabs
3)布局
4)相关的控件
2.页面逻辑
1)缺陷检测
yolo检测
VLM检测
2)检测记录
3)统计分… · 2026/11/7 11:09:17
3步在macOS安装Harp:让Claude Code与Codex并排工作的最快方式 【免费下载链接】harp Run many Claude Code and Codex agents side by side, in one sidebar that tells you which one needs you. An unofficial fork of Warp. 项目地址: https://gitcode.com/gh_mirrors/harp15/harp 点击查看 免费下载 Harp 是一款专为多 AI … · 2026/11/4 23:44:07
哈尔滨在哪能考电工证千万别踩坑,实操考试心里没底怕挂科 哈尔滨在哪能考电工证千万别踩坑,实操考试心里没底怕挂科 实操考试心里没底怕挂科,这几乎是每个想考电工证的人都会有的想法。特别是对那些在工地、车间一线工作的工人来说,电工证不仅是一张证书,更是他们工作的通行证。但问题来了:… · 2026/11/11 3:11:13
电工证要复审了丢了怎么补救 电子证书帮你解决燃眉之急 电工证要复审了丢了怎么补救 电子证书帮你解决燃眉之急 工地太忙根本没时间复习考试,现在电工证要复审了,结果发现证书丢了,这事儿可真让人头疼。特别是三门峡房建工程的工友,经常在项目赶工期时被各种琐事牵绊,证书丢了不仅影响复审进度,还可能影响后… · 2026/11/11 3:11:13
电工证要复审了丢了?值不值得考?别等丢了才慌! 电工证要复审了丢了?值不值得考?别等丢了才慌! 急需特种作业证才能上岗找工作,可偏偏这时候电工证要复审了,结果一不小心丢了,整个人都懵了。现在不是随便找个电工就能上岗的年代,特种作业证不光是入职门槛,更是你能否在这个行业立足的“身份证”。电… · 2026/11/11 3:11:13
电工证复审回执值不值得考?实操考试心里没底怕挂科怎么办? 电工证复审回执值不值得考?实操考试心里没底怕挂科怎么办? 实操考试心里没底怕挂科,这几乎是每个准备考电工证的学员都有的焦虑。尤其是像你这样,是驻马店中小施工企业负责人,需要为团队办理电工证复审回执,更要面对考试和复审双重压力。今天咱们不绕弯… · 2026/11/11 3:10:13
电工证丢失还能补吗?千万别踩坑,丢了证等于失业 电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/10 2:16:10
电力电缆作业证直播报名入口与办理流程良心建议 电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/10 17:46:39
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/10 17:11:43
_中职电工证最新政策解读 中职电工证在哪考?工地太忙根本没时间复习考试的救星来了 工地太忙根本没时间复习考试,这是很多正在备考 中职电工证 的建筑工友的真实写照。你不是不想考,而是真的没时间。但别担心,这期内容是 新乡初次报考人员… · 2026/11/11 0:00:52
昆明电工证培训价格值不值得考?老电工告诉你真相 昆明电工证培训价格值不值得考?老电工告诉你真相 之前考的证在外省能不能转过来?这个问题是很多在外地打工、换城市生活、或者是想在昆明发展的朋友最关心的。尤其是现在云南发展快,很多企业都在招持证上岗的电工,如果你手头有证但不在本地,那这个证是不… · 2026/11/11 0:00:52
特种电缆张工网上查询全攻略:外省证如何转过来 特种电缆张工网上查询全攻略:外省证如何转过来 之前考的证在外省能不能转过来?这是很多特种作业从业者最关心的问题,尤其是像特种电缆张工这类证书,直接关系到日常工作是否合规、能否顺利晋升。很多小伙伴因为证书归属地的问题,陷入职业发展的瓶颈,甚至… · 2026/11/11 0:00:52
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 20:19:29
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 19:22:45
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 17:00:47