Code Monkey home page Code Monkey logo

logback-redis's Introduction

IMPORTANT: PROJECT SUNSET AND ARCHIVED

No new maintainers found in #38

Logback Redis Batch Appender

Build Status Maven Central

Enables Java applications to log directly to redis via the jedis client as part of centralized logging with the ELK stack.

More specifically, it uses async appenders and JSON encoding of the logstash-logback-encoder project. Messages are sent to redis in batches for performance reasons. The redis sentinel functionality is supported.

Maven dependencies

<dependency>
   <groupId>de.idealo.logback</groupId>
   <artifactId>logback-redis</artifactId>
   <version>1.5.0</version>
</dependency>

used best in conjunction with

<dependency>
   <groupId>net.logstash.logback</groupId>
   <artifactId>logstash-logback-encoder</artifactId>
   <version>6.2</version>
</dependency>      

Configuration

Simple Configuration

<configuration>
    ...
    <appender name="REDIS" class="net.logstash.logback.appender.LoggingEventAsyncDisruptorAppender">
        <appender class="de.idealo.logback.appender.RedisBatchAppender">
            <connectionConfig>
                <scheme>SENTINEL</scheme>
                <sentinelMasterName>${sentinel.master.name}</sentinelMasterName>
                <sentinels>${sentinel.host.list}</sentinels>
                <key>${sentinel.key}</key>
                <ssl>${redis.ssl}</ssl> <!-- false (default) or true -->
            </connectionConfig>
            <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                <providers>
                    <arguments/>
                    <mdc/>
                    <pattern>
                        <pattern>
                            {
                            "@stage":"${STAGE}",
                            "app": "${projectName}",
                            "host": "${HOSTNAME}",
                            "key" : "userservices",
                            "level": "%level",
                            "logger": "%logger",
                            "message": "%message",
                            "thread": "%thread",
                            "timestamp": "%d{yyyy-MM-dd'T'HH:mm:ss.SSSZZ}"
                            }
                        </pattern>
                    </pattern>
                    <stackTrace/>
                </providers>
            </encoder>
        </appender>
    </appender>
    ...
</configuration>

Parameters

  • connectionConfig:
    • key: key under which messages are stored in redis
    • scheme (NODE | SENTINEL): defines whether redis is accessed via a single node or via sentinel
    • for scheme=SENTINEL:
      • sentinelMasterName: name of the sentinel master
      • sentinels: comma separated list of sentinels with the following structure: host1:port1,host2:port2
    • for scheme=NODE:
      • host: redis host
      • port: redis port
    • method (RPUSH | PUBLISH): defines the method to that should be used to send values to redis. with method PUBLISH the value defined as key is used as channel name. if method is omitted, then RPUSH is used.
    • ssl: Whether to use SSL to communicate with redis (false or true, default is false). Your client and server certificates must be set up correctly.
  • maxBatchMessages: number of messages which are sent as batch size to redis
  • maxBatchSeconds: time interval in seconds after a batch of messages is sent to redis if the batch size is not reached
  • encoder: encoder for JSON formatting of the messages
  • ringBuffer and waitStrategyType determine how the logstash-logback-encoder asynchronously processes the messages. Note that messages may be lost if the ring buffer size is too small ("If the RingBuffer is full (e.g. due to slow network, etc), then events will be dropped.").

Extended Configuration

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
    <appender name="REDIS_APPENDER" class="net.logstash.logback.appender.LoggingEventAsyncDisruptorAppender">
        <ringBufferSize>131072</ringBufferSize>
        <appender class="de.idealo.logback.appender.RedisBatchAppender">
            <connectionConfig>
                <!-- redis sentinel: -->
                <scheme>SENTINEL</scheme>
                <sentinelMasterName>mymaster</sentinelMasterName>
                <sentinels>server:26379</sentinels>
                <!-- redis node: -->
                <!--<scheme>NODE</scheme>-->
                <!--<host>server</host>-->
                <!--<port>6379</port>-->
                <key>keyForRedis</key>
            </connectionConfig>
            <maxBatchMessages>1000</maxBatchMessages>
            <maxBatchSeconds>10</maxBatchSeconds>
            <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                <providers>
                    <mdc/>
                    <pattern>
                        <pattern>
                            {
                            "timestamp": "%d{yyyy-MM-dd'T'HH:mm:ss.SSSZZ}",
                            "message": "%message",
                            "logger": "%logger",
                            "thread": "%thread",
                            "level": "%level",
                            "host": "${HOSTNAME}",
                            "file": "%file",
                            "line": "%line",
                            "app": "${projectName}"
                            }
                        </pattern>
                    </pattern>
                    <stackTrace>
                        <throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
                            <maxDepthPerThrowable>30</maxDepthPerThrowable>
                            <maxLength>4096</maxLength>
                            <shortenedClassNameLength>20</shortenedClassNameLength>
                            <rootCauseFirst>true</rootCauseFirst>
                        </throwableConverter>
                   </stackTrace>
                </providers>
            </encoder>
        </appender>
    </appender>
    ...
