Image by Pexels from Pixabay

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.

image

Click Add diagnostic setting.

image 1

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 Performance monitoring, trending, and alerting Performance monitoring, trending, 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.

image 12

Now, my diagnostic setting is there.

image 5

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.

image 10

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

image 13

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.

image 6

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.

image 7

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.

image 8

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.

image 9

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.

image 15

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.

Share.
Leave A Reply