<?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>Forem: Peter Nguyen</title>
    <description>The latest articles on Forem by Peter Nguyen (@pnvnd).</description>
    <link>https://forem.com/pnvnd</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%2F1037380%2F6ce30aa9-7e13-4462-87d9-21112d2c2a21.jpeg</url>
      <title>Forem: Peter Nguyen</title>
      <link>https://forem.com/pnvnd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pnvnd"/>
    <language>en</language>
    <item>
      <title>Visualize Tailscale Network Flow Logs with New Relic</title>
      <dc:creator>Peter Nguyen</dc:creator>
      <pubDate>Sun, 26 Oct 2025 18:06:35 +0000</pubDate>
      <link>https://forem.com/pnvnd/visualize-tailscale-network-flow-logs-with-new-relic-1mfg</link>
      <guid>https://forem.com/pnvnd/visualize-tailscale-network-flow-logs-with-new-relic-1mfg</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Did you know that Tailscale network flow logs can be visualized in New Relic? Take a look at my dashboard:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1o2bo187xkc5ggr3213.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1o2bo187xkc5ggr3213.png" alt="Tailscale Dashboard in New Relic" width="800" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Technical Details
&lt;/h1&gt;

&lt;p&gt;To get started, you'll need to have Tailscale Enterprise, as this is the only option that lets you stream network flow logs.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqi1uzh9le1axixbc5fnl.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqi1uzh9le1axixbc5fnl.png" alt="Tailscale Tiers" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While this is not &lt;em&gt;officially&lt;/em&gt; supported (yet), network flow logs from Tailscale &lt;em&gt;can&lt;/em&gt; be streamed to New Relic. The only thing you need is the log endpoint &lt;code&gt;https://log-api.newrelic.com/log/v1&lt;/code&gt; and your New Relic Ingest license key (ending with &lt;code&gt;NRAL&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;At a first glace, most people wouldn't know it can be done, thanks to the Tailscale admin dashboard only showing a few vendors to stream to:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F09sjm6hjogrjy04sfbrv.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F09sjm6hjogrjy04sfbrv.png" alt="Tailscale Network Flow Log streaming options" width="707" height="813"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since we only require the log endpoint and the license key, I tried using these two parametes with each of the vendors to see what actually gets the log data into New Relic.&lt;/p&gt;

&lt;p&gt;At the time of writing this, there are 7 supported stream options and results from my testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌AWS S3&lt;/li&gt;
&lt;li&gt;✅Axiom&lt;/li&gt;
&lt;li&gt;🟡Cribl&lt;/li&gt;
&lt;li&gt;❌Datadog&lt;/li&gt;
&lt;li&gt;❌Elasticsearch&lt;/li&gt;
&lt;li&gt;🟡Panther&lt;/li&gt;
&lt;li&gt;❌Splunk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ - Streaming Fails or additional parameters required&lt;br&gt;
🟡 - Works, but not optimal for New Relic&lt;br&gt;
✅ - Works, and optimal for New Relic&lt;/p&gt;
&lt;h2&gt;
  
  
  AWS S3
&lt;/h2&gt;

&lt;p&gt;This option requires AWS credentials such as access key id and secret access key. So, this option won't work to stream data into New Relic. One option, however, is to stream this into AWS S3, then forward the S3 logs into New Relic (inefficient).&lt;/p&gt;
&lt;h2&gt;
  
  
  Axiom
&lt;/h2&gt;

&lt;p&gt;Axiom was the only option that streamed the network flow logs in near "real-time", with attributes trimmed. Let me explain:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyi0nk8g9h04av7tu9ut.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyi0nk8g9h04av7tu9ut.png" alt="Tailscale network flow logs using Axiom option" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The data for the Network Flow Lows using the Axiom option is streamed almost in real-time, rather than being sent at 1-minute intervals (Cribl and Panther options).&lt;/p&gt;

&lt;p&gt;Since network flow logs can get heavy, you'll want to optimize the data ingest for this. If you look at the screenshot, the attributes are not prefixed with &lt;code&gt;event.&lt;/code&gt; compared to the other two options that work. As you can imagine, for high log volumes, having the extra &lt;code&gt;event.&lt;/code&gt; prefix can add up to excessive data ingestion with little value.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cribl
&lt;/h2&gt;

&lt;p&gt;This option works. Both configuration and network flow logs are sent to New Relic without issue. The only drawback here is the additional &lt;code&gt;event.&lt;/code&gt; prefix in the attributes, which can quickly add up to data ingest. Another thing to note is the Network Flow Logs are sent once a minute.&lt;/p&gt;
&lt;h2&gt;
  
  
  Datadog
&lt;/h2&gt;

&lt;p&gt;This option doesn't send any logs to New Relic.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidupfu4zq4awwyuqs36w.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fidupfu4zq4awwyuqs36w.png" alt="Tailscale log streaming with Datadog" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Elastic Search
&lt;/h2&gt;

&lt;p&gt;This option has an additional &lt;code&gt;Username&lt;/code&gt; option that is required. Using a random username won't send any logs to New Relic.&lt;/p&gt;
&lt;h2&gt;
  
  
  Panther
&lt;/h2&gt;

