项目方案:使用 Vector 日志采集工具收集 Java 服务日志

介绍

在 Java 服务开发中,日志是一个重要的组成部分,用于记录系统的运行状态和异常情况。为了更好地管理和分析日志,我们可以使用 Vector 日志采集工具来将 Java 服务的日志发送到中央集中的日志存储系统,如 Elasticsearch、Kafka 等。

本文将提供一个使用 Vector 日志采集工具收集 Java 服务日志的项目方案,包括配置 Vector、编写 Java 日志输出插件和代码示例。

Vector 配置

Vector 是一个开源的日志采集工具,可以将各种源头的日志数据发送到各种目标存储系统。以下是一个简单的 Vector 配置示例,用于收集 Java 服务的日志。

# vector.toml
[data_dir]
  type = "file"
  path = "/var/lib/vector"

[sources.log]
  type = "stdin"

[sinks.elasticsearch]
  type = "elasticsearch"
  inputs = ["log"]
  host = "http://elasticsearch:9200"
  index = "java-service-logs"
  batch_size = 500
  idle_timeout_secs = 10

[sinks.stdout]
  type = "console"
  inputs = ["log"]

在上述配置中,我们使用 stdin 源头来接收 Java 服务的日志,然后将日志数据发送到 Elasticsearch 存储系统中,并在控制台上输出日志。

Java 日志输出插件

为了将 Java 服务的日志发送到 Vector,我们需要编写一个日志输出插件。以下是一个示例代码,用于将日志输出到标准输出并通过标准输入流发送给 Vector:

import java.io.OutputStream;
import java.io.PrintStream;

public class VectorLogger {

    public static void main(String[] args) {
        redirectStdoutToVector();
        redirectStderrToVector();

        // Your Java service code here
        // ...

        // Close VectorLogger when service shutdown
        close();
    }

    public static void redirectStdoutToVector() {
        PrintStream ps = new PrintStream(new VectorOutputStream(System.out));
        System.setOut(ps);
    }

    public static void redirectStderrToVector() {
        PrintStream ps = new PrintStream(new VectorOutputStream(System.err));
        System.setErr(ps);
    }

    public static void close() {
        VectorOutputStream.close();
    }

    private static class VectorOutputStream extends OutputStream {

        private static final StringBuilder BUFFER = new StringBuilder();

        private final PrintStream originalOut;

        public VectorOutputStream(PrintStream originalOut) {
            this.originalOut = originalOut;
        }

        @Override
        public void write(int b) {
            if (b == '\n') {
                sendLog(BUFFER.toString());
                BUFFER.setLength(0);
            } else {
                BUFFER.append((char) b);
            }
            originalOut.write(b);
        }

        public static void sendLog(String log) {
            // Send log to Vector through standard input
            System.out.println(log);
        }

        public static void close() {
            if (BUFFER.length() > 0) {
                sendLog(BUFFER.toString());
            }
        }
    }
}

上述代码将标准输出和标准错误流重定向到 VectorOutputStream,并在每行结尾发送日志给 Vector。注意将该类的 main 方法作为 Java 服务的入口方法,并在服务关闭时调用 close 方法来关闭 VectorLogger。

示例代码

以下是一个简单的 Java 服务示例代码,演示如何使用上述的 VectorLogger 来发送日志给 Vector。

public class MyService {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyService.class);

    public static void main(String[] args) {
        VectorLogger.redirectStdoutToVector();
        VectorLogger.redirectStderrToVector();

        LOGGER.info("Starting MyService...");

        // Your service initialization code here
        // ...

        LOGGER.info("MyService started");

        // Your service logic here
        // ...

        LOGGER.info("MyService stopped");

        VectorLogger.close();
    }
}

上述代码中,我们通过调用 VectorLogger 的 redirectStdoutToVectorredirectStderrToVector 方法将日志输出重定向到 Vector,然后使用 SLF4J 的 LoggerFactory 创建一个 Logger 对象,用于记录服务的状态。

总结

本文提供了一个使用 Vector 日志采集工具收集 Java 服务日志的项目方案,包括 Vector 配置、Java 日志输出插件和示例代码。通过配置 Vector 和使用 VectorLogger 类,我们可以方