framework/Resources/Scripts/monitoring-backup.ps1

# ---------------- Monitoring Variables ----------------
$nc_workspaceName = "NC-$EnvironmentName-Workspace"
$nc_dceName = "NC-$EnvironmentName-DCE"
$nc_dcrName = "NC-$EnvironmentName-DCR"
$nc_tableName = "TelegrafMetrics_CL"
$nc_subscriptionId = (Get-AzContext).Subscription.Id

# ---------------- Resource Deployment Functions (per Account) ----------------

function New-Workspace {
    $workspace = Get-AzOperationalInsightsWorkspace -ResourceGroupName $nc_resource_group -Name $nc_workspaceName -ErrorAction SilentlyContinue
    if (-not $workspace) {
        Write-Host "$((Get-Date).ToString()) - Creating Log Analytics Workspace $nc_workspaceName"
        $workspace = New-AzOperationalInsightsWorkspace -Location $Location `
            -Name $nc_workspaceName `
            -ResourceGroupName $nc_resource_group `
            -Sku "PerGB2018"
    }

    # Wait for provisioning
    $attempt = 0
    $MaxAttempts = 20
    while ($workspace.ProvisioningState -ne "Succeeded" -and $attempt -lt $MaxAttempts) {
        $attempt++
        Start-Sleep -Seconds 15
        $workspace = Get-AzOperationalInsightsWorkspace -ResourceGroupName $nc_resource_group -Name $nc_workspaceName
    }

    if ($workspace.ProvisioningState -ne "Succeeded") {
        throw "Workspace did not become active in time."
    }

    return $workspace
}


function New-Table {
    $table = Get-AzOperationalInsightsTable -ResourceGroupName $nc_resource_group -WorkspaceName $nc_workspaceName -TableName $nc_tableName -ErrorAction SilentlyContinue
    if (-not $table) {
        Write-Host "$((Get-Date).ToString()) - Creating custom table $nc_tableName in workspace $nc_workspaceName"
        $table = New-AzOperationalInsightsTable `
            -ResourceGroupName $nc_resource_group `
            -WorkspaceName $nc_workspaceName `
            -TableName $nc_tableName `
            -TotalRetentionInDays 30 `
            -Column @{'TimeGenerated' = 'datetime'; 'fields' = 'string'; 'tags' = 'string' }
    }
    return $table
}

function New-DCE {
    $dce = Get-AzDataCollectionEndpoint -ResourceGroupName $nc_resource_group -Name $nc_dceName -ErrorAction SilentlyContinue
    if (-not $dce) {
        Write-Host "$((Get-Date).ToString()) - Creating Data Collection Endpoint $nc_dceName"
        $dce = New-AzDataCollectionEndpoint -Name $nc_dceName `
            -ResourceGroupName $nc_resource_group `
            -Location $Location `
            -NetworkAclsPublicNetworkAccess "Enabled" `
            -Description "DCE for NCache counters"
    }
    return $dce
}

function New-DCR {
    param(
        [Parameter(Mandatory)][string]$DcrJsonString
    )
    $dcr = Get-AzDataCollectionRule -ResourceGroupName $nc_resource_group -Name $nc_dcrName -ErrorAction SilentlyContinue
    if (-not $dcr) {
        Write-Host "$((Get-Date).ToString()) - Creating Data Collection Rule $nc_dcrName"
        $dcr = New-AzDataCollectionRule -ResourceGroupName $nc_resource_group `
            -Name $nc_dcrName `
            -JsonString $DcrJsonString
    }
    return $dcr
}

