Splunk Search

Query with multiple subsearch causing subsearch auto-finalized and truncating due to subsearch limits.

shenismyname
Engager

Hi Splunk Community, I am pretty new to using Splunk for reporting purposes. Below are my use case :

 

Every month, I am required to generate report to calculate monthly response time for each action report of that is requesting to our service our services. 

However, calculating the response time is not straight forward as in the report, we wanted to calculate NetResponseTime, where ResponseTime - MOMDuration (External API call) - EMCDuration (External API call).  By getting the NetResponseTime, this will only contains the internal related processing time.

All logs is able to be correlated by cid.

Currently, i am able to come up with the query and it is tested working accurately provided the subsearch limit is not reached, however, as the logs are increasing (number of logs/ per month), there is a concern where i noticed the subsearch is auto-finalized and it will be truncating due to some subsearch limits(i.e subsearch only returns 50k rows).

Would be helpful if someone is able to provide me some guidance on how can I refractor my query to use multi-search(with proper grouping event from multiple sources and performing computation within each sources) instead of subsearch. Below is the query(it will be quite long):

--------------------This is the main search: Get The Response Time for each request------------------------------------------
index=someindex sourcetype= DiagnosticsLog host=DiagServer
|eval ActionEnum= if(like(CsUriStem,"%StampTransactions%"),2,if(like(CsUriStem,"%/kiosk/api/Transactions/Stamp%"),2,if(like(CsUriStem,"%/kiosk/api/Transactions/Search/Passport%"),1,if(like(CsUriStem,"%/kiosk/api/Refund/emcpayAccount/%"),3,if(like(CsUriStem,"%/kiosk/api/Refund/emcpayAccountConfirmation%"),4,null())))))
|eval CsUriStem = if(like(CsUriStem,"%/kiosk/api/Refund/emcpayAccount/%"),(mvindex(split(CsUriStem,"/kiosk/api/Refund/emcpayAccount/"),0))+"/kiosk/api/Refund/emcpayAccount/",CsUriStem)
|eval DateTime_Unix=strptime(DateTime,"%Y-%m-%d %H:%M:%S.%7N")
|eval nStart=relative_time(now(),"-1mon@mon")
|eval nStart=relative_time(nStart,"-8h")
|eval nEnd=relative_time(now(),"@mon")
|eval nEnd=relative_time(nEnd,"-8h")
|where DateTime_Unix>=nStart AND DateTime_Unix<nEnd
|table LogId CsUriQuery CsUriStem DateTime DateTime_Unix SComputerName SPort SiteName TimeTaken TransferTime ActionEnum
|join type=left CsUriQuery
[search index=someindex
sourcetype= DiagnosticsLog host=DiagServer
|eval DateTime_Unix=strptime(DateTime,"%Y-%m-%d %H:%M:%S.%7N")
|eval nStart=relative_time(now(),"-1mon@mon")
|eval nStart=relative_time(nStart,"-8h")
|eval nEnd=relative_time(now(),"@mon")
|eval nEnd=relative_time(nEnd,"-8h")
|where DateTime_Unix>=nStart AND DateTime_Unix<nEnd
|eventstats values(CsUriQuery) by cid
|eval SearchPassportEndDateTime_Unix = if(like(CsUriStem,"%/kiosk/api/Transactions/Search/Passport%"),DateTime_Unix+(TimeTaken/1000),null())
|eval SearchPassportEndDateTime = strftime(SearchPassportEndDateTime_Unix,"%Y-%m-%d %H:%M:%S.%5N")
|table CsUriQuery SearchPassportEndDateTime SearchPassportEndDateTime_Unix
|where isnotnull(SearchPassportEndDateTime_Unix)]
|eval TimeTakenMilli=TimeTaken/1000
|eval TimeTakenNew=if(like(CsUriStem,"%RetrieveTransactions%") AND isnotnull(SearchPassportEndDateTime),if(DateTime_Unix>SearchPassportEndDateTime_Unix,TimeTaken,(DateTime_Unix+TimeTakenMilli-SearchPassportEndDateTime_Unix)*1000),TimeTaken)
|table LogId CsUriQuery CsUriStem DateTime SComputerName SPort SiteName TimeTaken TimeTakenNew TransferTime ActionEnum
|rename CsUriQuery as cid
--------------------This is the main search------------------------------------------
|join type=left cid,ActionEnum
--------------------This is the sub search:Computing MOMDuration (External API call)------------------------------------------
[search index=someindex Application=ExternalValidation (host=ValidationServer1 OR host=ValidationServer2) (Event="MomGateway_GetEP_Begin" OR Event="MomGateway_GetEP_End" )
|eval nStart=relative_time(now(),"-1mon@mon")
|eval nStart=relative_time(nStart,"-8h")
|eval nEnd=relative_time(now(),"@mon")
|where (Event="MomGateway_GetEP_Begin" OR Event="MomGateway_GetEP_End" )
|rex field=_raw "(?<epdate>\d\d\d\d-\w+-\d\d\s+\d\d:\d\d:\d\d\.\d+)"
|transaction cid startswith=(Event="MomGateway_GetEP_Begin") endswith=(Event="MomGateway_GetEP_End" ) mvlist=epdate
|eval MOM_start_time=mvindex(epdate,0)
|eval MOM_end_time=mvindex(epdate,1)
|eval MOM_end_timeUnix=strptime(MOM_end_time,"%Y-%m-%d %H:%M:%S.%5N")
|eval MOM_start_timeUnix=strptime(MOM_start_time,"%Y-%m-%d %H:%M:%S.%5N")
|eval MOM_request_type = "EP"
|eval differences = MOM_end_timeUnix-MOM_start_timeUnix
|where MOM_start_timeUnix>=nStart AND MOM_start_timeUnix<nEnd
|union
[search index=someindex Application ="ExternalValidation" (host=ValidationServer1 OR host=ValidationServer2) (Event="MomGateway_GetWP_Begin" OR Event="MomGateway_GetWP_End" )
|eval nStart=relative_time(now(),"-1mon@mon")
|eval nStart=relative_time(nStart,"-8h")
|eval nEnd=relative_time(now(),"@mon")
| where (Event="MomGateway_GetWP_Begin" OR Event="MomGateway_GetWP_End" )
|rex field=_raw "(?<wpdate>\d\d\d\d-\w+-\d\d\s+\d\d:\d\d:\d\d\.\d+)"
|transaction cid startswith=( Event="MomGateway_GetWP_Begin") endswith=(Event="MomGateway_GetWP_End") mvlist=wpdate
|eval MOM_start_time=mvindex(wpdate,0)
|eval MOM_end_time=mvindex(wpdate,1)
|eval MOM_end_timeUnix=strptime(MOM_end_time,"%Y-%m-%d %H:%M:%S.%5N")
|eval MOM_start_timeUnix=strptime(MOM_start_time,"%Y-%m-%d %H:%M:%S.%5N")
|eval MOM_request_type = "WP"
```8. Calculate the differences between start/end time for each transactions```
|eval differences = MOM_end_timeUnix-MOM_start_timeUnix
|where MOM_start_timeUnix>=nStart AND MOM_start_timeUnix<nEnd
]
|sort 0 cid MOM_start_time
|streamstats current=f window=0 global=f min(MOM_start_time) as MinTime max(MOM_end_time) as MaxTime min(MOM_start_timeUnix) as MinTimeUnix max(MOM_end_timeUnix) as MaxTimeUnix by cid
|eval overlapped=if(MOM_start_timeUnix<= MaxTimeUnix ,1,0)
|eval NetMOMDuration=if(overlapped>0,if(MOM_end_timeUnix>MaxTimeUnix,MOM_end_timeUnix-MaxTimeUnix,0),differences)
|join type=inner cid
[search index=someindex (host=ValidationServer1 OR host=ValidationServer2) (*TransactionsController_SearchByPassport_Begin* OR *TransactionsController_Stamp_Begin* OR *TransactionsController_SearchByPassport_End* OR *TransactionsController_Stamp_End*)
|where Application="ApiFacadeKiosk"
|rex field=_raw "(?<date>\d\d\d\d-\w+-\d\d\s+\d\d:\d\d:\d\d\.\d+)"
|eval nStart=relative_time(now(),"-1mon@mon")
|eval nStart=relative_time(nStart,"-8h")
|eval nEnd=relative_time(now(),"@mon")
|eval date_Unix=strptime(date,"%Y-%m-%d %H:%M:%S.%5N")
|eval startTime_SearchPassport = if(like(_raw,"%TransactionsController_SearchByPassport_Begin%"),date,null())
|eval startTime_Stamping = if(like(_raw,"%TransactionsController_Stamp_Begin%"),date,null())
|eval endTime_SearchPassport = if(like(_raw,"%TransactionsController_SearchByPassport_End%"),date,null())
|eval endTime_Stamping = if(like(_raw,"%TransactionsController_Stamp_End%"),date,null())
|where date_Unix>=nStart AND date_Unix<nEnd
|stats values(startTime_SearchPassport) AS startTime_SearchPassport values(startTime_Stamping) AS startTime_Stamping values(endTime_SearchPassport) AS endTime_SearchPassport values(endTime_Stamping) AS endTime_Stamping by cid
]
|eval startTime_Stamping_Filled=if(isnull(startTime_Stamping),null(),strptime(startTime_Stamping,"%Y-%m-%d %H:%M:%S.%5N"))
|eval startTime_SearchPassport_Filled=if(isnull(startTime_SearchPassport),null(),strptime(startTime_SearchPassport,"%Y-%m-%d %H:%M:%S.%5N"))
|eval endTime_Stamping_Filled=if(isnull(endTime_Stamping),null(),strptime(endTime_Stamping,"%Y-%m-%d %H:%M:%S.%5N"))
|eval endTime_SearchPassport_Filled=if(isnull(endTime_SearchPassport),null(),strptime(endTime_SearchPassport,"%Y-%m-%d %H:%M:%S.%5N"))
|eval ActionType=if(isnull(startTime_Stamping_Filled),"SearchPassport",if(startTime_Stamping_Filled<MOM_start_timeUnix,"Stamping","SearchPassport"))
|eventstats sum(NetMOMDuration) as TotalMOMDurationByAction count(cid) As TotalMOMRequest by cid ActionType
|eval ActionEnum= if(like(ActionType,"SearchPassport"),1,2)
|table cid TotalMOMDurationByAction ActionType TotalMOMRequest ActionEnum
|dedup cid TotalMOMDurationByAction ActionType TotalMOMRequest ActionEnum]
--------------------This is the sub search:Computing MOMDuration (External API call)------------------------------------------
|join type=left cid,ActionEnum
--------------------This is the sub search:Computing EMCDuration (External API call)------------------------------------------
[search index=someindex Application=RefundControl (host=ValidationServer1 OR host=ValidationServer2) (Event="PostFirstemcpay_Begin" OR Event="PostFirstemcpay_End" )
|where (Event="PostFirstemcpay_Begin" OR Event="PostFirstemcpay_End" )
|rex field=_raw "(?<emcpayfirstdate>\d\d\d\d-\w+-\d\d\s+\d\d:\d\d:\d\d\.\d+)"
|eval nStart=relative_time(now(),"-1mon@mon")
|eval nStart=relative_time(nStart,"-8h")
|eval nEnd=relative_time(now(),"@mon")
|transaction cid startswith=( Event=PostFirstemcpay_Begin) endswith=(PostFirstemcpay_End) mvlist=emcpayfirstdate
|eval emcpay_start_time=mvindex(emcpayfirstdate,0)
|eval emcpay_end_time=mvindex(emcpayfirstdate,1)
|eval emcpay_end_timeUnix=strptime(emcpay_end_time,"%Y-%m-%d %H:%M:%S.%5N")
|eval emcpay_start_timeUnix=strptime(emcpay_start_time,"%Y-%m-%d %H:%M:%S.%5N")
|eval emcpay_request_type = "emcpayAccount"
|eval NetemcpayDuration = emcpay_end_timeUnix-emcpay_start_timeUnix
|where emcpay_start_timeUnix>=nStart AND emcpay_start_timeUnix<nEnd
|sort 0 cid emcpay_start_time
|eventstats max(emcpay_start_timeUnix) As Maxemcpay_start_timeUnix by cid
|where emcpay_start_timeUnix = Maxemcpay_start_timeUnix
|table cid emcpay_start_time emcpay_end_time overlapped NetemcpayDuration emcpay_request_type
|union
[search index=someindex Application=RefundControl (host=ValidationServer1 OR host=ValidationServer2) (Event="PostSecondemcpay_Begin" OR Event="PostSecondemcpay_End" )
|where (Event="PostSecondemcpay_Begin" OR Event="PostSecondemcpay_End" )
|rex field=_raw "(?<emcpayseconddate>\d\d\d\d-\w+-\d\d\s+\d\d:\d\d:\d\d\.\d+)"
|eval nStart=relative_time(now(),"-1mon@mon")
|eval nStart=relative_time(nStart,"-8h")
|eval nEnd=relative_time(now(),"@mon")
|transaction cid startswith=( Event=PostSecondemcpay_Begin) endswith=(Event=PostSecondemcpay_End) mvlist=emcpayseconddate
|eval emcpay_start_time=mvindex(emcpayseconddate,0)
|eval emcpay_end_time=mvindex(emcpayseconddate,1)
|eval emcpay_end_timeUnix=strptime(emcpay_end_time,"%Y-%m-%d %H:%M:%S.%5N")
|eval emcpay_start_timeUnix=strptime(emcpay_start_time,"%Y-%m-%d %H:%M:%S.%5N")
|eval emcpay_request_type = "emcpayConfirm"
|eval NetemcpayDuration = emcpay_end_timeUnix-emcpay_start_timeUnix
|where emcpay_start_timeUnix>=nStart AND emcpay_start_timeUnix<nEnd
|sort 0 cid emcpay_start_time
|eventstats max(emcpay_start_timeUnix) As Maxemcpay_start_timeUnix by cid
|where emcpay_start_timeUnix = Maxemcpay_start_timeUnix
|table cid emcpay_start_time emcpay_end_time overlapped NetemcpayDuration emcpay_request_type]
|union
[search index=someindex Application=RefundControl (host=ValidationServer1 OR host=ValidationServer2) (Event="Writeemcpay_Begin" OR Event="Writeemcpay_End" )
|where (Event="NcsWriteGateway_WriteNcsemcpay_Begin" OR Event="NcsWriteGateway_WriteNcsemcpay_End" )
|rex field=_raw "(?<emcpaythirddate>\d\d\d\d-\w+-\d\d\s+\d\d:\d\d:\d\d\.\d+)"
|eval nStart=relative_time(now(),"-1mon@mon")
|eval nStart=relative_time(nStart,"-8h")
|eval nEnd=relative_time(now(),"@mon")
|transaction cid startswith=( Event=Writeemcpay_Begin) endswith=(Event=Writeemcpay_End) mvlist=emcpaythirddate
|eval emcpay_start_time=mvindex(emcpaythirddate,0)
|eval emcpay_end_time=mvindex(emcpaythirddate,1)
|eval emcpay_end_timeUnix=strptime(emcpay_end_time,"%Y-%m-%d %H:%M:%S.%5N")
|eval emcpay_start_timeUnix=strptime(emcpay_start_time,"%Y-%m-%d %H:%M:%S.%5N")
|eval emcpay_request_type = "emcpayRefund"
|eval NetemcpayDuration = emcpay_end_timeUnix-emcpay_start_timeUnix
|where emcpay_start_timeUnix>=nStart AND emcpay_start_timeUnix<nEnd
|sort 0 cid emcpay_start_time
|eventstats max(emcpay_start_timeUnix) As Maxemcpay_start_timeUnix by cid
|where emcpay_start_timeUnix = Maxemcpay_start_timeUnix
|table cid emcpay_start_time emcpay_end_time overlapped NetemcpayDuration emcpay_request_type]
|eventstats sum(NetemcpayDuration) as TotalemcpayDurationByAction count(cid) As TotalemcpayRequest by cid emcpay_request_type
|eval ActionEnum= if(like(emcpay_request_type,"emcpayAccount"),3,if(like(emcpay_request_type,"emcpayConfirm"),4,if(like(emcpay_request_type,"emcpayRefund"),2,null())))
|table cid TotalemcpayDurationByAction emcpay_request_type TotalemcpayRequest ActionEnum
|dedup cid TotalemcpayDurationByAction emcpay_request_type TotalemcpayRequest ActionEnum]
--------------------This is the sub search:Computing EMCDuration (External API call)------------------------------------------
|eval startTime_Stamping_Filled=if(isnull(startTime_Stamping),null(),strptime(startTime_Stamping,"%Y-%m-%d %H:%M:%S.%5N"))
|eval startTime_SearchPassport_Filled=if(isnull(startTime_SearchPassport),null(),strptime(startTime_SearchPassport,"%Y-%m-%d %H:%M:%S.%5N"))
|eval endTime_Stamping_Filled=if(isnull(endTime_Stamping),null(),strptime(endTime_Stamping,"%Y-%m-%d %H:%M:%S.%5N"))
|eval endTime_SearchPassport_Filled=if(isnull(endTime_SearchPassport),null(),strptime(endTime_SearchPassport,"%Y-%m-%d %H:%M:%S.%5N"))
|eval TotalemcpayDurationByAction=if(isnull(TotalemcpayDurationByAction),0,TotalemcpayDurationByAction*1000)
|eval TotalMOMDurationByAction=if(isnull(TotalMOMDurationByAction),0,TotalMOMDurationByAction*1000)
|eval NetResponseTime = TimeTakenNew-TotalMOMDurationByAction-TotalemcpayDurationByAction
|table LogId cid CsUriStem DateTime SComputerName SPort SiteName TimeTaken TimeTakenNew TransferTime ActionType TotalMOMDurationByAction TotalemcpayDurationByAction NetResponseTime

