/Some-Logparser-Queries-and-scripts

Some Logparser Queries to help my peers

Primary LanguagePowerShell

LogParser download links

LogParser scripts

In the repository, along with this Readme.md file, you'll find some LogParser PowerShell scripts generated with LogParser Studio for quick reference. I'll document these later on.

Some-Logparser-Queries

Some Logparser Queries to help my peers

Quantize by hour - use TO_LOCALTIME and QUANTIZE

Hint if you want to count stuff that happened by minute (60 seconds) or my hour (3600 seconds), we make use of

QUANTIZE(Time_Stamp, Sample_rate_in_seconds)

Example, the Sample rate of 3600 seconds will count all occurences by 3600 seconds = 1 hour

NOTE: for IIS logs, on newer servers, you may need to select the W3CLOG instead of IISW3CLOG if the latter does not return anything.

An application of QUANTIZE:

Log Type:W3CLOG

SELECT
    QUANTIZE(TO_TIMESTAMP(date, time), 60) AS Minute,
    COUNT(*) AS Total,  
    SUM(sc-bytes) AS TotBytesSent 
FROM
    '[LOGFILEPATH]'
WHERE
    date > '2016-04-23'
GROUP BY Minute
ORDER BY Minute

Another example, on an IIS log, with QUANTIZE, and TO_LOCALTIME to convert to local time - this one quantize to display information such as cs-URI-Stem aka URL reached, Average of time taken and in which log file, quantized in 5 minutes time slices:

Log Type:W3CLOG

SELECT TO_LOCALTIME(QUANTIZE(TO_TIMESTAMP(date, time), 300)) AS FiveMinuteInterval,
       cs-uri-stem,
       AVG(time-taken) as AverageTime,
       LogFileName
/*Use the below to target specific log file once found:*/      
/*FROM 'C:\temp\IISLogs\u_ex22101715_x.log'*/
/*Use the below to use LogParser Studio's Log files selected file or folder:*/
FROM '[LOGFILEPATH]'
WHERE cs-uri-stem not like '%/healthcheck.htm'
GROUP BY FiveMinuteInterval, LogFileNAme,cs-uri-stem

The below is similar to the above, instead we display the number of hits per URL reached (cs-uri-stem), in each log file, without timestamps and quantizing:

SELECT cs-uri-stem,
       COUNT(*) as hits,
       LogFileName
/*FROM 'C:\temp\IISLogs\u_ex22101715_x.log'*/
FROM '[LOGFILEPATH]'
WHERE cs-uri-stem not like '%/healthcheck.htm'
GROUP BY LogFileNAme,cs-uri-stem
ORDER BY hits DESC

