Splunk Search

How to find max(_time) for sourcetypes & host by sourcetype host?

sjringo
Contributor

I found the following search to identify Missing / New sourcetypes and made a few changes.
I am getting data and my next enhancement is to add the latest date/time a sourcetype was 'seen'.

Here is the search I am starting with:

index=anIndex earliest=-4d latest=now
| eval recent=if(_time>(now()-129600 ),1,0) ```<--- No Logs in 1.5 Days ```
| stats count(eval(recent=1)) AS CurrentCount count(eval(recent=0)) AS HistoricalCount BY sourcetype host
| where ( (CurrentCount < 1 AND HistoricalCount > 0) OR ( CurrentCount > 0 AND HistoricalCount < 1)) ```<--- Missing & New```
| eval status=case(CurrentCount > 0 AND HistoricalCount > 0, "OK",
CurrentCount < 1 AND HistoricalCount > 0, "MISSING",
CurrentCount > 0 AND HistoricalCount < 1, "NEW",
1=1,"Unknown" )
| sort sourcetype
| table status host sourcetype CurrentCount HistoricalCount

I think this is returning the last time a sourcetype was seen:

index=anIndex earliest=-2d latest=now
| stats max(_time) as last_searched by sourcetype host
| eval lastTime=strftime(last_searched, "%m/%d/%y %H:%M:%S")
| sort sourcetype host
| table host sourcetype lastTime

But, when I try to add these two lines into my original query I do not get any data ?

| stats max(_time) as last_searched by sourcetype host
| eval lastTime=strftime(last_searched, "%m/%d/%y %H:%M:%S")

I have tried placing it in several different places but always get 'No Results found...'
What am I missing ?

Labels (2)
0 Karma
1 Solution

yeahnah
Motivator

Hi @sjringo 

Sorry, I had not accounted for you count logic.  You can use tstats like this and then apply some logic to the results.

| tstats
    max(_time) AS max_current_time
    count AS CurrentCount
  WHERE index=anIndex earliest=-129600 latest=now
  BY sourcetype host
| append [| tstats
    max(_time) AS max_historical_time
    count AS HistoricalCount
  WHERE index=anIndex earliest=-4d latest=-129600
  BY sourcetype host ]
| stats values(*) AS * BY sourcetype host
| foreach *_time [ eval <<FIELD>>_hm=strftime('<<FIELD>>', "%c") ]  ``` not really needed ```
| eval _time=if(max_current_time > max_historical_time OR isnull(max_historical_time), max_current_time, max_historical_time)
| eval status=case(CurrentCount > 0 AND HistoricalCount > 0, "OK", isnull(CurrentCount), "MISSING", isnull(HistoricalCount), "NEW", true(), "Unknown" )
| sort sourcetype
| rename status AS Status, host AS Host, sourcetype AS "Source Type", CurrentCount AS "Log Entries in 1.5 Days", HistoricalCount AS "Log Entries over 1.5 Days"
| table Status Host "Source Type" "Log Entries in 1.5 Days" "Log Entries over 1.5 Days" _time

 It might not be perfect but will hopefully get you going

View solution in original post

yeahnah
Motivator

Hi @sjringo 

In the first query the _time field is not a result field, so you obviously cannot use it.  Here's a modified query that also returns the max time for each host sourcetype.  I've also demonstrated how to use the tstats command to make the query x100 times quicker and more efficient, but you can revert back to scanning _raw events if you prefer.

| tstats max(_time) AS _time WHERE index=anIndex earliest=-4d latest=now BY sourcetype host 
| eval recent=if(_time>(now()-129600 ),1,0) ```<--- No Logs in 1.5 Days ```
| stats max(_time) AS max_time count(eval(recent=1)) AS CurrentCount count(eval(recent=0)) AS HistoricalCount BY sourcetype host
| where ( (CurrentCount < 1 AND HistoricalCount > 0) OR ( CurrentCount > 0 AND HistoricalCount < 1)) ```<--- Missing & New```
| eval status=case(CurrentCount > 0 AND HistoricalCount > 0, "OK",
    CurrentCount < 1 AND HistoricalCount > 0, "MISSING",
    CurrentCount > 0 AND HistoricalCount < 1, "NEW",
    1=1,"Unknown" )