Labels (2)
0 Karma
1 Solution

bowesmana
SplunkTrust
SplunkTrust

Your search is quite involved with many joins (4) and you are repeatedly using inefficient constructs (transaction(5), eventstats (6)), so this is a search that is always going to be slow. You should also use 'fields' command instead of 'table' as the table command is a formatting command and will cause all the data to be sent from the indexers to the search head and will be stressing the search heads rather than using the indexers for the work (relevant in a clustered environment).

Generally in Splunk, the use of 'join' should be regarded as a last resort and ONLY when you KNOW that you will have a small result set to join with, otherwise you will hit the limits you have come across.

The general way to solve this type of problem in Splunk is to use this principle...

search data_set_1 OR data_set_2 OR data_set_3 ...
| eval type=case(data_set_1, 1, data_set_2, 2, data_set_3, 3)
| stats useful_aggregation_1 as ag_1
   values(eval(if(type==1,1,null())))
   values(eval(if(type==2,field2,null())))
   values(eval(if(type==3,field3,null())))
   by y
| eval do_calculations on found fields
| produce results

so, you search for all the data you need in your calculations in a single search and then use eval evaluations and conditional aggregations in statistics commands to "join" your data sets into a single row.

The search you have is complex and without knowing your data, I can't really offer specific advice, but the goal should be to remove the use of subsearches, e.g. your search/transaction/eventstats/union logic should not really need to be written like that - you may be able to make that a single search using stats and some conditional data set specific evals.

