Skip to content

Commit 1a77ab4

Browse files
author
Matthieu Morel
committed
add documentation and cosmetic changes
1 parent 09e8a44 commit 1a77ab4

File tree

3 files changed

+65
-34
lines changed

3 files changed

+65
-34
lines changed

System/Metrics.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,8 @@ registerDimensional
209209
-> Store -- ^ Metric store
210210
-> IO ()
211211
registerDimensional d f store =
212-
let x = readIORef (Dimensional._points d) >>= traverse f in
213-
register (Dimensional._name d) (DimensionalS (Dimensional._dimensions d) x) store
212+
let x = readIORef (Dimensional.dimensionalPoints d) >>= traverse f in
213+
register (Dimensional.dimensionalName d) (DimensionalS (Dimensional.dimensionalDimensions d) x) store
214214

215215
register :: T.Text
216216
-> MetricSampler

System/Metrics/Dimensional.hs

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,104 @@
11
{-# LANGUAGE LambdaCase #-}
22
{-# LANGUAGE OverloadedStrings #-}
3+
4+
-- | This module defines a type for mutable dimensional string-valued label.
5+
-- Dimensional label are variable values and can be used to track e.g. the
6+
-- current number of call to an api endpoint by its http return code.
7+
-- All operations on Dimensional label are thread-safe.
38
module System.Metrics.Dimensional where
49

510
import qualified System.Metrics.Counter as Counter
611
import qualified System.Metrics.Distribution as Distribution
712
import qualified System.Metrics.Gauge as Gauge
813
import qualified System.Metrics.Label as Label
914

10-
import Prelude hiding (lookup)
11-
import GHC.Exception (Exception)
15+
import Control.Applicative ((<$>), pure)
1216
import Control.Exception (throwIO)
13-
import Data.Text (Text)
14-
import Data.IORef (IORef, atomicModifyIORef', newIORef, readIORef)
1517
import Data.HashMap.Strict (HashMap, empty)
1618
import qualified Data.HashMap.Strict as HashMap
19+
import Data.IORef (IORef, atomicModifyIORef', newIORef, readIORef)
20+
import Data.Text (Text)
21+
import GHC.Exception (Exception)
22+
import Prelude hiding (lookup)
1723

1824
type Name = Text
25+
1926
type Explanation = Text
27+
2028
type Dimensions = [Text]
29+
2130
type Point = [Text]
2231

23-
data Dimensional a = Dimensional {
24-
_create :: !(IO a)
25-
, _name :: !Name
26-
, _explanation :: !Explanation
27-
, _dimensions :: !Dimensions
28-
, _points :: !(IORef (HashMap Point a))
32+
-- | Dimensional metrics storage
33+
data Dimensional a = Dimensional
34+
{ dimensionalCreate :: !(IO a)
35+
, dimensionalName :: !Name
36+
, dimensionalExplanation :: !Explanation
37+
, dimensionalDimensions :: !Dimensions
38+
, dimensionalPoints :: !(IORef (HashMap Point a))
2939
}
3040

31-
newDimensional :: IO a -> Name -> Explanation -> Dimensions -> IO (Dimensional a)
41+
-- | Create a new empty dimensional metrics
42+
newDimensional ::
43+
IO a -> Name -> Explanation -> Dimensions -> IO (Dimensional a)
3244
newDimensional new name explanation dimensions =
33-
Dimensional new name explanation dimensions <$> newIORef empty
45+
Dimensional new name explanation dimensions <$> newIORef empty
3446

35-
data DimensionError
36-
= DimensionError !Name !Dimensions !Point
47+
data DimensionError =
48+
DimensionError !Name
49+
!Dimensions
50+
!Point
3751
deriving (Show, Ord, Eq)
52+
3853
instance Exception DimensionError
3954

4055
data LookupFailure
4156
= UnmatchedDimensions DimensionError
4257
| NotFound
4358
deriving (Show, Ord, Eq)
4459

60+
-- | Returns dimensional metric with specified labels
4561
lookup :: Dimensional a -> Point -> IO (Either LookupFailure a)
4662
lookup d pt
47-
| not $ matchDimensions (_dimensions d) pt = pure $ Left (UnmatchedDimensions err)
63+
| not $ matchDimensions (dimensionalDimensions d) pt =
64+
pure $ Left (UnmatchedDimensions err)
4865
| otherwise = do
49-
toLookupResult . HashMap.lookup pt <$> readIORef (_points d)
66+
toLookupResult . HashMap.lookup pt <$> readIORef (dimensionalPoints d)
5067
where
5168
err :: DimensionError
52-
err = DimensionError (_name d) (_dimensions d) pt
53-
69+
err = DimensionError (dimensionalName d) (dimensionalDimensions d) pt
5470
toLookupResult Nothing = Left NotFound
5571
toLookupResult (Just x) = Right x
5672

5773
matchDimensions :: Dimensions -> Point -> Bool
5874
matchDimensions ds ps = length ds == length ps
5975

76+
-- | Initialize a new empty dimensional metric with specified labels
6077
create :: Dimensional a -> Point -> IO a
6178
create d pt
62-
| not $ matchDimensions (_dimensions d) pt = throwIO err
79+
| not $ matchDimensions (dimensionalDimensions d) pt = throwIO err
6380
| otherwise = do
64-
v <- _create d
65-
atomicModifyIORef' (_points d) (\store -> (HashMap.insert pt v store, ()))
66-
return v
81+
v <- dimensionalCreate d
82+
atomicModifyIORef'
83+
(dimensionalPoints d)
84+
(\store -> (HashMap.insert pt v store, ()))
85+
return v
6786
where
6887
err :: DimensionError
69-
err = DimensionError (_name d) (_dimensions d) pt
88+
err = DimensionError (dimensionalName d) (dimensionalDimensions d) pt
7089

90+
-- | Returns dimensional metric with specified labels, creating it if not exists
7191
lookupOrCreate :: Dimensional a -> Point -> IO a
72-
lookupOrCreate d pt = lookup d pt >>= \case
92+
lookupOrCreate d pt =
93+
lookup d pt >>= \case
7394
Left NotFound -> create d pt
7495
Left (UnmatchedDimensions err) -> throwIO err
7596
Right x -> return x
7697

7798
type Counter = Dimensional Counter.Counter
99+
78100
type Gauge = Dimensional Gauge.Gauge
101+
79102
type Label = Dimensional Label.Label
80-
type Distribution = Dimensional Distribution.Distribution
81103

82-
example :: IO ()
83-
example = do
84-
c <- newDimensional Counter.new "foo" "a foo" ["url", "status"]
85-
let url = "/hello"
86-
let status = "200"
87-
x <- lookupOrCreate c [url, status]
88-
Counter.inc x
104+
type Distribution = Dimensional Distribution.Distribution

examples/Dimensional.hs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import qualified System.Metrics.Counter as Counter
2+
import System.Metrics.Dimensional
3+
4+
main :: IO ()
5+
main = do
6+
c <-
7+
newDimensional
8+
Counter.new
9+
"wai.response"
10+
"endpoints status response"
11+
["url", "status"]
12+
let url = "/hello"
13+
let status = "200"
14+
x <- lookupOrCreate c [url, status]
15+
Counter.inc x

0 commit comments

Comments
 (0)