In this post, we’ll explain how to configure Azure Monitor with Azure Log Analytics in Microsoft Azure, so you can proactively monitor your Azure Resource Manager (ARM)-based Windows Virtual Desktop environment.
This blog post, which comes from a collaboration of different teams within Microsoft, aims to empower our customers on the ARM-based Windows Virtual Desktop. The information in this post is community driven. Nothing is officially launched by the Windows Virtual Desktop product team. I want to highlight @VanessaBruwer, @JasonByway and @ThomasVuylsteke at Microsoft for their work creating the custom workbook.
Let's begin. As shown in the diagram below, Azure Monitor can collect diagnostic data and operational insights from a variety of sources. You can monitor data for your workspace and virtual machine (VM) performance as well as tiered session information from your host pools, operating system and the services it relies on, and the platform itself.
By following the steps in this post, you can create a dashboard that provides access to insights about key elements of your Windows Virtual Desktop deployment, such as:
The custom dashboard gives you visibility of key elements for your Windows Virtual Desktop workspace. Here, we’re highlighting the top three insights: session details, host pool performance, and disk performance.
The dashboard view below shows the status of the most important session details—including top hosts, active users, and more—for your Windows Virtual Desktop workspace.
In this dashboard, you can collect and view information about the performance and registration statuses of your hosts.
Through the Disk Performance dashboard you can view captured information about the storage level consumption of your profile container—virtual (logical) disks. This information can help you measure input/output operations per second (IOPS) and latency to your Azure Files or Azure NetApp Files environment regarding FSLogix Profile Container use in your Windows Virtual Desktop workspace.
To monitor your ARM-based Windows Virtual Desktop environment, be sure you have the following prerequisites in place:
To install the Workspace agent on the session hosts as part of your Windows Virtual Desktop host pool(s), perform the following steps.
The agent will automatically be installed and pushed to the session hosts via Azure extensions. For additional information, see Enable Azure Monitor for VMs overview.
Terminal Services Session(*)\% Processor Time |
Terminal Services(*)\Active Sessions |
Terminal Services(*)\Inactive Sessions |
Terminal Services(*)\Total Sessions |
LogicalDisk(*)\% Free Space |
LogicalDisk(*)\Avg. Disk sec/Read |
LogicalDisk(*)\Avg. Disk sec/Write |
LogicalDisk(*)\Current Disk Queue Length |
LogicalDisk(*)\Disk Reads/sec |
LogicalDisk(*)\Disk Transfers/sec |
LogicalDisk(*)\Disk Writes/sec |
LogicalDisk(*)\Free Megabytes |
Processor(_Total)\% Processor Time |
Memory(*)\% Committed Bytes In Use |
Network Adapter(*)\Bytes Received/sec |
Network Adapter(*)\Bytes Sent/sec |
Process(*)\% Processor Time |
Process(*)\% User Time |
Process(*)\IO Read Operations/sec |
Process(*)\IO Write Operations/sec |
Process(*)\Thread Count |
Process(*)\Working Set |
RemoteFX Graphics(*)\Average Encoding Time |
RemoteFX Graphics(*)\Frames Skipped/Second - Insufficient Client Resources |
RemoteFX Graphics(*)\Frames Skipped/Second - Insufficient Network Resources |
RemoteFX Graphics(*)\Frames Skipped/Second - Insufficient Server Resources |
RemoteFX Network(*)\Current TCP Bandwidth |
RemoteFX Network(*)\Current TCP RTT |
RemoteFX Network(*)\Current UDP Bandwidth |
RemoteFX Network(*)\Current UDP RTT |
PhysicalDisk(*)\Avg. Disk Bytes/Read
|
PhysicalDisk(*)\Avg. Disk Bytes/Write
|
PhysicalDisk(*)\Avg. Disk sec/Write
|
PhysicalDisk(*)\Avg. Disk sec/Read
|
PhysicalDisk(*)\Avg. Disk Bytes/Transfer
|
PhysicalDisk(*)\Avg. Disk sec/Transfer
|
Now that you've enabled diagnostic data, here are some sample queries you can run.
Perf
| where ObjectName == "Terminal Services"
| where CounterName == "Active Sessions"
| summarize arg_max(TimeGenerated, *) by Computer
| project Computer, CounterName, CounterValue
Perf
| where ObjectName == "Terminal Services"
| where CounterName == "Inactive Sessions"
| summarize arg_max(TimeGenerated, *) by Computer
| project Computer, CounterName, CounterValue
Perf
| where ObjectName == "Terminal Services"
| where CounterName == "Total Sessions"
| summarize arg_max(TimeGenerated, *) by Computer
| project Computer, CounterName, CounterValue
Perf
| where ObjectName == "Terminal Services"
| where CounterName == "Total Sessions"
| summarize AggregatedValue = avg(CounterValue) by bin(TimeGenerated, 1h), Computer
Perf
| where ObjectName == "Terminal Services"
| where CounterName == "Total Sessions"
| summarize AggregatedValue = max(CounterValue) by bin(TimeGenerated, 1h), Computer
let Events = WVDConnections | where UserName == 'username';
Events
| where State == "Connected"
| project CorrelationId , UserName, ResourceAlias , StartTime=TimeGenerated
| join (Events
| where State == "Completed"
| project EndTime=TimeGenerated, CorrelationId)
on CorrelationId
| project Duration = EndTime - StartTime, ResourceAlias
| sort by Duration desc
Logical disk:
Perf
| where ObjectName == "LogicalDisk" and CounterName == "% Free Space"
| where InstanceName <> "_Total"
| summarize AggregatedValue = avg(CounterValue) by bin(TimeGenerated, 10m), Computer, InstanceName
Processor:
Perf
| where ObjectName == "Processor" and CounterName == "% Processor Time"
| summarize AggregatedValue = avg(CounterValue) by bin(TimeGenerated, 10m), Computer, InstanceName
Memory:
Perf
| where ObjectName == "Memory" and CounterName == "% Committed Bytes In Use"
| summarize AggregatedValue = avg(CounterValue) by bin(TimeGenerated, 10m), Computer, InstanceName
Network:
Perf
| where ObjectName == "Network Interface"
| summarize AggregatedValue = avg(CounterValue) by bin(TimeGenerated, 10m), Computer, InstanceName, CounterName
Processor utilization per user:
Perf
| where ObjectName == "Process"
| join
(
VMProcess
| where UserName !contains "system" and UserName !contains "service"
| extend InstanceName = ExecutableName
| project TimeGenerated, InstanceName, Computer, UserName, UserDomain
)
on InstanceName
| summarize AggregatedValue = avg(CounterValue) by bin(TimeGenerated, 10m), InstanceName, CounterName, UserName, Computer
VMConnection
| join
(
VMProcess
| where UserName !contains "system" and UserName !contains "service"
| extend ProcessName = ExecutableName
| project TimeGenerated, ProcessName, Computer, UserName, UserDomain
)
on ProcessName
Perf
| where ObjectName == "RemoteFX Network"
| where CounterName == "Current TCP RTT" or CounterName == "Current UDP RTT"
| summarize AggregatedValue = avg(CounterValue) by bin(TimeGenerated, 1h), Computer, InstanceName
WVDConnections
| where State == "Connected"
| summarize ClientCount = dcount(UserName) by ClientOS, ClientVersion
WVDConnections
| where State == "Connected"
| extend ClientOSType = pack("ClientOSVersion", ClientOS)
| summarize AggregatedValue = count() by ClientOS
Heartbeat
| summarize heartbeat_count = count() by bin(TimeGenerated, 30m), Computer // bin is used to set the time grain to 30 minutes
| extend Available=iff(heartbeat_count > 0, true, false)
| summarize LastCall = max(TimeGenerated) by Computer, alive
| project Computer, LastCall, alive
Perf
| where ObjectName contains "Terminal Services" and CounterName == "Total Sessions"
| summarize TotalSessions = max(CounterValue) by bin(TimeGenerated, 1d), Computer
Perf
| where ObjectName == "Processor" and CounterName == "% Processor Time"
| summarize AggregatedValue = avg(CounterValue) by bin(TimeGenerated, 1h), Computer
| where AggregatedValue > 80
| order by AggregatedValue desc
| take 10
Perf
| where ObjectName == "PhysicalDisk" and CounterName == "Avg. Disk Bytes/Read" and InstanceName !contains "Total"
| parse InstanceName with * " " DriveLetter
| summarize AggregatedValue = avg(CounterValue) by bin(TimeGenerated, 10m), Computer, DriveLetter
Creating a custom dashboard as a landing page for your Azure portal is beneficial. This dashboard can also be used as a central page for your IT department.
If you run into issues during setup, see Troubleshooting overview, feedback, and support for more information.
To stay informed about the latest Windows Virtual Desktop enhancements, join the Windows Virtual Desktop community on Tech Community, where you can also connect with the Windows Virtual Desktop Engineering team and your fellow public preview participants. For more information on tools that can help you empower end users to work securely in a remote work world, see Brad Anderson's post on New tools to help IT empower employees securely in a remote work world.
We welcome your feedback, comments, and questions below.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.