&lt;p&gt;This option works. Both configuration and network flow logs are sent to New Relic without issue. The only drawback here is the additional &lt;code&gt;event.&lt;/code&gt; prefix in the attributes, which can quickly add up to data ingest. Another thing to note is the Network Flow Logs are sent once a minute.&lt;/p&gt;
&lt;h2&gt;
  
  
  Splunk
&lt;/h2&gt;

&lt;p&gt;This option doesn't send any logs to New Relic.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frob18tg8obbuyef8hs6o.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frob18tg8obbuyef8hs6o.png" alt="Tailscale log streaming with Splunk" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Tailscale Logs in New Relic
&lt;/h1&gt;

&lt;p&gt;Once log streaming for both Configuration and Network Flow Logs are enabled, the logs look something like this:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F42f5qxoot7ewpwxdtecx.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F42f5qxoot7ewpwxdtecx.png" alt="Tailscale Configuration Logs in New Relic" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is what this looks like on the Tailscale Admin console:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F445umya516nf9cl2clbz.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F445umya516nf9cl2clbz.png" alt="Tailscale Configuration Logs in Admin console" width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's what I did to create my Tailscale Dashboard.&lt;/p&gt;
&lt;h2&gt;
  
  
  Network Flow Log Visualization
&lt;/h2&gt;

&lt;p&gt;Utilizing the Sankey Diagram visualization I created with Plotly in my &lt;a href="https://dev.to/pnvnd/plotly-charts-in-new-relic-22c1"&gt;previous post&lt;/a&gt;, I used the following NRQL query to generate widget:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;aparse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;`physicalTraffic`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'[{"src":"*","dst":"*","txPkts":*,"txBytes":*,"rxPkts":*,"rxBytes":*}]'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;txPkts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;txBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;rxPkts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;rxBytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;count&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="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;`physicalTraffic`&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="n"&gt;FACET&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dst&lt;/span&gt;
&lt;span class="n"&gt;SINCE&lt;/span&gt; &lt;span class="mi"&gt;72&lt;/span&gt; &lt;span class="n"&gt;HOURS&lt;/span&gt; &lt;span class="n"&gt;AGO&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="k"&gt;MAX&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This query parses the log data and generates a Sankey Diagram showing all of the physical traffic in Tailscale.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ws6lhszzpfg5chytkgu.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ws6lhszzpfg5chytkgu.png" alt="Sankey Diagram of Tailscale Network Flow Logs" width="800" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Network Flow Traffic
&lt;/h2&gt;

&lt;p&gt;You can also add a line chart to visualize the transmit/received bytes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;aparse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;`physicalTraffic`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'[{"src":"*","dst":"*","txPkts":*,"txBytes":*,"rxPkts":*,"rxBytes":*}]'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;txPkts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;txBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;rxPkts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;rxBytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="n"&gt;average&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;txBytes&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'Transmit Bytes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;average&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rxBytes&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'Received Bytes'&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Log&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;`physicalTraffic`&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="n"&gt;TIMESERIES&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt; &lt;span class="n"&gt;SECONDS&lt;/span&gt;
&lt;span class="n"&gt;SINCE&lt;/span&gt; &lt;span class="s1"&gt;'12:45-0400'&lt;/span&gt; &lt;span class="k"&gt;UNTIL&lt;/span&gt; &lt;span class="s1"&gt;'13:15-0400'&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="k"&gt;MAX&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvflpr96leey4xmyy25ce.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvflpr96leey4xmyy25ce.png" alt="Tailscale Network Flow Bytes in New Relic" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Network Flow Raw Data
&lt;/h2&gt;

&lt;p&gt;Since the data is streaming as-in to New Relic, we can use anchor parsing to make the data look clean in a table like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;aparse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;`physicalTraffic`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'[{"src":"*","dst":"*","txPkts":*,"txBytes":*,"rxPkts":*,"rxBytes":*}]'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;dst&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;txPkts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;txBytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;rxPkts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;rxBytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
&lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'Source IP'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;dst&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'Destination IP'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;txPkts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'txPkts'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;txBytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'txBytes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rxPkts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'rxPkts'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rxBytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'rxBytes'&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;`physicalTraffic`&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;rxBytes&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="n"&gt;SINCE&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="n"&gt;HOUR&lt;/span&gt; &lt;span class="n"&gt;AGO&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="k"&gt;MAX&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdj9g09hucrejr5pvnj7.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frdj9g09hucrejr5pvnj7.png" alt="Tailscale Network Flow Logs Cleaned Data" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Log Visualization
&lt;/h2&gt;

&lt;p&gt;Here's another useful visualization to see Configuration Changes at a quick glance:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fax63kt9i61dwxna1iixj.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fax63kt9i61dwxna1iixj.png" alt="Tailscale Configuration Change Logs in New Relic Pie Chart" width="430" height="328"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;count&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="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'Event Actions'&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Log&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;`target.type`&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="n"&gt;FACET&lt;/span&gt; &lt;span class="nv"&gt;`action`&lt;/span&gt;
&lt;span class="n"&gt;SINCE&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="n"&gt;HOURS&lt;/span&gt; &lt;span class="n"&gt;AGO&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="k"&gt;MAX&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for the actual data in a tabular format:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7q1y84jstctd5mn46of.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7q1y84jstctd5mn46of.png" alt="Tailscale Configuration Change Logs in New Relic Table" width="734" height="309"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="nv"&gt;`action`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;`actor.displayName`&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'Name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;`target.name`&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="s1"&gt;'Target'&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;Log&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;`target.type`&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="n"&gt;SINCE&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="n"&gt;HOURS&lt;/span&gt; &lt;span class="n"&gt;AGO&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="k"&gt;MAX&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Remarks
&lt;/h1&gt;

