lordmilko / PrtgAPI

C#/PowerShell interface for PRTG Network Monitor
MIT License
301 stars 37 forks source link

Add startDate parameter to WatchLogs() #139

Closed paulkva closed 4 years ago

paulkva commented 4 years ago

What are you trying to do, and to what extent does PrtgAPI provide existing functionality around this? The Powershell command Get-ObjectLog -Wait also respects the -StartDate argument, and it initially returns all logs from the specified StartDate before entering "wait" mode. The C# equivalent, WatchLogs(), does not accept a startDate argument, and replicating the Powershell functionality would require multiple calls (GetLogs() followed by WatchLogs()) and I think would have a slight risk of a race condition (if PRTG emits a log entry in between the two calls).

Is this something that has some sort of parallel in the PRTG UI? If so where do you go/how do you normally do it? This is something that has a parallel in PrtgAPI's Powershell implementation. 😃 We are trying to collect all PRTG logs into our Splunk instance. Based on a series of searches, I haven't found any option as robust as PrtgAPI. Using C# instead of Powershell would allow us to more easily pull the credentials we need securely, but without this functionality in C# we will likely try to accomplish this via Powershell.

Due Diligence Please enter an 'x' between the brackets to indicate you have done these

lordmilko commented 4 years ago

Hi @paulkva,

My imagined use case of the WatchLogs feature was waiting for some important event to occur, like an object changing state or a notification occurring or something. The PowerShell implementation of this only got the -StartDate parameter for free as this parameter was already present on the Get-ObjectLogs cmdlet, and the PowerShell implementations sometimes need to bypass PrtgClient to specify their parameters objects directly.

I thought it was pretty nifty seeing a couple of earlier records when specifying -StartDate, however if you actually have a use case for this I think this would be a pretty good idea! I'm currently working on implementing this, hopefully I should have a pre-release build of PrtgAPI 0.9.13 uploaded within a couple of hours

lordmilko commented 4 years ago

Hi @paulkva,

I have released a pre-release build of PrtgAPI 0.9.13 that includes this enhancement. Can you please follow the manual installation instructions and advise whether this works as expected?

Regards, lordmilko

paulkva commented 4 years ago

I can confirm that the startDate argument is available in the pre-release build, but to be quite frank I had only just barely started to build the logging mechanism that we had been contemplating, so it might be a few more days before I can verify everything works as expected. I'll keep you posted.

Thank you so much for the quick response and enhancement!

paulkva commented 4 years ago

Quick update. The proof-of-concept works! One small nitpick is startDate doesn't seem to have the granularity I expected. Subsequent runs of my code will read from a local log file to find the latest captured timestamp, then add 1ms and run WatchLogs() with that as its startDate, but it then picks up the latest log entry again. The logs emitted do have millisecond precision though.

This does get me "close enough" since I can just check for repeat entries, so if increasing date precision proves to be problematic (or if it's out of your control due to PRTG internals) I wouldn't worry about it too much.

Thanks again!

lordmilko commented 4 years ago

I'm not sure I fully understand what you're doing with your log file, however potentially it may be easier for you to implement implement your own custom WatchLogs method yourself

The InfiniteLogGenerator class handles the logic of streaming logs from PRTG. Whenever it checks for new logs, I believe you'll find it usuaully returns a bunch of logs you've seen previously as well. Logs that have been seen before are stored in a HashSet.

Since individual log entries don't have a unique identifier, we determine whether two logs are the same by creating a string from all of the object's properties - if two Log objects describe the same event happening to the same object at the same time, for all intents and purpose those records are considered to be equal. looks like I changed this to use a custom Expression that uses StructuralEqualityComparer for increased performance

Potentially this infrastructure may assist you in checking for repeat entries

paulkva commented 4 years ago

Our use case is to collect all PRTG logs that appear on the front end into Splunk via serializing them to JSON and writing them to local files. We plan to use that data to detect patterns over time that PRTG might not alert us to, e.g. an unstable sensor which jumps between "warning" and "up" frequently without ever reaching "down" status. We also generally find Splunk easier for investigation than PRTG's log UI.

We want to be able to get previous logs without duplicates so that we can ensure continuity if/when the collection process stops running for a while. To do that, we read the most recent entry we had previously written and use its DateTime field as the startDate parameter.

As for comparing two Log objects to detect duplicates, for reasons I don't understand yet I can't deserialize the previously written JSON back into a Log object. But that's something I'll be able to investigate further on my own.

As I said, I don't think our use case requires any further changes to PrtgAPI, but I hope that's helpful context.