Note that you have some seeming redundant where statements 

search index=someindex Application ="ExternalValidation" (host=ValidationServer1 OR host=ValidationServer2) (Event="MomGateway_GetWP_Begin" OR Event="MomGateway_GetWP_End" )
...
| where (Event="MomGateway_GetWP_Begin" OR Event="MomGateway_GetWP_End" )

and also some ones that will remove all data, as the where condition will never evaluate true 

search index=someindex Application=RefundControl (host=ValidationServer1 OR host=ValidationServer2) (Event="Writeemcpay_Begin" OR Event="Writeemcpay_End" )
|where (Event="NcsWriteGateway_WriteNcsemcpay_Begin" OR Event="NcsWriteGateway_WriteNcsemcpay_End" )

 and the if/if/if/if construct could use case(...)

|eval ActionEnum=
  if(like(CsUriStem,"%StampTransactions%"),2,
   if(like(CsUriStem,"%/kiosk/api/Transactions/Stamp%"),2,
    if(like(CsUriStem,"%/kiosk/api/Transactions/Search/Passport%"),1,
     if(like(CsUriStem,"%/kiosk/api/Refund/emcpayAccount/%"),3,
      if(like(CsUriStem,"%/kiosk/api/Refund/emcpayAccountConfirmation%"),4,null()
      )
     )
    )
   )
  )

