Last active
August 14, 2020 10:12
-
-
Save jhrcek/a6e7766b8b0cb503dea9f08763d20f6d to your computer and use it in GitHub Desktop.
This script prepends timestamps to lines streaming from stdin and prints them to stdout
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env stack | |
| -- stack script --resolver lts-16.9 --package conduit,text,mtl | |
| {-# LANGUAGE NumericUnderscores #-} | |
| {-# LANGUAGE OverloadedStrings #-} | |
| {-# LANGUAGE TypeApplications #-} | |
| {-# OPTIONS_GHC -Wall #-} | |
| import Conduit (decodeUtf8C, encodeUtf8C, mapMC, runConduit, stdinC, stdoutC, (.|)) | |
| import Control.Monad.State.Strict (StateT, evalStateT, get, liftIO, put) | |
| import Data.Text (Text) | |
| import qualified Data.Text as Text | |
| import Data.Word (Word64) | |
| import qualified GHC.Clock as Clock | |
| import Text.Printf | |
| {- This script prepends timestamps to lines streaming from stdin and prints them to stdout | |
| EXAMPLE USAGE: put the script somewhere on your path and pipe stuff via STDIN to it. For example | |
| stack build --no-terminal stack build --no-terminal 2>&1 | timelines.hs | |
| -} | |
| main :: IO () | |
| main = do | |
| startNanos <- Clock.getMonotonicTimeNSec | |
| evalStateT (prependTime startNanos) startNanos | |
| prependTime :: Word64 -> StateT Word64 IO () | |
| prependTime startNanos = | |
| runConduit $ | |
| stdinC | |
| .| decodeUtf8C | |
| .| mapMC (prependTimestamp startNanos) | |
| .| encodeUtf8C | |
| .| stdoutC | |
| prependTimestamp :: Word64 -> Text -> StateT Word64 IO Text | |
| prependTimestamp startNanos input = do | |
| previousNanos <- get | |
| nanosNow <- liftIO Clock.getMonotonicTimeNSec | |
| let secondsSinceStart = nanosToSeconds $ nanosNow - startNanos | |
| secondsSincePrev = nanosToSeconds $ nanosNow - previousNanos | |
| prevDelta = | |
| let textDelta = printf "+%.3f" secondsSincePrev | |
| in if secondsSincePrev > 10 --TODO make threshold configurable | |
| then highlight textDelta | |
| else textDelta | |
| timeData = printf "%7.3f [%s] " secondsSinceStart prevDelta | |
| put nanosNow | |
| pure $ Text.pack timeData <> input | |
| nanosToSeconds :: Word64 -> Double | |
| nanosToSeconds ns = fromIntegral ns / 1000_000_000 | |
| highlight :: String -> String | |
| highlight x = brightRed <> x <> reset | |
| where | |
| brightRed = "\ESC[1;31m" | |
| reset = "\ESC[0m" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment