Tracing in Azure (SaaS Deployment)
As part of the EmpowerID SaaS deployment, all application and diagnostic logs are collected centrally in Azure Log Analytics. This replaces the previous method of inspecting local logs through Windows Event Viewer.
This article explains how to access and query EmpowerID logs in Azure, using Kusto Query Language (KQL).
Overview
The EmpowerID application emits structured JSON logs using the EmpowerIDTraceContext class.
In a SaaS environment, these logs are automatically collected from each container and stored in Azure Log Analytics under tables such as:
ContainerLogContainerInventoryAzureDiagnostics
Each log entry contains contextual properties such as:
eidProcessprocessNamepidSourceContextprocessTimeeventTypedataormessage
These fields make it possible to correlate application events across processes, instances, and timeframes.
Accessing Logs in Azure
- Go to your Azure Portal.
- Open the Log Analytics Workspace for your EmpowerID environment.
- Select Logs from the left navigation pane.
- Choose the appropriate scope (e.g., AKS Cluster, Application Insights, or EmpowerID Workspace).
- Use the Kusto Query editor to run queries against the
ContainerLogtable.
Basic Query Template
The following base query retrieves EmpowerID logs for a specific container or application service.
let containers = ContainerInventory
| where Name contains "prod" and Name contains "eid-web"
| distinct ContainerID, Name;
ContainerLog
| join kind=inner containers on ContainerID
| extend log = parse_json(LogEntry)
| extend processTime = todatetime(log.processTime)
| extend pid = log.pid
| extend processName = log.processName
| extend eventType = log.eventType
| extend message = iff(isnotnull(log.message), log.message, log.data)
| project processTime, pid, processName, eventType, message, Name
| order by processTime desc
Tip: To focus on recent activity, you can add a time filter:
| where TimeGenerated > ago(30m)
Common Use Cases
Find Application Errors
ContainerLog
| extend log = parse_json(LogEntry)
| where log.eventType == "Error"
| project log.processTime, log.processName, log.message
| order by log.processTime desc
Filter by Workflow Name
ContainerLog
| extend log = parse_json(LogEntry)
| where log.message contains "WorkflowName:CreateAzureApplicationV3"
| project log.processTime, log.processName, log.eventType, log.message
| order by log.processTime desc
Search for SQL Timeout or Connectivity Issues
ContainerLog
| extend log = parse_json(LogEntry)
| where log.message contains "SqlNetTiersProvider: Error-CmdDetails"
| project log.processTime, log.processName, log.eventType, log.message
| order by log.processTime desc
Retrieve Logs for a Specific User or Actor
ContainerLog
| extend log = parse_json(LogEntry)
| where log.message contains "Actor: Z004DZCZ"
| project log.processTime, log.processName, log.eventType, log.message
| order by log.processTime desc
Trace a Workflow by Process ID (PID)
ContainerLog
| extend log = parse_json(LogEntry)
| where tostring(log.pid) == "12216"
| project log.processTime, log.processName, log.eventType, log.message
| order by log.processTime desc
Note: PIDs are reused periodically — always apply a time filter to narrow the search window.
Example: Troubleshooting a Workflow
-
Identify the workflow name from the EmpowerID portal or API (e.g.,
WorkflowName:OnBoardGroup). -
In the Azure Log Analytics query editor, run:
ContainerLog
| extend log = parse_json(LogEntry)
| where log.message contains "WorkflowName:OnBoardGroup"
| project log.processTime, log.processName, log.eventType, log.message
| order by log.processTime desc -
Review entries for any
ErrororExceptionevents. -
If you need to correlate logs for a specific instance, extract the
pidfrom one entry and re-query using it as shown above.
Advanced Examples
SQL Timeout Summary by Command
let containers = ContainerInventory
| where Name contains "prod" and Name contains "eid-web"
| distinct ContainerID, Name;
ContainerLog
| join kind=inner containers on ContainerID
| where LogEntry contains "SqlNetTiersProvider: Error-CmdDetails"
| extend log = parse_json(LogEntry)
| extend msg = tostring(log.data)
| extend parts = split(msg, ":")
| extend command = tostring(parts[2])
| summarize Count = count() by command
| order by Count desc
Application Gateway 50x Errors
AzureDiagnostics
| where Category == "ApplicationGatewayAccessLog"
| where httpStatus_d in ("502", "503")
| order by TimeGenerated desc
Check Container Health (Within 5 Minutes)
let activeContainers = ContainerInventory
| where ContainerHostname contains "eid"
| where TimeGenerated between (ago(5m) .. now())
| summarize lastInventoried = max(TimeGenerated) by Computer, ContainerID, ContainerHostname, clusterName = replace_regex(_ResourceId, @"^.+\/", ""), ImageTag;
let logs = ContainerLog
| where TimeGenerated between (ago(5m) .. now());
activeContainers
| join kind=leftouter logs on Computer, ContainerID
| summarize lastMsgTime = max(TimeGenerated), numMsgs = count() by Computer, ContainerID, ContainerHostname, lastInventoried, clusterName, ImageTag
| order by numMsgs, lastMsgTime
Query Tips
- Parsing JSON: Always use
parse_json(LogEntry)to extract structured log fields. - Case Sensitivity: Use
containsfor case-insensitive search,hasfor more exact term matching. - Date Range: Restrict queries with
TimeGeneratedfilters to improve performance. - Performance: Avoid scanning all containers — always scope to relevant names or environments (e.g.,
prod,uat,diag).
Related Resources
- EmpowerIDTraceContext Class Reference
- Kusto Query Language Documentation
- Azure Monitor Tables Reference
Summary
| Environment | Tracing Method | Location |
|---|---|---|
| On-Premises / Legacy | Windows Event Viewer | Local Server |
| SaaS (Cloud) | Azure Log Analytics | Azure Portal → Log Analytics Workspace |
Use EmpowerIDTraceContext to emit structured context logs, and use Azure Log Analytics (KQL) to analyze, filter, and correlate those logs across your distributed EmpowerID SaaS environment.