<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kirk Lewis</title>
    <description>The latest articles on DEV Community by Kirk Lewis (@kirklewis).</description>
    <link>https://dev.to/kirklewis</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F91937%2F1592e04d-814b-4d1f-9279-2884d6633179.jpg</url>
      <title>DEV Community: Kirk Lewis</title>
      <link>https://dev.to/kirklewis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kirklewis"/>
    <language>en</language>
    <item>
      <title>Template File Processing in Go</title>
      <dc:creator>Kirk Lewis</dc:creator>
      <pubDate>Thu, 29 Aug 2019 10:35:03 +0000</pubDate>
      <link>https://dev.to/kirklewis/template-file-processing-in-go-1ida</link>
      <guid>https://dev.to/kirklewis/template-file-processing-in-go-1ida</guid>
      <description>&lt;p&gt;In a &lt;a href="https://dev.to/kirklewis/go-text-template-processing-181d"&gt;previous post&lt;/a&gt; I demonstrated how to get a Go template's interpolated string result. However, if you just want to interpolate and then write the string result straight to file, this post demonstrates how.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Template File
&lt;/h2&gt;

&lt;p&gt;The following text can be saved to a file &lt;code&gt;templates/greeting.tmpl&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Greeting&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The template string above contains two annotations &lt;code&gt;.Greeting&lt;/code&gt; and &lt;code&gt;.Name&lt;/code&gt; which is enough for this demonstration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Execute and Write
&lt;/h2&gt;

&lt;p&gt;The first argument of the &lt;code&gt;text/template&lt;/code&gt; package's &lt;code&gt;Execute&lt;/code&gt; function uses an &lt;a href="https://golang.org/pkg/io/#Writer" rel="noopener noreferrer"&gt;io.Writer&lt;/a&gt; interface. As such, if we pass this argument an &lt;code&gt;os.File&lt;/code&gt;, its &lt;a href="https://github.com/golang/go/blob/fa02af4238a3d41e23bc945e7d48e50fe4429405/src/os/file.go#L145" rel="noopener noreferrer"&gt;write&lt;/a&gt; function will be used to write the processed template bytes straight to file.&lt;/p&gt;

&lt;p&gt;Add the following code to a file named &lt;code&gt;process-file.go&lt;/code&gt; .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"text/template"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// variables&lt;/span&gt;
    &lt;span class="n"&gt;vars&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Greeting"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello"&lt;/span&gt;
    &lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Dev"&lt;/span&gt;

    &lt;span class="c"&gt;// parse the template&lt;/span&gt;
    &lt;span class="n"&gt;tmpl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseFiles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"templates/greeting.tmpl"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// create a new file&lt;/span&gt;
    &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"greeting.txt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// apply the template to the vars map and write the result to file.&lt;/span&gt;
    &lt;span class="n"&gt;tmpl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;For brevity, I have omitted error checking in the code above by using an underscore&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run the file&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go run process-file.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the line above should create a file named &lt;code&gt;greeting.txt&lt;/code&gt;. Check the contents of this file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;greeting.txt

Hello Dev!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you for reading! The code used in this post can be found as a Github gist &lt;a href="https://gist.github.com/kirklewis/e502c234fe6e88137544762dc419c644" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>go</category>
      <category>templates</category>
    </item>
    <item>
      <title>Metrics with Prometheus StatsD Exporter and Grafana</title>
      <dc:creator>Kirk Lewis</dc:creator>
      <pubDate>Wed, 31 Jul 2019 15:46:04 +0000</pubDate>
      <link>https://dev.to/kirklewis/metrics-with-prometheus-statsd-exporter-and-grafana-5145</link>
      <guid>https://dev.to/kirklewis/metrics-with-prometheus-statsd-exporter-and-grafana-5145</guid>
      <description>&lt;p&gt;This post explains how to convert &lt;a href="https://github.com/statsd/statsd#statsd--" rel="noopener noreferrer"&gt;StatsD&lt;/a&gt; metrics using the Prometheus StatsD-exporter, and later visualising them with Grafana. &lt;/p&gt;

&lt;p&gt;I explain from the perspective of an application which is instrumented with StatsD but is monitored by a Prometheus server. As such, I will use the terminal as a pretend application emitting metrics &lt;strong&gt;;&lt;/strong&gt; Prometheus will monitor the application and collect any metrics &lt;strong&gt;;&lt;/strong&gt; and finally Grafana will be used to draw a graph by using Prometheus as a data source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of Technologies Used
&lt;/h2&gt;

&lt;p&gt;This section briefly covers why each technology is being used but to learn more, you can read about each using the links in the Recommended Reading section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Metrics
&lt;/h3&gt;

&lt;p&gt;During a system's runtime, measurements taken of any of its properties are known as &lt;em&gt;metrics&lt;/em&gt;. These metrics are typically in the form of &lt;em&gt;data points&lt;/em&gt; associated with some information to give it context. Metrics are things like the number memory bytes used, number of website visitors, the time a task took to complete, etc.&lt;/p&gt;

