DBA Scripts: Get Recent Error Log Entries

Part of the DBA-Tools Project.


The SQL Server error log records almost everything worth knowing about an instance’s recent health, and almost nobody reads it until they’re already troubleshooting something. It’s not that the information isn’t there, it’s that xp_readerrorlog returns thousands of lines dominated by routine noise, every successful backup, every log backup, every clean CHECKDB, until the two lines that actually matter are buried somewhere in the middle.

This script reads the last 24 hours of the error log and filters out the routine noise, backups, log backups, clean integrity checks, so what’s left is the entries actually worth looking at.


Why Recent Error Log Entries Matter

The error log is where SQL Server writes things no other view surfaces as directly:

  • Memory pressure warnings (“a significant part of SQL Server process memory has been paged out”) appear here well before a performance complaint reaches you, they’re an early signal, not a lagging indicator.
  • sp_server_diagnostics delay warnings point at scheduler or resource contention severe enough that SQL Server’s own internal health check is struggling to run on time, worth investigating even if nothing else looks obviously wrong yet.
  • Startup and shutdown events, failed logins, I/O errors, and corruption warnings all land here, often before they surface anywhere else in the monitoring stack.
  • It’s the first place support engineers and consultants look when troubleshooting an unfamiliar instance, because it’s a chronological record with no configuration required to start collecting it, it’s always been running.

Common Symptoms

  • General “something feels off” performance complaints with no obvious cause in wait stats or query plans.
  • A DBA scrolling through raw xp_readerrorlog output during an incident, manually skipping past hundreds of routine backup lines.
  • A memory or I/O issue that, in hindsight, had been warning about itself in the error log for hours or days before anyone noticed.

When to Run This Script

  • Routine SQL Server health checks
  • The first step in any troubleshooting session on an unfamiliar or newly inherited instance
  • After a performance complaint, before diving into wait stats or execution plans
  • Immediately after any unexpected restart, to see what led up to it

The Script

Run the following script against your SQL Server instance.

/*
Script Name : Get-RecentErrorLogEntries
Category    : maintenance-and-reliability
Purpose     : Show SQL Server error log entries from the last 24 hours, filtering routine noise.
Author      : Peter Whyte (https://sqldba.blog/dba-scripts-get-recent-error-log-entries/)
Requires    : VIEW SERVER STATE (xp_readerrorlog; sysadmin in practice for most instances)
HealthCheck : Yes
*/
-- SAFE:ReadOnly
-- IMPACT:Low
SET NOCOUNT ON;

IF OBJECT_ID('tempdb..#error_log') IS NOT NULL DROP TABLE #error_log;

CREATE TABLE #error_log (
    log_date     DATETIME,
    process_info NVARCHAR(100),
    log_text     NVARCHAR(4000)
);

INSERT INTO #error_log (log_date, process_info, log_text)
EXEC xp_readerrorlog 0, 1, NULL, NULL, NULL, NULL, 'asc';

SELECT TOP 500
    log_date,
    process_info,
    log_text
FROM #error_log
WHERE log_date >= DATEADD(HOUR, -24, GETDATE())
  AND log_text NOT LIKE '%This is an informational message%'
  AND log_text NOT LIKE '%found 0 errors%'
  AND log_text NOT LIKE '%without errors%'
  AND log_text NOT LIKE '%Log was backed up%'
  AND log_text NOT LIKE '%Database backed up%'
  AND log_text NOT LIKE '%I/O was resumed on database%'
  AND log_text NOT LIKE '%I/O is frozen on database%'
  AND log_text NOT LIKE '%CHECKDB%'
ORDER BY log_date DESC;

DROP TABLE #error_log;

This loads the current error log via xp_readerrorlog into a temp table, filters to the last 24 hours, strips out the recurring routine-noise patterns (backups, log backups, clean CHECKDB, I/O freeze/resume pairs), and returns whatever’s left in reverse chronological order.


How To Run From The Repo

Clone DBA Tools, initialize and run the script:

