Re: [Haskell-cafe] Instrumentation without requiring code-level changes?

On 27 Jan 2017 07:16, "Saurabh Nanda"
Hi Saurabh,
There's no direct equivalent to monkey-patching in Haskell (AFAIK (*)). Why not instrument things always? The performance impact is usually quite negligible, and the ability to switch instrumentation on at runtime in production is sometimes invaluable.
For instrumenting Scotty (in particular) or WAI-based apps (in general) you can instrument things simply by inserting an appropriate `Middleware`, a decision that can be deferred until service-startup time, and which involves no change to the Scotty-side code.
There's no equivalent to WAI for database access so I don't have a general answer in that case, but typically database APIs have only a few core `execute` or `query` functions that are quite straightforward to wrap with instrumentation if needs be.
This all kinda _has_ to be in IO anyway, as you're trying to measure a real-world activity. Certainly there's no problem with either Scotty or databases in this regard, as they're running in IO. Do you have an example where you need instrumentation of a pure (i.e. non-IO) computation? In such a case you could use the `unsafePerformIO` escape hatch (like `Debug.Trace` does) but you'll have to be very careful to measure what you think you're measuring: the language is quite free to reorder computations and avoid repeating duplicated computations via referential transparency etc.
(*) I mean, you could do something with dynamic libs and LD_PRELOAD (the original monkey-patching) but please don't!
Hope that helps,
David
On 27 Jan 2017 05:21, "Saurabh Nanda"
wrote: (another cross post from Reddit - https://www.reddit.com/r/haske ll/comments/5qfd36/instrumentation_without_required_application/)
Is it possible to collect instrumentation data from a Hakell application without requiring the core application to change code? Here are some examples of instrumentation data:
* Time taken to serve an HTTP request (not average time, but individual times, for individual requests) along with the incoming request params+headers and outgoing response length. * Time taken to make an SQL query along with the actual query (again, not average times, but individual times, for individual queries) * Time taken to fetch data from Redis along with the Redis command * Time taken to render an HTML page along with path to the HTML file
Most dynamic languages (like Ruby) allow monkey-patching OR "decorating" existing functions during runtime. Most instrumentation agents (like Skylight, Newrelic), simply monkey-patch the API surfaces of known libraries to collect this data. Therefore, using these instrumentation agents is a one line code change (just include the gem, or drop the JAR, or whatever).
What is the equivalent of this in Haskell?
Here's what I've tried so far [1] , but it has the following disadvantages:
* Requires changes to the application's cabal file to replace the non-instrumented versions of the libraries with the instrumented version (replace scotty with instrumentedscotty, in my example) * Requires the application to explicitly import the instrumented versions of the libraries (replace import Scotty with import InstrumentedScotty, in my example) * Forces all the code interacting with instrumented APIs to be run in a MonadIO environment - because of the underlying calls to getCurrentTime
I'm sure there's a better way, but I couldn't get my hands on it!
[1] https://gist.github.com/saurabhnanda/27592da0269bc35569ec6239e1a91b75
-- Saurabh.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
participants (1)
-
David Turner