&lt;p&gt;StatsD metrics allow such information to be recorded and represented using a &lt;a href="https://github.com/b/statsd_spec#statsd-metrics-export-specification-v01" rel="noopener noreferrer"&gt;text format&lt;/a&gt; specification. Below are two StatsD metric lines each representing how long an API request has taken.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# metric format: &amp;lt;metric name&amp;gt;:&amp;lt;value&amp;gt;|ms&lt;/span&gt;
test_api_call.orders-api.timer./v1/orders:84|ms
test_api_call.orders-api.timer./v1/orders:95|ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, two API calls to &lt;code&gt;GET /api/orders&lt;/code&gt; are measured at 84 and 95 milliseconds each. The &lt;code&gt;|ms&lt;/code&gt; is used with StatsD timer metrics. StatsD also supports other metric types like Counters, Gauges, Histograms and &lt;a href="https://github.com/statsd/statsd/blob/master/docs/metric_types.md#statsd-metric-types" rel="noopener noreferrer"&gt;more&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why dot-delimited?
&lt;/h4&gt;

&lt;p&gt;To record information about the metric, in this case the name of the API and its endpoint, the &lt;code&gt;&amp;lt;metric name&amp;gt;&lt;/code&gt; part is &lt;em&gt;dot-delimited&lt;/em&gt; so those details can be captured.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fytsp6k7bu0c591vz0hu1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fytsp6k7bu0c591vz0hu1.png" title="Figure 1: StatsD metric in dotted notation" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Later you will see how the Statsd-exporter will help us capture the dot-delimited parts we are concerned with.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prometheus for Monitoring
&lt;/h3&gt;

&lt;p&gt;Prometheus can be used to monitor the performance of an instrumented system such as, a microservice, a host server, etc. The system will need to expose its metrics in order for Prometheus to collect them - this is also known scraping. The scraped metrics can then be visualised or queried using the Prometheus &lt;a href="https://prometheus.io/docs/visualization/browser/#expression-browser" rel="noopener noreferrer"&gt;expression-browser&lt;/a&gt;. Prometheus also has an &lt;a href="https://prometheus.io/docs/alerting/alertmanager/" rel="noopener noreferrer"&gt;AlertManager&lt;/a&gt; which can send alerts about certain metrics being monitored - it has support for Slack, PagerDuty, email and &lt;a href="https://prometheus.io/docs/introduction/faq/#can-i-send-alerts" rel="noopener noreferrer"&gt;more&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The following diagram shows Prometheus scraping an application's metrics which are exposed on  the&lt;code&gt;/metrics&lt;/code&gt; path. Grafana can then use these metrics for visualisations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fseqaahl8z0q0hhgrslck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fseqaahl8z0q0hhgrslck.png" title="Figure 2: Prometheus scraping metrics from two applications" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Statsd-exporter
&lt;/h3&gt;

&lt;p&gt;The statsd-exporter is used to convert Statsd metrics into Prometheus metrics. This is because the StatsD &lt;a href="https://github.com/b/statsd_spec#statsd-metrics-export-specification-v01" rel="noopener noreferrer"&gt;text-format&lt;/a&gt; represents metrics differently to Prometheus' &lt;a href="https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md#text-format-example" rel="noopener noreferrer"&gt;exposition format&lt;/a&gt; which is represented like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;time series name&amp;gt;{&amp;lt;label name&amp;gt;=&amp;lt;label value&amp;gt;,...}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following diagram shows how a StatsD metric, is converted to Prometheus metrics by using an exporter's mapping rules.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F2vvlwz5t26l5fu6dzl69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F2vvlwz5t26l5fu6dzl69.png" title="Figure 3: StatsD-exporter mapping configuration" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;It is very common for a system to record its metrics in a format different to Prometheus, therefore there are many &lt;a href="https://prometheus.io/docs/instrumenting/exporters" rel="noopener noreferrer"&gt;Exporters&lt;/a&gt; written which allow such metrics to be converted to Prometheus' time series notation&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Where did count, sum and quantile come from?
&lt;/h4&gt;

&lt;p&gt;The StatsD-exporter automatically converts timer metrics into a &lt;a href="https://prometheus.io/docs/concepts/metric_types/#summary" rel="noopener noreferrer"&gt;Prometheus summary&lt;/a&gt;. The summary contains extra information like the count, sum and each quantile for the current observation. &lt;em&gt;By default the quantiles are 0.5, 0.9 and 0.99&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the image above, 10 API requests took 80 milliseconds each to respond. As such a summary is generated with these details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;_count&lt;/code&gt; of 10.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_sum&lt;/code&gt; of 0.799999999999999 for that observation.&lt;/li&gt;
&lt;li&gt;and each &lt;code&gt;_quantile&lt;/code&gt; where 0.5 (50th percentile) is the median.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now there is an understanding of what each technology does in relation to each other, we can get started implementing our test application.&lt;/p&gt;




&lt;h2&gt;
  
  
  Configure Prometheus and Statsd-exporter
&lt;/h2&gt;

&lt;p&gt;In this section the configuration files for both Prometheus and the statsd-exporter are created.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the Directory and Files
&lt;/h3&gt;

&lt;p&gt;Create a directory named &lt;code&gt;.prometheus&lt;/code&gt; to contain the files &lt;code&gt;prometheus.yml&lt;/code&gt; and &lt;code&gt;test-mapping.yml&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# I have created mine in $HOME/.prometheus/&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/.prometheus &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;
&lt;span class="nb"&gt;touch&lt;/span&gt; ./&lt;span class="o"&gt;{&lt;/span&gt;prometheus,test-mapping&lt;span class="o"&gt;}&lt;/span&gt;.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;tree&lt;/code&gt; or &lt;code&gt;find .&lt;/code&gt; to verify the files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prometheus Configuration
&lt;/h3&gt;