</configuration>

This appender configuration can either be included in a logback.xml file (via "included" tag) or be directly contained in a logback.xml (without "included" tag).

JSON Format Created by the Appender (Example) (= Input for Logstash)

{
    "_index": "myIndex-2015.09.15.12",
    "_type": "logs",
    "_id": "AU_RAKiIuARjD1TqcEFe",
    "_score": null,
    "_source": {
        "mdcKey1": "value1",
        "mdcKey2": "value2",
        "seq": "198",
        "timestamp": "2015-09-15T14:35:19.256+0200",
        "message": "logback-1:198",
        "logger": "LoggingTest",
        "thread": "main",
        "level": "INFO",
        "host": "myHost",
        "file": "?",
        "line": "?",
        "@version": "1",
        "@timestamp": "2015-09-15T12:35:25.251Z",
        "type": "logs"
},
    "fields": {
    "@timestamp": [
        1442320525251
    ]
},
    "sort": [
    1442320525251
]
}

Logging Appender Errors to a File

The following logger configuration in the logback.xml is recommended in order to write error messages of the appender directly to a file in error situations (especially if redis is not available):

<logger name="de.idealo.logback.appender" level="error" additivity="false">
    <appender-ref ref="FILE_FOR_REDISBATCHAPPENDER"/>
</logger>

Shutdown

Shutdown Hook

The redis batch appender must be shut down on application shutdown in order to ensure that cleans up background threads and pools and ensures that remaining messages are sent to Redis before shutting down the app. This is performed by the stop method of the redis batch appender that is automatically called when putting a shutdown hook in logback.xml:

<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>

The shutdown hook above doesn't work in Spring Boot apps when they are shut down via the actuator shutdown URL (POST {baseUrl}/shutdown). Instead, this can be done by the following Spring component:

@Component
public class LogbackStopListener implements ApplicationListener<ContextClosedEvent> {
    @Override
    public void onApplicationEvent(final ContextClosedEvent event) {
        LogbackUtils.stopLogback();
    }
}

logback-redis's People

Contributors

cdanzl avatar dependabot[bot] avatar hieudbui avatar lkwg82 avatar mgerlach avatar mle-enso avatar roechi avatar schabe77 avatar vsdev1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

logback-redis's Issues

Encoder version mismatch?

Hi,

I'm already using "net.logstash.logback:logstash-logback-encoder:4.11" in my app, which depends on
logback-core 1.1.11.

I want to add your redis appender, but this method
de.idealo.logback.appender.RedisBatchAppender#createEncodedEvent relies on logback-core 1.2.3 : encoder.encode does not exist in logback-core 1.1.11

