Windows için Log Analytics aracısıyla ilgili sorunları giderme

Bu makale, Azure İzleyici'de Windows için Log Analytics aracısında karşılaşabileceğiniz hataları giderme konusunda yardım sağlar ve bunları çözmek için olası çözümler önerir.

Log Analytics Sorun Giderme Aracı

Windows için Log Analytics aracısı Sorun Giderme Aracı, Log Analytics aracısıyla ilgili sorunları bulmaya ve tanılamaya yardımcı olmak için tasarlanmış bir PowerShell betikleri koleksiyonudur. Yüklemeden sonra aracıya otomatik olarak eklenir. Aracı çalıştırmak, bir sorunu tanılamanın ilk adımı olmalıdır.

Sorun Giderme Aracı'nı kullanma

  1. Log Analytics aracısının yüklü olduğu makinede Yönetici olarak PowerShell istemini açın.

  2. Aracın bulunduğu dizine gidin:

    cd "C:\Program Files\Microsoft Monitoring Agent\Agent\Troubleshooter"

  3. Şu komutu kullanarak ana betiği yürütür:

    .\GetAgentInfo.ps1

  4. Bir sorun giderme senaryosu seçin.

  5. Konsoldaki yönergeleri izleyin. İzleme günlükleri adımlarının günlük toplamayı durdurmak için el ile müdahale gerektirdiğini unutmayın. Sorunun yeniden üretilebilirliğine bağlı olarak, süreyi bekleyin ve günlük toplamayı durdurmak için "s" öğesini seçin ve sonraki adıma geçin.

    Sonuç dosyasının konumu tamamlandıktan sonra günlüğe kaydedilir ve dosyayı vurgulayan yeni bir gezgin penceresi açılır.

Yükleme

Sorun Giderme Aracı, Log Analytics Aracısı derlemesi 10.20.18053.0 ve sonrasında otomatik olarak eklenir.

Kapsanan senaryolar

Sorun Giderme Aracı aşağıdaki senaryoları denetler:

  • Aracı veri bildirmiyor veya sinyal verileri eksik.
  • Aracı uzantısı dağıtımı başarısız oluyor.
  • Aracı kilitleniyor.
  • Aracı yüksek CPU veya bellek kullanıyor.
  • Yükleme ve kaldırma deneyimi hataları.
  • Özel günlüklerde sorunlar vardır.
  • OMS Ağ Geçidi'nin sorunları var.
  • Performans sayaçlarında sorunlar vardır.
  • Aracı günlükleri toplanamaz.

Dekont

Bir sorunla karşılaştığınızda Sorun Giderme Aracı'nı çalıştırın. Günlüklerin başlangıçta olması, destek ekibimizin sorununuzu daha hızlı gidermesine yardımcı olur.

Önemli sorun giderme kaynakları

Aracı, Windows için Log Analytics aracısı ile ilgili sorunları gidermeye yardımcı olmak için, olayları Windows Olay Günlüğü'ne , özellikle Application and Services\Operations Manager altında günlüğe kaydeder.

Bağlantı sorunları

Aracı bir ara sunucu veya güvenlik duvarı üzerinden iletişim kuruyorsa, kaynak bilgisayardan ve Azure İzleyici hizmetinden iletişimi engelleyen kısıtlamalar söz konusu olabilir. Yanlış yapılandırma nedeniyle iletişim engellenirse, aracıyı yüklemeye veya kurulum sonrasında aracıyı başka bir çalışma alanına rapor vermek üzere yapılandırmaya çalışırken çalışma alanına kayıt başarısız olabilir. Aracı iletişimi başarılı bir kayıt sonrasında başarısız olabilir. Bu bölümde, Windows aracısıyla ilgili bu tür sorunları giderme yöntemleri açıklanmaktadır.

Güvenlik duvarının veya ara sunucusunun aşağıdaki tabloda açıklanan aşağıdaki bağlantı noktalarına ve URL'lere izin verecek şekilde yapılandırılıp yapılandırılmadığını bir kez daha denetleyin. Ayrıca web trafiği için HTTP incelemesinin etkinleştirilmediğini onaylayın. Aracı ile Azure İzleyici arasında güvenli bir TLS kanalını engelleyebilir.