# Clone dba-tools repo:
git clone https://github.com/peterwhyte-lgtm/dba-tools

# Initialize environment:
cd dba-tools
.\Initialize-Environment.ps1

# Read the last 24 hours of the error log with routine noise filtered out:
.\run.ps1 Get-RecentErrorLogEntries

# To run against a remote sql server:
.\run.ps1 Get-RecentErrorLogEntries -ServerInstance SQLSERVER01

This script lives in the repo at:


Example Output

Get-RecentErrorLogEntries output showing filtered SQL Server error log entries
Real output captured against a local SQL Server 2025 instance, a genuine finding, not staged: this lab box is under real memory pressure, the OS has paged out a large share of SQL Server’s working set for over 63 hours straight (227,151 seconds), and sp_server_diagnostics itself is running slow as a result. Exactly the kind of thing that’s easy to miss without a check like this filtering the noise away from it.


Understanding the Results

  • Memory paging warnings are the highest-priority finding here. working set (KB) shrinking well below committed (KB) means the OS is under enough memory pressure to swap SQL Server’s own memory out to disk, which degrades performance across the entire instance, not just one query. memory utilization in the message is the working set as a percentage of committed memory, lower means more has been paged out.
  • sp_server_diagnostics delay warnings are a secondary symptom of the same root cause on this box, when the OS is busy paging memory, SQL Server’s internal diagnostics scheduler itself falls behind. Seeing both together in the same window, as in this example, points at one shared cause rather than two separate problems.
  • process_info tells you the source, spidNN values are regular sessions, spidNNs values (the trailing s) are system background processes like this one, useful for telling apart a user-triggered event from an internal one.
  • Anything that survives the noise filter is worth reading in full, the filter is deliberately conservative, it only strips patterns that are genuinely routine on every healthy instance.

Common Causes

Memory paging like the example above usually traces back to the OS being under more memory pressure than SQL Server’s own configuration accounts for, max server memory set too high for the box’s physical RAM, other processes competing for memory on the same machine, or simply a server that’s undersized for its workload. A single occurrence during a known heavy batch window is less concerning than a sustained, hours-long duration like the one captured here.


Best Practices

  • Run this script daily or as part of routine health checks, not just during active troubleshooting, catching a warning early is the whole value of this check.
  • Treat any memory paging warning as worth investigating even if performance “feels fine”, it’s an early indicator, not a lagging one.
  • Cross-check max server memory against the box’s physical RAM whenever a paging warning appears, the Memory Configuration and Usage script covers that check.
  • Keep the noise filter list in the script itself up to date if your environment has other routine, high-frequency messages worth excluding, better to extend the filter deliberately than to scroll past the same false positive every day.

Related Scripts

You may also find these scripts useful:


Frequently Asked Questions

How do I read the SQL Server error log without SSMS?

Run xp_readerrorlog 0, 1, NULL, NULL, NULL, NULL, 'asc' directly, which is what this script wraps, or use sqlcmd/Invoke-Sqlcmd from a terminal. Both work identically whether or not SSMS is installed.

What does “a significant part of SQL Server process memory has been paged out” mean?

It means the operating system is under enough memory pressure that it moved part of SQL Server’s own working memory out to disk (paging), which slows down anything that needs that memory back. It’s SQL Server reporting a real OS-level resource constraint, not a SQL Server bug, worth investigating physical memory sizing or max server memory configuration.

How far back does xp_readerrorlog go?

As far as the current error log cycle covers, which depends on how many archived logs SQL Server retains (7 by default, configurable) and how often the log has been cycled, whether by a scheduled job, a restart, or a manual sp_cycle_errorlog call. This script only reads the current, active log (log number 0).


Summary

The error log rarely lies, but it does bury its most important lines under a mountain of routine noise, and that noise is exactly why most people only open it once something’s already gone wrong. Filtering it down to the last 24 hours, minus the routine patterns, turns a five-minute manual scroll into a one-query check.

Run it as part of routine health checks, not just during an incident, the whole value here is catching the warning before it becomes the incident.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *