Skip to main content
Jorge Bernhardt Jorge Bernhardt
  1. Posts/

Terraform - Deploying Azure Application Insights

·1309 words·7 mins· 100 views · 5 likes ·
Terraform Microsoft Azure Azure Monitor IaC

Monitoring and analyzing performance in modern cloud-based environments is crucial to ensure reliability. Azure Application Insights is a powerful tool for monitoring your applications, helping you detect and diagnose errors. Building on our previous discussion on Azure Log Analytics workspaces, This blog post will guide you through implementing Azure Application Insights with a Terraform module. You can create a comprehensive monitoring solution for your cloud resources by integrating Application Insights and Log Analytics. Let’s go for it!

Prerequisites>

Prerequisites #

  • You need Terraform CLI on your local machine, if you’re new to using Terraform to deploy Microsoft Azure resources, then I recommend you check out this link.
  • A text editor or IDE of your choice (Visual Studio Code with Terraform extension is my recommendation)
Declare Azure Provider in Terraform>

Declare Azure Provider in Terraform #

The provider.tf file in Terraform is used to specify and configure the providers used in your Terraform configuration. A provider is a service or platform where the resources will be managed. This could be a cloud provider like Microsoft Azure, AWS, Google Cloud, etc.

This file is important because it tells Terraform which provider’s API to use when creating, updating, and deleting resources. Without it, Terraform wouldn’t know where to manage your resources.

provider "azurerm" {
  features {}
}
Deploy Azure Resources Using Terraform>

Deploy Azure Resources Using Terraform #

In the case of Azure Application Insights deployment, the main.tf file contains the following key components:

  • locals: This block is used to filter the settings for creating new Resource Groups. It uses a list comprehension to generate a new list, rg_required_settings, containing only those settings where require_new_resource_group is set to true.

  • azurerm_resource_group: This resource block is responsible for creating new Azure Resource Groups if specified by the require_new_resource_group attribute in the settings.

  • azurerm_application_insights: This resource block is the core of the module, creating Application Insights instances based on the settings provided.

// Locals block to filter out settings that require a new resource group
locals {
  rg_required_settings = [for setting in var.application_insights_settings : setting if setting.require_new_resource_group]
}

// Create Resource Groups based on filtered settings
resource "azurerm_resource_group" "rg" {
  for_each = { for setting in local.rg_required_settings : "${setting.resource_group_name}-${setting.name}" => setting }

  location = each.value.resource_group_location
  name     = each.value.resource_group_name

  tags = var.tags
}

// Create Application Insights resources
resource "azurerm_application_insights" "appi" {
  for_each = { for setting in var.application_insights_settings : "${setting.resource_group_name}-${setting.name}" => setting }

  application_type                      = each.value.application_type
  daily_data_cap_in_gb                  = each.value.daily_data_cap_in_gb
  daily_data_cap_notifications_disabled = each.value.daily_data_cap_notifications_disabled
  disable_ip_masking                    = each.value.disable_ip_masking
  force_customer_storage_for_profiler   = each.value.force_customer_storage_for_profiler
  internet_ingestion_enabled            = each.value.internet_ingestion_enabled
  internet_query_enabled                = each.value.internet_query_enabled
  local_authentication_disabled         = each.value.local_authentication_disabled
  location                              = each.value.resource_group_location
  name                                  = each.value.name
  retention_in_days                     = each.value.retention_in_days
  resource_group_name                   = each.value.resource_group_name
  sampling_percentage                   = each.value.sampling_percentage
  workspace_id                          = each.value.workspace_id

  tags = var.tags

  depends_on = [
    azurerm_resource_group.rg
  ]
}
Declaration of input variables>

Declaration of input variables #

The variables.tf file in Terraform defines the variables I will use in the main.tf file. These variables allow for more flexibility and reusability in the code. In this example, the variables are defined in the variables.tf include:

  • application_insights_settings: This complex object variable allows you to specify various settings for each Application Insights instance, such as its name, resource group, location, and various other configuration options. It also includes validation rules to enforce best practices and constraints on values like application_type ,sampling_percentage and location.

  • tags: This block declares a variable named tags, which is a map of strings. It is used to assign tags to the Azure resources being created. For example, you can use a key-value pair such as Terraform = true to indicate that the resource was deployed with Terraform.