This search will not be trivial to optimise, but if you bring all the data into a single search, you should then be able to work out the different eval statements/aggregations and other logic to carve it up into the distinct blocks you need.

Your key dimension is 'cid', so work with that to massage the data into the set you need. Image a large table, where each row will have some columns with some data relating to the dataset it holds. At some point you can then collapse (join) all that data together using stats values(*) as * by cid.

Some other tips - always reduce the data you are processing as quickly as possible, so for example

|table CsUriQuery SearchPassportEndDateTime SearchPassportEndDateTime_Unix
|where isnotnull(SearchPassportEndDateTime_Unix)

should be

|where isnotnull(SearchPassportEndDateTime_Unix)
|fields CsUriQuery SearchPassportEndDateTime SearchPassportEndDateTime_Unix

because your original first sends all the data to the search head (table) and then you drop some of it with the where statement.

Good luck.

 

View solution in original post

bowesmana
SplunkTrust
SplunkTrust

Your search is quite involved with many joins (4) and you are repeatedly using inefficient constructs (transaction(5), eventstats (6)), so this is a search that is always going to be slow. You should also use 'fields' command instead of 'table' as the table command is a formatting command and will cause all the data to be sent from the indexers to the search head and will be stressing the search heads rather than using the indexers for the work (relevant in a clustered environment).