&lt;p&gt;This gives us some basic configuration for the Prometheus server such as static service discovery, and how often to scrape each discovered service.&lt;/p&gt;

&lt;p&gt;Add the following to the &lt;code&gt;prometheus.yml&lt;/code&gt; file and save it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scrape_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;      &lt;span class="s"&gt;15s&lt;/span&gt;
  &lt;span class="na"&gt;evaluation_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;15s&lt;/span&gt;

&lt;span class="na"&gt;scrape_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# optional: this makes the metrics available to us about Promethus itself.&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;prometheus'&lt;/span&gt;
    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost:9090'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="c1"&gt;# tells Prometheus to scrape metrics an address over port 9123&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test_metrics'&lt;/span&gt;
    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host.docker.internal:9123'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# see statsd-exporter further down&lt;/span&gt;
        &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;host'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test-app-001'&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# optional: just a way to identify the system exposing metrics&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Prometheus also supports &lt;a href="https://github.com/prometheus/prometheus/tree/master/discovery" rel="noopener noreferrer"&gt;dynamic service discovery&lt;/a&gt; which is useful if you deploy applications on AWS ECS or other scalable cloud solutions.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Statsd-Exporter Configuration
&lt;/h3&gt;

&lt;p&gt;This is the file used by the Prometheus statsd-exporter so it knows how to convert StatsD metrics into Prometheus metrics.&lt;/p&gt;

&lt;p&gt;Add the following to the &lt;code&gt;test-mapping.yml&lt;/code&gt; file and save it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;mappings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# usage: test_api_call.product-api.timer./v1/product&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test_api_call.*.timer.*"&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;test_api_call"&lt;/span&gt;
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;api_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;$1"&lt;/span&gt;
        &lt;span class="na"&gt;api_endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;$2"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Startup the Statsd Exporter
&lt;/h2&gt;

&lt;p&gt;Before visualising any metrics with Grafana, we can check whether our Statsd metrics are being converted correctly.&lt;/p&gt;

&lt;p&gt;To start, run the the official Prometheus &lt;a href="https://hub.docker.com/r/prom/statsd-exporter" rel="noopener noreferrer"&gt;statsd-exporter&lt;/a&gt; Docker image, and then send it metrics over port 8125.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Make sure you are inside the &lt;code&gt;.prometheus&lt;/code&gt; directory.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prom-statsd-exporter &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-p&lt;/span&gt; 9123:9102 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-p&lt;/span&gt; 8125:8125/udp &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$PWD&lt;/span&gt;/test-mapping.yml:/tmp/test-mapping.yml &lt;span class="se"&gt;\&lt;/span&gt;
    prom/statsd-exporter &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;--statsd&lt;/span&gt;.mapping-config&lt;span class="o"&gt;=&lt;/span&gt;/tmp/test-mapping.yml &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;--statsd&lt;/span&gt;.listen-udp&lt;span class="o"&gt;=&lt;/span&gt;:8125 &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;--web&lt;/span&gt;.listen-address&lt;span class="o"&gt;=&lt;/span&gt;:9102
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What this does
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;listens for metrics sent to an address on port &lt;code&gt;8125&lt;/code&gt; - &lt;em&gt;e.g.&lt;/em&gt; &lt;code&gt;echo "hello:1|c" | nc -w 0 -u 127.0.0.1 8125&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;converts Statsd metrics to Prometheus ones by using the &lt;code&gt;test-mapping.yml&lt;/code&gt; file created earlier.&lt;/li&gt;
&lt;li&gt;expose the metrics for Prometheus to scrape - in this case over host port &lt;code&gt;9123&lt;/code&gt; - container port &lt;code&gt;9102&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After running the image you should see output like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5hh4mcrkzrfzmv011932.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5hh4mcrkzrfzmv011932.png" title="Figure 4: StatsD-exporter Docker logs after startup" width="800" height="63"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Startup Prometheus
&lt;/h2&gt;

&lt;p&gt;Now the Prometheus server can be started so it can scrape the metrics exposed on port 9123.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Recall that the &lt;code&gt;prom-statsd-exporter&lt;/code&gt; container, is exposing metrics on container port 9102 which were remapped to host port 9123.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To start, run the official &lt;a href="https://hub.docker.com/r/prom/prometheus" rel="noopener noreferrer"&gt;Prometheus&lt;/a&gt; Docker image.&lt;/p&gt;
&lt;h3&gt;
  
  
  Running
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Make sure you are inside the &lt;code&gt;.prometheus&lt;/code&gt; directory.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prometheus &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-p&lt;/span&gt; 9090:9090 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;$PWD&lt;/span&gt;/prometheus.yml:/prometheus.yml &lt;span class="se"&gt;\&lt;/span&gt;
    prom/prometheus &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;--config&lt;/span&gt;.file&lt;span class="o"&gt;=&lt;/span&gt;/prometheus.yml &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;--log&lt;/span&gt;.level&lt;span class="o"&gt;=&lt;/span&gt;debug &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;--web&lt;/span&gt;.listen-address&lt;span class="o"&gt;=&lt;/span&gt;:9090 &lt;span class="se"&gt;\&lt;/span&gt;
        &lt;span class="nt"&gt;--web&lt;/span&gt;.page-title&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'Prometheus - Test Metrics Demo'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What this does
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;runs Prometheus server and tells it to scrape metrics from the targets defined in &lt;code&gt;prometheus.yml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;allow us to visualise the metrics using the Prometheus browser and even query them using PromQL
&lt;/li&gt;
&lt;li&gt;allows Grafana to use Prometheus as a data source over address port 9090&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After running the image you should see output like this:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fxw8h1lwgymu21aju5mrp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fxw8h1lwgymu21aju5mrp.png" title="Figure 5: Prometheus Docker logs after startup" width="800" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The above informs us that the &lt;code&gt;prometheus.yml&lt;/code&gt; file was loaded, and Prometheus knows about the two targets to scrape.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Verify the Targets are Up and Running
&lt;/h3&gt;