// Application Insights Settings
variable "application_insights_settings" {
  description = "List of settings for Application Insights instances"

  type = list(object({
    name                                  = string
    require_new_resource_group            = bool
    resource_group_name                   = string
    resource_group_location               = string
    application_type                      = string
    daily_data_cap_in_gb                  = number
    daily_data_cap_notifications_disabled = bool
    retention_in_days                     = number
    sampling_percentage                   = number
    disable_ip_masking                    = bool
    workspace_id                          = string
    local_authentication_disabled         = bool
    internet_ingestion_enabled            = bool
    internet_query_enabled                = bool
    force_customer_storage_for_profiler   = bool
  }))

  // Validation for application type
  validation {
    condition = alltrue([
      for s in var.application_insights_settings : s.application_type == "web"
    ])
    error_message = "The only valid value for application_type is web."
  }

  // Validation for sampling percentage
  validation {
    condition = alltrue([
      for appi in var.application_insights_settings : contains([100, 50, 33, 25, 12.5, 8.3, 4, 2, 1], appi.sampling_percentage)
    ])
    error_message = "Valid Data Sampling percentages are 100, 50, 33, 25, 12.5, 8.3, 4, 2, and 1."
  }

  // Validation for location
  validation {
    condition = alltrue([
      for appi in var.application_insights_settings : contains([
        "West Europe",
        "North Europe",
      ], appi.resource_group_location)
    ])
    error_message = "Valid locations are West Europe and North Europe."
  }
}

// Common tags for all Azure resources
variable "tags" {
  description = "Common tags for all resources"
  type        = map(string)
  default = {
    Environment = "www.jorgebernhardt.com"
    Terraform   = "true"
  }
}
Declaration of output values>

Declaration of output values #

The output.tf file in Terraform extracts and displays information about the resources created or managed by your Terraform configuration. These outputs are defined using the output keyword and can be used to return information that can be useful for the user, for other Terraform configurations, or for programmatically using the information in scripts or other tools.

In this example, the output.tf file returns information about the names, Instrumentation Keys, and App IDs of the Azure Application Insights instances that are created by the Terraform configuration.

To ensure greater security, you can designate certain output variables as sensitive. This can be achieved by including the argument sensitive=true in the output block of your output.tf file. Terraform will then prevent these values, such as Instrumentation Keys, from being displayed in the standard output, which helps to minimize the possibility of unintended exposure.

Once Terraform has finished applying your configuration, it will display the defined outputs, giving you immediate access to important resource attributes like Resource Group names and App IDs.

// Output Resource Group Names
output "rg_names" {
  value = {
    for settings in local.rg_required_settings :
    settings.name => azurerm_resource_group.rg["${settings.resource_group_name}-${settings.name}"].name
  }
  description = "The names of the created or managed Azure Resource Groups."
}

// Output Application Insights Instrumentation Keys
output "appi_instrumentation_keys" {
  value = {
    for settings in var.application_insights_settings :
    settings.name => azurerm_application_insights.appi["${settings.resource_group_name}-${settings.name}"].instrumentation_key
  }
  description = "The Instrumentation Keys for the Application Insights resources."
  sensitive   = true  // Mark the output as sensitive data
}

// Output Application Insights App IDs
output "appi_ids" {
  value = {
    for settings in var.application_insights_settings :
    settings.name => azurerm_application_insights.appi["${settings.resource_group_name}-${settings.name}"].app_id
  }
  description = "The App IDs for the Application Insights resources."
}
Executing the Terraform Deployment>

Executing the Terraform Deployment #

Now that you’ve declared the resources correctly, it’s time to take the following steps to deploy them in your Azure environment.

  • Initialization: To begin, execute the terraform init command. This will initialize your working directory that holds the .tf files and download the provider specified in the provider.tf file, and configure the Terraform backend. I suggest looking at this link if you’re curious about the process.

  • Planning: Next, execute the terraform plan. This command creates an execution plan and shows Terraform’s actions to achieve the desired state defined in your .tf files. This gives you a chance to review the changes before applying them.

  • Apply: When you’re satisfied with the plan, execute the terraform apply command. This will implement the required modifications to attain the intended infrastructure state. Before making any changes, you will be asked to confirm your decision.

  • Inspection: After applying the changes, you can use terraform show command to see the current state of your infrastructure.

  • Destroy (optional): when a project is no longer needed or when resources have become outdated. You can use the terraform destroy command. This will remove all the resources that Terraform has created.

References and useful links #

Thank you for taking the time to read my post. I sincerely hope that you find it helpful.