(I'm using spring boot 1.5.9 which provides also logback-core 1.1.11 )

How can we fix this?
Thanks!

Temporary errors while connecting the sentinel

From time to time the appender looses connection to the sentinel, which leads to log messages like…

redis.clients.jedis.JedisSentinelPool
ERROR
Lost connection to Sentinel at node-01:26379. Sleeping 5000ms and retrying.

This happens not with all applications connected to Redis, further results will be added here as investigation continues.

Application startup fails, when hosts for RedisAppender wrong/not reachable

2016-07-22 16:49:00.921 ERROR SpringApplication:821 [restartedMain] [] - Application startup failed
java.lang.IllegalStateException: Logback configuration error detected: 
ERROR in ch.qos.logback.core.joran.spi.Interpreter@52:16 - RuntimeException in Action for tag [appender] redis.clients.jedis.exceptions.JedisConnectionException: All sentinels down, cannot determine where is logging master is running...

This should never happens.

Goal: Never fail when supportive system is temporary unavailable.

Adapt to API changes in logback-core >= 1.2.0

https://logback.qos.ch/news.html informs about an API change:

Encoder interface has changed and is no longer expected to handle an OutputStream.

The logback-redis artifact relies on exactly this breaking change at the following place:

de.idealo.logback.appender.RedisBatchAppender.createEncodedEvent(DeferredProcessingAware)

So we need an upgrade at least for this method to stay upgradable to Logback >= 1.2.0 which is a mangaged dependency of https://github.com/spring-projects/spring-boot/tree/master/spring-boot-starters/spring-boot-starter-logging.

strange error message

Exception while retrying to append the event '[ERROR] Exception while retrying to append the event 'null' with a re-initialized Jedis client. The event is lost.' with a re-initialized Jedis client. The event is lost.

redis.clients.jedis.exceptions.JedisException: Could not get a resource from the pool
    at redis.clients.util.Pool.getResource(Pool.java:51)
    at redis.clients.jedis.JedisSentinelPool.getResource(JedisSentinelPool.java:209)
    at redis.clients.jedis.JedisSentinelPool.getResource(JedisSentinelPool.java:17)
    at de.idealo.logback.appender.RedisBatchAppender.initJedisClient(RedisBatchAppender.java:220)
    at de.idealo.logback.appender.RedisBatchAppender.append(RedisBatchAppender.java:122)
    at de.idealo.logback.appender.RedisBatchAppender.append(RedisBatchAppender.java:34)
    at ch.qos.logback.core.AppenderBase.doAppend(AppenderBase.java:82)
    at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:48)
    at net.logstash.logback.appender.DelegatingAsyncDisruptorAppender$DelegatingEventHandler.onEvent(DelegatingAsyncDisruptorAppender.java:53)
    at net.logstash.logback.appender.DelegatingAsyncDisruptorAppender$DelegatingEventHandler.onEvent(DelegatingAsyncDisruptorAppender.java:49)
    at net.logstash.logback.appender.AsyncDisruptorAppender$EventClearingEventHandler.onEvent(AsyncDisruptorAppender.java:320)
    at net.logstash.logback.appender.AsyncDisruptorAppender$EventClearingEventHandler.onEvent(AsyncDisruptorAppender.java:308)
    at net.logstash.logback.encoder.com.lmax.disruptor.BatchEventProcessor.run(BatchEventProcessor.java:129)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.util.NoSuchElementException: Unable to validate object
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:506)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363)
    at redis.clients.util.Pool.getResource(Pool.java:49)
    ... 19 common frames omitted

The event is not lost and later reported, but logged as error.

This error happend at the time we had internal DNS problems.

Documentation for SSL configuration

Hi,
I'm trying to use this appender with SSL but it's not at all obvious to me how to configure the redis appender for SSL, presumably because the doco lags the code capability, but even when I debug the code it's not clear how it gets its SSL configuration. Can someone provide a few pointers and update the online doco as well?

Improve resilience on connection failures

We notices some issues when the redis cluster was up, but not ready.

  • ensure connection failures are not crashing the app on startup (#7)
  • ensure connection failures are not filling the logs (some logs are ok)
  • ensure connection failures are not eating up the cpu
  • make <retryOnInitializeError>false</retryOnInitializeError>obsolet

get rid off of these logs

2016-09-08 12:00:14.254  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.254  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.254  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.254  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.257  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.258  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.258  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.258  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.258  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.258  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.258  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.259  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.259  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.259  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.259  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.259  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.259  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.260  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.260  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.260  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.260  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready
2016-09-08 12:00:14.260  WARN RedisBatchAppender:SubstituteLogger.java:217 [logback-appender-REDIS-2] [] - pipeline not ready

Looking for new maintainer

Hi there,

this is a message for everyone using this library, especially those of you who forked it: @ask4gilles @huluohu @lkwg82 @mle-enso @radical-systems @roechi @yiyingcanfeng @zavalit @zhiweicoding (cc @vsdev1).

We at idealo are no longer using the library and are looking for a new owner who is actively using it and should thus be able to maintain it much better than we can. E. g., the lib could use a great deal of dependency bumping (e. g., via a dependabot configuration), maybe switch to GitHub actions for PR verification and Maven Central deployment, etc.

So, if you are actively using logback-redis, could you imagine taking ownership and be responsible for the maven central releases?

Thanks,
Martin

logstash-logback-encoder version

You write in the documentation:

used best in conjuction with

<dependency>
   <groupId>net.logstash.logback</groupId>
   <artifactId>logstash-logback-encoder</artifactId>
   <version>4.11</version>
</dependency>      

Is there a strong need to use 4.11 or could it also be the latest version?

(which is at the moment)

 <version>5.1</version>

Possible connection/thread leak when Redis Sentinels/Nodes not reachable

At idealo we experienced the situation that on connection problems with Redis and the Sentinels, apps using the Appender created a lot of connections but never cleaned them up. This was also visible in many master listener threads where there should only be one per sentinel (afaik).

We may want to double check how the Redis client (Jedis) is used in the library. It may be missing some exception handling and timeout configuration.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.