<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mohammed Al-Nuaimi</title>
    <description>The latest articles on DEV Community by Mohammed Al-Nuaimi (@mohammedalnuaimi).</description>
    <link>https://dev.to/mohammedalnuaimi</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%2F700335%2F5b4ed619-7a7e-42a5-9f82-f31fc16638b9.png</url>
      <title>DEV Community: Mohammed Al-Nuaimi</title>
      <link>https://dev.to/mohammedalnuaimi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mohammedalnuaimi"/>
    <language>en</language>
    <item>
      <title>Instrument Newrelic for Lambda written in Typescript using Terraform</title>
      <dc:creator>Mohammed Al-Nuaimi</dc:creator>
      <pubDate>Fri, 17 Feb 2023 11:12:49 +0000</pubDate>
      <link>https://dev.to/mohammedalnuaimi/instrument-newrelic-for-lambda-written-in-typescript-using-terraform-20ca</link>
      <guid>https://dev.to/mohammedalnuaimi/instrument-newrelic-for-lambda-written-in-typescript-using-terraform-20ca</guid>
      <description>&lt;p&gt;I have picked up a task to setup some AWS Lambda alerts in &lt;code&gt;Newrelic&lt;/code&gt;, and quickly realised that to be able to get some data about Invocations and Errors it would require setting up a Newrelic Agent in Lambda, i.e. not only relying on the &lt;code&gt;Newrelic&lt;/code&gt; integration with AWS.&lt;/p&gt;

&lt;p&gt;Looking into the installation setup, I found that there are two ways to do it, the first way, which is now a legacy option, was to install &lt;code&gt;newrelic&lt;/code&gt; &lt;code&gt;npm&lt;/code&gt; package, then import it in the lambda and use a function called &lt;code&gt;setLambdaHandler()&lt;/code&gt; to wrap the whole lambda code, see example below.&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;newrelic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&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;newrelic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Other module loads go under the require statement above&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newrelic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setLambdaHandler&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;// This is your handler function code&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Lambda executed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above option caused me issues with testing, as the lambda is wrapped by Newrelic function and this requires it to instrument when running the unit test.&lt;/p&gt;

&lt;p&gt;The testing part was a painful experience as I had to mock Newrelic in Jest and it proved to be a complete waste of time. Mocking wasn't the issue, but Newrelic package hasn't provided interfaces that could easily be mocked, and to mock the whole Newrelic was not an option as it was wrapping the whole lambda code.&lt;/p&gt;

&lt;p&gt;Having said that, if we were to write custom events, then we still need to import &lt;code&gt;newrelic&lt;/code&gt;, but we won't need to wrap the whole function, we just need to inject a code in the place where we want to send a custom event data, like the following example:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;newrelic&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;newrelic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;//use the below function call wherever you want to send custom event&lt;/span&gt;
 &lt;span class="nx"&gt;newrelic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recordCustomEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DaznCustomEvent&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="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Event name`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;appName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;Name of your App&amp;gt;&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to instrument Newrelic lambda agent?
&lt;/h2&gt;

&lt;p&gt;Luckily, there is a better option to do it, which is using &lt;strong&gt;Newrelic Lambda Layer&lt;/strong&gt;, this gives us the same thing without having to inject Newrelic module to the code or wrapping up the lambda function&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To setup the lambda layer using terraform, check this example&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_lambda_function"&lt;/span&gt; &lt;span class="s2"&gt;"example-lambda"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;function_name&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lambda_name&lt;/span&gt;
  &lt;span class="nx"&gt;filename&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"LAMBDA-CODE.zip"&lt;/span&gt;
  &lt;span class="nx"&gt;role&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ROLE&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ARN&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nx"&gt;layers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;us&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;west&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;451483290750&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;layer&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;NewRelicNodeJS16X&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nx"&gt;handler&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"newrelic-lambda-wrapper.handler"&lt;/span&gt;
  &lt;span class="nx"&gt;runtime&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nodejs16.x"&lt;/span&gt;

   &lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;variables&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;NEW_RELIC_LAMBDA_HANDLER&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"index.handler"&lt;/span&gt;
    &lt;span class="nx"&gt;NEW_RELIC_ACCOUNT_ID&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Your_Newrelic_Account&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;NEW_RELIC_LICENSE_KEY&lt;/span&gt;                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Your_Newrelic_License_Key&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;NEW_RELIC_TRUSTED_ACCOUNT_KEY&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Your_Newrelic_Trusted_Account_Key&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;NEW_RELIC_LAMBDA_EXTENSION_ENABLED&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;NEW_RELIC_DISTRIBUTED_TRACING_ENABLED&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;NEW_RELIC_NO_CONFIG_FILE&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;AWS_NODEJS_CONNECTION_REUSE_ENABLED&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nx"&gt;NEW_RELIC_APP_NAME&lt;/span&gt;                    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lambda_name&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Find the ARN of the lambda layers that matches your system here in this page: &lt;a href="https://layers.newrelic-external.com/"&gt;https://layers.newrelic-external.com/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is important to provide the right api and licence keys to the lambda through the environment variables shown in the above example&lt;/p&gt;

&lt;p&gt;Once you done the above, you can now create your alerts in &lt;code&gt;Newrelic&lt;/code&gt; using terraform.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Check the terraform documentation which should be easy to follow comprehensive about each resource&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating an alert policy
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://registry.terraform.io/providers/newrelic/newrelic/latest/docs/resources/alert_policy"&gt;https://registry.terraform.io/providers/newrelic/newrelic/latest/docs/resources/alert_policy&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating an alert condition, there are more than one type, but for lambda we need the &lt;code&gt;newrelic_nrql_alert_condition&lt;/code&gt; alert condition
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://registry.terraform.io/providers/newrelic/newrelic/latest/docs/resources/nrql_alert_condition"&gt;https://registry.terraform.io/providers/newrelic/newrelic/latest/docs/resources/nrql_alert_condition&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Hope the above is useful for anyone wants to setup Newrelic in lambda&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>aws</category>
      <category>newrelic</category>
      <category>lambda</category>
    </item>
  </channel>
</rss>