Aracı kaynağı Bağlantı noktaları Yön HTTPS denetlemesi atlaması
*.ods.opinsights.azure.com Bağlantı Noktası 443 Giden Evet
*.oms.opinsights.azure.com Bağlantı Noktası 443 Giden Evet
*.blob.core.windows.net Bağlantı Noktası 443 Giden Evet
*.agentsvc.azure-automation.net Bağlantı Noktası 443 Giden Evet

Azure Kamu için gereken güvenlik duvarı bilgileri için bkz. Azure Kamu yönetimi. Ortamınızda runbook'ları veya yönetim çözümlerini kullanmak üzere Otomasyon hizmetine bağlanmak ve bu hizmete kaydolmak için Azure Otomasyonu Karma Runbook Çalışanı'nı kullanmayı planlıyorsanız, bağlantı noktası numarasına ve Karma Runbook Çalışanı için ağınızı yapılandırma başlığında açıklanan URL'lere erişimi olmalıdır.

Aracının Azure İzleyici ile başarılı bir şekilde iletişim kurarak iletişim kurmadığını doğrulamanın birkaç yolu vardır:

  • Çalışma alanında Azure Log Analytics Aracısı Sistem Durumu değerlendirmesini etkinleştirin. Aracının listelenip listelenmediğini hızla görmek için Aracı Durumu panosunda Yanıt vermeyen aracı sayısı sütununu görüntüleyin.

  • Aracının raporlamak üzere yapılandırıldığı çalışma alanına sinyal gönderdiğini onaylamak için aşağıdaki sorguyu çalıştırın. değerini makinenin gerçek adıyla değiştirin <ComputerName> .

    Heartbeat 
    | where Computer like "<ComputerName>"
    | summarize arg_max(TimeGenerated, * ) by Computer 
    

    Bilgisayar hizmetle başarıyla iletişim kuruyorsa, sorgu bir sonuç döndürmelidir. Sorgu bir sonuç döndürmediyse, önce aracının doğru çalışma alanına rapor vermek üzere yapılandırıldığını doğrulayın. Doğru yapılandırılmışsa, 3. adıma geçin ve aracının Azure İzleyici ile iletişim kurmasını engelleyebilecek sorunu günlüğe kaydedip kaydetmediğini belirlemek için Windows Olay Günlüğü'nü arayın.

  • Bağlantı sorununu tanımlamanın bir diğer yöntemi de TestCloud Bağlan ivity aracını çalıştırmaktır. Araç varsayılan olarak aracı %SystemRoot%\Program Files\Microsoft Monitoring Agent\Agent klasöründe yüklüdür. Yükseltilmiş bir komut isteminden klasöre gidin ve aracı çalıştırın. Araç sonuçları döndürür ve testin başarısız olduğu noktayı vurgular. Örneğin, engellenen belirli bir bağlantı noktası veya URL ile ilgili olabilir.

    Screenshot that shows TestCloudConnection tool execution results.

  • Operations Manager olay günlüğünü Olay kaynaklarına Sistem Sağlığı Hizmeti Modüllere, HealthService'e ve Hizmet Bağlan ve Olay DüzeyiUyarısı ve Hatasına göre filtreleyerek aşağıdaki tablodan olaylar yazıp yazmadığını onaylayın. Varsa, her olası olay için dahil edilen çözüm adımlarını gözden geçirin.

    Olay Kodu Source Açıklama Çözüm
    2133 & 2129 Sistem Sağlığı Hizmeti Aracıdan hizmete Bağlan başarısız oldu. Bu hata, aracının Azure İzleyici hizmetine doğrudan veya bir güvenlik duvarı veya ara sunucu üzerinden iletişim kuramadığında oluşabilir. Aracı proxy ayarlarını doğrulayın veya ağ güvenlik duvarının veya ara sunucunun bilgisayardan hizmete TCP trafiğine izin verdiğinden emin olun.
    2138 Sistem Sağlığı Hizmeti Modülleri Ara sunucu kimlik doğrulaması gerektirir. Aracı proxy ayarlarını yapılandırın ve ara sunucuyla kimlik doğrulaması yapmak için gereken kullanıcı adını/parolayı belirtin.
    2129 Sistem Sağlığı Hizmeti Modülleri Bağlantı başarısız oldu. TLS anlaşması başarısız oldu. Ağ bağdaştırıcınızın TCP/IP ayarlarını ve aracı proxy ayarlarını denetleyin.
    2127 Sistem Sağlığı Hizmeti Modülleri Alınan veri gönderme hatası hata kodu. Yalnızca gün içinde belirli aralıklarla gerçekleşirse, yoksayılabilir rastgele bir anomali olabilir. Ne sıklıkta gerçekleştiğini anlamak için izleyin. Gün boyunca sık sık oluyorsa, önce ağ yapılandırmanızı ve ara sunucu ayarlarınızı denetleyin. Açıklama HTTP hata kodu 404'i içeriyorsa ve aracı hizmete ilk kez veri göndermeye çalışıyorsa, iç 404 hata koduyla 500 hatası içerir. 404 hata kodu, yeni çalışma alanı için depolama alanının hala sağlandığını gösteren "bulunamadı" anlamına gelir. Bir sonraki yeniden denemede veriler beklendiği gibi çalışma alanına başarıyla yazılacaktır. HTTP hatası 403 bir izin veya kimlik bilgileri sorununu gösterebilir. Sorunun giderilmesine yardımcı olmak için 403 hatasına daha fazla bilgi eklenmiştir.
    4000 Hizmet Bağlayıcısı DNS ad çözümlemesi başarısız oldu. Makine hizmete veri gönderirken kullanılan internet adresini çözümleyemedi. Bu sorun makinenizdeki DNS çözümleyici ayarları, yanlış ara sunucu ayarları veya sağlayıcınızla ilgili geçici bir DNS sorunu olabilir. Düzenli aralıklarla gerçekleşirse, bunun nedeni ağla ilgili geçici bir sorun olabilir.
    4001 Hizmet Bağlayıcısı Hizmete Bağlan başarısız oldu. Bu hata, aracının Azure İzleyici hizmetine doğrudan veya bir güvenlik duvarı veya ara sunucu üzerinden iletişim kuramadığında oluşabilir. Aracı proxy ayarlarını doğrulayın veya ağ güvenlik duvarının veya ara sunucunun bilgisayardan hizmete TCP trafiğine izin verdiğinden emin olun.
    4002 Hizmet Bağlayıcısı Hizmet, sorguya yanıt olarak 403 HTTP durum kodunu döndürdü. Hizmetin sistem durumu için hizmet yöneticisine başvurun. Sorgu daha sonra yeniden denenecek. Bu hata, aracının ilk kayıt aşaması sırasında yazılır. https:// workspaceID.oms.opinsights.azure.com/AgentService.svc/AgentTopologyRequest<> benzer bir URL görürsünüz. 403 hata kodu "yasak" anlamına gelir ve yanlış yazılmış çalışma alanı kimliği veya anahtarı nedeniyle oluşabilir. Tarih ve saat bilgisayarda da yanlış olabilir. Süre geçerli saatten +/- 15 dakika sonraysa ekleme başarısız olur. Bu sorunu düzeltmek için Windows bilgisayarınızın tarih ve/veya saatini güncelleştirin.

