Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

version 0.3.2 cause null sender from FluentLoggerFactory.getLogger #64

Open
ghost opened this issue Mar 7, 2017 · 1 comment
Open

Comments

@ghost
Copy link

ghost commented Mar 7, 2017

I have read some issues before about the reason to use a WeakHashMap in FluentLoggerFactory. And the WeakHashMap was changed from WeakHashMap<String, FluentLogger> (version 0.3.1) to WeakHashMap<FluentLogger, String>(current version 0.3.2).

But I got a FluentLogger with null sender in version 0.3.2 when using logback in Spring Boot application.

The sender could not be connecting to fluent server for long time. So the sender should be assigned to null after calling FluentLogger.close().

But in my situation, how can I get a work-well logger after Spring Boot application has been luanched.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

public class FluentLoggerFactory {

    private final Map<FluentLogger, String> loggers;

    public FluentLoggerFactory() {
        loggers = new WeakHashMap<FluentLogger, String>();
    }

    public synchronized FluentLogger getLogger(String tagPrefix, String host, int port, int timeout, int bufferCapacity,
            Reconnector reconnector) {
        String key = String.format("%s_%s_%d_%d_%d", new Object[] { tagPrefix, host, port, timeout, bufferCapacity });

        for (Map.Entry<FluentLogger, String> entry : loggers.entrySet()) {
            if (entry.getValue().equals(key)) {
                FluentLogger found = entry.getKey();
                if(found != null) {
                    return found;  // the found contains a null valued sender
                }
                break;
            }
        }

        Sender sender = null;
        Properties props = System.getProperties();
        if (!props.containsKey(Config.FLUENT_SENDER_CLASS)) {
            // create default sender object
            sender = new RawSocketSender(host, port, timeout, bufferCapacity, reconnector);
        } else {
            String senderClassName = props.getProperty(Config.FLUENT_SENDER_CLASS);
            try {
                sender = createSenderInstance(senderClassName, new Object[] { host, port, timeout, bufferCapacity });
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        FluentLogger logger = new FluentLogger(tagPrefix, sender);
        loggers.put(logger, key);
        return logger;
    }
...
...
}
@SpringBootApplication
public class Application {

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

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        LOGGER.info("hello world);
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
    ​
    <springProperty scope="context" name="springAppName" source="spring.application.name"/>

    <property name="CONSOLE_LOG_PATTERN"
              value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([${springAppName:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-B3-ParentSpanId:-},%X{X-Span-Export:-}]){yellow} %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>

    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <appender name="FLUENT_TEXT_SYNC" class="ch.qos.logback.more.appenders.FluentLogbackAppender">
        <tag>debug</tag>
        <label>logback</label>
        <remoteHost>localhost</remoteHost>
        <port>24224</port>
    </appender>

    <appender name="FLUENT_TEXT" class="ch.qos.logback.classic.AsyncAppender">
        <queueSize>999</queueSize>
        <appender-ref ref="FLUENT_TEXT_SYNC" />
    </appender>

    <logger name="org.springframework" level="INFO"/>

    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FLUENT_TEXT"/>
    </root>

</configuration>
public class FluentLogger {

    public boolean log(String tag, Map<String, Object> data, long timestamp) {
        String concatTag = null;
        if (tagPrefix == null || tagPrefix.length() == 0) {
            concatTag = tag;
        }
        else {
            concatTag = tagPrefix + "." + tag;
        }

        if (timestamp != 0) {
            return sender.emit(concatTag, timestamp, data);
        } else {
            return sender.emit(concatTag, data);
        }
    }

    public void flush() {
        sender.flush();
    }

    public void close() {
        if (sender != null) {
            sender.flush();
            sender.close();
            sender = null;  //  set sender to null after closing FluentLogger
        }
    }
}
@hoedic44
Copy link

hoedic44 commented Feb 15, 2018

I have same behavior while live updating logback.xml file (to change log level or log appender destination). Bugfix seems to resolve problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant