packages feed

ekg-json (empty) → 0.1.0.0

raw patch · 4 files changed

+208/−0 lines, 4 filesdep +aesondep +basedep +ekg-coresetup-changed

Dependencies added: aeson, base, ekg-core, text, unordered-containers

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2015, Johan Tibell++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Johan Tibell nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ System/Metrics/Json.hs view
@@ -0,0 +1,144 @@+{-# LANGUAGE OverloadedStrings #-}++-- | Encoding of ekg metrics as JSON. The encoding defined by the+-- functions in this module are standardized and used by the ekg web+-- UI. The purpose of this module is to let other web servers and+-- frameworks than the one used by the ekg package expose ekg metrics.+module System.Metrics.Json+    ( -- * Converting metrics to JSON values+      sampleToJson+    , valueToJson++      -- ** Newtype wrappers with instances+    , Sample(..)+    , Value(..)+    ) where++import Data.Aeson ((.=))+import qualified Data.Aeson.Encode as A+import qualified Data.Aeson.Types as A+import qualified Data.HashMap.Strict as M+import Data.Int (Int64)+import qualified Data.Text as T+import qualified System.Metrics as Metrics+import qualified System.Metrics.Distribution as Distribution++------------------------------------------------------------------------+-- * Converting metrics to JSON values+++-- | Encode metrics as nested JSON objects. Each "." in the metric+-- name introduces a new level of nesting. For example, the metrics+-- @[("foo.bar", 10), ("foo.baz", "label")]@ are encoded as+--+-- > {+-- >   "foo": {+-- >     "bar": {+-- >       "type:", "c",+-- >       "val": 10+-- >     },+-- >     "baz": {+-- >       "type": "l",+-- >       "val": "label"+-- >     }+-- >   }+-- > }+--+sampleToJson :: Metrics.Sample -> A.Value+sampleToJson metrics =+    buildOne metrics $ A.emptyObject+  where+    buildOne :: M.HashMap T.Text Metrics.Value -> A.Value -> A.Value+    buildOne m o = M.foldlWithKey' build o m++    build :: A.Value -> T.Text -> Metrics.Value -> A.Value+    build m name val = go m (T.splitOn "." name) val++    go :: A.Value -> [T.Text] -> Metrics.Value -> A.Value+    go (A.Object m) [str] val      = A.Object $ M.insert str metric m+      where metric = valueToJson val+    go (A.Object m) (str:rest) val = case M.lookup str m of+        Nothing -> A.Object $ M.insert str (go A.emptyObject rest val) m+        Just m' -> A.Object $ M.insert str (go m' rest val) m+    go v _ _                        = typeMismatch "Object" v++typeMismatch :: String   -- ^ The expected type+             -> A.Value  -- ^ The actual value encountered+             -> a+typeMismatch expected actual =+    error $ "when expecting a " ++ expected ++ ", encountered " ++ name +++    " instead"+  where+    name = case actual of+        A.Object _ -> "Object"+        A.Array _  -> "Array"+        A.String _ -> "String"+        A.Number _ -> "Number"+        A.Bool _   -> "Boolean"+        A.Null     -> "Null"++-- | Encodes a single metric as a JSON object. Example:+--+-- > {+-- >   "type": "c",+-- >   "val": 89460+-- > }+--+valueToJson :: Metrics.Value -> A.Value+valueToJson (Metrics.Counter n)      = scalarToJson n CounterType+valueToJson (Metrics.Gauge n)        = scalarToJson n GaugeType+valueToJson (Metrics.Label l)        = scalarToJson l LabelType+valueToJson (Metrics.Distribution l) = distrubtionToJson l++-- | Convert a scalar metric (i.e. counter, gauge, or label) to a JSON+-- value.+scalarToJson :: A.ToJSON a => a -> MetricType -> A.Value+scalarToJson val ty = A.object+    ["val" .= val, "type" .= metricType ty]+{-# SPECIALIZE scalarToJson :: Int64 -> MetricType -> A.Value #-}+{-# SPECIALIZE scalarToJson :: T.Text -> MetricType -> A.Value #-}++data MetricType =+      CounterType+    | GaugeType+    | LabelType+    | DistributionType++metricType :: MetricType -> T.Text+metricType CounterType      = "c"+metricType GaugeType        = "g"+metricType LabelType        = "l"+metricType DistributionType = "d"++-- | Convert a distribution to a JSON value.+distrubtionToJson :: Distribution.Stats -> A.Value+distrubtionToJson stats = A.object+    [ "mean" .= Distribution.mean stats+    , "variance" .= Distribution.variance stats+    , "count" .= Distribution.count stats+    , "sum" .= Distribution.sum stats+    , "min" .= Distribution.min stats+    , "max" .= Distribution.max stats+    , "type" .= metricType DistributionType+    ]++------------------------------------------------------------------------+-- ** Newtype wrappers with instances++-- | Newtype wrapper that provides a 'A.ToJSON' instances for the+-- underlying 'Metrics.Sample' without creating an orphan instance.+newtype Sample = Sample Metrics.Sample+    deriving Show++-- | Uses 'sampleToJson'.+instance A.ToJSON Sample where+    toJSON (Sample s) = sampleToJson s++-- | Newtype wrapper that provides a 'A.ToJSON' instances for the+-- underlying 'Metrics.Value' without creating an orphan instance.+newtype Value = Value Metrics.Value+    deriving Show++-- | Uses 'valueToJson'.+instance A.ToJSON Value where+    toJSON (Value v) = valueToJson v
+ ekg-json.cabal view
@@ -0,0 +1,32 @@+name:                ekg-json+version:             0.1.0.0+synopsis:            JSON encoding of ekg metrics+description:+  Encodes ekg metrics as JSON, using the same encoding as used by the+  ekg package, thus allowing ekg metrics to be served by other HTTP+  servers than the one used by the ekg package.+homepage:            https://github.com/tibbe/ekg-json+bug-reports:         https://github.com/tibbe/ekg-json/issues+license:             BSD3+license-file:        LICENSE+author:              Johan Tibell+maintainer:          johan.tibell@gmail.com+category:            Distribution+build-type:          Simple+cabal-version:       >=1.10++library+  exposed-modules:+    System.Metrics.Json+  build-depends:+    aeson < 0.11,+    base >= 4.5 && < 4.9,+    ekg-core >= 0.1 && < 0.2,+    text < 1.3,+    unordered-containers < 0.3++  default-language: Haskell2010++source-repository head+  type:     git+  location: https://github.com/tibbe/ekg-json.git