【syslog】搭建日志服务器

搭建日志服务器

1、安装rsyslog

yum install -y rsyslog

2、修改rsyslog.conf配置文件

/etc/rsyslog.conf

# rsyslog configuration file

# For more information see /usr/share/doc/rsyslog-*/rsyslog_conf.html
# If you experience problems, see http://www.rsyslog.com/doc/troubleshoot.html

#### MODULES ####

# The imjournal module bellow is now used as a message source instead of imuxsock.
$ModLoad imuxsock # provides support for local system logging (e.g. via logger command)
$ModLoad imjournal # provides access to the systemd journal
#$ModLoad imklog # reads kernel messages (the same are read from journald)
#$ModLoad immark  # provides --MARK-- message capability

# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514

# Provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 513


#### GLOBAL DIRECTIVES ####
template(name="DynFile" type="string" string="/var/log/system-%HOSTNAME%.log")

# Where to place auxiliary files
$WorkDirectory /var/lib/rsyslog

# Use default timestamp format
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat

# File syncing capability is disabled by default. This feature is usually not required,
# not useful and an extreme performance hit
#$ActionFileEnableSync on

# Include all config files in /etc/rsyslog.d/
$IncludeConfig /etc/rsyslog.d/*.conf

# Turn off message reception via local log socket;
# local messages are retrieved through imjournal now.
$OmitLocalLogging on

# File to store the position in the journal
$IMJournalStateFile imjournal.state


#### RULES ####

# Log all kernel messages to the console.
# Logging much else clutters up the screen.
#kern.*                                                 /dev/console

# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none;cron.none                /var/log/messages

# The authpriv file has restricted access.
authpriv.*                                              /var/log/secure

# Log all the mail messages in one place.
mail.*                                                  -/var/log/maillog


# Log cron stuff
cron.*                                                  /var/log/cron

# Everybody gets emergency messages
*.emerg                                                 :omusrmsg:*

# Save news errors of level crit and higher in a special file.
uucp,news.crit                                          /var/log/spooler

# Save boot messages also to boot.log
local7.*                                                /var/log/boot.log


# ### begin forwarding rule ###
# The statement between the begin ... end define a SINGLE forwarding
# rule. They belong together, do NOT split them. If you create multiple
# forwarding rules, duplicate the whole block!
# Remote Logging (we use TCP for reliable delivery)
#
# An on-disk queue is created for this action. If the remote host is
# down, messages are spooled to disk and sent when it is up again.
#$ActionQueueFileName fwdRule1 # unique name prefix for spool files
#$ActionQueueMaxDiskSpace 1g   # 1gb space limit (use as much as possible)
#$ActionQueueSaveOnShutdown on # save messages to disk on shutdown
#$ActionQueueType LinkedList   # run asynchronously
#$ActionResumeRetryCount -1    # infinite retries if host is down
# remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional
#*.* @@remote-host:514
# ### end of the forwarding rule ###

3、重启rsyslog

systemctl restart rsyslog

输入systemctl status rsyslog,确保出现以下画面(active (running)):

[root@10-18-93-115 ccs]# systemctl status rsyslog
● rsyslog.service - System Logging Service
   Loaded: loaded (/usr/lib/systemd/system/rsyslog.service; enabled; vendor preset: enabled)
   Active: active (running) since 四 2022-09-08 14:19:59 CST; 1h 1min ago
     Docs: man:rsyslogd(8)
           http://www.rsyslog.com/doc/
 Main PID: 12668 (rsyslogd)
    Tasks: 9
   Memory: 1.4M
   CGroup: /system.slice/rsyslog.service
           └─12668 /usr/sbin/rsyslogd -n

9月 08 14:19:59 10-18-93-115 systemd[1]: Starting System Logging Service...
9月 08 14:19:59 10-18-93-115 rsyslogd[12668]:  [origin software="rsyslogd" swVersion="8.24.0-57.el7_9.1" x-pid="12668" x-info="http://www.rsyslog.com"] start
9月 08 14:19:59 10-18-93-115 systemd[1]: Started System Logging Service.

4、SpringBoot下配置

注:
以下是我项目中的实际使用方式

4.1、导入maven包

        <!-- logback -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>

        <dependency>
            <groupId>org.graylog2</groupId>
            <artifactId>syslog4j</artifactId>
            <version>0.9.60</version>
        </dependency>

4.2、新建三个java工具类

SyslogClientUtils.java

package com.viewsources.ccs.server.syslog;

import lombok.Data;
import org.graylog2.syslog4j.Syslog;
import org.graylog2.syslog4j.SyslogConstants;
import org.graylog2.syslog4j.SyslogIF;

/**
 * 转发工具类
 *
 * @author Yohann
 * @since 2021-12-1 17:08:34
 */