Veri toplama sorunları

Aracı yüklendikten ve yapılandırılan çalışma alanına veya çalışma alanlarına rapor verdikten sonra, etkinleştirilen ve bilgisayarı hedefleyen işlemlere bağlı olarak yapılandırmayı almayı ve performansı, günlükleri veya diğer verileri hizmete iletmeyi veya toplamayı durdurabilir. Aşağıdakileri belirlemeniz gerekir:

  • Belirli bir veri türü mü yoksa çalışma alanında kullanılamayan tüm veriler mi?
  • Veri türü bir çözüm tarafından mı yoksa çalışma alanı veri toplama yapılandırmasının bir parçası olarak mı belirtildi?
  • Kaç bilgisayar etkileniyor? Çalışma alanına rapor eden tek bir bilgisayar mı yoksa birden çok bilgisayar mı?
  • Çalışıyor muydu ve günün belirli bir saatinde durdu mu yoksa hiç toplanmadı mı?
  • Kullandığınız günlük arama sorgusu tam olarak doğru mu?
  • Aracı yapılandırmasını Azure İzleyici'den hiç aldı mı?

Sorun gidermenin ilk adımı, bilgisayarın sinyal olayı gönderip göndermediğini belirlemektir.

Heartbeat 
    | where Computer like "<ComputerName>"
    | summarize arg_max(TimeGenerated, * ) by Computer