| sort sourcetype
| table status host sourcetype CurrentCount HistoricalCount max_time
| stats max(max_time) as last_searched by sourcetype host
| eval lastTime=strftime(last_searched, "%m/%d/%y %H:%M:%S")

  Hope that helps

sjringo
Contributor

Ok, I had to massage your posting somewhat to work with what I was looking for.

I am aware of TSTATS but struggling to get it to work for the query that I am starting with ?

Here is what I have working:

index=anIndex earliest=-4d latest=now

| eval recent=if(_time>(now()-129600 ),1,0) ```<--- No Logs in 1.5 Days ```

| stats max(_time) AS max_time count(eval(recent=1)) AS CurrentCount count(eval(recent=0)) AS HistoricalCount BY sourcetype host

| where ( (CurrentCount < 1 AND HistoricalCount > 0) OR ( CurrentCount > 0 AND HistoricalCount < 1)) ```<--- Missing & New```

| eval status=case(CurrentCount > 0 AND HistoricalCount > 0, "OK", CurrentCount < 1 AND HistoricalCount > 0, "MISSING", CurrentCount > 0 AND HistoricalCount < 1, "NEW", 1=1,"Unknown" )

| eval lastTime=strftime(max_time, "%m/%d/%y %H:%M:%S")

| sort sourcetype

| rename status AS Status, host AS Host, sourcetype AS "Source Type", CurrentCount AS "Log Entries in 1.5 Days", HistoricalCount AS "Log Entries over 1.5 Days", lastTime AS "Last Log Entry"

| table Status Host "Source Type" "Log Entries in 1.5 Days" "Log Entries over 1.5 Days" "Last Log Entry"

Any help in getting it to work with TSTATS would be appreciated...

0 Karma

yeahnah
Motivator

Hi @sjringo 

Sorry, I had not accounted for you count logic.  You can use tstats like this and then apply some logic to the results.

| tstats
    max(_time) AS max_current_time
    count AS CurrentCount
  WHERE index=anIndex earliest=-129600 latest=now
  BY sourcetype host
| append [| tstats
    max(_time) AS max_historical_time
    count AS HistoricalCount
  WHERE index=anIndex earliest=-4d latest=-129600
  BY sourcetype host ]
| stats values(*) AS * BY sourcetype host
| foreach *_time [ eval <<FIELD>>_hm=strftime('<<FIELD>>', "%c") ]  ``` not really needed ```
| eval _time=if(max_current_time > max_historical_time OR isnull(max_historical_time), max_current_time, max_historical_time)
| eval status=case(CurrentCount > 0 AND HistoricalCount > 0, "OK", isnull(CurrentCount), "MISSING", isnull(HistoricalCount), "NEW", true(), "Unknown" )
| sort sourcetype
| rename status AS Status, host AS Host, sourcetype AS "Source Type", CurrentCount AS "Log Entries in 1.5 Days", HistoricalCount AS "Log Entries over 1.5 Days"
| table Status Host "Source Type" "Log Entries in 1.5 Days" "Log Entries over 1.5 Days" _time

 It might not be perfect but will hopefully get you going

sjringo
Contributor

Getting results using your updated TSTATS query.  I am going to need a little time to compare data from both queries and mash up the results just to figure out if both results are returning the same results, etc...

But the speed of the query results is better.  a few seconds compared to 15 minutes !!!

TSTATS is still a little bit fuzzy but having something that works will help me going forward...

Thanks for your help ...

0 Karma
Career Survey
First 500 qualified respondents will receive a $20 gift card! Tell us about your professional Splunk journey.

Can’t make it to .conf25? Join us online!

Get Updates on the Splunk Community!

Leveraging Automated Threat Analysis Across the Splunk Ecosystem

Are you leveraging automation to its fullest potential in your threat detection strategy?Our upcoming Security ...

Can’t Make It to Boston? Stream .conf25 and Learn with Haya Husain

Boston may be buzzing this September with Splunk University and .conf25, but you don’t have to pack a bag to ...

Splunk Lantern’s Guide to The Most Popular .conf25 Sessions

Splunk Lantern is a Splunk customer success center that provides advice from Splunk experts on valuable data ...