&lt;p&gt;Overall, streaming both the configuration logs and network flow logs from Tailscale to New Relic was easy. In my scenario, I used the Axiom option. It would be nice if Tailscale had a New Relic option, or at least an "Other" option to add a generic URL and generic header to accommodate other vendors.&lt;/p&gt;

</description>
      <category>newrelic</category>
      <category>tailscale</category>
      <category>networkflow</category>
      <category>logs</category>
    </item>
    <item>
      <title>Monitor R Applications with an OpenTelemetry Collector</title>
      <dc:creator>Peter Nguyen</dc:creator>
      <pubDate>Thu, 26 Sep 2024 01:36:53 +0000</pubDate>
      <link>https://forem.com/pnvnd/monitor-r-applications-with-an-opentelemetry-collector-bnl</link>
      <guid>https://forem.com/pnvnd/monitor-r-applications-with-an-opentelemetry-collector-bnl</guid>
      <description>&lt;h2&gt;
  
  
  R - Plumber Monitoring
&lt;/h2&gt;

&lt;p&gt;I didn't find any OpenTelemetry packages for R, so for this to work, I've made use of the &lt;a href="https://cran.r-project.org/web/packages/openmetrics/index.html" rel="noopener noreferrer"&gt;openmetrics&lt;/a&gt; package that is essentially a Prometheus client for R using the &lt;a href="https://openmetrics.io/" rel="noopener noreferrer"&gt;OpenMetrics&lt;/a&gt; format.&lt;/p&gt;

&lt;p&gt;Since we are dealing with Prometheus, I've also made use of the &lt;a href="https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/receiver/prometheusreceiver" rel="noopener noreferrer"&gt;OpenTelemetry Contrib Collector&lt;/a&gt;, which has a Prometheus receiver built-in.  Note, the base OpenTelemetry Collector does &lt;em&gt;not&lt;/em&gt; have a Prometheus receiver built-in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequsites
&lt;/h3&gt;

&lt;p&gt;\1. Download and install R.&lt;/p&gt;

&lt;p&gt;\2. For Windows: Add this to a &lt;code&gt;Path&lt;/code&gt; environment variable (change version as needed)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\Program Files\R\R-4.3.0\bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;\3. Launch &lt;code&gt;R.exe&lt;/code&gt; or &lt;code&gt;R.app&lt;/code&gt; and install the following packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;install.packages("openmetrics")
install.packages("plumber")
install.packages("httr")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;\4. Download &lt;a href="https://github.com/open-telemetry/opentelemetry-collector-releases/releases" rel="noopener noreferrer"&gt;&lt;code&gt;otelcol-contrib&lt;/code&gt;&lt;/a&gt; and extract somewhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  Plumber
&lt;/h3&gt;

&lt;p&gt;Before starting, save these files, as we'll be using them as an example.&lt;br&gt;
&lt;code&gt;plumber.R&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="c1"&gt;# plumber.R&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;#* Echo back the input&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;#* @param msg The message to echo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;#* @get /echo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;paste0&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"The message is: '"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"'"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;#* Plot a histogram&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;#* @serializer png&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;#* @get /plot&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rnorm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;hist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;#* Return the sum of two numbers&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;#* @param a The first number to add&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;#* @param b The second number to add&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;#* @post /sum&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nf"&gt;as.numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;as.numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c1"&gt;#* Return the n-th Fibonacci number&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;#* @param n The n-th Fibonacci number&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;#* @get /fibonacci&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;fibonacci&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nf"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nf"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nf"&gt;return&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;as.numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="m"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;as.numeric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="m"&gt;-2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;plumberSrv.R&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight r"&gt;&lt;code&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;openmetrics&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;register_default_metrics&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;srv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;plumber&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;plumb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"plumber.R"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;srv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;register_plumber_metrics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;srv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;srv&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;c&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;\1. Run this in a terminal to start the Plumber server.  You may need to allow this app over the firewall.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RScript plumberSrv.R
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fldzrifidrjlgjmnq13al.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fldzrifidrjlgjmnq13al.png" alt="Windows Firewall Dialog"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;\2. Go to &lt;a href="http://127.0.0.1:8000/__docs__/" rel="noopener noreferrer"&gt;http://127.0.0.1:8000/__docs__/&lt;/a&gt; to generate some traffic.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgtqbq7nagt7pcv908ma3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgtqbq7nagt7pcv908ma3.png" alt="Swagger Documentation for Plumber App"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;\3. Go to &lt;a href="http://localhost:8000/metrics" rel="noopener noreferrer"&gt;http://localhost:8000/metrics&lt;/a&gt; to see the following metrics.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;metric name&lt;/th&gt;
&lt;th&gt;metric type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;process_cpu_seconds_total&lt;/td&gt;
&lt;td&gt;counter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;process_cpu_seconds_total_created&lt;/td&gt;
&lt;td&gt;gauge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;http_request_total&lt;/td&gt;
&lt;td&gt;counter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;http_request_total_created&lt;/td&gt;
&lt;td&gt;gauge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;http_request_duration_seconds&lt;/td&gt;
&lt;td&gt;histogram&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;http_request_duration_seconds_created&lt;/td&gt;
&lt;td&gt;gauge&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;\4. Save this YML file as &lt;code&gt;otel-config_r-plumber.yml&lt;/code&gt;. Since I'll be visualizing this data in New Relic, I've used an OTLP endpoint from New Relic, as well as an &lt;code&gt;Ingest License Key&lt;/code&gt; to send these metrics to New Relic.&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;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;prometheus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;scrape_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;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;my-plumber-api'&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;5s&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:8000'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;metricstransform/plumber&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;transforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http_request_duration_seconds&lt;/span&gt;
      &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;update&lt;/span&gt;
      &lt;span class="na"&gt;new_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http.server.duration&lt;/span&gt;
      &lt;span class="na"&gt;operations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;experimental_scale_value&lt;/span&gt;
          &lt;span class="na"&gt;experimental_scale&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;update_label&lt;/span&gt;
          &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;path&lt;/span&gt;
          &lt;span class="na"&gt;new_label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http.target&lt;/span&gt;

  &lt;span class="na"&gt;attributes/plumber&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service.instance.id&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;insert&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;localhost-osx&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tags.team&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;insert&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;datacrunch&lt;/span&gt;

&lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://otlp.nr-data.net:4317&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;api-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${NEW_RELIC_LICENSE_KEY}&lt;/span&gt;

&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metrics&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;prometheus&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;metricstransform/plumber&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;attributes/plumber&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;\5. Run the &lt;a href="https://github.com/open-telemetry/opentelemetry-collector/releases" rel="noopener noreferrer"&gt;OpenTelemetry Contrib Collector&lt;/a&gt; with the &lt;code&gt;otel-config_r-plumber.yaml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./otelcol-contrib.exe --config=file:'./otel-config_r-plumber.yml'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4987nt8gxonltncg2j3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4987nt8gxonltncg2j3.png" alt="Running OpenTelemetry Collector Manually"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  New Relic Example
&lt;/h2&gt;

&lt;p&gt;Go to APM &amp;amp; Services &amp;gt; OpenTelemetry to see the Plumber entity.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczuy0o318adop9b4ubxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczuy0o318adop9b4ubxd.png" alt="Plumber Service in New Relic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check the Summary &amp;gt; Metrics page to see basic information&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frie6dv7ibkb4pqtpnu5u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frie6dv7ibkb4pqtpnu5u.png" alt="Plumber Service Summary in New Relic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;code&gt;Transactions&lt;/code&gt; on the left to see additional metrics.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjjaaj89f82503inhgxas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjjaaj89f82503inhgxas.png" alt="Plumber Service Transactions in New Relic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, go to the &lt;code&gt;Metrics Explorer&lt;/code&gt; to see everything else.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7064lixs1ykjnjsoqmx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7064lixs1ykjnjsoqmx.png" alt="Plumber Metrics in New Relic"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Remarks
&lt;/h2&gt;

&lt;p&gt;Using a similar methodology, I was able to repeat this for Shiny applications running with R, as well as batch jobs running in R. Check out these examples here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/pnvnd/otel-config-examples/tree/main/r-plumber" rel="noopener noreferrer"&gt;https://github.com/pnvnd/otel-config-examples/tree/main/r-plumber&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pnvnd/otel-config-examples/tree/main/r-shiny" rel="noopener noreferrer"&gt;https://github.com/pnvnd/otel-config-examples/tree/main/r-shiny&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pnvnd/otel-config-examples/tree/main/r-batch" rel="noopener noreferrer"&gt;https://github.com/pnvnd/otel-config-examples/tree/main/r-batch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opentelemetry</category>
      <category>newrelic</category>
      <category>r</category>
      <category>prometheus</category>
    </item>
    <item>
      <title>Plotly Charts in New Relic</title>
      <dc:creator>Peter Nguyen</dc:creator>
      <pubDate>Fri, 13 Sep 2024 15:09:47 +0000</pubDate>
      <link>https://forem.com/pnvnd/plotly-charts-in-new-relic-22c1</link>
      <guid>https://forem.com/pnvnd/plotly-charts-in-new-relic-22c1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;New Relic comes with several chart types you can use on a dashboard, line, stacked bar, pie, histogram, heatmap, just to name a few. However, I needed a "grouped bar chart" and there was no option for this. Luckily, New Relic has a programmability platform that lets you create custom visualizations.&lt;/p&gt;

&lt;p&gt;Here's a link to my GitHub repository with the grouped bar charted created with Plotly: &lt;a href="https://github.com/pnvnd/nr1-custom-visualizations" rel="noopener noreferrer"&gt;https://github.com/pnvnd/nr1-custom-visualizations&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;This first example groups the data by application name, then country code as seen in the &lt;code&gt;FACET&lt;/code&gt; clause.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqsylchrcxbsqitw5got.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flqsylchrcxbsqitw5got.png" alt="Grouped Bar Chart with 2 FACET" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This second example groups the data by country code, then application name:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi41kr26wwmxjqh17dcwl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi41kr26wwmxjqh17dcwl.png" alt="Grouped Bar Chart with 2 FACET reversed" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  General Instructions
&lt;/h2&gt;