Sorgu sonuçları döndürürse belirli bir veri türünün toplanmadığını ve hizmete iletilip iletilmediğini belirlemeniz gerekir. Bu sorun, aracının hizmetten güncelleştirilmiş yapılandırmayı almamasından veya aracının normal çalışmasını engelleyen başka bir belirtiden kaynaklanabilir. Daha fazla sorun gidermek için aşağıdaki adımları gerçekleştirin.

  1. Bilgisayarda yükseltilmiş bir komut istemi açın ve girerek net stop healthservice && net start healthservicearacı hizmetini yeniden başlatın.

  2. Operations Manager olay günlüğünü açın ve Olay kaynağıHealthService'ten 7023, 7024, 7025, 7028 ve 1210 olay kimliklerini arayın. Bu olaylar aracının Azure İzleyici'den yapılandırmayı başarıyla aldığını ve bilgisayarı etkin bir şekilde izlediğini gösterir. Olay kimliği 1210 için olay açıklaması da son satırda aracıda izleme kapsamına dahil edilen tüm çözümleri ve Analizler belirtir.

    Screenshot that shows an Event ID 1210 description.

  3. Birkaç dakika bekleyin. Sorgu sonuçlarında veya görselleştirmede beklenen verileri görmüyorsanız, operations Manager olay günlüğünden bir çözümden veya İçgörüden verileri görüntüleyip görüntülemediğinize bağlı olarak Olay kaynaklarıHealthService ve Sistem Sağlığı Hizmeti Modülleri'ni arayın. Aşağıdaki tablodan olaylar yazıp yazmadığını onaylamak için Olay DüzeyiUyarısı ve Hatasına göre filtreleyin.

    Olay Kodu Source Açıklama Çözüm
    8000 HealthService Bu olay, performans, olay veya toplanan diğer veri türüyle ilgili bir iş akışının çalışma alanına alım için hizmete iletilip iletilemediğini belirtir. HealthService kaynağından Olay Kimliği 2136 bu olayla birlikte yazılır ve aracının hizmetle iletişim kuramadığını gösterebilir. Olası nedenler ara sunucu ve kimlik doğrulama ayarlarının yanlış yapılandırılması, ağ kesintisi veya ağ güvenlik duvarı ya da ara sunucusunun bilgisayardan hizmete TCP trafiğine izin vermemesi olabilir.
    10102 ve 10103 Sistem Sağlığı Hizmeti Modülleri İş akışı veri kaynağını çözümleyemedi. Belirtilen performans sayacı veya örneği bilgisayarda yoksa veya çalışma alanı veri ayarlarında yanlış tanımlanmışsa bu sorun oluşabilir. Bu kullanıcı tarafından belirtilen bir performans sayacıysa, belirtilen bilgilerin doğru biçimde olduğunu ve hedef bilgisayarlarda mevcut olduğunu doğrulayın.
    26002 Sistem Sağlığı Hizmeti Modülleri İş akışı veri kaynağını çözümleyemedi. Belirtilen Windows olay günlüğü bilgisayarda yoksa bu sorun oluşabilir. Bilgisayarda bu olay günlüğünün kayıtlı olması beklenmiyorsa bu hata güvenle yoksayılabilir. Aksi takdirde, bu kullanıcı tarafından belirtilen bir olay günlüğüyse, belirtilen bilgilerin doğru olduğunu doğrulayın.

Eski Microsoft monitoring agents ile sabitlenmiş sertifika sorunları - hataya neden olan değişiklik

Kök CA Değişikliğine Genel Bakış

30 Haziran 2023 itibarıyla Log Analytics arka ucu artık eski bir kök sertifikaya başvuran MMA bağlantılarını kabul etmeyecektir. Bu MMA'lar, Kış 2020 sürümünden (Log Analytics Aracısı) önceki ve SCOM 2019 UR3 (SCOM) öncesi eski sürümlerdir. Herhangi bir sürüm, Paket: 10.20.18053 / Uzantı: 1.0.18053.0 veya üzeri sürümlerde ve SCOM 2019 UR3'ün üzerinde herhangi bir sürümde sorun olmaz. Bundan eski tüm aracılar bozulacak ve artık çalışmıyor ve Log Analytics'e yükleniyor.

