@@ -49,13 +49,18 @@ module System.Metrics
49
49
, registerLabel
50
50
, registerDistribution
51
51
, registerGroup
52
+ , registerDimensional
52
53
53
54
-- ** Convenience functions
54
55
-- $convenience
55
56
, createCounter
56
57
, createGauge
57
58
, createLabel
58
59
, createDistribution
60
+ , createDimensionalCounter
61
+ , createDimensionalGauge
62
+ , createDimensionalLabel
63
+ , createDimensionalDistribution
59
64
60
65
-- ** Predefined metrics
61
66
-- $predefined
@@ -70,7 +75,9 @@ module System.Metrics
70
75
71
76
import Control.Applicative ((<$>) )
72
77
import Control.Monad (forM )
78
+ import Data.Either (partitionEithers )
73
79
import Data.Int (Int64 )
80
+ import Data.Monoid ((<>) )
74
81
import qualified Data.IntMap.Strict as IM
75
82
import Data.IORef (IORef , atomicModifyIORef , newIORef , readIORef )
76
83
import qualified Data.HashMap.Strict as M
@@ -86,6 +93,8 @@ import System.Metrics.Gauge (Gauge)
86
93
import qualified System.Metrics.Gauge as Gauge
87
94
import System.Metrics.Label (Label )
88
95
import qualified System.Metrics.Label as Label
96
+ import System.Metrics.Dimensional (Dimensional )
97
+ import qualified System.Metrics.Dimensional as Dimensional
89
98
90
99
-- $naming
91
100
-- Compound metric names should be separated using underscores.
@@ -137,6 +146,7 @@ data MetricSampler = CounterS !(IO Int64)
137
146
| GaugeS ! (IO Int64 )
138
147
| LabelS ! (IO T. Text )
139
148
| DistributionS ! (IO Distribution. Stats )
149
+ | DimensionalS ! Dimensional. Dimensions ! (IO (M. HashMap Dimensional. Point Value ))
140
150
141
151
-- | Create a new, empty metric store.
142
152
newStore :: IO Store
@@ -192,6 +202,16 @@ registerDistribution
192
202
registerDistribution name sample store =
193
203
register name (DistributionS sample) store
194
204
205
+ -- | Registers a dimensional metric.
206
+ registerDimensional
207
+ :: Dimensional a
208
+ -> (a -> IO Value ) -- ^ Function to sample the dimensional metric to a Value.
209
+ -> Store -- ^ Metric store
210
+ -> IO ()
211
+ 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
214
+
195
215
register :: T. Text
196
216
-> MetricSampler
197
217
-> Store
@@ -323,6 +343,48 @@ createDistribution name store = do
323
343
registerDistribution name (Distribution. read event) store
324
344
return event
325
345
346
+ -- | Create and register a zero-initialized dimensional counter.
347
+ createDimensionalCounter :: T. Text -- ^ Counter name
348
+ -> Store -- ^ Metric store
349
+ -> Dimensional. Dimensions -- ^ Dimension names.
350
+ -> IO (Dimensional Counter )
351
+ createDimensionalCounter name store dims = do
352
+ counter <- Dimensional. newDimensional Counter. new name " " dims
353
+ registerDimensional counter (fmap Counter . Counter. read ) store
354
+ return counter
355
+
356
+ -- | Create and register a zero-initialized dimensional gauge.
357
+ createDimensionalGauge :: T. Text -- ^ Gauge name
358
+ -> Store -- ^ Metric store
359
+ -> Dimensional. Dimensions -- ^ Dimension names.
360
+ -> IO (Dimensional Gauge )
361
+ createDimensionalGauge name store dims = do
362
+ gauge <- Dimensional. newDimensional Gauge. new name " " dims
363
+ registerDimensional gauge (fmap Gauge . Gauge. read ) store
364
+ return gauge
365
+
366
+ -- | Create and register a zero-initialized dimensional label.
367
+ createDimensionalLabel :: T. Text -- ^ Label name
368
+ -> Store -- ^ Metric store
369
+ -> Dimensional. Dimensions -- ^ Dimension names.
370
+ -> IO (Dimensional Label )
371
+ createDimensionalLabel name store dims = do
372
+ label <- Dimensional. newDimensional Label. new name " " dims
373
+ registerDimensional label (fmap Label . Label. read ) store
374
+ return label
375
+
376
+ -- | Create and register a zero-initialized dimensional distribution.
377
+ createDimensionalDistribution :: T. Text -- ^ Distribution name
378
+ -> Store -- ^ Metric store
379
+ -> Dimensional. Dimensions -- ^ Dimension names.
380
+ -> IO (Dimensional Distribution )
381
+ createDimensionalDistribution name store dims = do
382
+ distribution <- Dimensional. newDimensional Distribution. new name " " dims
383
+ registerDimensional distribution (fmap Distribution . Distribution. read ) store
384
+ return distribution
385
+
386
+
387
+
326
388
------------------------------------------------------------------------
327
389
-- * Predefined metrics
328
390
@@ -590,7 +652,7 @@ gcParTotBytesCopied = Stats.parAvgBytesCopied
590
652
-- metrics atomically.
591
653
592
654
-- | A sample of some metrics.
593
- type Sample = M. HashMap T. Text Value
655
+ type Sample = M. HashMap ( T. Text, [( T. Text , T. Text )]) Value
594
656
595
657
-- | Sample all metrics. Sampling is /not/ atomic in the sense that
596
658
-- some metrics might have been mutated before they're sampled but
@@ -601,9 +663,10 @@ sampleAll store = do
601
663
let metrics = stateMetrics state
602
664
groups = stateGroups state
603
665
cbSample <- sampleGroups $ IM. elems groups
604
- sample <- readAllRefs metrics
605
- let allSamples = sample ++ cbSample
606
- return $! M. fromList allSamples
666
+ (dimSamples, sample) <- partitionEithers <$> readAllRefs metrics
667
+ let noDimSamples = [((k,[] ),v) | (k,v) <- sample ++ cbSample]
668
+ let flatDimSamples = [ ((k,zip ds dvs),v) | (k, ds, pointVals) <- dimSamples, (dvs,v) <- pointVals]
669
+ return $! M. fromList (noDimSamples ++ flatDimSamples)
607
670
608
671
-- | Sample all metric groups.
609
672
sampleGroups :: [GroupSampler ] -> IO [(T. Text , Value )]
@@ -621,17 +684,22 @@ data Value = Counter {-# UNPACK #-} !Int64
621
684
| Distribution ! Distribution. Stats
622
685
deriving (Eq , Show )
623
686
624
- sampleOne :: MetricSampler -> IO Value
625
- sampleOne (CounterS m) = Counter <$> m
626
- sampleOne (GaugeS m) = Gauge <$> m
627
- sampleOne (LabelS m) = Label <$> m
628
- sampleOne (DistributionS m) = Distribution <$> m
687
+ type Value2 = Either (Dimensional. Dimensions , [(Dimensional. Point , Value )]) Value
688
+
689
+ sampleOne :: MetricSampler -> IO Value2
690
+ sampleOne (CounterS m) = Right . Counter <$> m
691
+ sampleOne (GaugeS m) = Right . Gauge <$> m
692
+ sampleOne (LabelS m) = Right . Label <$> m
693
+ sampleOne (DistributionS m) = Right . Distribution <$> m
694
+ sampleOne (DimensionalS dims m) = Left . (\ pairs -> (dims, pairs)) . M. toList <$> m
629
695
630
696
-- | Get a snapshot of all values. Note that we're not guaranteed to
631
697
-- see a consistent snapshot of the whole map.
632
698
readAllRefs :: M. HashMap T. Text (Either MetricSampler GroupId )
633
- -> IO [(T. Text , Value )]
699
+ -> IO [Either (T. Text , Dimensional. Dimensions , [( Dimensional. Point , Value )]) ( T. Text , Value )]
634
700
readAllRefs m = do
635
701
forM ([(name, ref) | (name, Left ref) <- M. toList m]) $ \ (name, ref) -> do
636
702
val <- sampleOne ref
637
- return (name, val)
703
+ return $ case val of
704
+ Left (dims, pairs) -> Left (name, dims, pairs)
705
+ Right v -> Right (name, v)
0 commit comments