Generally in Splunk, the use of 'join' should be regarded as a last resort and ONLY when you KNOW that you will have a small result set to join with, otherwise you will hit the limits you have come across.

The general way to solve this type of problem in Splunk is to use this principle...

search data_set_1 OR data_set_2 OR data_set_3 ...
| eval type=case(data_set_1, 1, data_set_2, 2, data_set_3, 3)
| stats useful_aggregation_1 as ag_1
   values(eval(if(type==1,1,null())))
   values(eval(if(type==2,field2,null())))
   values(eval(if(type==3,field3,null())))
   by y
| eval do_calculations on found fields
| produce results

so, you search for all the data you need in your calculations in a single search and then use eval evaluations and conditional aggregations in statistics commands to "join" your data sets into a single row.

The search you have is complex and without knowing your data, I can't really offer specific advice, but the goal should be to remove the use of subsearches, e.g. your search/transaction/eventstats/union logic should not really need to be written like that - you may be able to make that a single search using stats and some conditional data set specific evals.

Note that you have some seeming redundant where statements 

search index=someindex Application ="ExternalValidation" (host=ValidationServer1 OR host=ValidationServer2) (Event="MomGateway_GetWP_Begin" OR Event="MomGateway_GetWP_End" )
...
| where (Event="MomGateway_GetWP_Begin" OR Event="MomGateway_GetWP_End" )