&lt;p&gt;Go to &lt;a href="http://localhost:9090/targets" rel="noopener noreferrer"&gt;localhost:9090/targets&lt;/a&gt;. Each one endpoint for each target should be &lt;code&gt;up&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3ljdorq2rdwmzlj4g1gg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3ljdorq2rdwmzlj4g1gg.jpg" title="Figure 6: Prometheus showing the targets it can scrape" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can start sending metrics and prometheus will scrape them.&lt;/p&gt;
&lt;h2&gt;
  
  
  Sending some Metrics
&lt;/h2&gt;

&lt;p&gt;Now try sending a couple metric over localhost IP address and port 127.0.0.1:8125 using the lines below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"test_api_call.orders-api.timer./v1/orders:89|ms"&lt;/span&gt; | nc &lt;span class="nt"&gt;-w&lt;/span&gt; 0 &lt;span class="nt"&gt;-u&lt;/span&gt; 127.0.0.1 8125
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"test_api_call.orders-api.timer./v1/orders:68|ms"&lt;/span&gt; | nc &lt;span class="nt"&gt;-w&lt;/span&gt; 0 &lt;span class="nt"&gt;-u&lt;/span&gt; 127.0.0.1 8125
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now goto &lt;a href="http://localhost:9123" rel="noopener noreferrer"&gt;http://localhost:9123&lt;/a&gt; to view the metrics. If you have updated your &lt;code&gt;hosts&lt;/code&gt; file to resolve &lt;code&gt;host.docker.internal&lt;/code&gt; to &lt;code&gt;localhost&lt;/code&gt; then you can visit &lt;code&gt;http://host.docker.internal:9123&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;Search for &lt;code&gt;test_api_call&lt;/code&gt; and you should see a Prometheus summary similar to the following.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzbv3qxzvj9a2l4i072j8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzbv3qxzvj9a2l4i072j8.jpg" title="Figure 7: Prometheus Scraped metrics" width="800" height="119"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Visualise the API Call Metrics in Grafana
&lt;/h2&gt;

&lt;p&gt;This final section looks at starting up Grafana on port 3000, adding a Prometheus data source, and creating a Graph to visualise the API call metrics.&lt;/p&gt;

&lt;p&gt;Start by running the official &lt;a href="https://hub.docker.com/r/grafana/grafana" rel="noopener noreferrer"&gt;Grafana&lt;/a&gt; Docker image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;grafana &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 grafana/grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The default &lt;em&gt;username&lt;/em&gt; and &lt;em&gt;password&lt;/em&gt; for Grafana are both &lt;em&gt;admin&lt;/em&gt; and &lt;em&gt;admin&lt;/em&gt; respectively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding a Prometheus Data Source to Grafana
&lt;/h3&gt;

&lt;p&gt;To add a Prometheus data source and add a Graph you can follow the instructions at the Prometheus website - &lt;em&gt;instead of me repeating the same instructions here&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://prometheus.io/docs/visualization/grafana/#creating-a-prometheus-data-source" rel="noopener noreferrer"&gt;Create a Prometheus data source&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://prometheus.io/docs/visualization/grafana/#creating-a-prometheus-graph" rel="noopener noreferrer"&gt;Creating-a-prometheus-graph&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Plotting the average request duration&lt;/strong&gt;&lt;br&gt;
Within the the section &lt;em&gt;"Creating a Prometheus Graph"&lt;/em&gt; where it mentions 'Entering a Prometheus expression' into the Query field, use the expression &lt;code&gt;rate(test_api_call_sum[1m]) / rate(test_api_call_count[1m])&lt;/code&gt; as seen below. This expression calculates the average request duration for the last minute using the Prometheus summary for &lt;code&gt;test_api_call&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Optionally, you can also update the legend field to &lt;code&gt;{{api_name}} - {{api_endpoint}}&lt;/code&gt; as seen below also - doing so will display the legend like this: &lt;code&gt;orders-api - /v1/orders&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fqsp44osw217xnqte0kbq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fqsp44osw217xnqte0kbq.jpg" title="Figure 8: Grafana Prometheus Query and Legend" width="800" height="205"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Emit Metrics Continuously
&lt;/h3&gt;