@Data
public class SyslogClientUtils {

    private String host;
    private int port;
    private String protocolType;

    private static SyslogIF syslog;
    private volatile static SyslogClientUtils instance;

    private SyslogClientUtils(String host, int port, String protocolType) {
        if ("UDP".equals(protocolType)) {
            syslog = Syslog.getInstance(SyslogConstants.UDP);
        } else {
            syslog = Syslog.getInstance(SyslogConstants.TCP);
        }
        syslog.getConfig().setHost(host);
        syslog.getConfig().setPort(port);
        this.host = host;
        this.port = port;
        this.protocolType = protocolType;
    }

    public static SyslogClientUtils getInstance(String newHost, int newPort, String newProtocolType) {
        if (instance == null || !newHost.equals(instance.getHost()) || newPort != instance.port || !newProtocolType.equals(instance.getProtocolType())) {
            synchronized (SyslogClientUtils.class) {
                if (instance == null || !newHost.equals(instance.getHost()) || newPort != instance.getPort()) {
                    instance = new SyslogClientUtils(newHost, newPort, newProtocolType);
                }
            }
        }
        return instance;
    }

    public void send(String info) {
        syslog.log(0, info);
    }
}

TcpUdpSyslogAppender.java:

package com.viewsources.ccs.server.syslog;

import ch.qos.logback.classic.net.SyslogAppender;
import ch.qos.logback.core.net.SyslogOutputStream;

import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * 自定义 logback syslog appender
 * @author Yohann
 */
public class TcpUdpSyslogAppender extends SyslogAppender {

    private String protocolType;

    public String getProtocolType() {
        return protocolType;
    }

    public void setProtocolType(String protocolType) {
        this.protocolType = protocolType;
    }
    @Override
    public SyslogOutputStream createOutputStream() throws SocketException, UnknownHostException {
        return new TcpUdpSyslogOutputStream(getSyslogHost(), getPort(),protocolType);
    }

}

TcpUdpSyslogOutputStream.java:

package com.viewsources.ccs.server.syslog;

import ch.qos.logback.core.net.SyslogOutputStream;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * @author Yohann
 */
public class TcpUdpSyslogOutputStream extends SyslogOutputStream {

    private final String ip;
    private final String protocolType;
    private final int port;
    private final ByteArrayOutputStream baos;

    public TcpUdpSyslogOutputStream(String ip, int port, String protocolType) throws UnknownHostException, SocketException {
        super(ip, port);
        this.ip = ip;
        this.port = port;
        this.protocolType = protocolType;
        this.baos = new ByteArrayOutputStream();
    }


    private static final int MAX_LEN = 1024;

    @Override
    public void write(byte[] byteArray, int offset, int len) throws IOException {
        baos.write(byteArray, offset, len);
    }

    @Override
    public void flush() throws IOException {
        byte[] bytes = baos.toByteArray();
        // clean up for next round
        baos.reset();

        // after a failure, it can happen that bytes.length is zero
        // in that case, there is no point in sending out an empty message/
        if (bytes.length == 0) {
            return;
        }
        SyslogClient.getInstance(ip,port,protocolType).send(new String(bytes));
    }

    @Override
    public int getPort() {
        return port;
    }

