java 当将Elasticsearch附加器添加到记录器org.apache.http时,应用程序挂起

7qhs6swi  于 2023-06-28  发布在  Java
关注(0)|答案(1)|浏览(119)

我们有一个Elastic Search appender

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//


import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.net.InetAddress;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpHost;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ElasticSearchAppender extends AppenderBase<ILoggingEvent> {
    private static final Logger log = LoggerFactory.getLogger(ElasticSearchAppender.class);
    private static ObjectMapper mapper = new ObjectMapper();
    private static RestHighLevelClient elastic;
    private ExecutorService executorService = Executors.newFixedThreadPool(10);
    private static RequestOptions COMMON_OPTIONS;
    private String hostname;
    private Integer port;
    private String index;
    private String application;
    private String login;
    private String password;

    public ElasticSearchAppender() {
    }

    public String getLogin() {
        return this.login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getApplication() {
        return this.application;
    }

    public void setApplication(String application) {
        this.application = application;
    }

    public String getHostname() {
        return this.hostname;
    }

    public void setHostname(String hostname) {
        this.hostname = hostname;
    }

    public Integer getPort() {
        return this.port;
    }

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

    public String getIndex() {
        return this.index;
    }

    public void setIndex(String index) {
        this.index = index;
    }

    protected void append(ILoggingEvent event) {
        if (elastic == null) {
            this.createElasticConnection(this.hostname, this.port);

            try {
                CreateIndexRequest createIndexRequest = new CreateIndexRequest(this.index);
                createIndexRequest.source(mapper.writeValueAsString(new Message(InetAddress.getLocalHost().getHostName(), LocalDateTime.ofInstant(Instant.ofEpochMilli(event.getTimeStamp()), ZoneOffset.UTC).toString(), event.getLevel().toString(), event.getLoggerName(), event.getMDCPropertyMap(), event.getFormattedMessage(), this.application)), XContentType.JSON);
                elastic.indices().create(createIndexRequest, COMMON_OPTIONS);
            } catch (ElasticsearchStatusException var3) {
                log.error(var3.getMessage(), var3);
            } catch (IOException var4) {
            }
        } else {
            this.executorService.submit(() -> {
                try {
                    IndexRequest indexRequest = new IndexRequest(this.index);
                    indexRequest.source(mapper.writeValueAsString(new Message(InetAddress.getLocalHost().getHostName(), LocalDateTime.ofInstant(Instant.ofEpochMilli(event.getTimeStamp()), ZoneOffset.UTC).toString(), event.getLevel().toString(), event.getLoggerName(), event.getMDCPropertyMap(), event.getFormattedMessage(), this.application)), XContentType.JSON);
                    elastic.index(indexRequest, COMMON_OPTIONS);
                } catch (IOException var3) {
                }

            });
        }

    }

    private void createElasticConnection(String hostname, int port) {
        elastic = new RestHighLevelClient(RestClient.builder(new HttpHost[]{new HttpHost(hostname, port, "http")}).setRequestConfigCallback((requestConfigBuilder) -> {
            return requestConfigBuilder.setConnectTimeout(5000).setSocketTimeout(60000);
        }).setHttpClientConfigCallback((httpClientBuilder) -> {
            return httpClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(200).build());
        }));
        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
        builder.addHeader("Authorization", "Basic " + Base64.encodeBase64String((this.login + ":" + this.password).getBytes()));
        COMMON_OPTIONS = builder.build();
    }

    private class Message {
        private String hostname;
        private String time;
        private String level;
        private String loggerName;
        private Map<String, String> mdcProperty;
        private String msg;
        private String applicationName;

        public String getHostname() {
            return this.hostname;
        }

        public String getTime() {
            return this.time;
        }

        public String getLevel() {
            return this.level;
        }

        public String getLoggerName() {
            return this.loggerName;
        }

        public Map<String, String> getMdcProperty() {
            return this.mdcProperty;
        }

        public String getMsg() {
            return this.msg;
        }

        public String getApplicationName() {
            return this.applicationName;
        }

        public void setHostname(String hostname) {
            this.hostname = hostname;
        }

        public void setTime(String time) {
            this.time = time;
        }

        public void setLevel(String level) {
            this.level = level;
        }

        public void setLoggerName(String loggerName) {
            this.loggerName = loggerName;
        }

        public void setMdcProperty(Map<String, String> mdcProperty) {
            this.mdcProperty = mdcProperty;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public void setApplicationName(String applicationName) {
            this.applicationName = applicationName;
        }

        public Message() {
        }

        public Message(String hostname, String time, String level, String loggerName, Map<String, String> mdcProperty, String msg, String applicationName) {
            this.hostname = hostname;
            this.time = time;
            this.level = level;
            this.loggerName = loggerName;
            this.mdcProperty = mdcProperty;
            this.msg = msg;
            this.applicationName = applicationName;
        }
    }
}

当我们把它放在logback.xml中时

<appender name="Elastic" class="***.log.appender.ElasticSearchAppender">
    <hostname>${elkHostname}</hostname>
    <port>${elkPort}</port>
    <index>${elkIndex}</index>
    <application>${applicationName}</application>
    <login>${login}</login>
    <password>${password}</password>
</appender>

如果我们能够

<logger name="org.apache.http" level="debug" additivity="false">
     <appender-ref ref="STDOUT"/>
     <appender-ref ref="Elastic"/>
 </logger>

然后,根据我们的日志,我们的应用程序在第一个http调用caomint时挂起,或者由应用程序启动

jdgnovmf

jdgnovmf1#

事实证明,由于org.apache.http logger,Elastic发起的调用本身应该由Elastic appender记录,因为Elastic执行http调用。因此,它变成了递归和堆栈溢出。
但在日志中,它看起来就像什么也没发生。
要解决这个问题,就要避免对org.apache.http logger使用Elastic appender。

<logger name="org.apache.http" level="debug" additivity="false">
     <appender-ref ref="STDOUT"/>
     <!--<appender-ref ref="Elastic"/>-->
 </logger>

相关问题