C++日志库log4cplus:SocketAppender记录日志到log Server
转载请注明出处:http://blog.csdn.net/jmppok/article/details/17375057
1.问题
C++程序在后台运行时,可通过log4cplus记录日志。当C++程序运行在远程服务器上时,我们就需要远程登陆到该服务器才能查看日志。进一步,如果该C++程序一个并行程序或者分布式程序,为了查看程序的运行状态,我们就需要登陆到N台服务器上,tail -f xx.log.这种情形听起来就很令人不爽,而实际上,很多服务端开发者都遇到过或正在遭受这个问题的困扰。
2.LoggingServer
作为Log4J的翻版,Log4cplus也提供了SockeAppender,可以通过SocketAppender将日志输出到一个指定的log server上,从而解决上述问题。
关于Log4cplus的介绍,请参考C++开源日志库log4cplus
在Log4cplus的源码包中,有一个loggingServer目录,该目录中实现了一个LoggingServer。
在编译Log4cplus时,会自动编译该目录,在目录中生成loggingServer可执行文件,当然可以自己make(需要依赖log4cplus库)。
loggingServer使用方式如下:
./loggingserver 9000 log4cplus.properties
9000表示监听的端口号(不需要地址,默认监听本机地址)
log4cplus.properties是一个log4cplus的配置文件,和普通的log4cplus配置文件相同,loggingserver收到各个socket发来的日志后,根据配置文件信息,将其写入文件。
下面是一个简单的配置文件示例:
log4cplus.rootLogger=DEBUG, STDOUT, ALL_MSGSlog4cplus.appender.STDOUT=log4cplus::ConsoleAppender
log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout
#log4cplus.appender.STDOUT.layout.ConversionPattern=%d{%m/%d/%y %H:%M:%S} [%t] %-5p %c{2} %%%x%% - %m [%l]%n
log4cplus.appender.STDOUT.layout.ConversionPattern=[%-5p %d{%y-%m-%d %H:%M:%S}] [%l]%n%m%n%n#设置日志追加到文件尾
log4cplus.appender.ALL_MSGS=log4cplus::RollingFileAppender #设置日志文件大小
log4cplus.appender.ALL_MSGS.MaxFileSize=100MB#设置生成日志最大个数
log4cplus.appender.ALL_MSGS.MaxBackupIndex=10#设置输出日志路径
log4cplus.appender.ALL_MSGS.File=log/test.log
log4cplus.appender.ALL_MSGS.layout=log4cplus::PatternLayout
#设置日志打印格式
#log4cplus.appender.ALL_MSGS.layout.ConversionPattern=|%D:%d{%Q}|%p|%t|%l|%m|%n
log4cplus.appender.ALL_MSGS.layout.ConversionPattern=[%-5p %d{%y-%m-%d %H:%M:%S}] [%l]%n%m%n%n
#匹配相同日志级别,只有debug日志才输入到该文件中
#log4cplus.appender.ALL_MSGS.filters.1=log4cplus::spi::LogLevelMatchFilter
#log4cplus.appender.DEBUG_MSGS.filters.1.LogLevelToMatch=DEBUG
#log4cplus.appender.DEBUG_MSGS.filters.1.AcceptOnMatch=true
#log4cplus.appender.DEBUG_MSGS.filters.2=log4cplus::spi::DenyAllFilter
loggingserver本身十分简单,其代码如下(当然如果觉得它不爽,你也可以自己实现一个更cool的):
// Module: LOG4CPLUS
// File: loggingserver.cxx
// Created: 5/2003
// Author: Tad E. Smith
//
//
// Copyright 2003-2010 Tad E. Smith
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.#include <cstdlib>
#include <iostream>
#include <log4cplus/configurator.h>
#include <log4cplus/socketappender.h>
#include <log4cplus/helpers/socket.h>
#include <log4cplus/thread/threads.h>
#include <log4cplus/spi/loggingevent.h>namespace loggingserver
{class ClientThread : public log4cplus::thread::AbstractThread
{
public:ClientThread(log4cplus::helpers::Socket clientsock): clientsock(clientsock) {std::cout << "Received a client connection!!!!" << std::endl;}~ClientThread(){std::cout << "Client connection closed." << std::endl;}virtual void run();private:log4cplus::helpers::Socket clientsock;
};}int
main(int argc, char** argv)
{if(argc < 3) {std::cout << "Usage: port config_file" << std::endl;return 1;}int port = std::atoi(argv[1]);const log4cplus::tstring configFile = LOG4CPLUS_C_STR_TO_TSTRING(argv[2]);log4cplus::PropertyConfigurator config(configFile);config.configure();log4cplus::helpers::ServerSocket serverSocket(port);if (!serverSocket.isOpen()) {std::cout << "Could not open server socket, maybe port "<< port << " is already in use." << std::endl;return 2;}while(1) {loggingserver::ClientThread *thr = new loggingserver::ClientThread(serverSocket.accept());thr->start();}return 0;
}// loggingserver::ClientThread implementationvoid
loggingserver::ClientThread::run()
{while(1) {if(!clientsock.isOpen()) {return;}log4cplus::helpers::SocketBuffer msgSizeBuffer(sizeof(unsigned int));if(!clientsock.read(msgSizeBuffer)) {return;}unsigned int msgSize = msgSizeBuffer.readInt();log4cplus::helpers::SocketBuffer buffer(msgSize);if(!clientsock.read(buffer)) {return;}log4cplus::spi::InternalLoggingEvent event= log4cplus::helpers::readFromBuffer(buffer);log4cplus::Logger logger= log4cplus::Logger::getInstance(event.getLoggerName());logger.callAppenders(event); }
}
3.应用程序中SocketAppender配置
前面启动了LoggingServer,下面说一下需要收集其日志的各个应用程序中配置。
说白了,就是在原来的基础上加一个SocketAppender,SocketAppender会自动将日志发送给loggingserver。这样直接在loggingserver上就可以查看所有服务器上的日志信息啦。哥终于不用再担心你们的运行状态啦!
log4cplus.rootLogger=DEBUG, STDOUT, ALL_MSGS,RemoteServerlog4cplus.appender.STDOUT=log4cplus::ConsoleAppender
log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout
#log4cplus.appender.STDOUT.layout.ConversionPattern=%d{%m/%d/%y %H:%M:%S} [%t] %-5p %c{2} %%%x%% - %m [%l]%n
log4cplus.appender.STDOUT.layout.ConversionPattern=[%-5p %d{%y-%m-%d %H:%M:%S}] [%l]%n%m%n%n#设置日志追加到文件尾
log4cplus.appender.ALL_MSGS=log4cplus::RollingFileAppender #设置日志文件大小
log4cplus.appender.ALL_MSGS.MaxFileSize=100MB#设置生成日志最大个数
log4cplus.appender.ALL_MSGS.MaxBackupIndex=10#设置输出日志路径
log4cplus.appender.ALL_MSGS.File=log/test.log
log4cplus.appender.ALL_MSGS.layout=log4cplus::PatternLayout
#设置日志打印格式
#log4cplus.appender.ALL_MSGS.layout.ConversionPattern=|%D:%d{%Q}|%p|%t|%l|%m|%n
log4cplus.appender.ALL_MSGS.layout.ConversionPattern=[%-5p %d{%y-%m-%d %H:%M:%S}] [%l]%n%m%n%n
#匹配相同日志级别,只有debug日志才输入到该文件中
#log4cplus.appender.ALL_MSGS.filters.1=log4cplus::spi::LogLevelMatchFilter
#log4cplus.appender.DEBUG_MSGS.filters.1.LogLevelToMatch=DEBUG
#log4cplus.appender.DEBUG_MSGS.filters.1.AcceptOnMatch=true
#log4cplus.appender.DEBUG_MSGS.filters.2=log4cplus::spi::DenyAllFilterlog4cplus.appender.RemoteServer=log4cplus::SocketAppender
log4cplus.appender.RemoteServer.host=localhost
log4cplus.appender.RemoteServer.port=9000
上面第一行的RemoteServer和最后三行即为添加一个SocketAppender。将日志发送到远端的loggingserver。
当然对本地的日志记录没有影响,本地仍正常记录。
同时我们还可以设置多个RemoetServer....,不过貌似也没这个必要...
4.更加高端大气上档次
当然我们可以实现自己的loggingserver,更加的高端大气上档次。
a.将来自不同客户端的日志分别存储;
b.不同级别的日志单独存储;
c.在发现错误时,邮件通知;
d.实现一个B/S的日志浏览工具;
e.日志入库;
f.存入HDFS,用Hadoop Map/Reduce挖掘;
g.接入Storm(实时流处理框架)对其进行分析;
...
C++日志库log4cplus:SocketAppender记录日志到log Server相关推荐
- 开源日志库log4cplus+VS2008使用整理
一.简介 log4cplus是C++编写的开源的日志系统,功能非常全面.本文介绍如何在Windows+VS2008中使用该日志库. 二.下载 可从网站[url]http://log4cplu ...
- C++:日志库log4cplus 2.0的使用说明
以前在做java开发时一直都在用log4j,它配置灵活,功能强大.如果C++中也存在类似配置的日志库,则可以省去不少学习的时间.在C++中的确有这样的一些库,本文就拿其中用的最多的log4cplus来 ...
- c++日志库log4cplus使用
项目中需要打印log,方便程序调试和问题定位分析.C++实现的log4cplus日志库是一种易于使用的C ++日志记录API,可提供线程安全,灵活且任意粒度的日志管理和配置控制. 下面介绍一下在lin ...
- C/C++日志库-log4cplus(log4j的C++版本)
Log4j以其简单的使用方式(引入一个jar包,一行代码即可调用),灵活(可通过配置文件随意配置),功能强大(多个级别,可配置多个输出目的地,Console,File,系统日志,远端的LogSer ...
- android log耗性能吗,一个高性能的Android日志库
clue 一个高性能的Android日志库. 为什么性能高 通常的Android日志库, 为了获取到class名, 方法名, 行号, 都是通过以下API实现的: StackTraceElement[] ...
- go日志库log/zap/logrus
一个好的日志记录器能够提供下面这些功能: 能够将事件记录到文件中,而不是应用程序控制台. 日志切割-能够根据文件大小.时间或间隔等来切割日志文件. 支持不同的日志级别.例如INFO,DEBUG,ERR ...
- 【Rust】日志库log
日志库一般会实现日志分级.日志过滤.日志输出格式化.日志回滚等功能.本文介绍了Rust log库的使用,并给出了几个常用日志库的使用示例. 一.Rust log 1.log库 这个log库给出了日志库 ...
- (1)go web开发之 zap日志库的使用及gin框架配置zap记录日志详细文档讲解分析
(一)介绍 zap 是go 中比较火的一个日志库,提供不同级别的日志,并且速度快 官方文档: https://pkg.go.dev/go.uber.org/zap#section-readme, 也可 ...
- 日志库EasyLogging++学习系列(1)—— 简要介绍
对于有开发经验的程序员来说,记录程序执行日志是一件必不可少的事情.通过查看和分析日志信息,不仅可以有效地帮助我们调试程序,而且当程序正式发布运行之后,更是可以帮助我们快速.准确地定位问题.在现在这个开 ...
最新文章
- JavaScript数据类型
- linux hdparm 测试磁盘io,hdparm测试硬盘性能
- 初学React,setState后获取到的thisstate没变,还是初始state?
- 在Eigrp做不等值路由的负载均衡
- 【ArcGIS风暴】ArcGIS10.6获取栅格影像边界范围的三种方法案例详解
- 触发键盘_雷蛇这款光轴机械键盘开箱评测,光速触发,颜值爆表
- 利用httponly提升应用程序安全性
- 比特币可视化工具_这个比特币交易“可视化”网站,用一辆公交车带你“上车”...
- 95-170-050-源码-Time-flink的时间及时区问题解决
- log4net配置自定义字段存入数据库
- Golang 主机字节序的判断
- HTTP 500 - 内部服务器错误的解决
- 《嵌入式Linux基础教程学习笔记一》
- 人工智能(AI)测试方法
- 中国智慧园区标准化白皮书 附下载
- 固定资产管理系统项目总结
- MATLAB学习笔记:求偏导
- 21个免费学习编程的网站
- SIM卡中ICCID标识与IMSI的区别
- 联想笔记本上Ubuntu无线网卡问题