Build and Automate a SQL Server Status Report on Server Restart or Scheduled

By:   |   Comments (14)   |   Related: > Monitoring


Problem

Do you know when a SQL Server instance restarts? When you manage many SQL Server instances you may not know when one restarts, so having an automated report emailed to you could be helpful to get an idea what's going on for that instance.

Solution

This tip shows you how to build a SQL Server status report and have it emailed to you when an instance restarts or on a set schedule.

Prerequisites

  • One prerequisite is that you enable email on your instance. See tip 1100 by Greg Robidoux for that.
  • Next we will be using tip 2347 by Bru Medishetty on HTML formatting in emails.
  • The last restart time tip is 2501 by Greg Robidoux.
  • Lastly we will build a SQL Server job and if you need help on the SQL Server job system see tip 4848 by Rick Dobson.

Step 1 - Build a stored procedure to collect important information

Tip : Use a test mode to email yourself then turn off test mode to email the usual monitoring group.

The call for running the stored procedure in test mode is:

Exec [DBA].[dbo].[usp_sql_server_status_check_HTML] @Test=’Yes’			

The call for running the stored procedure when test mode off is:

Exec [DBA].[dbo].[usp_sql_server_status_check_HTML] @Test=’No’			

The stored procedure has many components to check for various SQL Server conditions. 

This is the first part of the stored procedure.

-- File name : usp_sql_server_status_check_HTML.sql
Use [DBA] -- Name your administrative database here
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

begin try
   drop procedure [dbo].[usp_sql_server_status_check_HTML]
end try
begin catch
end catch
go
 
Create procedure [dbo].[usp_sql_server_status_check_HTML] @Test nvarchar(3)= null
as
BEGIN
set nocount on
 
-- File name : usp_sql_server_status_check_HTML.sql
-- Author    : Graham Okely B App Sc (IT)
-- Reference : https://www.mssqltips.com/sqlserverauthor/106/graham-okely/
Declare @Reference nvarchar(128) = 'https://www.mssqltips.com/sqlserverauthor/106/graham-okely/'
Declare @Report_Name nvarchar(128) = 'SQL Server Status Report'
 
