Get started with New Relic Provider for Terraform

Discover how to set up New Relic for real-time web application performance monitoring using Terraform. Learn how to provision alert policies, conditions, channels, and dashboards. Follow the step-by-step guide to configuring the New Relic provider.

On the other hand, New Relic is a web application performance service designed to work in real-time with your live web app.

In this get-started guide, you can learn how to set up New Relic. More specifically, you can provision an alert policy, alert conditions, alert channels, and Dashboard.

Before you begin

To use this guide, you should have some basic knowledge of both New Relic and Terraform. If you haven't deployed a New Relic open-source agent yet, install New Relic for your application. Also, install the Terraform CLI.

Bootstrap Terraform

mkdir your-project && cd your-project

touch main.tf

Now, let's instruct Terraform to install and use the NewRelic provider by setting the terraform and required_providers block in main.tf

terraform {
  # Require Terraform version 1.x.x (recommended)
  required_version = "~> 1.0"
  
  # Require the latest 2.x version of the New Relic provider
  required_providers {
    newrelic = {
      source = "newrelic/newrelic"
      version = "~> 2.0"
    }
  }
}

πŸ‘†What is happening here?

  • required_version is your Terraform version validation. You can check your Terraform version with terraform -v.
  • required_providers.source is the name of NewRelic providers. That brings the new relic provider to interact with the new relic using terraform.
  • required_providers.version ensures the new relic provider version that you wish to use.

Configure New Relic Provider

With Terraform all set, let's configure the New Relic provider with the following items:

provider "newrelic" {
  account_id = "<your account>"
  api_key    = "NRAK-<your api key>" # usually prefixed with 'NRAK'
  region     = "EU" # Valid regions are US and EU
}

πŸ‘†What is happening here?

You can also configure the New Relic provider using the environment variable. This is a useful way to set default values instead of hard coding into code and publishing it to the repository.

The table below shows the available environment variables equivalent to attributes and all of these are required attributes.

Schema Attribute Equivalent Env Variable
account_id NEW_RELIC_ACCOUNT_ID
api_key NEW_RELIC_API_KEY
region NEW_RELIC_REGION

With the New Relic provider configured, initialize the Terraform:

πŸ‘‰ terraform init

Reference your New Relic Application in Terraform

You can define various resources for your application. As you will be targeting a specific application. You can use newrelic_entity data to fetch information from New Relic to reference in terraform code.

data "newrelic_entity" "app_apm" {
  name   = "<Your APM application Name>" # Must be an exact match to your application name in New Relic
  domain = "APM"        # or BROWSER, INFRA, MOBILE, SYNTH, depending on your entity's domain
  type   = "APPLICATION"
}

data "newrelic_entity" "app_browser" {
  name   = "<Your Browser application name>" # Must be an exact match to your application name in New Relic
  domain = "BROWSER"                   # or BROWSER, INFRA, MOBILE, SYNTH, depending on your entity's domain
  type   = "APPLICATION"
}

data "newrelic_account" "acc" {
  scope      = "global"
  account_id = "<your account>"
}

πŸ‘†What is happening here?

  • newrelic_entity.app_apm is to fetch information for APM New Relic Application.
  • newrelic_entity.app_browser is to fetch information for Browser New Relic.
  • newrelic_account is to get information about the New Relic account so you can reference it later in your configuration.

It's considered a best practice to tag all your resources on Cloud. You can tag New Relic resources with newrelic_entity_tags. Let's tag our APM and Browser New Relic application.

resource "newrelic_entity_tags" "app_apm_tags" {
  guid = data.newrelic_entity.app_apm.guid
  tag {
    key    = "Environment"
    values = ["Production"]
  }
}

resource "newrelic_entity_tags" "app_browser_tags" {
  guid = data.newrelic_entity.app_browser.guid
  tag {
    key    = "Environment"
    values = ["Production"]
  }
}

At this point, you should be able to add tags to your application after the command terraform apply.

Now you have basic infrastructure as code for Terraform up and running. Let's provision other available resources to mature our New Relic implementation with the help of Terraform IAC.

Create a New Relic alert policy

resource "newrelic_alert_policy" "golden_signal_policy" {
  name = "Golden Signal - Managed Policy "
}

πŸ‘† name is the name of the Alert Policy.

πŸ’‘ Info! At this point, you can apply your terraform code with terraform apply. Every time you apply changes, Terraform asks you to confirm the actions you've told it to run. Type "yes".

Add alert conditions in the alert policy

Let's add alert conditions based on the four golden signals: latency, traffic, errors, and saturation. Apply these alert conditions to the alert policy you created in the previous step.

