Posted on Leave a comment

Monitoring Windows service on Azure with Event Viewer and Log Analytics

A Log Analytics workspace is a unique environment for log data from Azure Monitor and other Azure services, such as Microsoft Sentinel and Microsoft Defender for Cloud. Expect from that it can be used also for monitoring combined with Azure alerts given that you create the appropriate query.

The below query can be used to monitor a windows server service by querying log analytics. In more detail it searches for eventID=7036 which indicates the service stopped status.

Query code in Kusto language will return the service name, state and time of the event.

Event
| where TimeGenerated >ago(1h)
| where EventLog  == "System" and EventID ==7036 and Source == "Service Control Manager" 
| parse kind=relaxed EventData with * '<Data Name="param1">' Windows_Service_Name '</Data><Data Name="param2">' Windows_Service_State '</Data>'*
| sort by TimeGenerated desc
| where Windows_Service_Name startswith "Docker Desktop" and Windows_Service_State contains "stopped"
| project Computer, Windows_Service_Name, Windows_Service_State, TimeGenerated

You can use the above query to create a azure alert when a service is found as stopped. As I want to monitor the Docker Desktop service, I will need to use that in the where clause of the query where Windows_Service_Name. The alert logic should indicate when a result is returned as a row in a given timeframe then an alert should be generated. This happens because a row is returned only when the event is captured on the event viewer. This means that the service stopped during the TimeGenerated interval of the query. The frequency of evaluation will be the time on which we want to repeat the log analytics query. For example if we need to search every 5 minutes for a stopped service then we should add 5 minutes there.

Finally the alert will be triggered and inform you about windows stopped services.

Posted on Leave a comment

Query servers disk size – Azure Log Analytics

Log Analytics can be a powerful monitoring tool for your infrastructure as you can query various metrics that are important for your servers availability like disk space.

The below query can be used to get free space for your Linux VM disks.

 InsightsMetrics
| where Origin == "vm.azm.ms"
    and Namespace == "LogicalDisk"  
    and Name == "FreeSpaceMB"
| extend Disk=tostring(todynamic(Tags)["vm.azm.ms/mountId"]),
    Disk_Size_GB=(todynamic(Tags)["vm.azm.ms/diskSizeMB"]) / (1024)
| summarize Disk_Free_Space_GB = avg(Val) / (1024)
    by Computer,
    Disk, Disk_Size_GB, _ResourceId
| where Disk in ('sda1', 'sdb1', 'sdc1', 'sdd1','/')
| project Computer, Disk, Disk_Size_GB, Disk_Free_Space_GB

You can also select the scope of the query in order to get results for specific resources/resource groups.

The result will bring all disks size and free space that their name is included in the list

('sda1', 'sdb1', 'sdc1', 'sdd1','/')

The same query with a small change can be applied also for windows vms in order to get the available space for your C: drive.

 InsightsMetrics
| where Origin == "vm.azm.ms"
    and Namespace == "LogicalDisk"  
    and Name == "FreeSpaceMB"
| extend Disk=tostring(todynamic(Tags)["vm.azm.ms/mountId"]),
    Disk_Size_GB=(todynamic(Tags)["vm.azm.ms/diskSizeMB"]) / (1024)
| summarize Disk_Free_Space_GB = avg(Val) / (1024)
    by Computer,
    Disk, Disk_Size_GB, _ResourceId
| where Disk in ('C:')
| project Computer, Disk, Disk_Size_GB, Disk_Free_Space_GB

Finally you can pin this result inside an Azure dashboard by clicking pin and select the specific dashboard.

Posted on Leave a comment

Add log analytics workspace to Azure app service – Terraform

Most times you will need to store logs for your azure resources in order to troubleshoot when things do not work as expected. Diagnostic settings for an app service can be enabled from the pane under Monitoring.

Then you should configure the diagnostic settings that will point which logs should be forwarded.

You can choose from the available categories shown below.

Lets now discover how we can enable diagnostic settings for an app service using terraform.

Create a file for example diagnostic_settings.tf and apply. The below configuration will enable all diagnostic settings categories.

resource "azurerm_monitor_diagnostic_setting" "diag_settings" {
  name               = "diag-settings"
  target_resource_id = azurerm_windows_web_app.app_service1.id
  log_analytics_workspace_id = local.log_analytics_workspace_id
  
  log {
    category = "AppServiceHTTPLogs"
    enabled  = true

    retention_policy {
      enabled = false
    }
  }

    log {
    category = "AppServiceConsoleLogs"
    enabled  = true

    retention_policy {
      enabled = false
    }
  }

    log {
    category = "AppServiceAppLogs"
    enabled  = true

    retention_policy {
      enabled = false
    }
  }

    log {
    category = "AppServiceAuditLogs"
    enabled  = true

    retention_policy {
      enabled = false
    }
  }

    log {
    category = "AppServiceIPSecAuditLogs"
    enabled  = true

    retention_policy {
      enabled = false
    }
  }

     log {
    category = "AppServicePlatformLogs"
    enabled  = true

    retention_policy {
      enabled = false
    }
  }

  metric {
    category = "AllMetrics"

    retention_policy {
      enabled = false
      days = 30
    }
  }

}

You can also perform the same using a loop and a local variable in order to minimize code and make it more readable.

Assign a new variable inside your locals.tf file.

 log_analytics_log_categories     = ["AppServiceHTTPLogs", "AppServiceConsoleLogs","AppServiceAppLogs","AppServiceAuditLogs","AppServiceIPSecAuditLogs","AppServicePlatformLogs"]

Then perform terraform apply.

resource "azurerm_monitor_diagnostic_setting" "diag_settings" {
  name               = "diag-rule"
  target_resource_id = azurerm_windows_web_app.app_service1.id
  log_analytics_workspace_id = local.log_analytics_workspace_id
  
  dynamic "log" {
    iterator = entry
    for_each = local.log_analytics_log_categories
    content {
        category = entry.value
        enabled  = true

        retention_policy {
      enabled = false
        }
    }
   
  }

  metric {
    category = "AllMetrics"

    retention_policy {
      enabled = false
      days = 30
    }
  }

}

After applying terraform all the settings will be enabled.