&lt;p&gt;Now to save us having to send metrics manually - &lt;em&gt;just to update the graph more frequently&lt;/em&gt;, we can write a simple command-line statement which will send a metric every second. This will be done in two shells, in order to simulate API calls to our fictional &lt;code&gt;orders-api&lt;/code&gt; and &lt;code&gt;invoice-api&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Below the &lt;a href="https://explainshell.com/explain?cmd=shuf+-i+50-150+-n+1" rel="noopener noreferrer"&gt;shuf&lt;/a&gt; command is used to generate a random range of milliseconds between 50 and 150.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shell 1: orders-api&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"test_api_call.orders-api.timer./v1/orders:&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;shuf&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; 50-150 &lt;span class="nt"&gt;-n&lt;/span&gt; 1&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;|ms"&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
    nc &lt;span class="nt"&gt;-w&lt;/span&gt; 1 &lt;span class="nt"&gt;-u&lt;/span&gt; 127.0.0.1 8125&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Shell 2: invoice-api&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"test_api_call.invoice-api.timer./v1/invoice:&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;shuf&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; 50-150 &lt;span class="nt"&gt;-n&lt;/span&gt; 1&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;|ms"&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
    nc &lt;span class="nt"&gt;-w&lt;/span&gt; 1 &lt;span class="nt"&gt;-u&lt;/span&gt; 127.0.0.1 8125&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;use &lt;strong&gt;ctrl&lt;/strong&gt;+&lt;strong&gt;c&lt;/strong&gt; to stop either loop&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Visualisation
&lt;/h3&gt;

&lt;p&gt;After a few seconds you should see the graph drawing. And some time later - in my case 5 minutes your graph should look similar to the image below. &lt;em&gt;Make sure the Dashboard's refresh rate is at least 5 seconds.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fq6h9iruipr7vnt4gydmm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fq6h9iruipr7vnt4gydmm.jpg" title="Figure 9: The API call metrics visualisation" width="800" height="616"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I emit metrics from a real application?
&lt;/h2&gt;

&lt;p&gt;There are StatsD client libraries written for Go, Node, Python, Perl  and more. See link below:&lt;br&gt;
&lt;a href="https://github.com/statsd/statsd/wiki#client-implementations" rel="noopener noreferrer"&gt;https://github.com/statsd/statsd/wiki#client-implementations&lt;/a&gt;&lt;br&gt;
Some of the libraries also default the host &lt;code&gt;localhost&lt;/code&gt; and port to &lt;code&gt;8125&lt;/code&gt; so you can get up and running quickly.&lt;/p&gt;
&lt;h3&gt;
  
  
  Node StatsD Client Example
&lt;/h3&gt;

&lt;p&gt;This example uses the NPM module &lt;a href="https://github.com/sivy/node-statsd#node-statsd" rel="noopener noreferrer"&gt;node-statsd&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;StatsD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-statsd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;statsdClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StatsD&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// defaults to localhost:8125&lt;/span&gt;

&lt;span class="nx"&gt;statsdClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;example.response_time&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// record 80ms response time&lt;/span&gt;
&lt;span class="nx"&gt;statsdClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;example.site_visit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// record a new site visitor count +1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Can I just emit metrics to Prometheus format instead of StatsD?
&lt;/h2&gt;

&lt;p&gt;Yes, it is possible instrument an application to record metrics in Prometheus format. This approach eliminates the need to use a Prometheus exporter sidecar and the extra work of creating a mapping file.&lt;/p&gt;

&lt;p&gt;To instrument your application with Prometheus, use one of the &lt;a href="https://prometheus.io/docs/instrumenting/clientlibs" rel="noopener noreferrer"&gt;official or unofficial&lt;/a&gt; client libraries.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Getting Statsd metrics out of an application (terminal for this demo) and into Grafana, only required the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;two configuration files.&lt;/li&gt;
&lt;li&gt;running statsd-exporter, Prometheus and Grafana.&lt;/li&gt;
&lt;li&gt;emitting metrics over a host address and port with UDP using the Statsd line protocol.&lt;/li&gt;
&lt;li&gt;setting Prometheus as a data source in Grafana and configuring a graph.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That was it! The majority of this post is mostly explaining some essentials which I think are very important to understand. Although the terminal is used as a pretend application 'to emit metrics', the principles are the same for a real application. So whether you write your application in Go, Node, Python, etc, you can just use a StatsD client library to emit metrics from it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Recommended Reading
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Learn more about Prometheus - &lt;a href="https://prometheus.io" rel="noopener noreferrer"&gt;https://prometheus.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Prometheus Exporters - &lt;a href="https://prometheus.io/docs/instrumenting/exporters" rel="noopener noreferrer"&gt;https://prometheus.io/docs/instrumenting/exporters&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Instrument an application using Prometheus itself - &lt;a href="https://prometheus.io/docs/instrumenting/clientlibs" rel="noopener noreferrer"&gt;https://prometheus.io/docs/instrumenting/clientlibs&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Statsd Github - &lt;a href="https://github.com/statsd/statsd#statsd--" rel="noopener noreferrer"&gt;https://github.com/statsd/statsd#statsd--&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.flickr.com/photos/kirklewis/48423312857/" rel="noopener noreferrer"&gt;Cover image&lt;/a&gt;&lt;/p&gt;

</description>
      <category>metrics</category>
      <category>statsd</category>
      <category>prometheus</category>
      <category>grafana</category>
    </item>
    <item>
      <title>Go Text Template Processing</title>
      <dc:creator>Kirk Lewis</dc:creator>
      <pubDate>Sat, 27 Apr 2019 23:37:09 +0000</pubDate>
      <link>https://dev.to/kirklewis/go-text-template-processing-181d</link>
      <guid>https://dev.to/kirklewis/go-text-template-processing-181d</guid>
      <description>&lt;p&gt;I recently worked on a project where I used Go's template package for parsing and interpolating templates. After processing the templates, I needed to use the interpolated string result for saving new file content, and also naming directories and files. This post is a walkthrough of the functions I wrote to help process text templates, then afterwards each function is demonstrated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go Project Setup
