gpt4 book ai didi

spring - 如何通过 GELF 将 spring boot 访问日志发送到远程服务器?

转载 作者:行者123 更新时间:2023-11-28 21:51:18 26 4
gpt4 key购买 nike

对于我们的 spring boot 应用程序,我们使用 logback + GELF将应用程序日志发送到我们可以分析它们的中央日志服务器。是否可以对 spring boot 的访问日志做同样的事情?

如果没有,对于从中央服务器上的多个 spring boot 应用程序收集访问日志,是否有任何其他建议或最佳实践?

最佳答案

好的,经过一番研究我发现了。您需要向 tomcat 添加自定义阀:

@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
TomcatEmbeddedServletContainerFactory factory
= new TomcatEmbeddedServletContainerFactory();
GelfAccessLogValve gelfAccessLogValve = new GelfAccessLogValve();
gelfAccessLogValve.setPattern("%h %m %U %I %l %u %t "%r" %s %b");
factory.addContextValves(gelfAccessLogValve);
return factory;
}

我写的valve是基于paluch.biz's valve但不同之处在于它仅依赖于 graylog 的 gelf 客户端。因此,您需要将此依赖项添加到您的 pom:

<dependency>
<groupId>org.graylog2</groupId>
<artifactId>gelfclient</artifactId>
<version>1.4.0</version>
</dependency>

这是阀门代码:

public class GelfAccessLogValve extends AccessLogValve {

private final static Map<Class, String> names = Collections.unmodifiableMap(new HashMap<Class, String>() {
{
put(HeaderElement.class, "Header");
put(CookieElement.class, "Cookie");
put(ResponseHeaderElement.class, "ResponseHeader");
put(SessionAttributeElement.class, "SessionAttribute");
put(RemoteAddrElement.class, "RemoteAddr");
put(LocalAddrElement.class, "LocalAddr");
put(ByteSentElement.class, "ByteSent");
put(ElapsedTimeElement.class, "ElapsedTime");
put(HostElement.class, "Host");
put(ProtocolElement.class, "Protocol");
put(MethodElement.class, "Method");
put(PortElement.class, "LocalPort");
put(QueryElement.class, "Query");
put(RequestElement.class, "Request");
put(FirstByteTimeElement.class, "FirstByteTime");
put(HttpStatusCodeElement.class, "HttpStatusCode");
put(SessionIdElement.class, "SessionId");
put(DateAndTimeElement.class, "DateAndTime");
put(UserElement.class, "User");
put(RequestURIElement.class, "RequestURI");
put(LocalServerNameElement.class, "LocalServerName");
put(ThreadNameElement.class, "ThreadName");
}
});

private String host = "localhost";
private int port = 1234;
private GelfTransport gelfSender;

@Override
public void log(Request request, Response response, long time) {

if (gelfSender == null || !getState().isAvailable() || !getEnabled() || logElements == null || condition != null
&& null != request.getRequest().getAttribute(condition) || conditionIf != null
&& null == request.getRequest().getAttribute(conditionIf)) {
return;
}

/**
* XXX This is a bit silly, but we want to have start and stop time and duration consistent. It would be better to keep
* start and stop simply in the request and/or response object and remove time (duration) from the interface.
*/
long start = request.getCoyoteRequest().getStartTime();
Date date = new Date(start + time);

GelfMessage message = new GelfMessage(request.getMethod() + " " + request.getRequestURI());
message.addAdditionalField("facility", getClass().getSimpleName());
message.setFullMessage(request.getMethod() + " " + request.getRequestURI());
message.setTimestamp(start + time);
message.setLevel(GelfMessageLevel.INFO);

for (int i = 0; i < logElements.length; i++) {

String name = names.get(logElements[i].getClass());
if (name == null) {
continue;
}

CharArrayWriter result = new CharArrayWriter(128);
logElements[i].addElement(result, date, request, response, time);
message.addAdditionalField(name, result.toString());
}

try {
gelfSender.send(message);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

private void createSender() {
GelfConfiguration configuration = new GelfConfiguration(host, port);
gelfSender = GelfTransports.create(configuration);
}

@Override
protected synchronized void startInternal() throws LifecycleException {
createSender();

super.startInternal();
}

@Override
protected synchronized void stopInternal() throws LifecycleException {
if (gelfSender != null) {
gelfSender.stop();
gelfSender = null;
}
super.stopInternal();
}

public String getHost() {
return host;
}

public void setHost(String host) {
this.host = host;
}

public int getPort() {
return port;
}

public void setPort(int port) {
this.port = port;
}
}

关于spring - 如何通过 GELF 将 spring boot 访问日志发送到远程服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42945201/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com