{"id":1278,"date":"2022-02-19T13:23:22","date_gmt":"2022-02-19T20:23:22","guid":{"rendered":"https:\/\/bullyrooks.com\/?p=1278"},"modified":"2022-02-21T15:36:31","modified_gmt":"2022-02-21T22:36:31","slug":"kube-cloud-pt4-logging","status":"publish","type":"post","link":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/19\/kube-cloud-pt4-logging\/","title":{"rendered":"Kube Cloud Pt4 | Logging"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\" id=\"add-structured-logging\">Add Structured Logging<\/h2>\n\n\n\n<p>Structured logging means that we&#8217;re going to log our output in json format.  This is extremely useful because it allows tools to easily parse the json to make the individual log message attributes available for searching and allows you to control the presentation (highlight signal, reduce noise).  You&#8217;re probably more familiar with the unstructured logging that comes by default with spring boot.  Essentially, they have already parsed the logs and presented them to you in a mostly useful format, but we are going to want more control than that because we may have needs that extend beyond the basic functionality.<\/p>\n\n\n\n<p>Create a new branch in <code>message-generator<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ git checkout -b logging\nSwitched to a new branch 'logging'\n<\/code><\/pre>\n\n\n\n<p>Update your pom.xml to include logz&#8217;s logback encoder and appender<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    &lt;properties&gt;\n        ...\n        &lt;logstash-logback-encoder.version&gt;7.0.1&lt;\/logstash-logback-encoder.version&gt;\n        &lt;log4j2.version&gt;2.17.1&lt;\/log4j2.version&gt;\n        &lt;logzio-logback-appender.version&gt;1.0.25&lt;\/logzio-logback-appender.version&gt;\n    &lt;\/properties&gt; \n\n       &lt;!-- logging --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;net.logstash.logback&lt;\/groupId&gt;\n            &lt;artifactId&gt;logstash-logback-encoder&lt;\/artifactId&gt;\n            &lt;version&gt;${logstash-logback-encoder.version}&lt;\/version&gt;\n        &lt;\/dependency&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;io.logz.logback&lt;\/groupId&gt;\n            &lt;artifactId&gt;logzio-logback-appender&lt;\/artifactId&gt;\n            &lt;version&gt;${logzio-logback-appender.version}&lt;\/version&gt;\n        &lt;\/dependency&gt;<\/code><\/pre>\n\n\n\n<p>A few things here:  <\/p>\n\n\n\n<p>We&#8217;re updating log4j to the most current version because there was a <a href=\"https:\/\/logging.apache.org\/log4j\/2.x\/security.html\">major security vulnerability discovered<\/a>.  By adding this property, we&#8217;re telling the spring boot starter parent to override the version it normally brings in.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/logfellow\/logstash-logback-encoder\">Logstash logback encoder<\/a> tells logback how to present the structured logs in logstash format.  Logstash is the &#8220;L&#8221; in ELK (elasticsearch, logstash and kibana) and is the &#8220;pump&#8221; that will push the logs over the network into elasticsearch for storage.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/logzio\/logzio-logback-appender\">Logzio logback appender<\/a> adds a logback appender which has all of the default configuration needed to communicate back to logz.io.<\/p>\n\n\n\n<p>We need to gather some information from logz.io so that we can connect to our account.  Navigate to the send your logs menu item <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"303\" height=\"365\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-6.png?resize=303%2C365&#038;ssl=1\" alt=\"\" class=\"wp-image-1279\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-6.png?w=303&amp;ssl=1 303w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-6.png?resize=249%2C300&amp;ssl=1 249w\" sizes=\"auto, (max-width: 303px) 100vw, 303px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>Search for Java<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"564\" height=\"406\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-7.png?resize=564%2C406&#038;ssl=1\" alt=\"\" class=\"wp-image-1280\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-7.png?w=564&amp;ssl=1 564w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-7.png?resize=300%2C216&amp;ssl=1 300w\" sizes=\"auto, (max-width: 564px) 100vw, 564px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>Navigate to logback<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"245\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-8-1024x261.png?resize=960%2C245&#038;ssl=1\" alt=\"\" class=\"wp-image-1281\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-8.png?resize=1024%2C261&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-8.png?resize=300%2C76&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-8.png?resize=768%2C195&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-8.png?w=1187&amp;ssl=1 1187w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>Scroll down to the configuration and get the token<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"759\" height=\"341\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-9.png?resize=759%2C341&#038;ssl=1\" alt=\"\" class=\"wp-image-1282\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-9.png?w=759&amp;ssl=1 759w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-9.png?resize=300%2C135&amp;ssl=1 300w\" sizes=\"auto, (max-width: 759px) 100vw, 759px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>Now we just need to add some configuration so that logback understands how we want to log.  Add a file called <code>logback-spring.xml<\/code> to your <code>src\/main\/resources<\/code> directory with this content<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;configuration&gt;\n    &lt;shutdownHook class=\"ch.qos.logback.core.hook.DelayingShutdownHook\"\/&gt;\n    &lt;include resource=\"org\/springframework\/boot\/logging\/logback\/defaults.xml\"\/&gt;\n    &lt;appender name=\"CONSOLE\" class=\"ch.qos.logback.core.ConsoleAppender\"&gt;\n        &lt;layout class=\"ch.qos.logback.classic.PatternLayout\"&gt;\n            &lt;Pattern&gt;\n                %black(%d{ISO8601}) %highlight(%-5level) &#91;%blue(%t)] &#91;%cyan(%X{trace_id}),%cyan(%X{span_id})] %yellow(%C{1.}): %msg%n%throwable\n            &lt;\/Pattern&gt;\n        &lt;\/layout&gt;\n    &lt;\/appender&gt;\n    &lt;appender name=\"LogzioLogbackAppender\" class=\"io.logz.logback.LogzioLogbackAppender\"&gt;\n        &lt;token&gt;${LOGZIO_LOGGER_TOKEN}&lt;\/token&gt;\n        &lt;logzioUrl&gt;https:\/\/listener.logz.io:8071&lt;\/logzioUrl&gt;\n        &lt;logzioType&gt;message-generator&lt;\/logzioType&gt;\n    &lt;\/appender&gt;\n    &lt;springProfile name=\"dev\"&gt;\n        &lt;root level=\"info\"&gt;\n            &lt;appender-ref ref=\"CONSOLE\"\/&gt;\n        &lt;\/root&gt;\n    &lt;\/springProfile&gt;\n    &lt;springProfile name=\"!dev\"&gt;\n        &lt;root level=\"info\"&gt;\n            &lt;appender-ref ref=\"CONSOLE\"\/&gt;\n            &lt;appender-ref ref=\"LogzioLogbackAppender\"\/&gt;\n        &lt;\/root&gt;\n    &lt;\/springProfile&gt;\n&lt;\/configuration&gt;<\/code><\/pre>\n\n\n\n<p>Here we&#8217;re setting up two appenders.  Console will log out in a parsed string pattern which I think is easier to read and we&#8217;ve included some colors to help things stand out.  Next we&#8217;re setting up the logback appender to push logs over to logz.io.  Make sure to put your token in and make the logzioType reflect your service name since this is an attribute that matches the logs to your service.  <\/p>\n\n\n\n<p>We&#8217;re also setting up some profile configuration so that when we&#8217;re developing locally we&#8217;re not necessarily pushing logs up to logz.io.  You can turn this on and off by setting the active spring profile (<code>-Dspring.profiles.active=dev<\/code>), but we&#8217;re going to leave this off for now while we&#8217;re testing.<\/p>\n\n\n\n<p>We don&#8217;t want logging to logz.io during our tests because this creates an unneeded dependency on an external system.  So create this <code>logback-test.xml<\/code> under <code>src\/test\/resources<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;configuration&gt;\n    &lt;shutdownHook class=\"ch.qos.logback.core.hook.DelayingShutdownHook\"\/&gt;\n    &lt;include resource=\"org\/springframework\/boot\/logging\/logback\/defaults.xml\"\/&gt;\n    &lt;appender name=\"CONSOLE\" class=\"ch.qos.logback.core.ConsoleAppender\"&gt;\n        &lt;layout class=\"ch.qos.logback.classic.PatternLayout\"&gt;\n            &lt;Pattern&gt;\n                %d{ISO8601} %highlight(%-5level) &#91;%cyan(%X{trace_id}),%cyan(%X{span_id})] %yellow(%C{1}): %msg%n%throwable\n            &lt;\/Pattern&gt;\n        &lt;\/layout&gt;\n    &lt;\/appender&gt;\n\n    &lt;root level=\"INFO\"&gt;\n        &lt;appender-ref ref=\"CONSOLE\"\/&gt;\n    &lt;\/root&gt;\n&lt;\/configuration&gt;<\/code><\/pre>\n\n\n\n<p>You should see a difference when you start up locally:<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"353\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-10-1024x376.png?resize=960%2C353&#038;ssl=1\" alt=\"\" class=\"wp-image-1283\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-10.png?resize=1024%2C376&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-10.png?resize=300%2C110&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-10.png?resize=768%2C282&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-10.png?w=1508&amp;ssl=1 1508w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>And you should see your logs in logz.io<\/p>\n\n\n\n<p>Navigate to kibana<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"303\" height=\"128\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-11.png?resize=303%2C128&#038;ssl=1\" alt=\"\" class=\"wp-image-1284\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-11.png?w=303&amp;ssl=1 303w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-11.png?resize=300%2C127&amp;ssl=1 300w\" sizes=\"auto, (max-width: 303px) 100vw, 303px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>And you should see them in a few minutes (it takes some time to get them over, parsed, stored and indexed)<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"502\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-12-1024x535.png?resize=960%2C502&#038;ssl=1\" alt=\"\" class=\"wp-image-1285\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-12.png?resize=1024%2C535&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-12.png?resize=300%2C157&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-12.png?resize=768%2C401&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-12.png?w=1265&amp;ssl=1 1265w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"add-logs\">Add Logs<\/h2>\n\n\n\n<p>Our logging stance is pretty sparse at this point, so lets start beefing it up.<\/p>\n\n\n\n<p>I use an aspect to hang off of every method and log the input and output of each method.  This removes the tedium of adding lots of log statements that need to be maintained.  Aspects aren&#8217;t used a lot, but they can be handy.  Be careful of overusing them though, because they hide a lot of functionality and can make debugging troublesome.<\/p>\n\n\n\n<p>First, add aspectj as a dependency to our <code>pom.xml<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-boot-starter-aop&lt;\/artifactId&gt;\n        &lt;\/dependency&gt;<\/code><\/pre>\n\n\n\n<p>Next we&#8217;re going to use an annotation to activate the logging, so create the annotation in a new package called <code>com.bullyrooks.messagegenerator.config<\/code>.  Create a class called <code>LoggingEnabled<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.bullyrooks.messagegenerator.config;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target(ElementType.TYPE)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface LoggingEnabled {\n}\n<\/code><\/pre>\n\n\n\n<p>Now create the aspect in the same package as a class called <code>LoggingAspect<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.bullyrooks.messagegenerator.config;\n\nimport com.fasterxml.jackson.core.JsonProcessingException;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.ObjectWriter;\nimport lombok.extern.slf4j.Slf4j;\nimport org.aspectj.lang.ProceedingJoinPoint;\nimport org.aspectj.lang.annotation.Around;\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.annotation.Pointcut;\nimport org.aspectj.lang.reflect.MethodSignature;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.StopWatch;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n@Aspect\n@Component\n@Slf4j\n@Profile(\"!test\")\npublic class LoggingAspect {\n\n    ObjectMapper om = new ObjectMapper();\n\n    @Pointcut(\"within(@com.bullyrooks.messagegenerator.config.LoggingEnabled *)\")\n    public void loggingEnabled() {\n    }\n\n    @Pointcut(\"execution(public * *(..))\")\n    public void publicMethod() {\n    }\n\n    @Pointcut(\"execution(private * *(..))\")\n    public void privateMethod() {\n    }\n\n\n    @Around(\"loggingEnabled() &amp;&amp; (publicMethod() || privateMethod())\")\n    public Object profileAllMethods(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {\n        logMethodInvocationAndParameters(proceedingJoinPoint);\n\n        final StopWatch stopWatch = new StopWatch();\n\n        \/\/Measure method execution time\n        stopWatch.start();\n        Object result = proceedingJoinPoint.proceed();\n        stopWatch.stop();\n\n        \/\/Log method execution time\n        logMethodResultAndParameters(proceedingJoinPoint, result, stopWatch.getTotalTimeMillis());\n\n        return result;\n    }\n\n    private void logMethodResultAndParameters(ProceedingJoinPoint proceedingJoinPoint,\n                                              Object result, long totalTimeMillis) {\n        try {\n            MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();\n            String className = methodSignature.getDeclaringType().getSimpleName();\n            String methodName = methodSignature.getName();\n            ObjectWriter writer = om.writer();\n            if (writer != null) {\n                log.debug(\"&lt;- {}.{} returns:{}.  Execution time: {}ms\",\n                        className,\n                        methodName,\n                        writer.writeValueAsString(result),\n                        totalTimeMillis);\n            }\n        } catch (JsonProcessingException e) {\n            log.error(\"unable to write log value: {}\", e.getMessage(), e);\n        }\n    }\n\n\n    private void logMethodInvocationAndParameters(ProceedingJoinPoint jp) {\n        try {\n            String&#91;] argNames = ((MethodSignature) jp.getSignature()).getParameterNames();\n            Object&#91;] values = jp.getArgs();\n            Map&lt;String, Object&gt; params = new HashMap&lt;&gt;();\n            if (argNames != null &amp;&amp; argNames.length != 0) {\n                for (int i = 0; i &lt; argNames.length; i++) {\n                    params.put(argNames&#91;i], values&#91;i]);\n                }\n            }\n            ObjectWriter writer = om.writer();\n            if (writer != null) {\n                String className = jp.getSignature().getDeclaringType().getSimpleName();\n                String methodName = jp.getSignature().getName();\n                log.debug(\"-&gt; {}.{} invocation.  params: {}\",\n                        className,\n                        methodName,\n                        writer.writeValueAsString(params));\n            }\n        } catch (JsonProcessingException e) {\n            log.error(\"unable to write log value: {}\", e.getMessage(), e);\n        }\n\n    }\n}\n<\/code><\/pre>\n\n\n\n<p>There&#8217;s a lot going on here, I&#8217;ll try to help explain.  <\/p>\n\n\n\n<p>First, we&#8217;re describing our pointcuts.  These will be any class that has our annotation, any public method and any private method.  Then I create a profile which combines those pointcuts and says what to execute.  In this case, it says before the method is invoked, log the input, then start a timer, call the method and stop the timer when it returns and log the output.<\/p>\n\n\n\n<p>The <code>logMethodInvocationAndParameters <\/code>method logs the input its a little complicated, but essentially, it grabs the input parameters, the class name and method and writes them to the log along with a direction arrow.<\/p>\n\n\n\n<p>The <code>logMethodResultAndParameters<\/code> essentially does the same thing, but instead of getting the input parameters it has direct access to the returned object so it just logs that in json format.<\/p>\n\n\n\n<p>Finally the @Profile annotation tells this aspect to ignore when running in the test profile, which means that our logs won&#8217;t get created during testing.<\/p>\n\n\n\n<p>Now, everything is logging at <code>debug <\/code>level, so we&#8217;re going to need to adjust our log configuration to display them.  Add these lines to your <code>application.yaml<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>logging:\n  level:\n    root: INFO\n    com.bullyrooks: DEBUG<\/code><\/pre>\n\n\n\n<p>This is saying to log everything at <code>INFO <\/code>level or above, except our packages which should log at <code>DEBUG<\/code>.<\/p>\n\n\n\n<p>Finally, add these annotations to <code>MessageController <\/code>and <code>MessageService<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@LoggingEnabled\n@Slf4j<\/code><\/pre>\n\n\n\n<p>Restart the application and hit the <code>\/message<\/code> endpoint.  You should see logs similar to this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"61\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-13-1024x65.png?resize=960%2C61&#038;ssl=1\" alt=\"\" class=\"wp-image-1287\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-13.png?resize=1024%2C65&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-13.png?resize=300%2C19&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-13.png?resize=768%2C49&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-13.png?resize=1536%2C98&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-13.png?w=1551&amp;ssl=1 1551w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>Note, this is <em>almost<\/em> tracing (but isn&#8217;t nearly as good as it can be).  Also, the logs are written via the aspect, so that aspect package and class are written here.<\/p>\n\n\n\n<p>You should also see them in logz.io<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"118\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-14-1024x126.png?resize=960%2C118&#038;ssl=1\" alt=\"\" class=\"wp-image-1289\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-14.png?resize=1024%2C126&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-14.png?resize=300%2C37&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-14.png?resize=768%2C94&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-14.png?w=1256&amp;ssl=1 1256w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>Lets go ahead and push up these changes and deploy to okteto.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git add .\n\ngit commit -m \"logging enabled\"\n\n\ngit push --set-upstream origin logging                             \nEnumerating objects: 33, done.\nCounting objects: 100% (33\/33), done.\nDelta compression using up to 4 threads\nCompressing objects: 100% (15\/15), done.\n...\n * &#91;new branch]      logging -&gt; logging\nBranch 'logging' set up to track remote branch 'logging' from 'origin'.<\/code><\/pre>\n\n\n\n<p>When that succeeds, merge to main<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>git checkout main\n\ngit merge logging\n\ngit push<\/code><\/pre>\n\n\n\n<p>Once it builds and deploys we should see the logs in okteto&#8217;s console<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"103\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-16-1024x110.png?resize=960%2C103&#038;ssl=1\" alt=\"\" class=\"wp-image-1292\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-16.png?resize=1024%2C110&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-16.png?resize=300%2C32&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-16.png?resize=768%2C83&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-16.png?w=1272&amp;ssl=1 1272w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>as well as in logz.io<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"128\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-17-1024x137.png?resize=960%2C128&#038;ssl=1\" alt=\"\" class=\"wp-image-1293\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-17.png?resize=1024%2C137&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-17.png?resize=300%2C40&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-17.png?resize=768%2C103&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-17.png?w=1149&amp;ssl=1 1149w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>Note, for some reason my debug logging level wasn&#8217;t getting passed through.  You can verify the log level through actuator with this endpoint <code>\/actuator\/loggers\/com.bullyrooks<\/code> (it was set to <code>INFO<\/code>).  You can use actuator to change the inflight configuration by <code>POST<\/code>ing to that same endpoint with this body<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\"configuredLevel\": \"DEBUG\"}<\/code><\/pre>\n\n\n\n<p>If you GET again, you should see it updated<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>{\n    \"configuredLevel\": \"DEBUG\",\n    \"effectiveLevel\": \"DEBUG\"\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"update-cloud-application\">Update Cloud Application<\/h2>\n\n\n\n<p>Now, make the same updates to cloud application and push that up to okteto before we move on to the tracing.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"entry-summary\">\nAdd Structured Logging Structured logging means that we&#8217;re going to log our&hellip;\n<\/div>\n<div class=\"link-more\"><a href=\"https:\/\/bullyrooks.com\/index.php\/2022\/02\/19\/kube-cloud-pt4-logging\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &ldquo;Kube Cloud Pt4 | Logging&rdquo;<\/span>&hellip;<\/a><\/div>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[41],"tags":[187,186,183,185,184,165],"course":[164],"class_list":["post-1278","post","type-post","status-publish","format-standard","hentry","category-software-development","tag-aop","tag-aspect-oriented-programming","tag-elk","tag-kibana","tag-logback","tag-logz-io","course-kube-cloud-4-observability","entry"],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":1276,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/19\/kube-cloud-pt4-observability\/","url_meta":{"origin":1278,"position":0},"title":"Kube Cloud Pt4 | Observability","author":"Bullyrook","date":"February 19, 2022","format":false,"excerpt":"In this course, I'm going to walk through how to implement the 3 pillars of observability on our example application using the logz.io platform. Before we do that, I'm going to explain the 3 pillars of observability, which are: LoggingTracingMetrics Logging Logz.io uses ELK for their log management platform. There's\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":831,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-5-a2d164711554\/","url_meta":{"origin":1278,"position":1},"title":"Logging, Tracing and Error Handling","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"Now that we\u2019ve got an almost fully functional webservice we\u2019re going to make sure that we can debug it properly before moving forward to deployment. In this article we\u2019re going to describe how to setup logging. Logging We need to start by actually logging something. Spring boot comes packaged with\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1395,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/03\/12\/kube-cloud-pt6-update-to-consumer-contract\/","url_meta":{"origin":1278,"position":2},"title":"Kube Cloud Pt6 | Break the Contract from a Consumer Change","author":"Bullyrook","date":"March 12, 2022","format":false,"excerpt":"We're going to go back to cloud-application at this point and update our client to expect a field that isn't being currently provided (message generated date). This should break our contract test and prevent us from deploying, but there's some updates we need to make to support this. Add the\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/03\/image-25.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/03\/image-25.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/03\/image-25.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1301,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/20\/kube-cloud-pt4-metrics\/","url_meta":{"origin":1278,"position":3},"title":"Kube Cloud Pt4 | Metrics","author":"Bullyrook","date":"February 20, 2022","format":false,"excerpt":"Logz.io uses prometheus for metrics. Go ahead and enable metrics collection in logz.io. Navigate to send your metrics Search for java Choose java custom metrics via micrometer. We're using micrometer because its integrated into spring boot and available via actuator, which we're already using. The important part here is that\u2026","rel":"","context":"In &quot;General&quot;","block_context":{"text":"General","link":"https:\/\/bullyrooks.com\/index.php\/category\/general\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-22.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":1094,"url":"https:\/\/bullyrooks.com\/index.php\/2021\/07\/24\/terraform-setup-and-first-install\/","url_meta":{"origin":1278,"position":4},"title":"Terraform Setup and First Install","author":"Bullyrook","date":"July 24, 2021","format":false,"excerpt":"Terraform is a system that allows you to define your infrastructure in a series of configuration files. These configuration files are linked to a provider library which will execute the infrastructure create, update and teardown commands on the platform you want to deploy to. This is called \"Infrastructure as Code\"\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-19.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-19.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-19.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-19.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":706,"url":"https:\/\/bullyrooks.com\/index.php\/2021\/01\/28\/installing-transmission-with-openvpn\/","url_meta":{"origin":1278,"position":5},"title":"Installing Transmission with OpenVPN","author":"Bullyrook","date":"January 28, 2021","format":false,"excerpt":"Now we're going to setup a bittorrent client as well as an OpenVPN client to keep our traffic secure. This is another straightforward docker-compose modification. Get an OpenVPN Provider You'll need a VPN provider. I highly recommend private internet access because I've been using them for years. They have good\u2026","rel":"","context":"In &quot;Home Networking&quot;","block_context":{"text":"Home Networking","link":"https:\/\/bullyrooks.com\/index.php\/category\/technology\/home-networking\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/01\/image-80.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]}],"_links":{"self":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/1278","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/comments?post=1278"}],"version-history":[{"count":10,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/1278\/revisions"}],"predecessor-version":[{"id":1332,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/1278\/revisions\/1332"}],"wp:attachment":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/media?parent=1278"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/categories?post=1278"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/tags?post=1278"},{"taxonomy":"course","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/course?post=1278"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}