
Logging is a necessity in the database world, well, the entire tech world. You need to know what is happening in and around your databases. It’s easy to setup in Azure SQL DB.
This post will guide you through setting up and querying diagnostic settings to access your database logs easily.
Setting up a diagnostic setting
It’s a good idea to have a dedicated log analytics workspace, rather than using the default one. You can use this to create one before setting up your diagnostic setting, or you can use an existing one.
It’s quite easy to set up capturing errors for Azure SQL DB. You need to set up a diagnostic setting at the database level, under Monitoring > Diagnostic Settings.

Click Add diagnostic setting.

Logging/metrics options
Let’s review our options for logging.
Logs Category | What It Gets |
---|---|
SQL Insights | Query performance analysis, execution plans, resource usage patterns, and optimization recommendations |
Automatic Tuning | Index recommendations, query plan corrections, automatic index creation/drop events, and tuning actions taken by SQL Server |
Query Store Runtime Statistics | Captures query execution metrics, wait statistics, performance counters, and runtime execution data for query performance monitoring. |
Query Store Wait Statistics | Wait events during query execution (locks, I/O waits, CPU waits, memory waits, etc.) |
Errors | SQL Server error messages, failed logins, constraint violations, deadlock victims, and other exception events |
Database Wait Statistics | System-wide wait statistics showing resource bottlenecks and performance issues |
Timeouts | Query timeout events, connection timeouts, and other time-based failures |
Blocks | Blocking chains, lock escalations, and sessions waiting on resources held by other sessions |
Deadlocks | Deadlock graphs, victim selection details, and resources involved in deadlock scenarios |
Devops Operations Audit Logs | Administrative actions, deployments, configuration changes, and operational events |
SQL Security Audit Event (I don’t use this, as it doesn’t seem to work; instead, use Auditing, which is further discussed in the article.) | Login attempts, permission changes, data access events, schema modifications, and security-related activities |
Additionally, you have some other options with metrics.
Metric Category | What It Gets |
---|---|
Basic | Core performance counters like CPU usage, memory utilization, disk I/O rates, network throughput, active connections, transactions per second, and fundamental database operations |
InstanceAndAppAdvanced | Advanced instance-level metrics, including buffer pool statistics, plan cache hit ratios, lock statistics, wait statistics, batch requests/sec, page life expectancy, memory grants, and application-specific performance counters |
WorkloadManagement | Resource governance metrics such as resource pool statistics, workload group performance, query execution resource consumption, memory allocation per workload, CPU throttling events, and resource usage by different application workloads |
The logs and metrics capture different types of information.
Aspect | Logs | Metrics |
---|---|---|
Data Type | Event-based records (what happened, when, why) | Numerical measurements (how much, how fast, how often) |
Format | Structured log entries with timestamps and details | Time-series data points and counters |
Purpose | Debugging, auditing, and root cause analysis | Performance monitoring and operational alerting |
For example:
- Metrics show you that there’s a problem (high CPU, long waits)
- Logs show you what caused it (specific queries, deadlocks, errors)
Scenario | Metrics Show | Logs Provide |
---|---|---|
Performance Issue | High CPU usage, increased wait times | Specific slow queries (SQL Insights), blocking chains (Blocks) |
Deadlock Problem | Decreased throughput, timeout spikes | Deadlock graphs and victim details (Deadlocks) |
Security Concern | Unusual connection patterns | Failed login attempts, permission changes (SQL Security Audit) |
Optimization | Resource usage trends | Auto-tuning actions taken, index recommendations (Automatic Tuning) |
When choosing what to select, allLogs gives you all the logs (imagine that!), and audit gives you only Devops Operations Audit Logs and SQL Security Audit Event.
Configuring the diagnostic setting
I’ve decided to set up all logs except SQL Security Audit Event, which I will configure separately, along with all metrics, and then put it in my SQLLAW and click Save.

Now, my diagnostic setting is there.

To capture audits of what happens inside the database, you also need to enable auditing, and I’ll put it in the same Log Analytics workspace as my logs.

And once you save that auditing piece, you can revisit the diagnostic settings and see it there.

