Skip to main content

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:

  • ContainerLog
  • ContainerInventory
  • AzureDiagnostics

Each log entry contains contextual properties such as:

  • eidProcess
  • processName
  • pid
  • SourceContext
  • processTime
  • eventType
  • data or message

These fields make it possible to correlate application events across processes, instances, and timeframes.

Accessing Logs in Azure

  1. Go to your Azure Portal.
  2. Open the Log Analytics Workspace for your EmpowerID environment.
  3. Select Logs from the left navigation pane.
  4. Choose the appropriate scope (e.g., AKS Cluster, Application Insights, or EmpowerID Workspace).
  5. Use the Kusto Query editor to run queries against the ContainerLog table.

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

  1. Identify the workflow name from the EmpowerID portal or API (e.g., WorkflowName:OnBoardGroup).

  2. 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
  3. Review entries for any Error or Exception events.

  4. If you need to correlate logs for a specific instance, extract the pid from 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 contains for case-insensitive search, has for more exact term matching.
  • Date Range: Restrict queries with TimeGenerated filters to improve performance.
  • Performance: Avoid scanning all containers — always scope to relevant names or environments (e.g., prod, uat, diag).

Summary

EnvironmentTracing MethodLocation
On-Premises / LegacyWindows Event ViewerLocal Server
SaaS (Cloud)Azure Log AnalyticsAzure 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.