&lt;p&gt;You'll need &lt;code&gt;git&lt;/code&gt;, &lt;code&gt;npm&lt;/code&gt;, and &lt;a href="https://github.com/pnvnd/nr1-custom-visualizations?tab=readme-ov-file#setup-nr1-cli" rel="noopener noreferrer"&gt;&lt;code&gt;nr1&lt;/code&gt;&lt;/a&gt; to get started. Check to make sure everything is installed correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nt"&gt;--version&lt;/span&gt;
npm &lt;span class="nt"&gt;-v&lt;/span&gt;
nr1 version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, clone the repository, install npm packages, and publish the nerdpack.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/pnvnd/nr1-custom-visualizations.git
&lt;span class="nb"&gt;cd &lt;/span&gt;nr1-custom-visualizations
npm &lt;span class="nb"&gt;install
&lt;/span&gt;nr1 nerdpack:uuid &lt;span class="nt"&gt;--generate&lt;/span&gt; &lt;span class="nt"&gt;--force&lt;/span&gt;
nr1 nerdpack:publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the New Relic console, go to Apps &amp;gt; Go to Apps and Visualizations&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabs9lr0d15ffcgp6k1u6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabs9lr0d15ffcgp6k1u6.png" alt="Apps and Visualizations" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Search for the nerdpack, in this case &lt;code&gt;Custom Visualizations&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfdp2xpwkx2mcommvfgg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfdp2xpwkx2mcommvfgg.png" alt="Custom Visualization Nerdpack" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;Add this app&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpwq95r19b4wszeiu7ok6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpwq95r19b4wszeiu7ok6.png" alt="Add this app" width="800" height="717"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select accounts that should have access to this Nerdpack and click &lt;code&gt;Update&lt;/code&gt; on the top right.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3svyt385as3qpbmph42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg3svyt385as3qpbmph42.png" alt="Subscribe account to Nerdpack" width="800" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go back to Apps &amp;gt; Custom Visualizations&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fertwbkuwoy9sz3b3utby.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fertwbkuwoy9sz3b3utby.png" alt="Custom Visualizations" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the &lt;code&gt;Grouped Bar Chart&lt;/code&gt; to start using the Plotly chart&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp1pu6prfk7n5vobb2wor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp1pu6prfk7n5vobb2wor.png" alt="Plotly Grouped Bar Chart" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This particular grouped bar chart must have two &lt;code&gt;FACET&lt;/code&gt; items. Here's an example:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famjat0l681nr7eyyogdv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famjat0l681nr7eyyogdv.png" alt="Grouped Bar Chart Example" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you are satisfied with your query, you can add this to a dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu1z0pr4ldbmeqlxskpdf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu1z0pr4ldbmeqlxskpdf.png" alt="Grouped Bar Chart on Dashboard" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Remarks
&lt;/h2&gt;

&lt;p&gt;I've previously built a similar grouped bar chart with Recharts (simple bar chart) and here is the side-by-side comparison of what it looks like on a New Relic dashboard.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgla2eqstg14bkxk7uo2r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgla2eqstg14bkxk7uo2r.png" alt="Plotly vs Recharts" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Plotly charts are interactive where you can zoom in and out, and save a screenshot of the chart.&lt;/p&gt;

</description>
      <category>plotly</category>
      <category>newrelic</category>
      <category>programmability</category>
      <category>react</category>
    </item>
    <item>
      <title>Send incident.io Status to New Relic with Synthetics</title>
      <dc:creator>Peter Nguyen</dc:creator>
      <pubDate>Fri, 06 Sep 2024 22:07:28 +0000</pubDate>
      <link>https://forem.com/pnvnd/send-incidentio-status-to-new-relic-with-synthetics-590f</link>
      <guid>https://forem.com/pnvnd/send-incidentio-status-to-new-relic-with-synthetics-590f</guid>
      <description>&lt;p&gt;Here's a quick way to monitor a status page hosted by &lt;a href="https://incident.io/" rel="noopener noreferrer"&gt;incident.io&lt;/a&gt; with New Relic. Specifically, I'll be using Synthetic monitoring to achieve this with a Scripted API test.&lt;/p&gt;