# Low throughput
resource "newrelic_alert_condition" "throughput_web" {
  policy_id       = newrelic_alert_policy.golden_signal_policy.id
  name            = "Low Throughput (Web)"
  type            = "apm_app_metric"
  entities        = [data.newrelic_entity.app_apm.application_id]
  metric          = "throughput_web"
  condition_scope = "application"

  # Define a critical alert threshold that will
  # trigger after 5 minutes below 5 requests per minute.
  term {
    priority      = "critical"
    duration      = 5
    operator      = "below"
    threshold     = "5"
    time_function = "all"
  }
}
# High CPU usage
resource "newrelic_infra_alert_condition" "high_cpu_utils" {
  policy_id   = newrelic_alert_policy.golden_signal_policy.id
  name        = "${local.alarm_label_prefix}:High_CPU_Utilisation"
  type        = "infra_metric"
  event       = "SystemSample"
  select      = "cpuPercent"
  comparison  = "above"
  runbook_url = "https://www.example.com"
  where       = "(`applicationId` = '${data.newrelic_entity.app_akgalleria.application_id}')"

  # Define a critical alert threshold that will trigger after 5 minutes above 90% CPU utilization.
  critical {
    duration      = 5
    value         = 90
    time_function = "all"
  }
}
# Response time
resource "newrelic_alert_condition" "response_time_web" {
  policy_id       = newrelic_alert_policy.golden_signal_policy.id
  name            = "High Response Time (Web) - ${data.newrelic_entity.app_akgalleria.name}"
  type            = "apm_app_metric"
  entities        = [data.newrelic_entity.app_akgalleria.application_id]
  metric          = "response_time_web"
  runbook_url     = "https://www.example.com"
  condition_scope = "application"

  term {
    duration      = 5
    operator      = "above"
    priority      = "critical"
    threshold     = "5"
    time_function = "all"
  }
}

# Error percentage
resource "newrelic_alert_condition" "error_percentage" {
  policy_id       = newrelic_alert_policy.golden_signal_policy.id
  name            = "High Error Percentage"
  type            = "apm_app_metric"
  entities        = [data.newrelic_entity.app_akgalleria.application_id]
  metric          = "error_percentage"
  runbook_url     = "https://www.example.com"
  condition_scope = "application"

  # Define a critical alert threshold that will trigger after 5 minutes above a 5% error rate.
  term {
    duration      = 5
    operator      = "above"
    threshold     = "5"
    time_function = "all"
  }
}

Get notified when an alert triggers

There are multiple ways available from New Relic to get notified when an alert triggers. For starters, you can use Email and Slack notifications.

resource "newrelic_alert_channel" "team_email" {
  name = "Email-Notification"
  type = "email"

  config {
    recipients              = "<Notification Email>"
    include_json_attachment = "1"
  }
}

If you want to specify multiple recipients, use a comma-delimited list of emails.

resource "newrelic_alert_channel" "slack_notification" {
  name = "Slack-Notification"
  type = "slack"

  config {
    # Use the URL provided in your New Relic Slack integration
    url     = "<Slack Hooks>"
    channel = "proj-alerts"
  }
}

You need to add New Relic Slack App to your Slack account. and select the Slack channel to send the notification.

Last, but not least, you need to associate them with the respective New Relic alert policy. Create newrelic_alert_policy_channel.

resource "newrelic_alert_policy_channel" "golden_signals" {
  policy_id   = newrelic_alert_policy.golden_signal_policy.id
  channel_ids = [newrelic_alert_channel.team_email.id, 			newrelic_alert_channel.slack_notification.id]
}

Currently, I am not able to find a possible way to segregate the alerts based on priority. For Example, send warning notifications to the Slack channel and critical notifications to the email channel.

One possible way could be to separate alert policies for warning and critical, and associate channels to respective alert policies.

Browser Dashboard

You can also define the New Relic dashboard with newrelic_one_dashboard.

resource "newrelic_one_dashboard" "dashboard_website_performance" {
  name = "Website Performance"

  page {
    name = "Sessions"

widget_line {
  title  = "Unique User Sessions"
  row    = 1
  column = 1

  nrql_query {
    query = "FROM PageView SELECT uniqueCount(session) WHERE appName='${data.newrelic_entity.app_browser.name}' TIMESERIES"
  }
}

widget_markdown {
  title  = "Dashboard Note"
  row    = 1
  column = 9

  text = "### Helpful Links\n\n* [New Relic One](https://one.newrelic.com)\n* [Developer Portal](https://developer.newrelic.com)"
}
  }
}

πŸ‘† is creating "Website Performance" with the example "Unique User Sessions" and the markdown widget. Add the appropriate tag(s) to the dashboard:

resource "newrelic_entity_tags" "dashboard_website_performance_tags" {
  guid = newrelic_one_dashboard.dashboard_website_performance.guid
  tag {
    key    = "Environment"
    values = ["Production"]
  }
}

Organize New Relic resources in Work Load

resource "newrelic_workload" "workload_production" {
  name       = "Production-WorkLoad"
  account_id = data.newrelic_account.acc.account_id

  entity_search_query {
    query = "tags.accountId='${data.newrelic_account.acc.account_id}' AND tags.Environment='Production'"
  }

  scope_account_ids = [data.newrelic_account.acc.account_id]
}

πŸ‘† This will provision New Relic Work Load with the

  • name of "Production-WorkLoad"
  • account_id on the defined account
  • and entity_search_query would be based on environment tags defined in the implementation of resources with newrelic_entity_tags.

You may also want to consider automating this process in your CI/CD pipeline. Use Terraform's recommended practices guide to learn more about their recommended workflow and how to evolve your provisioning practices.

Congratulations! You're officially practicing observability-as-code. Review the New Relic Terraform provider documentation to learn how you can take your configuration to the next level.

#devops, #terraform, #newrelic, #iac


Discover more insightful content , just go to my blog Introduction to DevOps, advantages over traditional SDLC


Hi! I am Safoor Safdar a Senior SRE. Read More. Don't hesitate to reach out! You can find me on Linkedin, or simply drop me an email at me@safoorsafdar.com