function Get-DcrJsonString {

    $laGuid = (New-Guid).ToString()
    if ($OS -eq "Linux") {
        return "{
            `"location`": `"$Location`",
            `"kind`": `"Linux`",
            `"type`": `"Microsoft.Insights/dataCollectionRules`",
            `"properties`": {
                `"dataCollectionEndpointId`": `"/subscriptions/$nc_subscriptionId/resourceGroups/$nc_resource_group/providers/Microsoft.Insights/dataCollectionEndpoints/$nc_dceName`",
                `"dataSources`": {
                    `"logFiles`": [
                        {
                            `"streams`": [ `"Custom-Json-TelegrafMetrics_CL`" ],
                            `"filePatterns`": [ `"/var/log/telegraf/*.json`" ],
                            `"format`": `"json`",
                            `"name`": `"Custom-Json-TelegrafMetrics_CL`"
                        }
                    ]
                },
                `"destinations`": {
                    `"logAnalytics`": [
                        {
                            `"workspaceResourceId`": `"/subscriptions/$nc_subscriptionId/resourceGroups/$nc_resource_group/providers/Microsoft.OperationalInsights/workspaces/$nc_workspaceName`",
                            `"name`": `"$laGuid`"
                        }
                    ]
                },
                `"dataFlows`": [
                    {
                        `"streams`": [ `"Custom-Json-TelegrafMetrics_CL`" ],
                        `"destinations`": [ `"$laGuid`" ],
                        `"outputStream`": `"Custom-TelegrafMetrics_CL`"
                    }
                ],
                `"streamDeclarations`": {
                    `"Custom-Json-TelegrafMetrics_CL`": {
                        `"columns`": [
                            { `"name`": `"TimeGenerated`", `"type`": `"datetime`" },
                            { `"name`": `"fields`", `"type`": `"string`" },
                            { `"name`": `"tags`", `"type`": `"string`" }
                        ]
                    }
                }
            }
        }"

    }
    else {
        return "{
            `"location`": `"$Location`",
            `"kind`": `"Windows`",
            `"type`": `"Microsoft.Insights/dataCollectionRules`",
            `"properties`": {
                `"dataCollectionEndpointId`": `"/subscriptions/$nc_subscriptionId/resourceGroups/$nc_resource_group/providers/Microsoft.Insights/dataCollectionEndpoints/$nc_dceName`",
                `"dataSources`": {
                    `"performanceCounters`": [
                        {
                            `"streams`": [ `"Microsoft-Perf`" ],
                            `"samplingFrequencyInSeconds`": 1,
                            `"counterSpecifiers`": [
                                `"\\NCache(democache)\\Additions/sec`",
                                `"\\NCache(democache)\\Fetches/sec`",
                                `"\\NCache(democache)\\Updates/sec`",
                                `"\\NCache(democache)\\Deletes/sec`",
                                `"\\NCache(democache)\\Cache Size`"
                            ],
                            `"name`": `"perfCounterDataSource1`"
                        }
                    ]
                },
                `"destinations`": {
                    `"logAnalytics`": [
                        {
                            `"workspaceResourceId`": `"/subscriptions/$nc_subscriptionId/resourceGroups/$nc_resource_group/providers/Microsoft.OperationalInsights/workspaces/$nc_workspaceName`",
                            `"name`": `"$laGuid`"
                        }
                    ]
                },
                `"dataFlows`": [
                    {
                        `"streams`": [ `"Microsoft-Perf`" ],
                        `"destinations`": [ `"$laGuid`" ],
                        `"outputStream`": `"Microsoft-Perf`"
                    }
                ],
                `"streamDeclarations`": { }
            }
        }"

    }
}

function Install-MonitoringResources {
    if (-not $nc_subscriptionId) {
        throw "Could not determine subscription ID."
    }

    New-Workspace
    if ($OS -eq "Linux") {
        New-Table
    }
    New-DCE
    $dcrJson = Get-DcrJsonString
    New-DCR -DcrJsonString $dcrJson

    Write-Host "$((Get-Date).ToString()) - Monitoring resources deployed successfully."
}

# ---------------- VM Preparation Functions (per VM) ----------------
function Install-AMAExtension {
    param(
        [Parameter(Mandatory)][string]$VmName
    )

    Write-Host "$((Get-Date).ToString()) - Installing Azure Monitor Agent (AMA) on VM $VmName"
    Set-AzVMExtension `
        -ResourceGroupName $nc_resource_group `
        -VMName $VmName `
        -Name "AzureMonitor$($OS)Agent" `
        -Publisher "Microsoft.Azure.Monitor" `
        -ExtensionType "AzureMonitor$($OS)Agent" `
        -TypeHandlerVersion "1.0" `
        -Location $Location `
        -EnableAutomaticUpgrade $true `
        -ForceRerun (New-Guid).ToString()

    # Wait for provisioning
    $maxAttempts = 20
    $attempt = 0
    $ext = Get-AzVMExtension -ResourceGroupName $nc_resource_group -VMName $VmName -Name "AzureMonitor$($OS)Agent"
    while ($ext.ProvisioningState -ne "Succeeded" -and $attempt -lt $maxAttempts) {
        $attempt++
        Start-Sleep -Seconds 15
        $ext = Get-AzVMExtension -ResourceGroupName $nc_resource_group -VMName $VmName -Name "AzureMonitor$($OS)Agent"
    }

    if ($ext.ProvisioningState -ne "Succeeded") {
        throw "AMA did not become active in time."
    }
}

function Install-TelegrafSetup {
    param(
        [Parameter(Mandatory)][string]$VmName
    )

    Write-Host "$((Get-Date).ToString()) - Running Telegraf setup script on VM $VmName"
    $scriptContent = Get-Content -Path $nc_telegraf_setup_lin -Raw
    Invoke-AzVMRunCommand `
        -ResourceGroupName $nc_resource_group `
        -VMName $VmName `
        -CommandId 'RunShellScript' `
        -ScriptString $scriptContent
}

function Add-DceAssociation {
    param(
        [Parameter(Mandatory)][string]$VmName
    )

    Write-Host "$((Get-Date).ToString()) - Associating DCE with VM $VmName"
    New-AzDataCollectionRuleAssociation -AssociationName "configurationAccessEndpoint" `
        -ResourceUri "/subscriptions/$nc_subscriptionId/resourceGroups/$nc_resource_group/providers/Microsoft.Compute/virtualMachines/$VmName" `
        -DataCollectionEndpointId "/subscriptions/$nc_subscriptionId/resourceGroups/$nc_resource_group/providers/Microsoft.Insights/dataCollectionEndpoints/$nc_dceName" `
        -Description "Associate DCE with VM"

    # Wait for provisioning
    Write-Host "$((Get-Date).ToString()) - Waiting for DCE association to settle..."
    $attempt = 0
    $MaxAttempts = 20
    $check = $null
    while (-not $check -and $attempt -lt $MaxAttempts) {
        Start-Sleep -Seconds 15
        $check = Get-AzDataCollectionRuleAssociation -TargetResourceId "/subscriptions/$nc_subscriptionId/resourceGroups/$nc_resource_group/providers/Microsoft.Compute/virtualMachines/$VmName" `
        | Where-Object { $_.Name -eq "configurationAccessEndpoint" }
        $attempt++
    }

    if (-not $check) {
        throw "DCE for VM $VmName did not become active in time."
    }
    return $check
}

function Add-DcrAssociation {
    param(
        [Parameter(Mandatory)][string]$VmName
    )

    Write-Host "$((Get-Date).ToString()) - Associating DCR with VM $VmName"
    $assoc = New-AzDataCollectionRuleAssociation -AssociationName "$VmName-association" `
        -ResourceUri "/subscriptions/$nc_subscriptionId/resourceGroups/$nc_resource_group/providers/Microsoft.Compute/virtualMachines/$VmName" `
        -DataCollectionRuleId "/subscriptions/$nc_subscriptionId/resourceGroups/$nc_resource_group/providers/Microsoft.Insights/dataCollectionRules/$nc_dcrName" `
        -Description "Associate DCR with VM"

    return $assoc
}

function Install-MonitoringOnVM {
    param(
        [Parameter(Mandatory)][string]$VmName
    )

    Enable-SystemAssignedIdentity -VmName $VmName
    Install-AMAExtension -VmName $VmName
    Add-DceAssociation -VmName $VmName
    Add-DcrAssociation -VmName $VmName
}