Tam olarak ne değişiyor?

Çeşitli Azure hizmetlerinde devam eden bir güvenlik çalışmasının parçası olarak Azure Log Analytics resmi olarak Baltimore CyberTrust CA Kökünden DigiCert Global G2 CA Köküne geçiş yapacaktır. Yeni DigiCert Global G2 CA Kök sertifikası işletim sisteminde eksikse veya uygulama eski Baltimore Kök CA'ya başvuruyorsa, bu değişiklik Log Analytics ile TLS iletişimlerini etkiler. Bu da Log Analytics'in kullanımdan kaldırıldıktan sonra MMA'dan bu eski kök CA'nın kullanıldığı bağlantıları kabul etmeyeceği anlamına gelir.

Çözüm ürünleri

Microsoft Monitoring Agent'ı kişisel olarak yüklememiş olsanız bile hataya neden olan değişiklik bildirimini almış olabilirsiniz. Bunun nedeni, çeşitli Azure ürünlerinin Microsoft Monitoring Agent'a sahip olmasıdır. Bu ürünlerden birini kullanıyorsanız Windows Log Analytics Aracısı'nı kullandıklarından etkilenebilirsiniz. Aşağıdaki bağlantıları olan ürünler için, en son aracıya yükseltmenizi gerektirecek belirli yönergeler olabilir.

HataYa neden olan Aracıları Belirleme ve Yeniden Başlatma

Sınırlı sayıda aracı içeren dağıtımlar için, bu yönetim yönergeleri aracılığıyla düğüm başına aracınızı yükseltmenizi kesinlikle öneririz.

Birden çok düğüme sahip dağıtımlar için abonelik başına etkilenen hata AA'larını algılayacak ve ardından bunları en son sürüme yükseltecek bir betik yazdık. Bu betiklerin UpdateMMA.ps1 ve upgradeMMA.ps1 ile başlayarak sırayla çalıştırılması gerekir. Makineye bağlı olarak betik biraz zaman alabilir. Zaman aşımından kaçınmak için PowerShell 7 veya üzeri gereklidir.

UpdateMMA.ps1 Bu betik, aboneliklerinizdeki VM'lerden geçer, yüklü mevcut MMA'ları denetler ve yükseltilmesi gereken aracılardan oluşan bir .csv dosyası oluşturur.

UpgradeMMA.ps1 Bu betik kullanır. Tüm hataya neden olan MMA'ları yükseltmek için UpdateMMA.ps1'de oluşturulan CSV dosyası.

Bu betiklerin her ikisinin de tamamlanması biraz zaman alabilir.

# UpdateMMA.ps1
# This script is to be run per subscription, the customer has to set the az subscription before running this within the terminal scope.
# This script uses parallel processing, modify the $parallelThrottleLimit parameter to either increase or decrease the number of parallel processes
# PS> .\UpdateMMA.ps1 GetInventory
# The above command will generate a csv file with the details of VM's and VMSS that require MMA upgrade. 
# The customer can modify the csv by adding/removing rows if needed
# Update the MMA by running the script again and passing the csv file as parameter as shown below:
# PS> .\UpdateMMA.ps1 Upgrade
# If you don't want to check the inventory, then run the script wiht an additional -no-inventory-check
# PS> .\UpdateMMA.ps1 GetInventory & .\UpdateMMA.ps1 Upgrade


# This version of the script requires Powershell version >= 7 in order to improve performance via ForEach-Object -Parallel
# https://docs.microsoft.com/powershell/scripting/whats-new/migrating-from-windows-powershell-51-to-powershell-7?view=powershell-7.1
if ($PSVersionTable.PSVersion.Major -lt 7) 
{
    Write-Host "This script requires Powershell version 7 or newer to run. Please see https://docs.microsoft.com/powershell/scripting/whats-new/migrating-from-windows-powershell-51-to-powershell-7?view=powershell-7.1."
    exit 1
}

$parallelThrottleLimit = 16
$mmaFixVersion = [version]"10.20.18053.0"