and also some ones that will remove all data, as the where condition will never evaluate true 

search index=someindex Application=RefundControl (host=ValidationServer1 OR host=ValidationServer2) (Event="Writeemcpay_Begin" OR Event="Writeemcpay_End" )
|where (Event="NcsWriteGateway_WriteNcsemcpay_Begin" OR Event="NcsWriteGateway_WriteNcsemcpay_End" )

 and the if/if/if/if construct could use case(...)

|eval ActionEnum=
  if(like(CsUriStem,"%StampTransactions%"),2,
   if(like(CsUriStem,"%/kiosk/api/Transactions/Stamp%"),2,
    if(like(CsUriStem,"%/kiosk/api/Transactions/Search/Passport%"),1,
     if(like(CsUriStem,"%/kiosk/api/Refund/emcpayAccount/%"),3,
      if(like(CsUriStem,"%/kiosk/api/Refund/emcpayAccountConfirmation%"),4,null()
      )
     )
    )
   )
  )

This search will not be trivial to optimise, but if you bring all the data into a single search, you should then be able to work out the different eval statements/aggregations and other logic to carve it up into the distinct blocks you need.

Your key dimension is 'cid', so work with that to massage the data into the set you need. Image a large table, where each row will have some columns with some data relating to the dataset it holds. At some point you can then collapse (join) all that data together using stats values(*) as * by cid.

Some other tips - always reduce the data you are processing as quickly as possible, so for example

|table CsUriQuery SearchPassportEndDateTime SearchPassportEndDateTime_Unix
|where isnotnull(SearchPassportEndDateTime_Unix)

should be

|where isnotnull(SearchPassportEndDateTime_Unix)
|fields CsUriQuery SearchPassportEndDateTime SearchPassportEndDateTime_Unix

because your original first sends all the data to the search head (table) and then you drop some of it with the where statement.

Good luck.

 

Get Updates on the Splunk Community!

Index This | I am a number, but when you add ‘G’ to me, I go away. What number am I?

March 2024 Edition Hayyy Splunk Education Enthusiasts and the Eternally Curious!  We’re back with another ...

What’s New in Splunk App for PCI Compliance 5.3.1?

The Splunk App for PCI Compliance allows customers to extend the power of their existing Splunk solution with ...

Extending Observability Content to Splunk Cloud

Register to join us !   In this Extending Observability Content to Splunk Cloud Tech Talk, you'll see how to ...