&lt;p&gt;After digging a bit, it looks like data from a typical public status page hosted by &lt;a href="https://incident.io/" rel="noopener noreferrer"&gt;incident.io&lt;/a&gt; is in this format:  &lt;a href="https://status.incident.io/proxy/statuspage-name" rel="noopener noreferrer"&gt;https://status.incident.io/proxy/statuspage-name&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you go to this page, you'll get something that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcefhef4cak4ltxdaldq7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcefhef4cak4ltxdaldq7.png" alt="Typical incident.io JSON payload" width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since this is structured JSON data, we can format this and ingest this data as an event in New Relic. Here's the full script&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sgcr0l510f6vbwfunce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sgcr0l510f6vbwfunce.png" alt="Synthetic script to send incident.io data to New Relic" width="800" height="664"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also find this here:&lt;br&gt;
&lt;a href="https://github.com/pnvnd/nodejs-synthetics/blob/main/scripted_api/incidentio.js" rel="noopener noreferrer"&gt;https://github.com/pnvnd/nodejs-synthetics/blob/main/scripted_api/incidentio.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or check it out here:&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;got&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;got&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;statuspage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-statuspage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;account_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$secure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ACCOUNT_ID&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ingest_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;$secure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INGEST_KEY&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getStatusPage&lt;/span&gt;&lt;span class="p"&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://status.incident.io/proxy/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;statuspage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;got&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a map for quick lookup of affected components by component_id&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;affectedComponentsMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;affected&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;affected_components&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;affectedComponentsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;affected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;component_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;affected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Update components with status if they are affected&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eventType&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;IncidentIOSample&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;statuspage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;statuspage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;affectedComponentsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;operational&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;got&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://insights-collector.newrelic.com/v1/accounts/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/events`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Api-Key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;ingest_key&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;json&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&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="nf"&gt;getStatusPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Validate the script is working in New Relic then click Save.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrhflcxkxpz0igquw4mz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrhflcxkxpz0igquw4mz.png" alt="Validate the JSON payload from the script" width="800" height="900"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let the synthetic monitor run for a bit and check the data. Using NRQL, you can query your data with something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;IncidentIOSample&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fql8k580n92trafgbp2jx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fql8k580n92trafgbp2jx.png" alt="NRQL query to see incident.io data" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another way of looking at this data is to view by component name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;IncidentIOSample&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;statuspage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'my-statuspage'&lt;/span&gt;
&lt;span class="n"&gt;FACET&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fie5yt5l7tm40yudt5sbb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fie5yt5l7tm40yudt5sbb.png" alt="NRQL query to get the latest staus of each component" width="800" height="639"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you have this data in New Relic, you can create alerts and stay on top of incidents hosted by public &lt;a href="//incident.io"&gt;incident.io&lt;/a&gt; status pages.&lt;/p&gt;

</description>
      <category>synthetics</category>
      <category>statuspage</category>
      <category>newrelic</category>
      <category>incidentio</category>
    </item>
    <item>
      <title>Monitoring Jenkins pipelines using OpenTelemetry and New Relic</title>
      <dc:creator>Peter Nguyen</dc:creator>
      <pubDate>Mon, 20 Mar 2023 19:01:00 +0000</pubDate>
      <link>https://forem.com/newrelic/monitoring-jenkins-pipelines-using-opentelemetry-and-new-relic-859</link>
      <guid>https://forem.com/newrelic/monitoring-jenkins-pipelines-using-opentelemetry-and-new-relic-859</guid>
      <description>&lt;h2&gt;
  
  
  Shift left by monitoring your continuous integration and continuous deployment pipelines for errors.
&lt;/h2&gt;

&lt;p&gt;Jenkins is a popular open-source automation tool for implementing continuous integration (CI) and continuous development (CD) workflows called pipelines. Continuous integration and continuous deployment are development practices that can help you deploy your applications faster—and with fewer bugs.  But if errors or other issues come up in your pipelines, it can negatively impact deployment and other steps in the DevOps lifecycle. That's why it’s important to monitor not just your applications but also the automation processes around development, including your CI and CD tools. This can help you shift left, which means incorporating more testing on the left side of the DevOps lifecycle, as shown in the next image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj4ga9lvu1ihyem514cw7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj4ga9lvu1ihyem514cw7.png" alt="Dev Ops diagram shows an infinity symbol with Dev on the left (planning and building) and Ops on the right (deployment and operations)." width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Shifting left isn't just about testing your code and automating the build and deployment process. It's about monitoring and testing your CI and CD pipelines, too.&lt;/p&gt;

&lt;p&gt;In this post, you’ll learn how to monitor your Jenkins jobs and pipelines using the Jenkins OpenTelemetry plugin and a New Relic quickstart integration. After you are finished, you'll be able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visualize key metrics on your Jenkins pipelines, such as how long your jobs are taking and error rates.&lt;/li&gt;
&lt;li&gt;Use distributed tracing to pinpoint where issues are coming from in your pipelines.&lt;/li&gt;
&lt;li&gt;Create alerts on your Jenkins pipelines.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next image shows a New Relic dashboard with some of the Jenkins metrics you’ll be able to visualize.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzen57mbjqnqrpbgwf2hi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzen57mbjqnqrpbgwf2hi.png" alt="New Relic dashboard shows Jenkins metrics such as length of time for jobs, error rate, and whether they succeeded or failed." width="800" height="416"&gt;&lt;/a&gt;&lt;br&gt;Install the Jenkins quickstart dashboard for a pre-built view of your key pipeline metrics.
    &lt;/p&gt;

&lt;p&gt;With this integration, you can shift left and get observability for the build and deploy phases of the DevOps lifecycle. Check out the next video or continue reading to get started.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ZCF75LTtdz0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;If you don’t have Jenkins yet, you need to install it. Alternatively, you can use Docker to follow along with this example.  If you’re using Docker, you can get an instance of Jenkins up and running with the following command: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker run --name jenkinsci -d -e OTEL_LOGS_EXPORTER="otlp" -p 8080:8080 jenkins/jenkins:lts&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the OpenTelemetry plugin
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Log into Jenkins (usually &lt;code&gt;http://localhost:8080&lt;/code&gt;) and log in with your username and password.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From the Jenkins dashboard, select &lt;strong&gt;Manage Jenkins&lt;/strong&gt; from the lefthand pane.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select &lt;strong&gt;Manage Plugins&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsq66947djx2pq2n4bnv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsq66947djx2pq2n4bnv.png" alt="Manage Jenkins page with Manage Jenkins selected in the lefthand pane." width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the &lt;strong&gt;Available&lt;/strong&gt; tab and type &lt;code&gt;OpenTelemetry&lt;/code&gt; in the search bar.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffp5afle1vw64m28u3281.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffp5afle1vw64m28u3281.png" alt="OpenTelemetry option comes up when typing OpenTelemetry in search bar." width="800" height="193"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the &lt;strong&gt;OpenTelemetry&lt;/strong&gt; checkbox and choose &lt;strong&gt;Install without restart&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyuh95a5fzym1c1xj0xwi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyuh95a5fzym1c1xj0xwi.png" alt="Plugin Manager in Jenkins" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After the installation is complete, select &lt;strong&gt;Restart Jenkins when installation is complete and no jobs are running&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1h70htzv7xhfy0zsntd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1h70htzv7xhfy0zsntd.png" alt="Installing Plugins/Upgrades page in Jenkins" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Log into Jenkins again and select &lt;strong&gt;Manage Jenkins&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Under &lt;strong&gt;System Configuration&lt;/strong&gt;, select &lt;strong&gt;Configure System&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8k0fht5b0k1c0tfegh0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8k0fht5b0k1c0tfegh0.png" alt="Manage Jenkins dashboard in Jenkins has Configure System selected." width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Scroll down to the OpenTelemetry section and change the following settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OTLP Endpoint should be &lt;code&gt;https://otlp.nr-data.net:4317&lt;/code&gt;.
&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyrerhshb1syaspnvxnv5.png" alt="OTLP endpoint entered in text field" width="800" height="273"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication&lt;/strong&gt; should be &lt;strong&gt;Header Authentication&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Header Name&lt;/strong&gt; should be &lt;code&gt;api-key&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For the &lt;strong&gt;Header Value&lt;/strong&gt;, select &lt;strong&gt;Add&lt;/strong&gt; &amp;gt; &lt;strong&gt;Jenkins&lt;/strong&gt;. You’ll need to create a secret text with the following fields:

&lt;ul&gt;
&lt;li&gt;For &lt;strong&gt;Kind&lt;/strong&gt;, choose &lt;strong&gt;Secret text&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Secret&lt;/strong&gt; should be your &lt;a href="https://docs.newrelic.com/docs/apis/intro-apis/new-relic-api-keys/#overview-keys?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=global-fy23-q4-monitoring_jenkins_pipelines" rel="noopener noreferrer"&gt;New Relic license ingest key&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;ID can be left blank.&lt;/li&gt;
&lt;li&gt;Add a description such as &lt;code&gt;New Relic INGEST - LICENSE key&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Add&lt;/strong&gt;.
&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fizmvkh7do08ydrr0rfg6.png" alt="Jenkins Credentials Provider Add Credentials screen." width="800" height="971"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After you’ve added your credentials, you’ll be able to select &lt;strong&gt;New Relic INGEST - LICENSE Key&lt;/strong&gt; from the Header Value dropdown menu.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select &lt;strong&gt;Save&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff57fp4gqclddxdg0e3d6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff57fp4gqclddxdg0e3d6.png" alt="New Relic INGEST - LICENSE Key selected from Header Value drop down in OpenTelemetry menu." width="800" height="682"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Sending Jenkins data to New Relic
&lt;/h2&gt;

&lt;p&gt;After you’ve set up your New Relic credentials in Jenkins, you’re ready to send data to New Relic. Let’s start by setting up a test pipeline that will automatically fail. By testing a pipeline, you’re making sure that the connection to New Relic is set up properly. You can set up a test pipeline with the following steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In the Jenkins dashboard, select &lt;strong&gt;New Item&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ukmfr3sak1aff60j5ds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ukmfr3sak1aff60j5ds.png" alt="New Item selected in Jenkins dashboard." width="498" height="599"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Enter an item name (the name in this example is test) and select &lt;strong&gt;Pipeline&lt;/strong&gt;. Then select &lt;strong&gt;OK&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9529a7fsffh3539htl7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg9529a7fsffh3539htl7.png" alt="Pipeline selected from Enter an item name list." width="800" height="1197"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scroll to the bottom, select &lt;strong&gt;Scripted Pipeline&lt;/strong&gt;, and then select &lt;strong&gt;Save&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff380kcfagkd8zxlx1d93.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff380kcfagkd8zxlx1d93.png" alt="Pipeline script selected." width="800" height="596"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some older versions of Jenkins don’t have sample pipelines that you can choose from the list. If this is the case for you, paste in the following script and select &lt;strong&gt;Save&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        git 'https://github.com/jglick/simple-maven-project-with-tests.git'
        sh "mvn -Dmaven.test.failure.ignore=true clean package"
      }
      post {
        success {
          echo "success"
        }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Select &lt;strong&gt;Build Now&lt;/strong&gt;. This sample pipeline should fail, which is the expected behavior.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6rjp8dn0yssutnlejwer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6rjp8dn0yssutnlejwer.png" alt="Pipeline test with Build Now option." width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Log into New Relic, go to &lt;strong&gt;Services - OpenTelemetry&lt;/strong&gt;, and select &lt;strong&gt;jenkins&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ef8rpxrdl1p4nar542e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ef8rpxrdl1p4nar542e.png" alt="Select jenkins from entity list in New Relic." width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now you can go to &lt;strong&gt;Transactions&lt;/strong&gt; to see your data. You should see all of the pipeline build steps, including both successes and failures. The next image shows a Jenkins dashboard in New Relic. It includes information on top transactions, top 20 transactions, and throughput.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F36tq91pdwykt5tau02ny.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F36tq91pdwykt5tau02ny.png" alt="New Relic dashboard shows Jenkins metrics such as top transactions." width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also go to &lt;strong&gt;Distributed Traces&lt;/strong&gt; to see data from your Jenkins pipeline.  In this example, you can see exactly where the pipeline starts failing, which is helpful for creating alerts. The next image shows a New Relic dashboard with specific spans in a Jenkins pipeline distributed trace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcud4ndlxg8bakswmv6tu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcud4ndlxg8bakswmv6tu.png" alt="New Relic dashboard shows distributed trace of Jenkins pipeline." width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’ve set the environment variable to &lt;code&gt;OTEL_LOGS_EXPORTER="otlp"&lt;/code&gt;, you can see your Jenkins console &lt;strong&gt;logs&lt;/strong&gt; in the Logs tab. The next image shows logs related to a Jenkins pipeline.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1t4hk4eb7aqmta9vut01.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1t4hk4eb7aqmta9vut01.png" alt="Jenkins pipeline logs in New Relic." width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Visualize your Jenkins data
&lt;/h2&gt;

&lt;p&gt;Once you have Jenkins data flowing into New Relic, you can add our quickstart dashboard to get an overview of your Jenkins environment. For example, you can see a summary of the number of Jenkins instances available, the number of successful jobs, the top errors, and the job queue status. To get this dashboard, simply follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to the &lt;a href="https://newrelic.com/instant-observability/jenkins?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=global-fy23-q4-monitoring_jenkins_pipelines" rel="noopener noreferrer"&gt;Jenkins quickstart&lt;/a&gt; in New Relic Instant Observability, and select &lt;strong&gt;Install now&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select an account and select &lt;strong&gt;Begin installation&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you've already completed the earlier steps in this tutorial, select &lt;strong&gt;Done&lt;/strong&gt; to move on to the next step.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The quickstart deploys the resources to your account. Select &lt;strong&gt;See your data&lt;/strong&gt; to get to the dashboard.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzen57mbjqnqrpbgwf2hi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzen57mbjqnqrpbgwf2hi.png" alt="New Relic dashboard shows Jenkins metrics such as length of time for jobs, error rate, and whether they succeeded or failed." width="800" height="416"&gt;&lt;/a&gt;&lt;br&gt;Install the Jenkins quickstart dashboard for a pre-built view of your key pipeline metrics.
  &lt;/p&gt;

&lt;p&gt;After you're done, you'll have complete visibility into your Jenkins pipelines, from high-level metrics to logs and distributed traces. You can also optionally choose to add alerts when certain thresholds are met, such as when jobs are taking too long or when the error rate gets too high. To do so, you can follow along with the docs to first &lt;a href="https://docs.newrelic.com/docs/alerts-applied-intelligence/new-relic-alerts/alert-policies/create-edit-or-find-alert-policy?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=global-fy23-q4-monitoring_jenkins_pipelines" rel="noopener noreferrer"&gt;create a policy&lt;/a&gt; and then &lt;a href="https://docs.newrelic.com/docs/alerts-applied-intelligence/new-relic-alerts/alert-conditions/create-alert-conditions?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=global-fy23-q4-monitoring_jenkins_pipelines" rel="noopener noreferrer"&gt;set conditions&lt;/a&gt; on that policy. You can &lt;a href="https://docs.newrelic.com/docs/alerts-applied-intelligence/new-relic-alerts/alert-notifications/notification-channels-control-where-send-alerts?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=global-fy23-q4-monitoring_jenkins_pipelines" rel="noopener noreferrer"&gt;send alerts&lt;/a&gt; to the notification channels of your choice. Options include Slack, PagerDuty, email, and more.&lt;/p&gt;

&lt;p&gt;Sending your Jenkins pipeline data to New Relic gives you observability into the building and deployment phases of the DevOps lifecycle, giving you more insights into your DevOps practices and helping you shift left.&lt;/p&gt;

&lt;p&gt;You can read the full blog post at New Relic &lt;a href="https://newrelic.com/blog/how-to-relic/monitoring-jenkins-pipelines?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=global-fy23-q4-monitoring_jenkins_pipelines" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>opentelemetry</category>
    </item>
  </channel>
</rss>