function GetVmsWithMMAInstalled
{
    param(
        $fileName
    )

    $vmList = az vm list --show-details --query "[?powerState=='VM running'].{ResourceGroup:resourceGroup, VmName:name}" | ConvertFrom-Json
    
    if(!$vmList)
    {
        Write-Host "Cannot get the VM list, this script can only detect the running VM's"
        return
    }

    $vmsCount = $vmList.Length
    
    $vmParallelThrottleLimit = $parallelThrottleLimit
    if ($vmsCount -lt $vmParallelThrottleLimit) 
    {
        $vmParallelThrottleLimit = $vmsCount
    }

    if($vmsCount -eq 1)
    {
        $vmGroups += ,($vmList[0])
    }
    else
    {
        # split the vm's into batches to do parallel processing
        for ($i = 0; $i -lt $vmsCount; $i += $vmParallelThrottleLimit) 
        { 
            $vmGroups += , ($vmList[$i..($i + $vmParallelThrottleLimit - 1)]) 
        }
    }

    Write-Host "Detected $vmsCount Vm's running in this subscription."
    $hash = [hashtable]::Synchronized(@{})
    $hash.One = 1

    $vmGroups | Foreach-Object -ThrottleLimit $parallelThrottleLimit -Parallel {
        $len = $using:vmsCount
        $hash = $using:hash
        $_ | ForEach-Object {
            $percent = 100 * $hash.One++ / $len
            Write-Progress -Activity "Getting VM Inventory" -PercentComplete $percent
            $vmName = $_.VmName
            $resourceGroup = $_.ResourceGroup
            $responseJson = az vm run-command invoke --command-id RunPowerShellScript --name $vmName -g $resourceGroup --scripts '@UpgradeMMA.ps1' --parameters "functionName=GetMMAVersion" --output json | ConvertFrom-Json
            if($responseJson)
            {
                $mmaVersion = $responseJson.Value[0].message
                if ($mmaVersion) 
                {
                    $extensionName = az vm extension list -g $resourceGroup --vm-name $vmName --query "[?name == 'MicrosoftMonitoringAgent'].name" | ConvertFrom-Json
                    if ($extensionName) 
                    {
                        $installType = "Extension"
                    }
                    else 
                    {
                        $installType = "Installer"
                    }
                    $csvObj = New-Object -TypeName PSObject -Property @{
                        'Name'           = $vmName
                        'Resource_Group' = $resourceGroup
                        'Resource_Type'  = "VM"
                        'Install_Type'   = $installType
                        'Version'        = $mmaVersion
                        "Instance_Id"    = ""
                    }
                    $csvObj | Export-Csv $using:fileName -Append -Force
                } 
            } 
        }
    }
}

function GetVmssWithMMAInstalled
{
    param(
        $fileName
    )

    # get the vmss list which are successfully provisioned
    $vmssList = az vmss list --query "[?provisioningState=='Succeeded'].{ResourceGroup:resourceGroup, VmssName:name}" | ConvertFrom-Json   

    $vmssCount = $vmssList.Length
    Write-Host "Detected $vmssCount Vmss running in this subscription."
    $hash = [hashtable]::Synchronized(@{})
    $hash.One = 1

    $vmssList | Foreach-Object -ThrottleLimit $parallelThrottleLimit -Parallel {
        $len = $using:vmssCount
        $hash = $using:hash
        $percent = 100 * $hash.One++ / $len
        Write-Progress -Activity "Getting VMSS Inventory" -PercentComplete $percent
        $vmssName = $_.VmssName
        $resourceGroup = $_.ResourceGroup

        # get running vmss instance ids
        $vmssInstanceIds = az vmss list-instances --resource-group $resourceGroup --name $vmssName --expand instanceView --query "[?instanceView.statuses[1].displayStatus=='VM running'].instanceId" | ConvertFrom-Json
        if ($vmssInstanceIds.Length -gt 0) 
        {
            $isMMAExtensionInstalled = az vmss extension list -g $resourceGroup --vmss-name $vmssName --query "[?name == 'MicrosoftMonitoringAgent'].name" | ConvertFrom-Json
            if ($isMMAExtensionInstalled ) 
            {
                # check an instance in vmss, if it needs an MMA upgrade. Since the extension is installed at VMSS level, checking for bad version in 1 instance should be fine.
                $responseJson = az vmss run-command invoke --command-id RunPowerShellScript --name $vmssName -g $resourceGroup --instance-id $vmssInstanceIds[0] --scripts '@UpgradeMMA.ps1' --parameters "functionName=GetMMAVersion" --output json | ConvertFrom-Json
                $mmaVersion = $responseJson.Value[0].message
                if ($mmaVersion) 
                {
                    $csvObj = New-Object -TypeName PSObject -Property @{
                        'Name'           = $vmssName
                        'Resource_Group' = $resourceGroup
                        'Resource_Type'  = "VMSS"
                        'Install_Type'   = "Extension"
                        'Version'        = $mmaVersion
                        "Instance_Id"    = ""
                    }
                    $csvObj | Export-Csv $using:fileName -Append -Force
                }
            }
            else 
            {
                foreach ($instanceId in $vmssInstanceIds) 
                {
                    $responseJson = az vmss run-command invoke --command-id RunPowerShellScript --name $vmssName -g $resourceGroup --instance-id $instanceId --scripts '@UpgradeMMA.ps1' --parameters "functionName=GetMMAVersion" --output json | ConvertFrom-Json
                    $mmaVersion = $responseJson.Value[0].message
                    if ($mmaVersion) 
                    {
                        $csvObj = New-Object -TypeName PSObject -Property @{
                            'Name'           = $vmssName
                            'Resource_Group' = $resourceGroup
                            'Resource_Type'  = "VMSS"
                            'Install_Type'   = "Installer"
                            'Version'        = $mmaVersion
                            "Instance_Id"    = $instanceId
                        }
                        $csvObj | Export-Csv $using:fileName -Append -Force
                    }
                }
            }
        }      
    }
}