&lt;/h2&gt;

&lt;p&gt;Since I am demonstrating these functions outside the project I created them for, I've created a simpler project for this post as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go-template-processing/
├── main.go
├── src
│   └── demo
│       └── template
│           └── process.go
└── templates
    └── got.tmpl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create the Template File
&lt;/h3&gt;

&lt;p&gt;Add the following text to the file &lt;code&gt;templates/got.tmpl&lt;/code&gt;.  This file template will be processed later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{{&lt;/span&gt;.Name&lt;span class="o"&gt;}}&lt;/span&gt; of house &lt;span class="o"&gt;{{&lt;/span&gt;.House&lt;span class="o"&gt;}}&lt;/span&gt;

&lt;span class="o"&gt;{{&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; .Traits -&lt;span class="o"&gt;}}&lt;/span&gt;
Traits:
    &lt;span class="o"&gt;{{&lt;/span&gt;- range .Traits&lt;span class="o"&gt;}}&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;{{&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; -&lt;span class="o"&gt;}}&lt;/span&gt;
    &lt;span class="o"&gt;{{&lt;/span&gt;end&lt;span class="o"&gt;}}&lt;/span&gt;
&lt;span class="o"&gt;{{&lt;/span&gt;end&lt;span class="o"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Anatomy of the Template
&lt;/h3&gt;

&lt;p&gt;The  annotations like &lt;code&gt;{{.Name}}&lt;/code&gt; and &lt;code&gt;{{.House}}&lt;/code&gt; will be replaced with their respective values, during template execution. The other annotations like &lt;code&gt;{{if}}&lt;/code&gt; and &lt;code&gt;{{range}}&lt;/code&gt;  know as &lt;a href="https://golang.org/pkg/text/template/#hdr-Actions" rel="noopener noreferrer"&gt;Actions&lt;/a&gt;, will also be evaluated. The hyphens &lt;code&gt;-&lt;/code&gt; to either side of the &lt;code&gt;{{&lt;/code&gt; and &lt;code&gt;}}&lt;/code&gt; delimiters, are used to trim any space before and after them respectively. The dot &lt;code&gt;.&lt;/code&gt; represents the current element in the range of Traits being iterated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set the GOPATH
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;go-template-processing
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GOPATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Interpolating the Parsed Template
&lt;/h2&gt;

&lt;p&gt;To separate the concern of first parsing then interpolating a template file or string, I've created a function in the file &lt;code&gt;process.go&lt;/code&gt; which does the interpolation first. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Go refers to the this interpolation as "executing the template", where the template is applied to a data structure.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"bytes"&lt;/span&gt;
    &lt;span class="s"&gt;"text/template"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// process applies the data structure 'vars' onto an already&lt;/span&gt;
&lt;span class="c"&gt;// parsed template 't', and returns the resulting string.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vars&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tmplBytes&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Buffer&lt;/span&gt;

    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;tmplBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tmplBytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;process&lt;/code&gt; function should be easy to reason with given its comment, annotations and implementation.&lt;/p&gt;

&lt;p&gt;The argument &lt;code&gt;vars&lt;/code&gt; is typed to an &lt;a href="https://tour.golang.org/methods/14" rel="noopener noreferrer"&gt;empty interface&lt;/a&gt;, so that any type like &lt;code&gt;map&lt;/code&gt; or &lt;code&gt;Struct&lt;/code&gt; with fields corresponding to the template's annotations can be used. Any &lt;code&gt;{{.Annotation}}&lt;/code&gt; without a corresponding field is replaced with &lt;code&gt;&amp;lt;no value&amp;gt;&lt;/code&gt;, or panics if it fails evaluation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Writing the &lt;code&gt;process&lt;/code&gt; function above is a pre-emptive &lt;a href="https://refactoring.guru/extract-method" rel="noopener noreferrer"&gt;extract method&lt;/a&gt; refactoring done to avoid &lt;a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself" rel="noopener noreferrer"&gt;DRY&lt;/a&gt; occurring later in the code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Processing a Template String
&lt;/h2&gt;

&lt;p&gt;The next function added to the &lt;code&gt;process.go&lt;/code&gt; file, will process a template string by creating a new &lt;a href="https://golang.org/pkg/text/template/#Template.New" rel="noopener noreferrer"&gt;Template&lt;/a&gt; and then parsing the given string &lt;code&gt;str&lt;/code&gt; argument. The new &lt;code&gt;Template&lt;/code&gt; assigned to &lt;code&gt;tmpl&lt;/code&gt; is then interpolated using the private &lt;code&gt;process&lt;/code&gt; function created earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ProcessString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vars&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tmpl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"tmpl"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmpl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function will be demonstrated later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Processing a Template File
&lt;/h2&gt;

&lt;p&gt;This function is very similar to &lt;code&gt;ProcessString&lt;/code&gt; but it processes the file indicated by the &lt;code&gt;fileName&lt;/code&gt; argument.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;a href="https://golang.org/pkg/text/template/#Template.ParseFiles" rel="noopener noreferrer"&gt;ParseFiles&lt;/a&gt; function can accept more than one file name argument. However, I only need to parse one file at a time, so I am using a single &lt;code&gt;fileName&lt;/code&gt; argument.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ProcessFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileName&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vars&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tmpl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseFiles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tmpl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it, both functions can now be consumed by client code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Process Functions
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;./main.go&lt;/code&gt; file below demonstrates how both process functions are used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"demo/template"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// data structure the template will be applied to&lt;/span&gt;
    &lt;span class="n"&gt;vars&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Brienne"&lt;/span&gt;
    &lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"House"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Tarth"&lt;/span&gt;
    &lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Traits"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Brave"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Loyal"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// process a template string&lt;/span&gt;
    &lt;span class="n"&gt;resultA&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProcessString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{{.Name}} of house {{.House}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// process a template file&lt;/span&gt;
    &lt;span class="n"&gt;resultB&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProcessFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"templates/got.tmpl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;go run main.go&lt;/code&gt;  should output the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Brienne of house Tarth

Brienne of house Tarth

Traits:
    * Brave
    * Loyal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both the template string and file have been successfully processed. The resulting string can be now used for an email body, the contents of a file, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supplying Vars via a Struct
&lt;/h3&gt;

&lt;p&gt;Once again, since &lt;code&gt;vars&lt;/code&gt; is typed to an empty interface, a struct can be used here also. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;I've added the following snippet just below the &lt;code&gt;fmt.Println(resultB)&lt;/code&gt; statement in &lt;code&gt;main.go&lt;/code&gt;.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// using a Struct&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Westerosi&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;   &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;House&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Traits&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;jorah&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Westerosi&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Ser Jorah"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Mormont"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Brave"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Protective"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="n"&gt;resultC&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProcessFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"templates/got.tmpl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jorah&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;code&gt;go run main.go&lt;/code&gt; again should now output the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Brienne of house Tarth

Brienne of house Tarth

Traits:
    * Brave
    * Loyal

Ser Jorah of house Mormont

Traits:
    * Brave
    * Protective
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Working with Go templates is pretty straight forward out of the box, making it easy to build your own project specific functions. While I have only covered a specific task in this post, you can read more about the Go template package at &lt;a href="https://golang.org/pkg/text/template/" rel="noopener noreferrer"&gt;https://golang.org/pkg/text/template&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The code used in the article is available on &lt;a href="https://github.com/kirklewis/go-template-processing" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;br&gt;
&lt;em&gt;Go version used at time of writing &lt;code&gt;go version go1.12.1&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading.&lt;/p&gt;

</description>
      <category>go</category>
      <category>template</category>
    </item>
    <item>
      <title>String Interpolation of Constants in Perl 5</title>
      <dc:creator>Kirk Lewis</dc:creator>
      <pubDate>Mon, 01 Oct 2018 21:06:57 +0000</pubDate>
      <link>https://dev.to/kirklewis/string-interpolation-of-constants-in-perl-5-181o</link>
      <guid>https://dev.to/kirklewis/string-interpolation-of-constants-in-perl-5-181o</guid>
      <description>&lt;p&gt;This post demonstrates how to use Perl 5 constants with String Interpolation and Regular Expressions. I will briefly explain how String Interpolation works in Perl 5, especially with constants. Finally I explain how to use constants with Regular Expressions, and a use case for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  String Interpolation
&lt;/h2&gt;

&lt;p&gt;In Perl 5, any scalar or list variables embedded within double-quotes will be substituted with their values at run-time. This type of string is known as an &lt;em&gt;Interpolated String&lt;/em&gt;, and it gets resolved in a process known as &lt;a href="https://en.wikipedia.org/wiki/String_interpolation" rel="noopener noreferrer"&gt;String Interpolation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$PI&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.14&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;@nums&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scalar: &lt;/span&gt;&lt;span class="si"&gt;$PI&lt;/span&gt;&lt;span class="s2"&gt; - list: &lt;/span&gt;&lt;span class="si"&gt;@nums&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scalar: 3.14 - list: 3 2 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, Interpolated Strings in Perl 5 can contain an &lt;em&gt;identifier&lt;/em&gt; wrapped in either &lt;code&gt;${}&lt;/code&gt; or &lt;code&gt;@{}&lt;/code&gt;, and depending on their type, they get resolved accordingly - &lt;em&gt;in this case scalar and list respectively&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scalar: &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt; &lt;span class="si"&gt;PI&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; - list: &lt;/span&gt;&lt;span class="si"&gt;@{&lt;/span&gt; &lt;span class="si"&gt;nums&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scalar: 3.14 - list: 3 2 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above string, Perl looks-up and finds each identifier &lt;em&gt;i.e.&lt;/em&gt; &lt;code&gt;PI&lt;/code&gt; and &lt;code&gt;nums&lt;/code&gt; within the current namespace, and they are resolved. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Since the expressions &lt;code&gt;${}&lt;/code&gt; and &lt;code&gt;@{}&lt;/code&gt;  highlight the intent of Interpolation more clearly, I will use them both going forward.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, a Constant created with the Perl 5 &lt;code&gt;constant&lt;/code&gt; prama is Sigilless, as such inserting one into a double-quoted string, will not be resolved. See below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;constant&lt;/span&gt; &lt;span class="s"&gt;DEV_OPS&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dev_ops&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt; &lt;span class="nv"&gt;$status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;

&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Team &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt; &lt;span class="si"&gt;DEV_OPS&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt; &lt;span class="si"&gt;status&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above results in the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Global symbol &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DEV_OPS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; requires an explicit package name...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above occurred because unlike &lt;code&gt;$status&lt;/code&gt;, the constant &lt;code&gt;DEV_OPS&lt;/code&gt; does not have a sigil, so Perl cannot look it up and resolve it - &lt;em&gt;with regards to quotes ""&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resolving the Constant
&lt;/h2&gt;

&lt;p&gt;To make the Interpolated String aware of any constants to be processed, a backslash &lt;code&gt;\&lt;/code&gt; is used to reference it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Team &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="si"&gt;DEV_OPS&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt; &lt;span class="si"&gt;status&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;span class="c1"&gt;# or if we use more than one constant&lt;/span&gt;
&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Team &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="si"&gt;DEV_OPS&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; - &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="si"&gt;DEV_OPS&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt; &lt;span class="si"&gt;status&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Team dev_ops is online
Team dev_ops - dev_ops is online
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  List Context
&lt;/h3&gt;

&lt;p&gt;Constant values are evaluated in List context  so  &lt;code&gt;[]&lt;/code&gt; can be used to reference them also. Then use the appropriate interpolation expression as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Team &lt;/span&gt;&lt;span class="si"&gt;@{&lt;/span&gt; &lt;span class="err"&gt;[&lt;/span&gt;&lt;span class="si"&gt;DEV_OPS&lt;/span&gt;&lt;span class="err"&gt;]&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;...&lt;/span&gt;&lt;span class="p"&gt;";&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, I find it simpler to use backslash &lt;code&gt;\&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Using Constants in Regular Expressions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Lets say you have three constants, and each represents a different colour as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;constant&lt;/span&gt; &lt;span class="s"&gt;BLUE&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;constant&lt;/span&gt; &lt;span class="s"&gt;GREEN&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;constant&lt;/span&gt; &lt;span class="s"&gt;RED&lt;/span&gt;   &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&lt;/span&gt;&lt;span class="p"&gt;';&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you have a list of colours &lt;code&gt;@colors&lt;/code&gt; which you want to validate against the three colours listed above, you may write something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt;  &lt;span class="nv"&gt;@colors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;qw(blue yellow orange red)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;my&lt;/span&gt;  &lt;span class="nv"&gt;$colors_regexp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;qr/^(blues|green|red)$/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;# typo intended...&lt;/span&gt;

&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="nv"&gt;$colors_regexp&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$_&lt;/span&gt;&lt;span class="s2"&gt; is valid&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$_&lt;/span&gt;&lt;span class="s2"&gt; is invalid&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="nv"&gt;@colors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;blue is invalid
yellow is invalid
orange is invalid
red is valid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now &lt;code&gt;blue&lt;/code&gt; in &lt;code&gt;@colors&lt;/code&gt; is actually valid, but the typo &lt;code&gt;blues&lt;/code&gt; in the Regular Expression, causes the match to fail. Whilst this typo is intentional, it could also happen by mistake, and be missed altogether.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since each colour is defined as a Constant, it is safer to compose the Regular Expression using each one. This is done the same way I explained earlier, by using a backslash &lt;code&gt;\&lt;/code&gt; to reference each constant.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lets make the regular expression a constant also&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nv"&gt;constant&lt;/span&gt; &lt;span class="s"&gt;COLORS_REGEXP&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="sx"&gt;qr/^(
    ${\BLUE}  |
    ${\GREEN} |
    ${\RED}
)$/&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;To make the Regular Expression easier to read, I've used the &lt;code&gt;x&lt;/code&gt; option. This option allows the Regular Expression to be written on new lines, and white spaces are ignored also.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally lets replace the Regular Expression &lt;code&gt;$colors_regexp&lt;/code&gt; with the &lt;code&gt;COLORS_REGEXP&lt;/code&gt; constant.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="k"&gt;my&lt;/span&gt;  &lt;span class="nv"&gt;@colors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;qw(blue yellow orange red)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;say&lt;/span&gt; &lt;span class="vg"&gt;$_&lt;/span&gt; &lt;span class="o"&gt;=~&lt;/span&gt; &lt;span class="nv"&gt;COLORS_REGEXP&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$_&lt;/span&gt;&lt;span class="s2"&gt; is valid&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$_&lt;/span&gt;&lt;span class="s2"&gt; is invalid&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt; &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="nv"&gt;@colors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;blue is valid
yellow is invalid
orange is invalid
red is valid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;String Interpolation using Constants in Perl 5 works the same as for scalars and lists, with the exception of using a backslash &lt;code&gt;\&lt;/code&gt; to reference the them. In Perl 6 however, you can just write &lt;code&gt;say "${ constant_name }"&lt;/code&gt; and that's it! Perl also has the &lt;a href="https://perldoc.perl.org/functions/sprintf.html" rel="noopener noreferrer"&gt;sprintf&lt;/a&gt; function, which allows formatting of variables embedded within strings.&lt;/p&gt;

&lt;p&gt;Thank you for reading, and the code used in this post is available on &lt;a href="https://gist.github.com/kirklewis/f2b9987cb330e7b702d1e8ed46f86a22#file-perl5-string-interpolation-pl" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>perl5</category>
      <category>interpolation</category>
      <category>constants</category>
    </item>
  </channel>
</rss>