-- Just in case @@Servername is null
Declare @Instance nvarchar(128) = ( Select isnull(@@Servername,cast(SERVERPROPERTY('MachineName') as nvarchar(128))+'\'+@@servicename) )
 
-- Get this many days from the SQL Agent log
Declare @Log_Days_Agent int = 4
 
-- Build a table for the report
Declare @SQL_Status_Report table ( Line_Number int NOT NULL identity(1,1),  Information nvarchar(max) )

Step 2 - What detail do we want to see

Some basics like the instance name. Then the active node the instance is on. That helps when managing clusters and does not hurt when it is a standalone instance.

Here are various code snippets that can be added to the stored procedure.

Add SQL Server Version Information

 -- Main title of the report
Insert into @SQL_Status_Report (Information)
Select 'SQL Server Status Check Report on '+  @Instance +' at '+cast(getdate() as nvarchar(28))  
Insert into @SQL_Status_Report (Information)
Select 'On node : '+ cast(SERVERPROPERTY('ComputerNamePhysicalNetBIOS') as nvarchar(1024))  
Insert into @SQL_Status_Report (Information)
Select @@version
-- This line makes a blank row in the report
Insert into @SQL_Status_Report (Information) select ''			

Add SQL Server Restart Time

 -- Get the last restart date and time from sqlserver_start_time
Insert into @SQL_Status_report
SELECT 'Start time from DMV sqlserver_start_time ' + cast(sqlserver_start_time as nvarchar (28)) 
FROM sys.dm_os_sys_info			

Add Space Free on Each Disk Linked to the Instance

 -- Disk Drive Space
Insert into @SQL_Status_Report  (Information)
Select 'Drive space on '+@Instance +' (Lowest space free first)'
declare @drives  table( drive nvarchar(1), MbFree int)
insert into @drives
   exec xp_fixeddrives
Insert into @SQL_Status_Report  (Information)
select drive+ ' has  ' + cast (MbFree/1000 as nvarchar(20))+' GB Free' 
from @drives
Order by MbFree asc -- Show least amount of space first			

Add Users Added in the Last X Days

Just so we know who was added.

 -- Users added in the last X days
Declare @DaysBack int=7
Insert into @SQL_Status_Report  (Information)
Select 'Users added in last '+ cast(@DaysBack as nvarchar(12))+' days'
Insert into @SQL_Status_Report  (Information)
Select name+' '+type_desc+ ' '+ cast(create_date as nvarchar(28))+' ' + cast(datediff(day,create_date,getdate()) as nvarchar(12)) + ' days ago'
From sys.server_principals
Where type_desc in ('WINDOWS_LOGIN','WINDOWS_GROUP','SQL_LOGIN')
and datediff(day,create_date,getdate())<@DaysBack
			

Add Total Number of Databases and Total Space

That gives me an idea of what is hosted.

 -- Gather summary of databases using sp_helpdb
Declare @sp_helpdb_results table( 
[db_name] nvarchar(256), [db_size] nvarchar(25), [owner] nvarchar(128), [db_id] int, 
[created_data] datetime, [status] nvarchar(max), [compatability] int)
INSERT INTO @sp_helpdb_results
          EXEC sp_helpdb
-- Flag databases with an unknown status
insert into @sp_helpdb_results( [db_name],[owner],[db_size])
   SELECT name,'Database Status Unknown' COLLATE database_default,0
   FROM sys.sysdatabases 
   Where [name] COLLATE database_default not in (Select [db_name] COLLATE database_default from @sp_helpdb_results)
-- Remove " MB"
UPDATE @sp_helpdb_results SET [db_size] = replace([db_size],' MB','')
Delete from @sp_helpdb_results Where [db_size]='0'
-- Report summary of databases using sp_helpdb
Insert into @SQL_Status_Report  (Information)
Select @Instance+' has ' +  cast(count(*) as nvarchar(8)) + ' databases with ' +
cast(cast(sum(cast(replace([db_size],' MB','')  as float)) as int)/1000 as nvarchar(20))  +  ' GB of data' 
FROM @sp_helpdb_results
			

Add Largest Database

That helps me know what the system mainly hosts.

-- Database sizes
Insert into @SQL_Status_Report (Information)
Select 'Largest database on '+@Instance+' in MB' 
Insert into @SQL_Status_Report (Information)
Select top 1 [db_name] + ' ' + convert(nvarchar(10),round(convert(numeric,ltrim(replace([db_size],' Mb',''))),0)) 
From @sp_helpdb_results
Order by [db_size] desc
			

Add Date of Oldest Backup

That lets me know if the backup system is OK.

 -- Oldest backup
Insert into @SQL_Status_Report (Information)
Select 'Oldest full database backup on '+@Instance 
Insert into @SQL_Status_Report (Information)
Select top 1 left(database_name,30)+' '+COALESCE(Convert(varchar(10), MAX(backup_finish_date), 121),'Not Yet Taken') 
From msdb..backupset 
Where database_name not in ( 'tempdb' )
and database_name in (select distinct name FROM master..sysdatabases)
and type = 'D' 
Group by database_name
Order by MAX(backup_finish_date) asc
			

Add Entries from the SQL Server Agent Log

 -- Agent log information
Insert into @SQL_Status_Report  (Information)
Select 'Agent log check on '+@Instance+' Last ' +cast( @Log_Days_Agent as nvarchar(12))+ ' days' 
Declare @SqlAgenterrorLog table(logdate  datetime, [ProcessInfo]  varchar(29), errortext  varchar(max))
insert into @SqlAgenterrorLog
   exec sys.xp_readerrorlog 0,2
-- Report
Insert into @SQL_Status_Report  (Information)
Select DISTINCT cast(logdate as nvarchar(28))+' '+[ProcessInfo]+' '+left(errortext,300) 
from  @SqlAgenterrorLog
where logdate>dateadd(day,-@Log_Days_Agent,getdate()) 
order by 1 desc			

Add Entries from the SQL Server Error Log

 -- Server log last 20 rows
Insert into @SQL_Status_Report (Information)
Select 'Sql Server log check on '+@Instance+' top 20 rows' 
Declare @SqlerrorLog table(logdate  datetime, [ProcessInfo]  varchar(29), errortext  varchar(max))
insert into @SqlerrorLog
   exec sys.xp_readerrorlog
Insert into @SQL_Status_Report (Information)
Select top 20 cast(logdate as nvarchar(28))+' '+[ProcessInfo]+' '+left(errortext,300) 
from  @SqlerrorLog 
order by 1 desc			

Add Your Own Checks

You can add anything else you would like to add.  Just follow the template from one of the above sections.

Add Report Footer

This is needed to close out the report as well as add END to the bottom of the stored procedure.

 -- Report Footer
Insert into @SQL_Status_Report (Information)
Select 'End of the ' + @Report_Name + ' on ' + @Instance + ' at ' + cast(getdate() as nvarchar(28))
Insert into @SQL_Status_Report (Information)
Select 'For more tips see : ' + @Reference

END			

Step 3 - Email Formatting and Delivery

Finally prepare and email the report.

You can add this section to email the report.  Just change the values below to match your database mail profile and the email addresses that you want to get the report.

 -- Prepare email
Declare @xml nvarchar(MAX)
Declare @body NVARCHAR(MAX)
 
SET @xml =  cast(( select ltrim(Information) as'td' 
FROM  @SQL_Status_Report ORDER BY Line_Number
FOR XML PATH('tr'), ELEMENTS ) AS nvarchar(MAX))
 
Declare @Subject_Line nvarchar(128) = 'SQL Server Status Report from ' + @Instance
 
SET @body ='<html><body><table border = 1 width="80%"><th><H3>' +@Subject_Line+'</H3></th>'    
 
SET @body = @body + @xml +'</table></body></html>'
If ( @Test='Yes' )
BEGIN
   Set @Subject_Line = @Subject_Line + ' Test Mode' 
   EXEC msdb.dbo.sp_send_dbmail
   @profile_name = 'DBA', -- replace with your SQL Database Mail Profile 
   @body = @body,
   @body_format ='HTML',
   @recipients = '[email protected]', -- replace with your email address
   @subject = @Subject_Line;
   print @body
END
Else
BEGIN
   EXEC msdb.dbo.sp_send_dbmail 
   @profile_name = 'DBA', -- replace with your SQL Database Mail Profile 
   @body = @body, 
   @body_format ='HTML', 
   @recipients = '[email protected]', -- replace with the monitoring email address 
   @subject = @Subject_Line; 
END			

Step 4 - Build

Copy all the parts you want to use from above into one file and build the stored procedure. Click here for the complete stored procedure.

Step 5 - Test

We can test the stored procedure using the following options.

 -- Send the email to the tester
Exec [DBA].[dbo].[usp_sql_server_status_check_HTML] @Test=’Yes’

-- Send the email to the monitoring group
Exec [DBA].[dbo].[usp_sql_server_status_check_HTML] @Test=’No’

-- Send the email to the monitoring group
Exec [DBA].[dbo].[usp_sql_server_status_check_HTML] 			

Step 6 - Schedule

To schedule the stored procedure to run, we can create a SQL Server Agent Job.

Deploy by Creating a SQL Server Agent Job

new job

Add a Job Step

One job step is all that is required.

job step properties

Job Step Exit Status

advanced

Set Job Schedule

Let’s make the job run on start-up and the third Tuesday of each month.

job properties

Example Email

Here is what a sample email looks like.

sql server status
Next Steps
  • Read more tips on Database Mail
  • Enable email on your instance. See tip 1100 by Greg Robidoux.
  • See tip 2347 by Bru Medishetty on HTML formatting in emails.
  • See this tip on the SQL Server job system tip 4848 by Rick Dobson.


sql server categories

sql server webinars

subscribe to mssqltips

sql server tutorials

sql server white papers

next tip



About the author
MSSQLTips author Graham Okely Graham Okely is a SQL Server DBA and has been working with database systems since 1984 and has been specializing in SQL Server since 2007.

This author pledges the content of this article is based on professional experience and not AI generated.

View all my tips



Comments For This Article




Wednesday, June 30, 2021 - 10:58:11 PM - Graham Okely Back To Top (88930)
Hello Gowtham
You should be able to do it.
Please read this article to get some ideas:
https://www.mssqltips.com/sqlservertip/2036/monitor-start-and-stop-sql-server-services-using-xpservicecontrol/

Saturday, June 26, 2021 - 5:43:09 AM - Gowtham Back To Top (88900)
Can you please help to include SSAS and SSRS services to the report

Wednesday, June 9, 2021 - 12:56:15 PM - Gowtham Back To Top (88830)
Great. Thank you very much.

Wednesday, June 9, 2021 - 4:07:44 AM - Graham Okely Back To Top (88828)
Hello Gowtham
This is one method:
Insert into @SQL_Status_Report (Information)
select 'SQL Server Serice ' + servicename + ' start up status ' + startup_type_desc + ' Current status ' + status_desc
from sys.dm_server_services

Tuesday, June 8, 2021 - 9:04:57 AM - Gowtham Back To Top (88821)
Can you please add all SQL Services status to this report

Thursday, October 29, 2020 - 4:07:43 AM - Graham Okely Back To Top (86712)
Due to this article: https://www.sqlservercentral.com/forums/topic/recovering-databases-from-a-master-backup

I thought it would be good to have a list of databases on the instance.
All I had to do was add this TSQL to the stored procedure. Now I get a list of databases on an instance via the email check.

-- Full list of databases
Insert into @SQL_Status_Report (Information)
Select 'Full list of databases '+@Instance
Insert into @SQL_Status_Report (Information)
Select distinct [name] FROM master..sysdatabases

Tuesday, December 18, 2018 - 7:42:19 PM - Graham Okely Back To Top (78524)

UPDATE:

The supplied TSQL for determining the oldest backup shows the date for databases that no longer exists.

To ensure you see the oldest backup date for current databases use the TSQL below:

 -- Oldest backup
Insert into @SQL_Status_Report (Information)
Select 'Oldest full database backup on '+@Instance
Insert into @SQL_Status_Report (Information)
Select top 1 left(database_name,30)+' '+COALESCE(Convert(varchar(10), MAX(backup_finish_date), 121),'Not Yet Taken')
From msdb..backupset
Where database_name not in ( 'tempdb' ) and database_name  in ( Select distinct name FROM master..sysdatabases)
and type = 'D'
Group by database_name
Order by MAX(backup_finish_date) asc

Wednesday, November 21, 2018 - 7:37:46 AM - Graham Okely Back To Top (78303)

Hello Renato

Thank for trying my tip!

Try copying and pasting the TSQL into notepad first, then copy ithe TSQL from notepad into SSMS for running.

If it still fails then read through the stored procedure and try to understand each step and spot what is missing.

It worked well for others.

Regards

Graham Okely


Monday, November 19, 2018 - 12:07:16 PM - Renato Castaņeda Back To Top (78289)

 Hi Graham, i have the next error when copy and executed the creation of the sp

Msg 102, Level 15, State 1, Procedure usp_sql_server_status_check_HTML, Line 19 [Batch Start Line 2]

Incorrect syntax near ')'.


Sunday, May 27, 2018 - 8:48:05 PM - Graham Okely Back To Top (76030)

Lee thanks, well spotted. I will get that adjusted. Graham


Friday, May 25, 2018 - 9:27:21 AM - Lee Back To Top (76024)

 

Thanks for taking the time to develop and share this procedure with us. Very useful. I had an issue with the section that retrieves data from the SQL Agent Log. Shoudn't the line:

where logdate>datediff(day,-@Log_Days_Agent,getdate()) be something like:

where logdate> DATEADD(day,-@Log_Days_Agent,GETDATE())

In my test SELECT datediff(day,-4,getdate()) returned 43247

Thanks again.

Lee


Thursday, May 24, 2018 - 10:53:56 AM - Cedrick Back To Top (76019)

 One of the best SQl Server articles that I have ever read and used!!! This is an invaluable tool for large environments.

Thanks for sharing!!!


Tuesday, May 15, 2018 - 8:34:00 PM - Vasanth Back To Top (75952)

 

 Great Article and hats off to your contribution to the SQL Server World, where me still Pupil.


Tuesday, May 15, 2018 - 6:21:55 AM - Srijaya Back To Top (75945)

 

 Great Article.   Thank you very much.















get free sql tips
agree to terms