{"id":1676,"date":"2014-12-18T14:17:01","date_gmt":"2014-12-18T14:17:01","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=1676"},"modified":"2014-12-18T14:17:01","modified_gmt":"2014-12-18T14:17:01","slug":"logging-couchbase-java-client","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/","title":{"rendered":"Logging with the Couchbase Java Client"},"content":{"rendered":"<p><em style=\"line-height: 23px; font-family: ff-meta-serif-web-pro-1, ff-meta-serif-web-pro-2, Georgia, 'Times New Roman', Times, serif;\">[This blog was syndicated from https:\/\/nitschinger.at\/]<\/em><\/p>\n<h2>Introduction<\/h2>\n<p>There is a huge variety in logging frameworks for Java, and its hard to please everyone. To understand how logging is currently handled in the SDK, we have to go back a few years. As you may know, the SDK depends on the <a href=\"https:\/\/code.google.com\/p\/spymemcached\/\">spymemcached<\/a>\u00a0library and therefore also inherits its logging mechanisms. Back in the days when <a href=\"https:\/\/twitter.com\/dlsspy\">@dustin<\/a>\u00a0wrote spy, there was no good abstraction for logging available (like <a href=\"https:\/\/www.slf4j.org\/\">SLF4J<\/a>), so he wrote his own. Nowadays things have changed, but spy still inherits this legacy.<\/p>\n<p>At the time of writing, the SDK supports logging to a simple default logger (logs to STDERR from INFO level up), <a href=\"https:\/\/logging.apache.org\/log4j\/1.2\/\">Log4J<\/a>\u00a0and the SunLogger (java.util.logging). In the upcoming 2.9.0 release of spymemcached, it will also support the SLF4J logging facade where you can plug in your own implementation. The next version of the SDK (most likely 1.1.7) will depend on spy 2.9, so you&#39;ll also get the benefits there.<\/p>\n<p>Before we dig into the concepts, here are the supported Log Levels (defined by <em>net.spy.memcached.compat.log.Level<\/em>):<\/p>\n<ol class=\"rteindent1\">\n<li>TRACE (with 2.9)<\/li>\n<li>DEBUG<\/li>\n<li>INFO<\/li>\n<li>WARN<\/li>\n<li>ERROR<\/li>\n<li>FATAL<\/li>\n<\/ol>\n<p>Keep in mind that different loggers implement different levels, so for some of them a mapping needs top happen. This will be noted during the descriptions of each implementation.<\/p>\n<p>We&#39;ll now look at the different logging mechanisms available and how you can configure them. SLF4J will be covered towards the end.<\/p>\n<h2>Switching Logging<\/h2>\n<p>If you don&#39;t change anything, the default logger will be used. This mechanism just prints log messages to STDERR (from INFO level upwards). Chances are that you want to integrate the SDK with the same logging library that you use as well. The LoggerFactory inside spy decides at construction which one to choose, based on a system property. So you can either change this programmatically or through a param to the <em>java<\/em> command.<\/p>\n<p>If you want to use the Log4JLogger programmatically, do it this way (before initializing the <em>CouchbaseClient<\/em>\u00a0object):<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">Properties systemProperties = System.getProperties();<br \/>systemProperties.put(&#8220;net.spy.log.LoggerImpl&#8221;, &#8220;net.spy.memcached.compat.log.Log4JLogger&#8221;);<br \/>System.setProperties(systemProperties);<\/div>\n<\/div>\n<p><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">Of course, you need to add the Log4J JAR to your CLASSPATH to make it work (as we&#39;ll see later). Alternatively, you can set it this way on the command line:<\/span><\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">java -Dnet.spy.log.LoggerImpl=net.spy.memcached.compat.log.Log4JLogger &#8230;<\/div>\n<\/div>\n<p>Now that we know how to enable the different implementations, let&#39;s look at them in greater detail.<\/p>\n<h2>The Simple Default Logger<\/h2>\n<p><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">If you don&#39;t change anything, the SDK will use the DefaultLogger (<\/span><em style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">net.spy.memcached.compat.log.DefaultLogger<\/em><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">). This logger has no dependencies and prints every log message that is INFO level or higher (INFO, WARN, ERROR and FATAL) to the systems STDERR. Since the STDERR is covered by most IDEs automatically, you&#39;ll also see them in the console output window.<\/span><\/p>\n<p>Since its so simple, you can&#39;t customize this behavior. Every log message gets timestamped as well (the format is <em>yyyy-MM-dd HH:mm:ss.SSS<\/em>). Connecting to Couchbase commonly looks like this:<\/p>\n<div>\u00a0<\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">2013-05-07 12:28:41.852 INFO com.couchbase.client.CouchbaseConnection: \u00a0Added {QA sa=\/127.0.0.1:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue<br \/>2013-05-07 12:28:41.862 INFO com.couchbase.client.CouchbaseConnection: \u00a0Connection state changed for sun.nio.ch.SelectionKeyImpl@3d9360e2<br \/>2013-05-07 12:28:41.887 INFO com.couchbase.client.ViewConnection: \u00a0Added localhost to connect queue<br \/>2013-05-07 12:28:41.888 INFO com.couchbase.client.CouchbaseClient: \u00a0viewmode property isn&#8217;t defined. Setting viewmode to production mode<br \/>2013-05-07 12:28:41.986 INFO com.couchbase.client.CouchbaseConnection: \u00a0Shut down Couchbase client<br \/>2013-05-07 12:28:41.991 INFO com.couchbase.client.ViewConnection: \u00a0Node localhost has no ops in the queue<br \/>2013-05-07 12:28:41.992 INFO com.couchbase.client.ViewNode: \u00a0I\/O reactor terminated for localhost<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<p>So the format is always: <em><timestamp> <level> <classname> <message><\/em>. Remeber that DEBUG messages or so will not be logged, so you won&#39;t see them with the DefaultLogger.<\/p>\n<div>\u00a0<\/div>\n<h2>The SunLogger (java.util.logging)<\/h2>\n<p>The SunLogger also doesn&#39;t introduce additional dependencies, since it depends on the <em>java.util.logging<\/em> implementation. The <em>java.util.logging.Level<\/em> enum defines the following levels: ALL, CONFIG, FINEST, FINER, FINE, INFO, WARNING, SEVERE and OFF. Since this does not map well to our defined Levels, here is the mapping that happens:<\/p>\n<div>\u00a0<\/div>\n<ol class=\"rteindent1\">\n<li>TRACE to FINEST (with 2.9)<\/li>\n<li><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">DEBUG to FINE<\/span><\/li>\n<li><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">INFO to INFO<\/span><\/li>\n<li><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">WARN to WARNING<\/span><\/li>\n<li><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">ERROR to SEVERE<\/span><\/li>\n<li><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">FATAL to SEVERE<\/span><\/li>\n<\/ol>\n<div>\u00a0<\/div>\n<div>Without any further changes, the SunLogger also prints from INFO level upwards like this:<\/div>\n<div>\u00a0<\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">May 7, 2013 12:42:16 PM com.couchbase.client.CouchbaseProperties setPropertyFile<br \/>INFO: Could not load properties file &#8220;cbclient.properties&#8221; because: File not found with system classloader.<br \/>May 7, 2013 12:42:16 PM net.spy.memcached.MemcachedConnection createConnections<br \/>INFO: Added {QA sa=\/127.0.0.1:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue<br \/>May 7, 2013 12:42:16 PM net.spy.memcached.MemcachedConnection handleIO<br \/>INFO: Connection state changed for sun.nio.ch.SelectionKeyImpl@4ce2cb55<br \/>May 7, 2013 12:42:16 PM com.couchbase.client.ViewConnection createConnections<br \/>INFO: Added localhost to connect queue<br \/>May 7, 2013 12:42:16 PM com.couchbase.client.CouchbaseClient <init><br \/>INFO: viewmode property isn&#8217;t defined. Setting viewmode to production mode<br \/>May 7, 2013 12:42:16 PM com.couchbase.client.CouchbaseConnection run<br \/>INFO: Shut down Couchbase client<br \/>May 7, 2013 12:42:16 PM com.couchbase.client.ViewConnection shutdown<br \/>INFO: Node localhost has no ops in the queue<br \/>May 7, 2013 12:42:16 PM com.couchbase.client.ViewNode$1 run<br \/>INFO: I\/O reactor terminated for localhost<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<p>If you want to change the log level to DEBUG and lower, you can do it like this:<\/p>\n<div>\u00a0<\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">Logger.getLogger(&#8220;com.couchbase.client&#8221;).setLevel(Level.FINEST);<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<p>Now there is one more thing you need to do if you want to print all debug messages to the console. You set the logging level correctly, but the `ConsoleHandler` is not set to debug yet (so most likely you will pay the price for debug logging, but won&#39;t actually see anything in your IDE).<\/p>\n<div>\u00a0<\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">for(Handler h : Logger.getLogger(&#8220;com.couchbase.client&#8221;).getParent().getHandlers()) {<br \/>\u00a0 \u00a0 \u00a0if(h instanceof ConsoleHandler) {<br \/>\u00a0 \u00a0 \u00a0 \u00a0 h.setLevel(Level.FINEST);<br \/>\u00a0 \u00a0 \u00a0}<br \/>}<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<p>So, here is a full example on how to use the `SunLogger` and get all Debug messages on the console.<\/p>\n<div>\u00a0<\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">\u00a0 \u00a0 Properties systemProperties = System.getProperties();<br \/>\u00a0 \u00a0 systemProperties.put(&#8220;net.spy.log.LoggerImpl&#8221;, &#8220;net.spy.memcached.compat.log.SunLogger&#8221;);<br \/>\u00a0 \u00a0 System.setProperties(systemProperties);<\/p>\n<p>\u00a0 \u00a0 Logger logger = Logger.getLogger(&#8220;com.couchbase.client&#8221;);<br \/>\u00a0 \u00a0 logger.setLevel(Level.FINEST);<br \/>\u00a0 \u00a0 for(Handler h : logger.getParent().getHandlers()) {<br \/>\u00a0 \u00a0 \u00a0 \u00a0if(h instanceof ConsoleHandler){<br \/>\u00a0 \u00a0 \u00a0 \u00a0 \u00a0h.setLevel(Level.FINEST);<br \/>\u00a0 \u00a0 \u00a0 \u00a0}<br \/>\u00a0 \u00a0 }<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<p>Then just go ahead and create your `CouchbaseClient` object, you will see detailed output like this (trimmed here):<\/p>\n<div>\u00a0<\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">May 7, 2013 12:54:34 PM com.couchbase.client.vbucket.ReconfigurableObserver update<br \/>FINEST: Received an update, notifying reconfigurables about a com.couchbase.client.vbucket.config.Bucketcom.couchbase.client.vbucket.config.Bucket@3d77949<br \/>May 7, 2013 12:54:34 PM com.couchbase.client.vbucket.ReconfigurableObserver update<br \/>FINEST: Received an update, notifying reconfigurables about a com.couchbase.client.vbucket.config.Bucketcom.couchbase.client.vbucket.config.Bucket@4e927ae<br \/>May 7, 2013 12:54:34 PM com.couchbase.client.vbucket.ReconfigurableObserver update<br \/>FINEST: It says it is default and it&#8217;s talking to \/pools\/default\/bucketsStreaming\/default?bucket_uuid=adfff22b70e09fafaa26ca37b7e05e9d<br \/>May 7, 2013 12:54:34 PM com.couchbase.client.vbucket.ReconfigurableObserver updat<br \/>FINEST: It says it is default and it&#8217;s talking to \/pools\/default\/bucketsStreaming\/default?bucket_uuid=adfff22b70e09fafaa26ca37b7e05e9d<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<h2>Log4J<\/h2>\n<p>Most people will need more flexibility, and Log4J was (and still is) standard in lots of applications. The SDK provides support for Log4J as well. To make it work, you first need to set the instance correctly:<\/p>\n<div>\u00a0<\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">\u00a0 \u00a0 Properties systemProperties = System.getProperties();<br \/>\u00a0 \u00a0 systemProperties.put(&#8220;net.spy.log.LoggerImpl&#8221;, &#8220;net.spy.memcached.compat.log.Log4JLogger&#8221;);<br \/>\u00a0 \u00a0 System.setProperties(systemProperties);<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<p>Now if you run this, you&#39;ll get an error that some of the Log4J classes can not be found. This is not a surprise, because its not on the classpath. Let&#39;s fix this by adding it accordingly. If you use maven, add the `log4j.log4j` dependency (current version is 1.2.17). You can also just download the JAR and add it to the CLASSPATH as needed.<\/p>\n<div>\u00a0<\/div>\n<div>Now if we run it again, we get another error:<\/div>\n<div>\u00a0<\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">log4j:WARN No appenders could be found for logger (com.couchbase.client.vbucket.ConfigurationProviderHTTP).<br \/>log4j:WARN Please initialize the log4j system properly.<br \/>log4j:WARN See https:\/\/logging.apache.org\/log4j\/1.2\/faq.html#noconfig for more info.<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<p>One way to fix this is to get a correct <em>log4j.xml<\/em>\u00a0configuration file into our CLASSPATH, but to make it work quickly Log4J provides a <em>BasicConfigurator<\/em>. Right after the system property configurations, add this:<\/p>\n<div>\u00a0<\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">org.apache.log4j.BasicConfigurator.configure();<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<p>If you run it with the code change applied, you will see that we get nicely printed log messages. You can also see that they show up straight from the DEBUG level (and even contain information from which thread they got logged):<\/p>\n<div>\u00a0<\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">69 [main] INFO com.couchbase.client.CouchbaseConnection \u00a0&#8211; Added {QA sa=\/127.0.0.1:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue<br \/>70 [main] DEBUG com.couchbase.client.vbucket.VBucketNodeLocator \u00a0&#8211; Updating nodesMap in VBucketNodeLocator.<br \/>73 [main] DEBUG com.couchbase.client.vbucket.VBucketNodeLocator \u00a0&#8211; Adding node with hostname 127.0.0.1:11210.<br \/>74 [main] DEBUG com.couchbase.client.vbucket.VBucketNodeLocator \u00a0&#8211; Node added is {QA sa=localhost\/127.0.0.1:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=8}.<br \/>74 [Memcached IO over {MemcachedConnection to localhost\/127.0.0.1:11210}] DEBUG com.couchbase.client.CouchbaseConnection \u00a0&#8211; Done dealing with queue.<br \/>74 [Memcached IO over {MemcachedConnection to localhost\/127.0.0.1:11210}] DEBUG com.couchbase.client.CouchbaseConnection \u00a0&#8211; Selecting with delay of 0ms<br \/>79 [Memcached IO over {MemcachedConnection to localhost\/127.0.0.1:11210}] DEBUG com.couchbase.client.CouchbaseConnection \u00a0&#8211; Selected 1, selected 1 keys<br \/>79 [Memcached IO over<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<p>You can control the logging levels through the usual Log4J mechanisms. I won&#39;t go into detail about them here, so please <a href=\"https:\/\/logging.apache.org\/log4j\/1.2\/manual.html\">check out<\/a>\u00a0their official documentation (for example on how to use the <em>PropertyConfigurator<\/em> instead).<\/p>\n<p>Speaking of Log4J, \u00a0<a href=\"https:\/\/twitter.com\/zooldk\">Steffen Larsen<\/a>\u00a0implemented a <a href=\"https:\/\/github.com\/zooldk\/log4j-couchbase\">Log4J appender<\/a>\u00a0to store logs in Couchbase (instead of a file)!<\/p>\n<h2>The new Facade: SLF4J<\/h2>\n<p>Not binding the application to a specific logging library is always a good idea. SLF4J is a facade for various pluggable logging frameworks behind it. So you can choose the logging implementation during runtime, be it <a href=\"https:\/\/logback.qos.ch\/\">logback<\/a>, Log4J or others. Since we already tried Log4J, let&#39;s make SLF4J work with Logback, one of the other very common log frameworks out there.<\/p>\n<p>Note that SLF4J support will be available in the 1.9.0 release of spymemcached and therefore also in one of the next releases of the Couchbase Java SDK.<\/p>\n<p>First, we need to configure it accordingly:<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">Properties systemProperties = System.getProperties();<br \/>systemProperties.put(&#8220;net.spy.log.LoggerImpl&#8221;, &#8220;net.spy.memcached.compat.log.SLF4JLogger&#8221;);<br \/>System.setProperties(systemProperties);<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<p>Now, we need to include two JARs into our classpath. The first one is the SLF4J facade API and the other one is our logging framework of choice. The facade API package is called `slf4j-api` (this package always needs to be in place) and since we want to use logback we need to include the `logback-classic` JAR. Note that this is not specific to the SDK, you can find this information <a href=\"https:\/\/logback.qos.ch\/manual\/introduction.html\">here<\/a>. If you use maven, you can use this snippet:<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">\u00a0 \u00a0 <dependency><br \/>\u00a0 \u00a0 \u00a0 <groupId>org.slf4j<\/groupId><br \/>\u00a0 \u00a0 \u00a0 <artifactId>slf4j-api<\/artifactId><br \/>\u00a0 \u00a0 \u00a0 <version>1.7.5<\/version><br \/>\u00a0 \u00a0 <\/dependency><br \/>\u00a0 \u00a0 <dependency><br \/>\u00a0 \u00a0 \u00a0 <groupId>ch.qos.logback<\/groupId><br \/>\u00a0 \u00a0 \u00a0 <artifactId>logback-classic<\/artifactId><br \/>\u00a0 \u00a0 \u00a0 <version>1.0.12<\/version><br \/>\u00a0 \u00a0 <\/dependency><\/div>\n<\/div>\n<div>\u00a0<\/div>\n<p>SLF4J will automatically pick up our logback implementation, so the logs will look like this:<\/p>\n<div>\u00a0<\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">13:25:43.692 [main] INFO \u00a0c.c.client.CouchbaseConnection &#8211; Added {QA sa=\/127.0.0.1:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue<br \/>13:25:43.694 [main] DEBUG c.c.c.vbucket.VBucketNodeLocator &#8211; Updating nodesMap in VBucketNodeLocator.<br \/>13:25:43.697 [main] DEBUG c.c.c.vbucket.VBucketNodeLocator &#8211; Adding node with hostname 127.0.0.1:11210.<br \/>13:25:43.697 [main] DEBUG c.c.c.vbucket.VBucketNodeLocator &#8211; Node added is {QA sa=localhost\/127.0.0.1:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=8}.<br \/>13:25:43.698 [Memcached IO over {MemcachedConnection to localhost\/127.0.0.1:11210}] DEBUG c.c.client.CouchbaseConnection &#8211; Done dealing with queue.<br \/>13:25:43.699 [Memcached IO over {MemcachedConnection to localhost\/127.0.0.1:11210}] DEBUG c.c.client.CouchbaseConnection &#8211; Selecting with delay of 0ms<br \/>13:25:43.702 [Memcached IO over {MemcachedConnection to localhost\/127.0.0.1:11210}] DEBUG c.c.client.CouchbaseConnection &#8211; Selected 1, selected 1 keys<br \/>13:25:43.703 [Memcached IO over {MemcachedConnection to localhost\/127.0.0.1:11210}] DEBUG c.c.client.CouchbaseConnection &#8211; Handling IO for: \u00a0sun.nio.ch.SelectionKeyImpl@48ff2413 (r=false, w=false, c=true, op={QA sa=localhost\/127.0.0.1:11210, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=8})<br \/>13:25:43.703 [Memcached IO over {MemcachedConnection to localhost\/127.0.0.1:11210}] INFO \u00a0c.c.client.CouchbaseConnection &#8211; Connection state changed for sun.nio.ch.SelectionKeyImpl@48ff2413<br \/>13:25:43.713<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<p>As you can see, they also include DEBUG level logging here. If you don&#39;t include the logging implementation during runtime, SLF4J will complain at startup:<\/p>\n<div>\u00a0<\/div>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family:monospace;\">SLF4J: Failed to load class &#8220;org.slf4j.impl.StaticLoggerBinder&#8221;.<br \/>SLF4J: Defaulting to no-operation (NOP) logger implementation<br \/>SLF4J: See https:\/\/www.slf4j.org\/codes.html#StaticLoggerBinder for further details<\/div>\n<\/div>\n<div>\u00a0<\/div>\n<div>If you want to learn how to configure logback, <a href=\"https:\/\/logback.qos.ch\/manual\/configuration.html\">look here<\/a>.<\/div>\n<div>\u00a0<\/div>\n<h2>Summary<\/h2>\n<p>Once you know the abstraction in spymemcached and how it works, switching logging implementations is easy and straightforward. If you work with one of the Couchbase people to report errors, please try to include output with DEBUG turned on, because this includes lots of useful information that can be used to determine the failure sources.<\/p>\n<p>With the SLF4J facade added in the next spy release (2.9), you will be able to plug every large logging framework out there into the SDK. Let us know if you see a use case not covered with these mechanisms or if you have other comments on this.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>[This blog was syndicated from https:\/\/nitschinger.at\/] Introduction There is a huge variety in logging frameworks for Java, and its hard to please everyone. To understand how logging is currently handled in the SDK, we have to go back a few [&hellip;]<\/p>\n","protected":false},"author":19,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[1281],"ppma_author":[8987],"class_list":["post-1676","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-logging"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Logging with the Couchbase Java Client - The Couchbase Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Logging with the Couchbase Java Client\" \/>\n<meta property=\"og:description\" content=\"[This blog was syndicated from https:\/\/nitschinger.at\/] Introduction There is a huge variety in logging frameworks for Java, and its hard to please everyone. To understand how logging is currently handled in the SDK, we have to go back a few [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-12-18T14:17:01+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Michael Nitschinger\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@daschl\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Michael Nitschinger\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/\"},\"author\":{\"name\":\"Michael Nitschinger\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/e5d4d332756da6f361dd88c1576de61d\"},\"headline\":\"Logging with the Couchbase Java Client\",\"datePublished\":\"2014-12-18T14:17:01+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/\"},\"wordCount\":2201,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"keywords\":[\"Logging\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/\",\"name\":\"Logging with the Couchbase Java Client - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2014-12-18T14:17:01+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/1\\\/2022\\\/11\\\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/logging-couchbase-java-client\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Logging with the Couchbase Java Client\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/admin-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/04\\\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/#\\\/schema\\\/person\\\/e5d4d332756da6f361dd88c1576de61d\",\"name\":\"Michael Nitschinger\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g95e178617974d46e3b02dd1754a3f60b\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g\",\"caption\":\"Michael Nitschinger\"},\"description\":\"Michael Nitschinger works as a Principal Software Engineer at Couchbase. He is the architect and maintainer of the Couchbase Java SDK, one of the first completely reactive database drivers on the JVM. He also authored and maintains the Couchbase Spark Connector. Michael is active in the open source community, a contributor to various other projects like RxJava and Netty.\",\"sameAs\":[\"https:\\\/\\\/nitschinger.at\",\"https:\\\/\\\/x.com\\\/daschl\"],\"url\":\"https:\\\/\\\/www.couchbase.com\\\/blog\\\/author\\\/michael-nitschinger\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Logging with the Couchbase Java Client - The Couchbase Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/","og_locale":"en_US","og_type":"article","og_title":"Logging with the Couchbase Java Client","og_description":"[This blog was syndicated from https:\/\/nitschinger.at\/] Introduction There is a huge variety in logging frameworks for Java, and its hard to please everyone. To understand how logging is currently handled in the SDK, we have to go back a few [&hellip;]","og_url":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/","og_site_name":"The Couchbase Blog","article_published_time":"2014-12-18T14:17:01+00:00","og_image":[{"width":1800,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png","type":"image\/png"}],"author":"Michael Nitschinger","twitter_card":"summary_large_image","twitter_creator":"@daschl","twitter_misc":{"Written by":"Michael Nitschinger","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/"},"author":{"name":"Michael Nitschinger","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/e5d4d332756da6f361dd88c1576de61d"},"headline":"Logging with the Couchbase Java Client","datePublished":"2014-12-18T14:17:01+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/"},"wordCount":2201,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["Logging"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/","url":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/","name":"Logging with the Couchbase Java Client - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2014-12-18T14:17:01+00:00","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/logging-couchbase-java-client\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Logging with the Couchbase Java Client"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/e5d4d332756da6f361dd88c1576de61d","name":"Michael Nitschinger","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g95e178617974d46e3b02dd1754a3f60b","url":"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g","caption":"Michael Nitschinger"},"description":"Michael Nitschinger works as a Principal Software Engineer at Couchbase. He is the architect and maintainer of the Couchbase Java SDK, one of the first completely reactive database drivers on the JVM. He also authored and maintains the Couchbase Spark Connector. Michael is active in the open source community, a contributor to various other projects like RxJava and Netty.","sameAs":["https:\/\/nitschinger.at","https:\/\/x.com\/daschl"],"url":"https:\/\/www.couchbase.com\/blog\/author\/michael-nitschinger\/"}]}},"acf":[],"authors":[{"term_id":8987,"user_id":19,"is_guest":0,"slug":"michael-nitschinger","display_name":"Michael Nitschinger","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/dad99b5e02a74ca4bec14352e9da710160647a97290814b669babb3aac0ea675?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/1676","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=1676"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/1676\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=1676"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=1676"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=1676"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=1676"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}