    @Override
    public void write(int b) throws IOException {
        baos.write(b);
    }

}

4.3、是否开启日志转发

    /**
     * 更新Syslog设置
     *
     * @param jsonStr
     */
    private void updateSysLogSetting(String jsonStr) {
        ResSysLogSetting setting = JSONUtil.toBean(jsonStr, ResSysLogSetting.class);
        if (setting.getStatus()) {
            // 开启日志转发
            if (setting.getLogType().contains(SYSTEM_LOG.getCode())) {
                // 转发系统日志
                startSyslogAppender("10.18.93.115", 514, "UDP");
            }
        } else {
            // 关闭日志转发
            stopSyslogAppender();
        }
    }

    private void stopSyslogAppender() {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        ch.qos.logback.classic.Logger root = loggerContext.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
        Iterator<Appender<ILoggingEvent>> it = root.iteratorForAppenders();
        Appender<ILoggingEvent> toRemoved = null;
        while (it.hasNext()) {
            Appender<ILoggingEvent> appender = it.next();
            if (appender instanceof TcpUdpSyslogAppender) {
                toRemoved = appender;
            }
        }
        root.detachAppender(toRemoved);
    }

    private void startSyslogAppender(String ip, int port, String protocol) {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        ch.qos.logback.classic.Logger root = loggerContext.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
        Iterator<Appender<ILoggingEvent>> it = root.iteratorForAppenders();

        String newAppenderName = buildAppenderName(ip, port, protocol);

        Appender<ILoggingEvent> old = null;
        while (it.hasNext()) {
            Appender<ILoggingEvent> appender = it.next();
            if (appender instanceof TcpUdpSyslogAppender) {
                old = appender;
            }
        }
        if (old != null) {
            if (old.getName().equals(newAppenderName)) {
                // 新旧一致则不改动
                return;
            }
            old.stop();
            root.detachAppender(old);
        }
        // 添加并启动新的
        TcpUdpSyslogAppender syslogAppender = new TcpUdpSyslogAppender();
        syslogAppender.setSyslogHost(ip);
        syslogAppender.setPort(port);
        syslogAppender.setName(newAppenderName);
        syslogAppender.setProtocolType(protocol);
        syslogAppender.setContext(root.getLoggerContext());
        syslogAppender.setFacility("LOCAL7");
        syslogAppender.start();
        root.addAppender(syslogAppender);
    }

    private String buildAppenderName(String ip, int port, String type) {
        return "syslogAppender:" + ip + ":" + port + ":" + type;
    }

4.4、转发mysql中的登录或操作日志

使用示例:

SyslogClientUtils udp = SyslogClientUtils.getInstance("10.18.93.115", 514, "UDP");
while (true){
  udp.send("helppppppppppppppppppppppppppppp");
  Thread.sleep(1000);
}

在添加操作日志或登录日志接口加上此代码:

    @Override
    @Async
    public void addOperationLog(Caller caller, String operatorContext, String operatorObject, int operatorState) {
        addOperationLog(caller.getUserId(), caller.getLoginIp(), caller.getTenantId(), caller.getLoginUa(),
                operatorContext, operatorObject, operatorState, LocalDateTime.now());
        // 根据系统设置是否发送操作日志到syslog
        SysValue syslogSetting = sysValueService.getOne(new LambdaQueryWrapper<SysValue>().eq(SysValue::getKeyParam, SYSLOG_SETTING));
        if (syslogSetting != null) {
            if (StringUtils.isNotBlank(syslogSetting.getValueParam())) {
                ResSysLogSetting sysLogSetting = JSONUtil.toBean(syslogSetting.getValueParam(), ResSysLogSetting.class);
                if (sysLogSetting.getStatus()) {
                    if (sysLogSetting.getLogType().contains(OPERATION_LOG.getCode())) {
                        // 发送到syslog
                        SyslogClientUtils.getInstance("10.18.93.115", 514, "UDP").send(operatorContext);
                    }
                }
            }
        }
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yohann*

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值