It would be nice if the SQL audit worked with the checkbox in the logging diagnostic setting I set up, but alas, it doesn’t, so I had to resort to using it with the official auditing function.
Now, we have all the bits and pieces for logging and auditing in the same log analytics workspace, and we can query it.
View the log and audit data
To do this, you need to access the Log Analytics workspace and run a Kusto query. I have a Kusto tutorial available here, but I’ll also provide some additional information below.
Before we even attempt to examine the logs, let’s make some things happen; otherwise, the results will be very uninteresting, namely, nothing returns. I logged into my database and attempted to create a table incorrectly, then created it correctly to ensure something was logged. If you are setting this up on a legit database that has things happening in it, you won’t have to do that.
That being said, I’m going to my log analytics workspace now and clicking on Logs.

A box of suggested queries pops up, but I never use it. I never found it particularly helpful for anything I wanted to do. I close that and use the query window, with KQL mode.

Querying log results
Then, I will run this query. This will display all the information in the log related to Azure SQL.
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.SQL"
There are a lot more columns, too.

What I find helpful is to project this out into a table with only the columns I want to see, and I also like to include some of the other filters in that query.
Maybe you only want to see one category of logs. Here are the categories available to you with Azure SQL DB:
Category | Description |
---|---|
SQLInsights | Intelligent Insights into database performance |
AutomaticTuning | Information about automatic tuning recommendations and actions |
QueryStoreRuntimeStatistics | Query runtime statistics (CPU usage, duration, execution counts) |
QueryStoreWaitStatistics | Query wait statistics (what queries waited on) |
Errors | SQL error messages and events |
DatabaseWaitStatistics | Database-level wait statistics by wait type |
Timeouts | Query timeout events |
Blocks | Blocking events and lock information |
Deadlocks | Deadlock events with XML reports |
Devops operations Audit Logs | DevOps Operations Audit Logs capture infrastructure and administrative operations such as deployments, scaling, user management, and configuration changes rather than data access activities. |
SQLSecurityAuditEvents | Login attempts, permission changes, data access events, schema modifications, and security-related activities |
Additionally, you have options for handling TimeGenerated, including functions and time units ago.
Function | Description | Example |
---|---|---|
ago() | Time relative to now | TimeGenerated > ago(1d) |
now() | Current time | TimeGenerated > now(-1d) |
datetime() | Specific date/time | TimeGenerated > datetime(2025-01-01) |
startofday() | Start of day | TimeGenerated > startofday(now()) |
startofweek() | Start of week | TimeGenerated > startofweek(now()) |
startofmonth() | Start of month | TimeGenerated > startofmonth(now()) |
Time Units for ago()
Unit | Abbreviation | Example |
---|---|---|
Minutes | m | ago(30m) |
Hours | h | ago(4h) |
Days | d | ago(7d) |
Weeks | w | ago(2w) |
Months | M | ago(3M) |
Years | y | ago(1y) |
And what we wind up with his something like this:
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.SQL"
and TimeGenerated > ago(1d)
and Category == "Errors"
| project TimeGenerated, Message, ResourceGroup, DatabaseName_s
If you have errors, you will get results similar to the following screenshot. Note that I don’t usually put things in the default resource group, but I was too lazy to create a new one for this demo, even though it’s not a lot of work.

Querying audit results
To get the audit records for people querying inside the db, you can use the following query, but note that SQL Security Audit Events can take longer (up to 2 hours delay after setting up) to process and appear compared to the other diagnostic logs like performance metrics, errors, etc.
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.SQL"
and TimeGenerated > ago(4d)
and Category == "SQLSecurityAuditEvents"
| where database_name_s != 'master'
| project
event_time_t,
ResourceGroup,
server_instance_name_s,
database_name_s,
statement_s,
server_principal_name_s,
succeeded_s,
client_ip_s,
application_name_s,
additional_information_s,
data_sensitivity_information_s
I specifically searched for the DROP TABLE statements I ran.

And if you haven’t used SQL audit before, you will be surprised at all the stuff that happens behind the scenes that also gets audited. You can configure the auditing to capture fewer actions by modifying the actions it captures. I cover that in this post.
I’m going to create a dashboard for these results, allowing anyone at my company to query this data in the future easily. That will be covered in a future post, but I will probably use Azure Workbooks.
The post Capturing errors and auditing in Azure SQL DB appeared first on sqlkitty.