An other example on an Exchange Tracking log (specific to Exchange Tracking Logs, we need to EXTRACT the "#Fields: date-time" string from the tracking log before calling TO_TIMESTAMP():

Log Type:EELLOG

SELECT TO_LOCALTIME(QUANTIZE(TO_TIMESTAMP(TO_STRING(EXTRACT_PREFIX([#Fields: date-time],0,'.')), 'yyyy-MM-ddThh:mm:ss'),3600)) AS Hour,
	cs-username,
	sc-status,
	etc...
	# NOTE: don't put a comma after the last element of the SELECT clause

COUNT(*) AS Messages
FROM '\\$Server\$TrackingLogPaths\*.log'
WHERE event-id='RECEIVE'
GROUP BY cs-username,sc-status,etc...,Hour /*<<<<<<<<<<<<<----- Group by the quantized time named on the SELECT clause*/ 
ORDER BY Hour ASC

Getting intel from IIS Logs

Pull IIS logs data with some fields, and convert IIS UTC time to local time, for a specific URI (/EWS/mrsproxy.svc)

/* Pull all requests*/
/* If an error is returned there may be no matches */
/*#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken*/

SELECT   TO_LOCALTIME(TO_TIMESTAMP(date, time)) as TimeStamp,
         cs-username,
         cs-uri-stem,
         sc-status,
         time-taken
FROM 'c:\temp\IIS logs\*.log'
WHERE cs-uri-stem LIKE '/EWS/mrsproxy.svc%'
ORDER BY TimeStamp

Pull IIS logs data with all fields for a specific URI (/EWS/mrsproxy.svc)

/* Pull all requests*/
/* If an error is returned there may be no matches */
/*#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status time-taken*/

SELECT   TO_LOCALTIME(TO_TIMESTAMP(date, time)) as TimeStamp,
         cs-username, 
         s-ip, 
         cs-method, 
         cs-uri-stem, 
         cs-uri-query, 
         s-port, 
         c-ip, 
         cs(User-Agent), 
         cs(Referer), 
         sc-status, 
         sc-substatus, 
         sc-win32-status, 
         time-taken

FROM     'c:\temp\IIS logs\*.log'
WHERE    cs-uri-stem LIKE '/EWS/mrsproxy.svc%'
ORDER BY TimeStamp

To save the results into a CSV

Simply use the following stance:

INTO     'C:\temp\My_CSV_Results.CSV'

For example, taking the above complete SQL like request, adding the INTO 'Myfile.csv' :

SELECT   TO_LOCALTIME(TO_TIMESTAMP(date, time)) as TimeStamp,
         cs-username,
         cs-uri-stem,
         sc-status,
         time-taken

INTO     'c:\temp\IISLog Filtered for MRSProxy.CSV'
FROM     'c:\temp\IIS logs\*.log'
WHERE    cs-uri-stem LIKE '/EWS/mrsproxy.svc%'
ORDER BY TimeStamp

NOTE: Saving direclty in a CSV file will not print the results into Logparser Studio.

image

Logparser requests for users and apps inventory

Show all ActiveSync users

SELECT   cs-username AS UserID, 
	cs(User-Agent) AS Application, 
	cs-uri-stem AS Vdir,
	s-ip AS SERVER,
	c-ip AS CLIENT,
	cs-method,
	Count(*)
FROM     '[LOGFILEPATH]'
WHERE    cs-uri-stem LIKE '%Microsoft-Server-ActiveSync%' and UserID not like '%health%'
GROUP BY UserID, Application, Vdir, Server, Client, cs-method
ORDER BY COUNT(*) DESC

Log Parser Studio Log type: IISW3CLOG

All Autodiscover requests

SELECT   cs-username AS UserID, 
	cs(User-Agent) AS Application, 
	cs-uri-stem AS Vdir,
	s-ip AS SERVER,
	c-ip AS CLIENT,
	cs-method,
	Count(*)
FROM     '[LOGFILEPATH]'
WHERE    cs-uri-stem LIKE '%Autodiscover%' and UserID not like '%health%'
GROUP BY UserID, Application, Vdir, Server, Client, cs-method
ORDER BY COUNT(*) DESC

Log Parser Studio Log type: IISW3CLOG

Query hits on specific URL (example with Autodiscover again), between 2 date/time stamps

Example 0 - dump everything just to have an idea of the fields and other filters you can make

The below query dumps all the IIS file intormation (note the wildcard * on the SELECT clause), including the time stamps (TO_TIMESTAMP(date,time)) converted to local time (TO_LOCALTIME()) as the default IIS time is the Universal Time Coordinated (UTC). I also filter some user names I don't want (cs-username NOT LIKE '') and filtering out the blank cs-username.

Log Type : W3CLOG

SELECT 
    TO_LOCALTIME(TO_TIMESTAMP(date, time)) AS LocalTime,
    *
FROM '\\E2019-01\C$\inetpub\logs\LogFiles\W3SVC1\*.log','\\E2019-02\C$\inetpub\logs\LogFiles\W3SVC1\*.log'
WHERE LocalTime BETWEEN TimeStamp('01/28/2023 00:00:00','MM/dd/yyyy hh:mm:ss') AND TimeStamp('01/28/2023 23:59:59','MM/dd/yyyy hh:mm:ss') AND cs-username NOT LIKE '%HealthMailbox%' AND cs-username IS NOT NULL
ORDER BY LocalTime

And then you want to filter the cs(User-Agent) which is the application used (like Outlook v15.0 for Outlook 2013), you would add on the WHERE clause:

cs(User-Agent) LIKE '%Outlook%' AND cs(User-Agent) LIKE '%15.0%'

the full WHERE clause would look like:

WHERE LocalTime BETWEEN TimeStamp('01/28/2023 00:00:00','MM/dd/yyyy hh:mm:ss') AND TimeStamp('01/28/2023 23:59:59','MM/dd/yyyy hh:mm:ss') AND cs-username NOT LIKE '%HealthMailbox%' AND cs-username IS NOT NULL AND cs(User-Agent) LIKE '%Outlook%' AND cs(User-Agent) LIKE '%15.0%'

Example 1 - show URL total hits quantized to every quarter, for Autodiscover, excluding Health Mailboxes, between 2 date/times

Use the sql TimeVariable BETWEEN TimeStamp('01/23/2022 06:00:00','MM/dd/yyyy hh:mm:ss') AND TimeStamp('01/23/2022 20:00:00','MM/dd/yyyy hh:mm:ss') synthax after the sql WHERE clause.

NOTE1: you can use sql TO_LOCALTIME(SYSTEM_TIMESTAMP()) if you want to query between a time in the past and the current time ... NOTE2: you can also substract a few minutes in case the latest data don't fill a quantized hour at the time of the run for example using the sql SUB(TO_LOCALTIME(SYSTEM_TIMESTAMP()),TIMESTAMP('20','mm')) sequence. use '20','mm' to remove 20 minutes, or '01','hh' to substract 1 hour, ...

SELECT QUANTIZE(TO_TIMESTAMP(date, time), 900) AS QuarterHour,
       /*cs-username as UserName,*/
       cs-uri-stem as TargetURL,
       /*cs(User-Agent) as ClientApp,*/
	COUNT(*) AS Total
FROM '\\E2016-01\C$\Users\samdrey.CANADADREY\Downloads\IISLogs\IISLogs\*.log', '\\E2016-02\C$\inetpub\logs\LogFiles\W3SVC1\*.log'
WHERE TargetURL like '%/autodiscover/autodiscover%' AND cs-username NOT LIKE '%HealthMailbox%' AND QuarterHour BETWEEN TimeStamp('10/17/2022 07:00:00','MM/dd/yyyy hh:mm:ss') and TimeStamp('10/17/2022 20:00:00','MM/dd/yyyy hh:mm:ss') 
/*
If you want to express time stamp corresponding to current time MINUS 20 minutes:
SUB(TO_LOCALTIME(SYSTEM_TIMESTAMP()),TIMESTAMP('20','mm'))
*/ 
GROUP BY QuarterHour, TargetURL
ORDER BY QuarterHour

Example 2 - show entries for RPC URL (RPC over HTTP) with user names, between 2 date/times on 2 remote IIS log folders

SELECT TO_LOCALTIME(TO_TIMESTAMP(date, time)) AS Minute,
       cs-uri-stem,
       cs-username,
	COUNT(*) AS Total 
FROM '\\E2019-01\C$\inetpub\logs\LogFiles\W3SVC1\*.log','\\E2019-02\C$\inetpub\logs\LogFiles\W3SVC1\*.log'
WHERE Minute BETWEEN TimeStamp('01/28/2023 00:00:00','MM/dd/yyyy hh:mm:ss') AND TimeStamp('01/28/2023 23:59:59','MM/dd/yyyy hh:mm:ss') AND cs-username NOT LIKE '%HealthMailbox%' AND cs-username IS NOT NULL AND cs-uri-stem LIKE '%rpc%'
GROUP BY Minute,cs-uri-stem, cs-username
ORDER BY Minute

image

Example 3 - show IIS files lines between to dates, with only the time stamp, User name, target URL, client application and HTTP status

SELECT TO_LOCALTIME(TO_TIMESTAMP(date, time)) AS DateTime,
       cs-username as UserName,
       cs-uri-stem as TargetURL,
       cs(User-Agent) as ClientApp,
       sc-status as HTTPStatus
FROM '\\E2019-01\C$\inetpub\logs\LogFiles\W3SVC1\*.log', '\\E2019-02\C$\inetpub\logs\LogFiles\W3SVC1\*.log'
/*WHERE TargetURL like '%/autodiscover/autodiscover%' AND cs-username NOT LIKE '%HealthMailbox%' AND DateTime BETWEEN TimeStamp('01/28/2023 00:00:00','MM/dd/yyyy hh:mm:ss') AND TimeStamp('01/28/2023 23:59:59','MM/dd/yyyy hh:mm:ss') */
WHERE DateTime BETWEEN TimeStamp('01/28/2023 00:00:00','MM/dd/yyyy hh:mm:ss') AND TimeStamp('01/28/2023 23:59:59','MM/dd/yyyy hh:mm:ss') AND cs-username NOT LIKE '%HealthMailbox%' AND cs-username IS NOT NULL AND cs(User-Agent) LIKE '%Outlook%' AND cs(User-Agent) LIKE '%15.0%'

/*
HINT:
If you want to express time stamp corresponding to current time MINUS 20 minutes:
SUB(TO_LOCALTIME(SYSTEM_TIMESTAMP()),TIMESTAMP('20','mm'))
For example between a set date in the past, and current date/time minus 20 minutes
*/ 

ORDER BY DateTime

Here's an extract for my lab servers (I only have 1 active user so you'll see always the same for me:

image

Example 4 - using COUNT(*) as HitCount

NOTE: When you use COUNT(*) on the SELECT clause to count the number of Hits, you must use GROUP BY before ORDER BY, followed by all the headers you have in SELECT (except the COUNT() header of course)

NOTE2: You can also uses QUANTIZE( Time stamp, seconds ) along with COUNT() to group the number of hits in a time interval like 5, 15, or 60 minutes:

SELECT QUANTIZE(TO_TIMESTAMP(date, time), 900) AS QuarterHour,
       cs-username as UserName,
       cs-uri-stem as TargetURL,
       cs(User-Agent) as ClientApp,
	COUNT(*) AS Total

FROM '\\E2019-01\C$\inetpub\logs\LogFiles\W3SVC1\*.log', '\\E2019-02\C$\inetpub\logs\LogFiles\W3SVC1\*.log'
WHERE TargetURL like '%/autodiscover/autodiscover%' AND cs-username NOT LIKE '%HealthMailbox%' AND QuarterHour BETWEEN TimeStamp('01/28/2023 20:00:00','MM/dd/yyyy hh:mm:ss') AND TO_LOCALTIME(SYSTEM_TIMESTAMP())

GROUP BY QuarterHour,UserName, TargetURL, ClientApp
ORDER BY QuarterHour

NOTE : here I aadded the QUANTIZE( time stamp , seconds ), and COUNT(*) as Total and then added GROUP BY with all SELECT fields.

NOTE 2 : I also used a WHERE filter to filter the search/results between a time in the past, and the system time.

Other examples wich are variants from the above examples...

/*
Display Autodiscover hits and UserName, URL stem, HTTP query, Client App, HTTP status, and hits in case there are many at the same date, time and second...
*/

SELECT TO_LOCALTIME(TO_TIMESTAMP(date, time)) AS DateTime,
       cs-username as UserName,
       cs-uri-stem as TargetURL,
       cs-uri-query as HTTPQuery,
       cs(User-Agent) as ClientApp,
       sc-status as HTTPStatus,
       COUNT(*) as Hits
FROM '\\E2019-01\C$\inetpub\logs\LogFiles\W3SVC1\*.log', '\\E2019-02\C$\inetpub\logs\LogFiles\W3SVC1\*.log'
/*WHERE TargetURL like '%/autodiscover/autodiscover%' AND cs-username NOT LIKE '%HealthMailbox%' AND DateTime BETWEEN TimeStamp('01/28/2023 00:00:00','MM/dd/yyyy hh:mm:ss') AND TimeStamp('01/28/2023 23:59:59','MM/dd/yyyy hh:mm:ss') */
WHERE DateTime BETWEEN TimeStamp('01/28/2023 20:00:00','MM/dd/yyyy hh:mm:ss') AND TO_LOCALTIME(SYSTEM_TIMESTAMP()) AND cs-username NOT LIKE '%HealthMailbox%' AND cs-username IS NOT NULL

/*
If you want to express time stamp corresponding to current time MINUS 20 minutes:
SUB(TO_LOCALTIME(SYSTEM_TIMESTAMP()),TIMESTAMP('20','mm'))
*/ 

GROUP BY DateTime, UserName, TargetURL, HttpQuery, ClientApp, HTTPStatus
ORDER BY DateTime DESC
/*
Dumps Time, UserName, URL stem, Client app, and HTTP status between a date in the past, and current date for Autodiscover entries in IIS log.
*/

SELECT TO_TIMESTAMP(date, time) AS LocalTime,
       cs-username as UserName,
       cs-uri-stem as TargetURL,
       sc-status as HTTPStatus,
       cs(User-Agent) as ClientApp
FROM '\\E2019-01\C$\inetpub\logs\LogFiles\W3SVC1\*.log', '\\E2019-02\C$\inetpub\logs\LogFiles\W3SVC1\*.log'
WHERE TargetURL like '%/autodiscover/autodiscover%' AND cs-username NOT LIKE '%HealthMailbox%' AND LocalTime BETWEEN TimeStamp('01/28/2023 20:00:00','MM/dd/yyyy hh:mm:ss') AND SYSTEM_TIMESTAMP()

/*
If you want to express time stamp corresponding to current time MINUS 20 minutes:
SUB(TO_LOCALTIME(SYSTEM_TIMESTAMP()),TIMESTAMP('20','mm'))
*/ 

ORDER BY LocalTime

And also below an example to show entries between a time in the past and the current time for all URL stems if you want to monitor until current activity for example:

/*
Display all IIS hits with UserName, URL stem, HTTP query, Client App, HTTP status,...
*/

SELECT TO_LOCALTIME(TO_TIMESTAMP(date, time)) AS LocalTime,
       cs-username as UserName,
       cs-uri-stem as TargetURL,
       cs-uri-query as HTTPQuery,
       cs(User-Agent) as ClientApp,
       sc-status as HTTPStatus
FROM '\\E2019-01\C$\inetpub\logs\LogFiles\W3SVC1\*.log', '\\E2019-02\C$\inetpub\logs\LogFiles\W3SVC1\*.log'
/*WHERE TargetURL like '%/autodiscover/autodiscover%' AND cs-username NOT LIKE '%HealthMailbox%' AND LocalTime BETWEEN TimeStamp('01/28/2023 00:00:00','MM/dd/yyyy hh:mm:ss') AND TimeStamp('01/28/2023 23:59:59','MM/dd/yyyy hh:mm:ss') */
WHERE LocalTime BETWEEN TimeStamp('01/28/2023 16:00:00','MM/dd/yyyy hh:mm:ss') AND SYSTEM_TIMESTAMP() AND TargetURL LIKE '%/autodiscover/autodiscover%'

/*
If you want to express time stamp corresponding to current time MINUS 20 minutes:
SUB(TO_LOCALTIME(SYSTEM_TIMESTAMP()),TIMESTAMP('20','mm'))
*/ 

ORDER BY LocalTime DESC

Show grouped stats about User names, target URL, Client Application used, HTTP status and number of hits, between 2 dates - a date in the past and current time. Local time is used. Also, there is a filtrer on the Application (Outlook) and its version (15.0 = Outlook 2013) to only display Outlook 2013 versions connecting to IIS:

/*
Show which user names target which URL stem with which Client App, and what's the HTTP status. Counts number of these by User Name, URL stem, client App and HTTP Status between 2 dates
*/

SELECT cs-username as UserName,
       cs-uri-stem as TargetURL,
       cs(User-Agent) as ClientApp,
       sc-status as HTTPStatus,
       COUNT(*) as NumberOfHits
FROM '\\E2019-01\C$\inetpub\logs\LogFiles\W3SVC1\*.log', '\\E2019-02\C$\inetpub\logs\LogFiles\W3SVC1\*.log'
WHERE TO_LOCALTIME(TO_TIMESTAMP(date, time)) BETWEEN TimeStamp('01/28/2023 00:00:00','MM/dd/yyyy hh:mm:ss') AND SYSTEM_TIMESTAMP() AND ClientApp LIKE '%Outlook%' AND ClientApp LIKE '%15.0%' AND UserName IS NOT NULL

/*
If you want to express time stamp corresponding to current time MINUS 20 minutes:
SUB(TO_LOCALTIME(SYSTEM_TIMESTAMP()),TIMESTAMP('20','mm'))
*/ 

GROUP BY UserName, TargetURL, ClientApp, HTTPStatus

Here's a sample output with my lab stats (connected with only one user)

image

Here's another example, grouped user names, HTTP status and number of hits regardless of the URL Stem and other fields, just the user and HTTP status code, still between 2 dates - a date in the past and current time. Local time is used. Like the previous example, there is a filter on the Application (Outlook) and its version (15.0 = Outlook 2013) to only display Outlook 2013 versions connecting to IIS:

/*
Show which user names target which URL stem with which Client App, and what's the HTTP status. Counts number of these by User Name, URL stem, client App and HTTP Status between 2 dates
*/

SELECT cs-username as UserName,
       sc-status as HTTPStatus,
       COUNT(*) as NumberOfHits
FROM '\\E2019-01\C$\inetpub\logs\LogFiles\W3SVC1\*.log', '\\E2019-02\C$\inetpub\logs\LogFiles\W3SVC1\*.log'
WHERE TO_LOCALTIME(TO_TIMESTAMP(date, time)) BETWEEN TimeStamp('01/28/2023 00:00:00','MM/dd/yyyy hh:mm:ss') AND SYSTEM_TIMESTAMP() AND cs(User-Agent) LIKE '%Outlook%' AND cs(User-Agent) LIKE '%15.0%' AND UserName IS NOT NULL

/*
If you want to express time stamp corresponding to current time MINUS 20 minutes:
SUB(TO_LOCALTIME(SYSTEM_TIMESTAMP()),TIMESTAMP('20','mm'))
*/ 

GROUP BY UserName, HTTPStatus

And a (very) sample Output with my unique user:

image

And here is another variant, same query as above, but I removed the version filter (%15.0%). I generated another user connection from Outlook 2016 this time:

/*
Show which user names target which URL stem with which Client App, and what's the HTTP status. Counts number of these by User Name, URL stem, client App and HTTP Status between 2 dates
*/

SELECT cs-username as UserName,
       cs-uri-stem as TargetURL,
       cs(User-Agent) as ClientApp,
       sc-status as HTTPStatus,
       COUNT(*) as NumberOfHits
FROM '\\E2019-01\C$\inetpub\logs\LogFiles\W3SVC1\*.log', '\\E2019-02\C$\inetpub\logs\LogFiles\W3SVC1\*.log'
WHERE TO_LOCALTIME(TO_TIMESTAMP(date, time)) BETWEEN TimeStamp('01/28/2023 00:00:00','MM/dd/yyyy hh:mm:ss') AND SYSTEM_TIMESTAMP() AND ClientApp LIKE '%Outlook%' AND UserName IS NOT NULL

GROUP BY UserName, TargetURL, ClientApp, HTTPStatus

And here's the result:

image

If I only want the user names who hit the server, regardless of the Outlook version, and regardless of the URL Outlook targetted, I simply comment the items I don't want to see in the SELECT clause, and don't forget to remove what we comment or remove on SELECT from the GROUP BY clause.

NOTE: if you comment or remove the "Property as MyCustomName" from SELECT and if you want to filter on this property that you removed, you need to filter on the original field name.

/*
Count the number of hits to any URL, by user and HTTP status, and show the number of hits.
*/

SELECT cs-username as UserName,
       /*cs-uri-stem as TargetURL,*/
       /*cs(User-Agent) as ClientApp,*/
       sc-status as HTTPStatus,
       COUNT(*) as NumberOfHits
FROM '\\E2019-01\C$\inetpub\logs\LogFiles\W3SVC1\*.log', '\\E2019-02\C$\inetpub\logs\LogFiles\W3SVC1\*.log'
WHERE TO_LOCALTIME(TO_TIMESTAMP(date, time)) BETWEEN TimeStamp('01/28/2023 00:00:00','MM/dd/yyyy hh:mm:ss') AND SYSTEM_TIMESTAMP() AND cs(User-Agent) LIKE '%Outlook%' AND UserName IS NOT NULL

/*
If you want to express time stamp corresponding to current time MINUS 20 minutes:
SUB(TO_LOCALTIME(SYSTEM_TIMESTAMP()),TIMESTAMP('20','mm'))
*/ 

GROUP BY UserName, HTTPStatus

And thet sample result:

image

Hope this helps on your LogParser queries !