function Upgrade
{
    param(
        $fileName = "MMAInventory.csv"
    )
    Import-Csv $fileName | ForEach-Object -ThrottleLimit $parallelThrottleLimit -Parallel {
        $mmaVersion = [version]$_.Version
        if($mmaVersion -lt $using:mmaFixVersion)
        {
            if ($_.Install_Type -eq "Extension") 
            {
                if ($_.Resource_Type -eq "VMSS") 
                {
                    # if the extension is installed with a custom name, provide the name using the flag: --extension-instance-name <extension name>
                    az vmss extension set --name MicrosoftMonitoringAgent --publisher Microsoft.EnterpriseCloud.Monitoring --force-update --vmss-name $_.Name --resource-group $_.Resource_Group --no-wait --output none
                }
                else 
                {
                    # if the extension is installed with a custom name, provide the name using the flag: --extension-instance-name <extension name>
                    az vm extension set --name MicrosoftMonitoringAgent --publisher Microsoft.EnterpriseCloud.Monitoring --force-update --vm-name $_.Name --resource-group $_.Resource_Group --no-wait --output none
                }
            }
            else {
                if ($_.Resource_Type -eq "VMSS") 
                {
                    az vmss run-command invoke --command-id RunPowerShellScript --name $_.Name -g $_.Resource_Group --instance-id $_.Instance_Id --scripts '@UpgradeMMA.ps1' --parameters "functionName=UpgradeMMA" --output none
                }
                else 
                {
                    az vm run-command invoke --command-id RunPowerShellScript --name $_.Name -g $_.Resource_Group --scripts '@UpgradeMMA.ps1' --parameters "functionName=UpgradeMMA" --output none
                }
            }
        }
    }
}

function GetInventory
{
    param(
        $fileName = "MMAInventory.csv"
    )

    # create a new file 
    New-Item -Name $fileName -ItemType File -Force
    GetVmsWithMMAInstalled $fileName
    GetVmssWithMMAInstalled $fileName
}

switch ($args.Count)
{
    0 {
        Write-Host "The arguments provided are incorrect."
        Write-Host "To get the Inventory: Run the script as: PS> .\UpdateMMA.ps1 GetInventory"
        Write-Host "To update MMA from Inventory: Run the script as: PS> .\UpdateMMA.ps1 Upgrade"
        Write-Host "To do the both steps together: PS> .\UpdateMMA.ps1 GetInventory & .\UpdateMMA.ps1 Upgrade"
    }
    1 {
        $funcname = $args[0]
        Invoke-Expression "& $funcname"
    }
    2 {
        $funcname = $args[0]
        $funcargs = $args[1]
        Invoke-Expression "& $funcname $funcargs"
    }
}