Write for Us
Step 4: Filter the dataBy now, we’ve got the messages in a table. The first thing we have to do now is filter the messages. This is the part I can’t help you with. You’ll have to decide for yourself whether you’re interested in a message from the virus scanner, or that service such-and-such has been successfully started.In the main stored proc I’ve included four lines of comment, where you can call a stored procedure that deletes the irrelevant messages.For example, you may not want to see the daily informational message about the uptime of SQL. If so, delete it with the following code:
DELETE FROM tblLogStaging WHERE source = 'MSSQLSERVER' AND eventid = '17177'
Or the fact that someone logged in successfully:
DELETE FROM tblApplicationLog WHERE Description LIKE '%Login succeeded for user%'
You may not even be interested in the message that login failed for a user. But you will definitely be interested in the following message that login failed for user ‘sa’. So be careful: don’t delete messages too fast.
You’ll have to figure out for yourself which messages can safely be ignored. This comes from experience in looking at your logs.
Step 5: Putting it all together
By now, we’ve got the 4 tables and the important code required. So, let’s create the stored procedures that do all the work. First the inner loop:
CREATE PROCEDURE [dbo].[uspReadEventLogs] @server char(20)ASBEGIN--Variable declarationDECLARE @sql varchar(1000)SET NOCOUNT ONSET CONCAT_NULL_YIELDS_NULL OFF –-some fragments will be NULLSET ANSI_NULLS ONSET QUOTED_IDENTIFIER ON
--Main--App logEXEC master..xp_cmdshell 'copy d:\apps\dumpevt\empty.csv d:\apps\dumpevt\evtlogdump.csv /Y', no_outputDELETE FROM tblLogStagingSET @sql = 'master..xp_cmdshell ''d:\apps\DumpEvt\DumpEvt.exe /logfile=app /outfile=d:\apps\dumpevt\evtlogdump.csv /computer=' + @server + char(39) + ', no_output'EXEC (@sql)
BULK INSERT tblLogStaging FROM 'd:\apps\dumpevt\evtlogdump.csv'WITH (FIELDTERMINATOR = ',')
/*Include filter on any column but description here, e.g. EXEC uspFilterApplicationStaging*/INSERT INTO tblApplicationLog ([Log], [Time], [Source], [EventID], [Type], [Category], [User], [Server], [Description])SELECT [Log], [Time], [Source], [EventID], [Type], [Category], [User], [Server], Fragment0 + Fragment1 + Fragment2 + Fragment3 + Fragment4 + fragment5 + Fragment6FROM tblLogStaging/*Include filter on description here */
--Sys logEXEC master..xp_cmdshell 'copy d:\apps\dumpevt\empty.csv d:\apps\dumpevt\evtlogdump.csv /Y', no_outputDELETE FROM tblLogStagingSET @sql = 'master..xp_cmdshell ''d:\apps\DumpEvt\DumpEvt.exe /logfile=sys /outfile=d:\apps\dumpevt\evtlogdump.csv /computer=' + @server + char(39)+ ', no_output'EXEC (@sql)
/*Include filter on any column but description here */INSERT INTO tblSystemLog ([Log], [Time], [Source], [EventID], [Type], [Category], [User], [Server], [Description])SELECT [Log], [Time], [Source], [EventID], [Type], [Category], [User], [Server], Fragment0 + Fragment1 + Fragment2 + Fragment3 + Fragment4 + Fragment5 + Fragment6FROM tblLogStaging/*Include filter on description here */
--Clean upSET CONCAT_NULL_YIELDS_NULL ONEND
Don’t forget to substitute the paths to the DumpEvt directory, if necessary.
As mentioned earlier, in the c.s.v. file, the description of the message is divided into 6 fragments, with a lot of NULL values. We have to concatenate these to form a readable description; for that, we use the set concat_null_yields_null off at the start of the stored proc. Otherwise, concatenating a fragment with an empty (NULL) fragment would result in an empty (NULL) description.This is also the reason there are two places to filter: the first time for filtering on anything but description, the second time for filtering on description. You may get lots of records, so it is faster to delete first, and then insert into the destination table.
Finally, let’s create the other stored procedure:
CREATE PROC [dbo].[uspCheckAllServers]AS
--Variable declarationDECLARE @server char(20)DECLARE @sql varchar(1000)SET NOCOUNT ONSET ANSI_NULLS ONSET QUOTED_IDENTIFIER ON
--MainDELETE FROM tblApplicationLogDELETE FROM tblSystemLog
PRINT ''DECLARE csrJobs CURSORFOR SELECT Server FROM tblServers WHERE status = 'active' ORDER BY ServerOPEN csrJobsFETCH NEXT FROM csrJobs INTO @server
WHILE @@FETCH_STATUS = 0BEGINPRINT 'Checking '+ @serverEXEC uspReadEventLogs @serverPRINT ' 'FETCH NEXT FROM csrJobs INTO @serverEND
--Clean upCLOSE csrJobsDEALLOCATE csrJobs
This is the ‘outer loop’. For each server in tblServer with a status of ‘active’ it will call the main stored proc (the ‘inner loop’). The name of the server will be passed as the variable @server from the outer loop to the inner loop.
Step 6: Use the results
That’s it! Now, you can just run the stored procedure and scroll through the output:
EXEC uspCheckAllServers;SELECT * FROM tblApplicationLog ORDER BY description, time
Personally, I run the stored proc manually every morning. Running it manually ensures you see the latest events, should you happen to perform the check on a different time than you normally would. It also ensures you won’t miss important messages if you can’t check it every day, because the way it is setup now, no history is saved. But you might want to run it more often, or schedule it. That’s up to you.