{"id":1301,"date":"2022-02-20T16:23:39","date_gmt":"2022-02-20T23:23:39","guid":{"rendered":"https:\/\/bullyrooks.com\/?p=1301"},"modified":"2022-02-21T10:36:31","modified_gmt":"2022-02-21T17:36:31","slug":"kube-cloud-pt4-metrics","status":"publish","type":"post","link":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/20\/kube-cloud-pt4-metrics\/","title":{"rendered":"Kube Cloud Pt4 | Metrics"},"content":{"rendered":"\n<p><a href=\"https:\/\/logz.io\/platform\/infrastructure-monitoring\/\">Logz.io uses prometheus for metrics<\/a>.  Go ahead and enable metrics collection in logz.io.  Navigate to send your metrics<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"304\" height=\"105\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-21.png?resize=304%2C105&#038;ssl=1\" alt=\"\" class=\"wp-image-1302\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-21.png?w=304&amp;ssl=1 304w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-21.png?resize=300%2C104&amp;ssl=1 300w\" sizes=\"auto, (max-width: 304px) 100vw, 304px\" 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=\"694\" height=\"242\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-22.png?resize=694%2C242&#038;ssl=1\" alt=\"\" class=\"wp-image-1303\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-22.png?w=694&amp;ssl=1 694w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-22.png?resize=300%2C105&amp;ssl=1 300w\" sizes=\"auto, (max-width: 694px) 100vw, 694px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>Choose java custom metrics via micrometer.  We&#8217;re using micrometer because its integrated into spring boot and available via actuator, which we&#8217;re already using.<\/p>\n\n\n\n<p>The important part here is that you grab the metrics token from the code example.  We&#8217;re not going to follow their example very closely, because spring boot offers some tools to make it easier.  The example is not very good either.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"securing-our-tokens\">Securing our Tokens<\/h2>\n\n\n\n<p>At this point we&#8217;ve got a new token to deal with and our logging token is hardcoded into a config file.  This is not good from a security aspect because now our logging token is available in our git repo.  So, let&#8217;s get this cleaned up and have good practices going forward.  We&#8217;re going to start with the <code>cloud-application <\/code>project.<\/p>\n\n\n\n<p>First, load our secrets up to kubernetes (replace with your logging and metric token from logz.io)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ kubectl create secret generic logzio-secrets --from-literal=LOGZIO_LOGGER_TOKEN=... --from-literal=LOGZIO_METRICS_TOKEN=...\nsecret\/logzio-secrets created\n<\/code><\/pre>\n\n\n\n<p>Now update your deployment.yaml file in the helm templates to inject the secrets into the environment<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>          env:\n          ...\n          - name: LOGZIO_LOGGER_TOKEN\n            valueFrom:\n              secretKeyRef:\n                name: logzio-secrets\n                key: LOGZIO_LOGGER_TOKEN\n          - name: LOGZIO_METRICS_TOKEN\n            valueFrom:\n              secretKeyRef:\n                name: logzio-secrets\n                key: LOGZIO_METRICS_TOKEN<\/code><\/pre>\n\n\n\n<p>Now reference the environment variable in logback-spring.yaml<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;token&gt;${LOGZIO_LOGGER_TOKEN}&lt;\/token&gt;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"activating-micrometer\">Activating Micrometer<\/h2>\n\n\n\n<p>Add the logzio micrometer library to your pom.xml<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>        &lt;micrometer-registry-logzio.version&gt;1.0.2&lt;\/micrometer-registry-logzio.version&gt;\n    &lt;\/properties&gt;\n...\n        &lt;dependency&gt;\n            &lt;groupId&gt;io.logz.micrometer&lt;\/groupId&gt;\n            &lt;artifactId&gt;micrometer-registry-logzio&lt;\/artifactId&gt;\n            &lt;version&gt;${micrometer-registry-logzio.version}&lt;\/version&gt;\n        &lt;\/dependency&gt;<\/code><\/pre>\n\n\n\n<p>Just this configuration alone should get you metrics on the actuator metrics endpoint.  However, we want to create some custom metrics as well in addition to pumping the metrics over to logz.io for visualization.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"metrics-registry-configuration\">Metrics Registry Configuration<\/h2>\n\n\n\n<p>Micrometer relies on a metrics registry to know what metrics are being collected and what it should present to the prometheus backend service.  Additionally, this registry depends on a configuration which tells it how to authenticate and the location of prometheus.  You can set them up by creating a configuration class in the <code>config <\/code>package called <code>LogzioMicrometerConfiguration <\/code>with this content.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.bullyrooks.cloud_application.config;\r\n\r\nimport io.micrometer.core.instrument.Clock;\r\nimport io.micrometer.core.instrument.MeterRegistry;\r\nimport io.micrometer.core.instrument.Tag;\r\nimport io.micrometer.core.instrument.simple.SimpleMeterRegistry;\r\nimport io.micrometer.logzio.LogzioConfig;\r\nimport io.micrometer.logzio.LogzioMeterRegistry;\r\nimport org.springframework.beans.factory.annotation.Value;\r\nimport org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;\r\nimport org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;\r\nimport org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;\r\nimport org.springframework.boot.autoconfigure.AutoConfigureAfter;\r\nimport org.springframework.boot.autoconfigure.AutoConfigureBefore;\r\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\r\nimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;\r\nimport org.springframework.context.annotation.Bean;\r\nimport org.springframework.context.annotation.Configuration;\r\n\r\nimport java.time.Duration;\r\nimport java.util.ArrayList;\r\nimport java.util.Hashtable;\r\n\r\n@Configuration\r\n@AutoConfigureBefore({\r\n        CompositeMeterRegistryAutoConfiguration.class,\r\n        SimpleMetricsExportAutoConfiguration.class\r\n})\r\n@AutoConfigureAfter(MetricsAutoConfiguration.class)\r\n@ConditionalOnClass(LogzioMeterRegistry.class)\r\npublic class LogzioMicrometerConfiguration {\r\n\r\n    @Value(\"${logzio.metrics.url:http:\/\/test.com}\")\r\n    String logzioMetricsUrl;\r\n    @Value(\"${logzio.metrics.token:TEST}\")\r\n    String logzioMetricsToken;\r\n\r\n    \/* real service instances connect to logzio *\/\r\n    @Bean\r\n    @ConditionalOnProperty(name=\"logzio.metrics.registry.mock\", havingValue=\"false\")\r\n    public LogzioConfig newLogzioConfig() {\r\n        return new LogzioConfig() {\r\n            @Override\r\n            public String get(String key) {\r\n                return null;\r\n            }\r\n\r\n            @Override\r\n            public String uri() {\r\n                return logzioMetricsUrl;\r\n                \/\/ example:\r\n                \/\/ return \"https:\/\/listener.logz.io:8053\";\r\n            }\r\n\r\n            @Override\r\n            public String token() {\r\n                return logzioMetricsToken;\r\n            }\r\n\r\n            @Override\r\n            public Duration step() {\r\n                return Duration.ofSeconds(30);\r\n                \/\/ example:\r\n                \/\/ return Duration.ofSeconds(30);\r\n            }\r\n\r\n            @Override\r\n            public Hashtable&lt;String, String> includeLabels() {\r\n                return new Hashtable&lt;>();\r\n            }\r\n\r\n            @Override\r\n            public Hashtable&lt;String, String> excludeLabels() {\r\n                return new Hashtable&lt;>();\r\n            }\r\n        };\r\n    }\r\n\r\n    @Bean\r\n    @ConditionalOnProperty(name=\"logzio.metrics.registry.mock\", havingValue=\"false\")\r\n    public MeterRegistry logzioMeterRegistry(LogzioConfig config) {\r\n        LogzioMeterRegistry logzioMeterRegistry =\r\n                new LogzioMeterRegistry(config, Clock.SYSTEM);\r\n        ArrayList&lt;Tag> tags = new ArrayList&lt;>();\r\n        tags.add(Tag.of(\"env\", \"dev\"));\r\n        tags.add(Tag.of(\"service\", \"cloud-application\"));\r\n        return logzioMeterRegistry;\r\n    }\r\n\r\n    \/* mock configuration used locally and in tests *\/\r\n\r\n    @Bean\r\n    @ConditionalOnProperty(name=\"logzio.metrics.registry.mock\", havingValue=\"true\")\r\n    public MeterRegistry testRegistry() {\r\n        return new SimpleMeterRegistry();\r\n    }\r\n    @Bean\r\n    @ConditionalOnProperty(name=\"logzio.metrics.registry.mock\", havingValue=\"true\")\r\n    public LogzioConfig logzioConfig(){\r\n            \/\/this is not needed\r\n            return null;\r\n        }\r\n}\r\n\n<\/code><\/pre>\n\n\n\n<p>The first section describes the live configuration.  The important parts in the configuration are the url and token.  The second bean depends on the configuration to setup the registry.  There&#8217;s not much here besides global tokens.  I don&#8217;t want metrics to connect to logz.io during local testing (and pipeline testing), so the second section describes how to setup mock instances of the needed metrics components.  We&#8217;re using a conditional property to control which beans are created.  So lets create those flags.<\/p>\n\n\n\n<p><code>application.yaml<\/code> in <code>src\/main\/resources<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>logzio:\r\n  metrics:\r\n    url: https:\/\/listener.logz.io:8053\r\n    registry:\r\n      mock: false<\/code><\/pre>\n\n\n\n<p><code>application-dev.yaml<\/code> in <code>src\/main\/resources<\/code>.  This is probably a new file for your setup.  It will inheirit from application.yaml and overwrite whatever is duplicated, so it only has this content.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">logzio:<br>  metrics:<br>    registry:<br>      mock: true<\/pre>\n\n\n\n<p>also <code>application-test.yaml<\/code> in <code>src\/test\/resources<\/code><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>logzio:\r\n  metrics:\r\n    registry:\r\n      mock: true<\/code><\/pre>\n\n\n\n<p>When we create the metrics later this will allow our tests to inject a mock registry instead of the logzio configured one.<\/p>\n\n\n\n<p>Lets go make sure that the configuration is set.  We&#8217;ve already added the metrics token to the kubernetes environment configuration so that will be taken care of at deploy time.  Update application.yaml with this configuration<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>logging:\n  level:\n    root: INFO\n    com.bullyrooks: DEBUG\n    io.micrometer.logzio: WARN\nlogzio:\n  metrics:\n    url: https:\/\/listener.logz.io:8053<\/code><\/pre>\n\n\n\n<p>Logz.io&#8217;s micrometer logging is really chatty, so we&#8217;re turning that down and setting that metrics url.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"custom-metrics\">Custom Metrics<\/h2>\n\n\n\n<p>Let&#8217;s go ahead and create the custom metrics.  For this case I&#8217;m tracking four metrics in cloud-application<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Number of message requests<\/li><li>Number of requests that didn&#8217;t have a message<\/li><li>Number of successfully generated messages<\/li><li>Number of successfully stored messages<\/li><\/ul>\n\n\n\n<p>Edit <code>MessageService <\/code>class.  First set some new attributes of the class<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    MeterRegistry logzioMeterRegistry;\n\n    Counter msgCount;\n    Counter genMsgCount;\n    Counter genMsgSuccess;\n    Counter messageSaved;\n<\/code><\/pre>\n\n\n\n<p>This is a reference to our registry and the new metrics that we&#8217;re going to capture.<\/p>\n\n\n\n<p>Now we&#8217;re going to change up the autowiring scheme to autowire by constructor so remove the autowire annotations and add this constructor<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    @Autowired\n    public MessageService(MessageRepository messageRepository,\n                          MessageGeneratorClient messageGeneratorClient,\n                          MeterRegistry logzioMeterRegistry){\n        this.messageRepository = messageRepository;\n        this.messageGeneratorClient = messageGeneratorClient;\n        this.logzioMeterRegistry = logzioMeterRegistry;\n        initCounters();\n    }<\/code><\/pre>\n\n\n\n<p>You can see we&#8217;ve got a new method to initialize the counters.  That logic is<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    private void initCounters() {\n        msgCount= Counter.builder(\"message.request.count\")\n                .description(\"Number of message requests received by the service\")\n                .register(logzioMeterRegistry);\n        genMsgCount = Counter.builder(\"message.generated.request.count\")\n                .description(\"Number of message generated requests to message-generator\")\n                .register(logzioMeterRegistry);\n        genMsgSuccess = Counter.builder(\"message.generated.request.success\")\n                .description(\"Number of message generated success responses from message-generator\")\n                .register(logzioMeterRegistry);\n        messageSaved = Counter.builder(\"message.stored.count\")\n                .description(\"Number of messages successfully stored in the repository\")\n                .register(logzioMeterRegistry);\n    }<\/code><\/pre>\n\n\n\n<p>There are several key points here.  Use a readable and maintainable key name, make sure to add a description for future developers and register the metric with the registry.<\/p>\n\n\n\n<p>Now instrument the service<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    public Message saveMessage(Message message){\n\n        msgCount.increment();\n        if (StringUtils.isEmpty(message.getMessage())){\n\n            genMsgCount.increment();\n            log.info(\"No message, retrieve from message generator\");\n            MessageResponseDTO dto = messageGeneratorClient.getMessage();\n            message.setMessage(dto.getMessage());\n            genMsgSuccess.increment();\n            log.info(\"retrieved message: {}\", message.getMessage());\n        }\n\n        MessageDocument msgDoc = MessageDocumentMapper.INSTANCE.modelToDocument(message);\n\n        log.info(\"saving document: {}\", msgDoc);\n        MessageDocument returnDoc = messageRepository.save(msgDoc);\n        messageSaved.increment();\n        return MessageDocumentMapper.INSTANCE.documentToModel(returnDoc);\n    }<\/code><\/pre>\n\n\n\n<p>Its pretty basic&#8230; just increment the counter when the relevant event occurs.  Its <strong>very<\/strong> similar to logging but the structure comes into play later.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"validate-the-metrics-endpoint\">Validate the Metrics Endpoint<\/h2>\n\n\n\n<p>Start up the application, hit the post message endpoint a few times and navigate to <code>\/actuator\/metrics<\/code> in postman.  You should see something like this<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"917\" height=\"573\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-23.png?resize=917%2C573&#038;ssl=1\" alt=\"\" class=\"wp-image-1304\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-23.png?w=917&amp;ssl=1 917w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-23.png?resize=300%2C187&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-23.png?resize=768%2C480&amp;ssl=1 768w\" sizes=\"auto, (max-width: 917px) 100vw, 917px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>There&#8217;s a lot of metrics that come preloaded.  Ours should be in here too.  This is essentially all of the existing metrics that have been registered with the micrometer registry.<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"475\" height=\"162\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-24.png?resize=475%2C162&#038;ssl=1\" alt=\"\" class=\"wp-image-1305\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-24.png?w=475&amp;ssl=1 475w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-24.png?resize=300%2C102&amp;ssl=1 300w\" sizes=\"auto, (max-width: 475px) 100vw, 475px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>And you can see the actual metrics if you navigate to the metric (<code>actuator\/metrics\/message.request.count<\/code>)<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"918\" height=\"519\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-25.png?resize=918%2C519&#038;ssl=1\" alt=\"\" class=\"wp-image-1306\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-25.png?w=918&amp;ssl=1 918w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-25.png?resize=300%2C170&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-25.png?resize=768%2C434&amp;ssl=1 768w\" sizes=\"auto, (max-width: 918px) 100vw, 918px\" data-recalc-dims=\"1\" \/><figcaption>Let&#8217;s go ahead and commit, push and deploy this to the cloud.<\/figcaption><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code>$ git add .\n$ git commit -m \"metrics\"\n&#91;main 6ce8574] metrics\n 7 files changed, 152 insertions(+), 5 deletions(-)\n create mode 100644 src\/main\/java\/com\/bullyrooks\/cloud_application\/config\/LogzioMicrometerConfiguration.java\n$ git push\nEnumerating objects: 40, done.\nCounting objects: 100% (40\/40), done.\nDelta compression using up to 4 threads\nCompressing objects: 100% (17\/17), done.\nWriting objects: 100% (21\/21), 3.24 KiB | 663.00 KiB\/s, done.\nTotal 21 (delta 10), reused 0 (delta 0), pack-reused 0\nremote: Resolving deltas: 100% (10\/10), completed with 10 local objects.\nTo github.com-bullyrook:bullyrooks\/cloud_application.git\n   c8542f4..6ce8574  main -&gt; main<\/code><\/pre>\n\n\n\n<p>While this is building and deploying, lets go build the visualizations in grafana<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"visualization-with-grafana\">Visualization with Grafana<\/h2>\n\n\n\n<p>Navigate to the grafana instance<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"275\" height=\"136\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-26.png?resize=275%2C136&#038;ssl=1\" alt=\"\" class=\"wp-image-1307\" data-recalc-dims=\"1\"\/><\/figure>\n\n\n\n<p>Create a new dashboard<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"203\" height=\"81\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-28.png?resize=203%2C81&#038;ssl=1\" alt=\"\" class=\"wp-image-1309\" data-recalc-dims=\"1\"\/><\/figure>\n\n\n\n<p>Add an empty panel<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"873\" height=\"420\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-29.png?resize=873%2C420&#038;ssl=1\" alt=\"\" class=\"wp-image-1310\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-29.png?w=873&amp;ssl=1 873w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-29.png?resize=300%2C144&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-29.png?resize=768%2C369&amp;ssl=1 768w\" sizes=\"auto, (max-width: 873px) 100vw, 873px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>In the Edit Panel page, add <code>sum(increase(message_request_count_total[1m])<\/code>) to the query and change the name to Number of Message Requests<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"452\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-30-1024x482.png?resize=960%2C452&#038;ssl=1\" alt=\"\" class=\"wp-image-1311\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-30.png?resize=1024%2C482&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-30.png?resize=300%2C141&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-30.png?resize=768%2C361&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-30.png?resize=1536%2C723&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-30.png?w=1638&amp;ssl=1 1638w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>And hit Apply.  You should see your dashboard with the new panel.  Make sure to save and name the dashboard.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"835\" height=\"412\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-31.png?resize=835%2C412&#038;ssl=1\" alt=\"\" class=\"wp-image-1312\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-31.png?w=835&amp;ssl=1 835w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-31.png?resize=300%2C148&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-31.png?resize=768%2C379&amp;ssl=1 768w\" sizes=\"auto, (max-width: 835px) 100vw, 835px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>Go ahead and repeat for all of the metrics.  Remember that the metric format is the name of your metric, substitute the &#8220;<code>.<\/code>&#8221; with &#8220;<code>_<\/code>&#8221; and append with &#8220;<code>_total<\/code>&#8220;.<\/p>\n\n\n\n<p>When you&#8217;re done you should see something like this:<br><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"380\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-32-1024x405.png?resize=960%2C380&#038;ssl=1\" alt=\"\" class=\"wp-image-1313\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-32.png?resize=1024%2C405&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-32.png?resize=300%2C119&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-32.png?resize=768%2C303&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-32.png?resize=1536%2C607&amp;ssl=1 1536w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-32.png?w=1577&amp;ssl=1 1577w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"visualizing-resource-metrics\">Visualizing Resource Metrics<\/h2>\n\n\n\n<p>At this point, we&#8217;re just visualizing our work metrics, but our resource metrics are just as important.  We&#8217;re going to want to see error rate and latency, which are provided by the default metrics.<\/p>\n\n\n\n<p>There are a few ways to do this.  You can create them all by hand (you have the metrics).  However, I think grafana is kind of difficult to work with.  An alternative is to find, download and import a dashboard that is already configured for spring boot service visualization.<\/p>\n\n\n\n<p>You can search <a href=\"https:\/\/grafana.com\/grafana\/dashboards\/\">grafana&#8217;s dashboard repository here<\/a>.<\/p>\n\n\n\n<p>Here&#8217;s a sample:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"581\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-34-1024x620.png?resize=960%2C581&#038;ssl=1\" alt=\"\" class=\"wp-image-1316\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-34.png?resize=1024%2C620&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-34.png?resize=300%2C182&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-34.png?resize=768%2C465&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-34.png?w=1226&amp;ssl=1 1226w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>You may have to do a little extra configuration, which I won&#8217;t dive into.  There&#8217;s usually some documentation that comes with these pre configured dashboards.<\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"entry-summary\">\nLogz.io uses prometheus for metrics. Go ahead and enable metrics collection in&hellip;\n<\/div>\n<div class=\"link-more\"><a href=\"https:\/\/bullyrooks.com\/index.php\/2022\/02\/20\/kube-cloud-pt4-metrics\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &ldquo;Kube Cloud Pt4 | Metrics&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":[1,41],"tags":[163,180,177,165,167,176,178,43,179],"course":[164],"class_list":["post-1301","post","type-post","status-publish","format-standard","hentry","category-general","category-software-development","tag-actuator","tag-dashboard","tag-grafana","tag-logz-io","tag-metrics","tag-micrometer","tag-prometheus","tag-spring-boot","tag-visualization","course-kube-cloud-4-observability","entry"],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":1356,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/27\/kube-cloud-pt5-create-an-event-consumer\/","url_meta":{"origin":1301,"position":0},"title":"Kube Cloud Pt5 | Create an Event Consumer","author":"Bullyrook","date":"February 27, 2022","format":false,"excerpt":"Now that we've got messages being published to kafka, we are going to need to build our consumer that receives those events and stores them into the mongo database. Go ahead and create a new repository called message-repository according to the microservice startup course here. This is the pom.xml that\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\/02\/image-49.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-49.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-49.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1264,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/13\/kube-cloud-pt3-health-indicators\/","url_meta":{"origin":1301,"position":1},"title":"Kube Cloud Pt3 | Health Indicators","author":"Bullyrook","date":"February 13, 2022","format":false,"excerpt":"Spring offers a way to tell if your services and their dependent resources are up and healthy. Kubernetes can leverage this functionality via their liveness and readiness probes to report if pods are available to service requests. In this session, we're going to enable and connect those health checks. Enable\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\/02\/image-4.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-4.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-4.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1276,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/19\/kube-cloud-pt4-observability\/","url_meta":{"origin":1301,"position":2},"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":1278,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/19\/kube-cloud-pt4-logging\/","url_meta":{"origin":1301,"position":3},"title":"Kube Cloud Pt4 | Logging","author":"Bullyrook","date":"February 19, 2022","format":false,"excerpt":"Add Structured Logging Structured logging means that we'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).\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\/02\/image-7.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":1069,"url":"https:\/\/bullyrooks.com\/index.php\/2021\/07\/23\/spring-boot-lambda-implementation\/","url_meta":{"origin":1301,"position":4},"title":"Spring Boot Lambda Implementation","author":"Bullyrook","date":"July 23, 2021","format":false,"excerpt":"Now we're going to add some code. I'm going to follow my ports and adapters method of building a DTO and value object that I've used previously. Yes, its a bit of overkill for this project (especially a hello world example), but if you're using this course as a springboard\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-4.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-4.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-4.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1296,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/02\/19\/kube-cloud-pt4-tracing\/","url_meta":{"origin":1301,"position":5},"title":"Kube Cloud Pt4 | Tracing","author":"Bullyrook","date":"February 19, 2022","format":false,"excerpt":"For this portion we're going to use OpenTelemetry for tracing. OpenTelemetry projects intent is to solve all of the observability space in an opensource way. Unfortunately, at this time the logging and metrics portions are still in development, so we won't be able to use them. However the tracing piece\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-35.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-35.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-35.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-35.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/02\/image-35.png?resize=1400%2C800&ssl=1 4x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/1301","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=1301"}],"version-history":[{"count":4,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/1301\/revisions"}],"predecessor-version":[{"id":1327,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/1301\/revisions\/1327"}],"wp:attachment":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/media?parent=1301"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/categories?post=1301"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/tags?post=1301"},{"taxonomy":"course","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/course?post=1301"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}