Skip to content

Commit 563a533

Browse files
Make Gauge polymorphic
1 parent 9de9779 commit 563a533

11 files changed

Lines changed: 81 additions & 39 deletions

File tree

prometheus.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ library
103103
, Prometheus.V3.Name
104104
, Prometheus.V3.Registry
105105
, Prometheus.V3.Sample
106+
, Prometheus.V3.Utils.FromRealFrac
106107

107108
build-depends: base >= 4.9 && < 5
108109
, atomic-primops >= 0.8 && < 0.9

src/Prometheus/V3/Metric/Gauge.hs

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
{-# LANGUAGE ConstraintKinds #-}
2+
{-# LANGUAGE FlexibleContexts #-}
13
{-# LANGUAGE FlexibleInstances #-}
24
{-# LANGUAGE ImportQualifiedPost #-}
35
{-# LANGUAGE NamedFieldPuns #-}
6+
{-# LANGUAGE TypeFamilies #-}
7+
{-# LANGUAGE TypeOperators #-}
48
{-# LANGUAGE NoFieldSelectors #-}
59
-- Remove after inlining V2.Gauge
610
{-# OPTIONS_GHC -Wno-orphans #-}
@@ -13,6 +17,7 @@ module Prometheus.V3.Metric.Gauge (
1317

1418
-- * Methods
1519
IsGauge,
20+
IsNumGauge,
1621
inc,
1722
add,
1823
dec,
@@ -36,22 +41,23 @@ import Prometheus.V3.Metric.Base
3641
import Prometheus.V3.Metric.Labelled (labels)
3742
import Prometheus.V3.Registry qualified as Registry
3843
import Prometheus.V3.Sample
44+
import Prometheus.V3.Utils.FromRealFrac (FromRealFrac, fromRealFrac)
3945
import System.Metrics.Prometheus.Metric.Gauge qualified as V2
4046
import UnliftIO (MonadUnliftIO)
4147
import UnliftIO.Exception (bracket_)
4248

4349

4450
-- | An alias for @'Registry.register' (new ...)@.
45-
register :: MetricName -> Description -> V2.Gauge
51+
register :: (Num a, ToSampleValue a) => MetricName -> Description -> V2.Gauge a
4652
register name description = Registry.register $ new name description
4753
{-# INLINE register #-}
4854

4955

50-
new :: MetricName -> Description -> Metric V2.Gauge
56+
new :: (Num a) => MetricName -> Description -> Metric (V2.Gauge a)
5157
new name description = newAt name description 0
5258

5359

54-
newAt :: MetricName -> Description -> Double -> Metric V2.Gauge
60+
newAt :: (Num a) => MetricName -> Description -> a -> Metric (V2.Gauge a)
5561
newAt name description val =
5662
Metric
5763
{ name
@@ -63,74 +69,84 @@ newAt name description val =
6369
}
6470

6571

66-
instance IsMetric V2.Gauge where
72+
instance (SampleValueNum a) => IsMetric (V2.Gauge a) where
6773
getMetricType _ = MetricTypeGauge
6874
getMetricSamples gauge = do
6975
n <- sample gauge
7076
pure [defaultSample{value = toSampleValue n}]
7177

7278

7379
class IsGauge g where
74-
getGauge :: g -> IO V2.Gauge
75-
instance IsGauge V2.Gauge where
80+
type GaugeElem g
81+
getGauge :: g -> IO (V2.Gauge (GaugeElem g))
82+
instance IsGauge (V2.Gauge a) where
83+
type GaugeElem (V2.Gauge a) = a
7684
getGauge = pure
77-
instance IsGauge (IO V2.Gauge) where
85+
instance IsGauge (IO (V2.Gauge a)) where
86+
type GaugeElem (IO (V2.Gauge a)) = a
7887
getGauge = id
7988

8089

81-
inc :: (IsGauge g, MonadIO m) => g -> m ()
90+
type IsNumGauge g a = (IsGauge g, a ~ GaugeElem g, Num a)
91+
92+
93+
inc :: (IsNumGauge g a, MonadIO m) => g -> m ()
8294
inc g = liftIO $ V2.inc =<< getGauge g
8395
{-# INLINE inc #-}
8496

8597

86-
add :: (IsGauge g, MonadIO m) => g -> Double -> m ()
98+
add :: (IsNumGauge g a, MonadIO m) => g -> a -> m ()
8799
add g x = liftIO $ V2.add x =<< getGauge g
88100
{-# INLINE add #-}
89101

90102

91-
dec :: (IsGauge g, MonadIO m) => g -> m ()
103+
dec :: (IsNumGauge g a, MonadIO m) => g -> m ()
92104
dec g = liftIO $ V2.dec =<< getGauge g
93105
{-# INLINE dec #-}
94106

95107

96-
sub :: (IsGauge g, MonadIO m) => g -> Double -> m ()
108+
sub :: (IsNumGauge g a, MonadIO m) => g -> a -> m ()
97109
sub g x = liftIO $ V2.sub x =<< getGauge g
98110
{-# INLINE sub #-}
99111

100112

101-
set :: (IsGauge g, MonadIO m) => g -> Double -> m ()
113+
set :: (IsNumGauge g a, MonadIO m) => g -> a -> m ()
102114
set g x = liftIO $ V2.set x =<< getGauge g
103115
{-# INLINE set #-}
104116

105117

106-
sample :: (IsGauge g, MonadIO m) => g -> m Double
118+
sample :: (IsNumGauge g a, MonadIO m) => g -> m a
107119
sample g = liftIO $ fmap V2.unGaugeSample . V2.sample =<< getGauge g
108120
{-# INLINE sample #-}
109121

110122

111-
modifyAndSample :: (IsGauge g, MonadIO m) => g -> (Double -> Double) -> m Double
123+
modifyAndSample :: (IsNumGauge g a, MonadIO m) => g -> (a -> a) -> m a
112124
modifyAndSample g f = liftIO $ fmap V2.unGaugeSample . V2.modifyAndSample f =<< getGauge g
113125
{-# INLINE modifyAndSample #-}
114126

115127

116128
{----- Helpers -----}
117129

118130
-- | Set to the current number of seconds since the epoch.
119-
setToCurrentTime :: (IsGauge g, MonadIO m) => g -> m ()
131+
setToCurrentTime ::
132+
(IsGauge g, FromRealFrac (GaugeElem g), MonadIO m) =>
133+
g -> m ()
120134
setToCurrentTime g = do
121135
now <- liftIO getPOSIXTime
122136
g' <- liftIO $ getGauge g
123-
set g' (realToFrac now)
137+
set g' (fromRealFrac now)
124138
{-# INLINE setToCurrentTime #-}
125139

126140

127141
-- | Increment the gauge when the given action is running and decrement when it's exited.
128-
trackInProgress :: (IsGauge g, MonadUnliftIO m) => g -> m a -> m a
142+
trackInProgress :: (IsNumGauge g a, MonadUnliftIO m) => g -> m a -> m a
129143
trackInProgress g = bracket_ (inc g) (dec g)
130144
{-# INLINE trackInProgress #-}
131145

132146

133147
-- | Set the gauge to the duration of the given action.
134-
time :: (IsGauge g, MonadUnliftIO m) => g -> m a -> m a
135-
time g = withDuration (set g)
148+
time ::
149+
(IsGauge g, FromRealFrac (GaugeElem g), MonadUnliftIO m) =>
150+
g -> m a -> m a
151+
time g = withDuration (set g . fromRealFrac)
136152
{-# INLINE time #-}

src/Prometheus/V3/Sample.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE ConstraintKinds #-}
12
{-# LANGUAGE OverloadedStrings #-}
23
{-# LANGUAGE NoFieldSelectors #-}
34

@@ -8,6 +9,7 @@ module Prometheus.V3.Sample (
89
-- * SampleValue
910
SampleValue (..),
1011
ToSampleValue (..),
12+
SampleValueNum,
1113
) where
1214

1315
import Data.Int (Int64)
@@ -49,3 +51,6 @@ instance ToSampleValue Double where
4951
toSampleValue = SampleValueDouble
5052
instance ToSampleValue Float where
5153
toSampleValue = SampleValueDouble . realToFrac
54+
55+
56+
type SampleValueNum a = (Num a, ToSampleValue a)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
module Prometheus.V3.Utils.FromRealFrac (
2+
FromRealFrac (..),
3+
) where
4+
5+
import Data.Word (Word64)
6+
7+
8+
class (Num a) => FromRealFrac a where
9+
fromRealFrac :: (RealFrac x) => x -> a
10+
11+
12+
instance FromRealFrac Int where
13+
fromRealFrac = round
14+
instance FromRealFrac Word64 where
15+
fromRealFrac = round
16+
17+
18+
instance FromRealFrac Double where
19+
fromRealFrac = realToFrac
20+
instance FromRealFrac Float where
21+
fromRealFrac = realToFrac

src/System/Metrics/Prometheus/Concurrent/Registry.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ registerCounter name labels = flip modifyMVarMasked register . unRegistry
4646
register = fmap swap . R.registerCounter name labels
4747

4848

49-
registerGauge :: Name -> Labels -> Registry -> IO Gauge
49+
registerGauge :: Name -> Labels -> Registry -> IO (Gauge Double)
5050
registerGauge name labels = flip modifyMVarMasked register . unRegistry
5151
where
5252
register = fmap swap . R.registerGauge name labels

src/System/Metrics/Prometheus/Concurrent/RegistryT.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ registerCounter :: MonadIO m => Name -> Labels -> RegistryT m Counter
3939
registerCounter n l = RegistryT ask >>= liftIO . R.registerCounter n l
4040

4141

42-
registerGauge :: MonadIO m => Name -> Labels -> RegistryT m Gauge
42+
registerGauge :: MonadIO m => Name -> Labels -> RegistryT m (Gauge Double)
4343
registerGauge n l = RegistryT ask >>= liftIO . R.registerGauge n l
4444

4545

src/System/Metrics/Prometheus/Encode/Text.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,5 @@ encodeCounter :: MetricId -> CounterSample -> Builder
6464
encodeCounter mid counter = encodeMetricId mid <> space <> encodeInt (unCounterSample counter)
6565

6666

67-
encodeGauge :: MetricId -> GaugeSample -> Builder
67+
encodeGauge :: MetricId -> GaugeSample Double -> Builder
6868
encodeGauge mid gauge = encodeMetricId mid <> space <> encodeDouble (unGaugeSample gauge)

src/System/Metrics/Prometheus/Metric.hs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,20 @@ import System.Metrics.Prometheus.Metric.Summary (SummarySample)
1414

1515
data Metric
1616
= CounterMetric Counter
17-
| GaugeMetric Gauge
18-
| -- | Summary S.Summary
19-
HistogramMetric Histogram
17+
| GaugeMetric (Gauge Double) -- \| Summary S.Summary
18+
| HistogramMetric Histogram
2019

2120

2221
data MetricSample
2322
= CounterMetricSample CounterSample
24-
| GaugeMetricSample GaugeSample
23+
| GaugeMetricSample (GaugeSample Double)
2524
| HistogramMetricSample HistogramSample
2625
| SummaryMetricSample SummarySample
2726

2827

2928
metricSample ::
3029
(CounterSample -> a) ->
31-
(GaugeSample -> a) ->
30+
(GaugeSample Double -> a) ->
3231
(HistogramSample -> a) ->
3332
(SummarySample -> a) ->
3433
MetricSample ->

src/System/Metrics/Prometheus/Metric/Gauge.hs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,39 @@ import Control.Applicative ((<$>))
1515
import Data.IORef (IORef, atomicModifyIORef', newIORef)
1616

1717

18-
newtype Gauge = Gauge {unGauge :: IORef Double}
19-
newtype GaugeSample = GaugeSample {unGaugeSample :: Double} deriving Show
18+
newtype Gauge a = Gauge {unGauge :: IORef a}
19+
newtype GaugeSample a = GaugeSample {unGaugeSample :: a} deriving (Show)
2020

2121

22-
new :: IO Gauge
22+
new :: (Num a) => IO (Gauge a)
2323
new = Gauge <$> newIORef 0
2424

2525

26-
modifyAndSample :: (Double -> Double) -> Gauge -> IO GaugeSample
26+
modifyAndSample :: (a -> a) -> Gauge a -> IO (GaugeSample a)
2727
modifyAndSample f = flip atomicModifyIORef' g . unGauge
2828
where
2929
g v = (f v, GaugeSample $ f v)
3030

3131

32-
add :: Double -> Gauge -> IO ()
32+
add :: (Num a) => a -> Gauge a -> IO ()
3333
add x g = modifyAndSample (+ x) g >> pure ()
3434

3535

36-
sub :: Double -> Gauge -> IO ()
36+
sub :: (Num a) => a -> Gauge a -> IO ()
3737
sub x g = modifyAndSample (subtract x) g >> pure ()
3838

3939

40-
inc :: Gauge -> IO ()
40+
inc :: (Num a) => Gauge a -> IO ()
4141
inc = add 1
4242

4343

44-
dec :: Gauge -> IO ()
44+
dec :: (Num a) => Gauge a -> IO ()
4545
dec = sub 1
4646

4747

48-
set :: Double -> Gauge -> IO ()
48+
set :: a -> Gauge a -> IO ()
4949
set x g = modifyAndSample (const x) g >> pure ()
5050

5151

52-
sample :: Gauge -> IO GaugeSample
52+
sample :: Gauge a -> IO (GaugeSample a)
5353
sample = modifyAndSample id

src/System/Metrics/Prometheus/Registry.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ registerCounter name labels registry = do
5959
collision k _ _ = throw (KeyError k)
6060

6161

62-
registerGauge :: Name -> Labels -> Registry -> IO (Gauge, Registry)
62+
registerGauge :: Name -> Labels -> Registry -> IO (Gauge Double, Registry)
6363
registerGauge name labels registry = do
6464
gauge <- Gauge.new
6565
return (gauge, Registry $ Map.insertWithKey collision mid (GaugeMetric gauge) (unRegistry registry))

0 commit comments

Comments
 (0)