Skip to content

Commit d7e2556

Browse files
committed
With Prometheus label support
1 parent ef5cd89 commit d7e2556

File tree

2 files changed

+39
-15
lines changed

2 files changed

+39
-15
lines changed

plugins/backend-ekg/lobemo-backend-ekg.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cabal-version: 2.0
22
name: lobemo-backend-ekg
3-
version: 0.1.0.3
3+
version: 0.1.1.0
44
synopsis: provides a backend implementation to EKG
55
-- description:
66
homepage: https://github.com/input-output-hk/iohk-monitoring-framework

plugins/backend-ekg/src/Cardano/BM/Backend/Prometheus.lhs

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import Snap.Http.Server (Config, ConfigLog (..), defaultConfig, setAcc
3333
import System.Metrics (Value (..), sampleAll)
3434
import qualified System.Remote.Monitoring as EKG
3535
36+
import Debug.Trace
37+
3638
\end{code}
3739
%endif
3840

@@ -50,12 +52,14 @@ data Metric
5052
| Metric
5153
{ mName :: !Text
5254
, mType :: !Text
53-
, mValue :: !Number
55+
, mLabel :: !(Maybe Text)
56+
, mNumber :: !Number
5457
}
5558
5659
instance A.ToJSON Metric where
5760
toJSON NoMetric = A.Null
58-
toJSON (Metric n t v) = A.object ["name" .= n, "type" .= t, "value" .= v]
61+
toJSON (Metric n t Nothing v) = A.object ["name" .= n, "type" .= t, "value" .= v]
62+
toJSON (Metric n t (Just l) v) = A.object ["name" .= n, "type" .= t, "label" .= l, "value" .= v]
5963
6064
data Number
6165
= NumberInt Integer
@@ -94,17 +98,28 @@ spawnPrometheus ekg host port prometheusOutput = Async.async $
9498
[ case sv of
9599
Counter c -> renderNamedValue sk (int64Dec c)
96100
Gauge g -> renderNamedValue sk (int64Dec g)
97-
Label l -> if isFloat l
98-
then renderNamedValue sk (byteString $ encodeUtf8 l)
99-
else mempty
101+
Label l -> trace ("renderSamples " <> T.unpack l) $
102+
if "{" `T.isPrefixOf` l
103+
then renderLabel sk l
104+
else renderNamedValue sk (byteString $ encodeUtf8 l)
100105
_ -> mempty
101106
| (sk,sv) <- samples ]
107+
102108
renderNamedValue :: Text -> Builder -> Builder
103109
renderNamedValue nm bld =
104110
(byteString $ prepareName nm)
105111
<> charUtf8 ' '
106112
<> bld
107113
<> charUtf8 '\n'
114+
115+
renderLabel :: Text -> Text -> Builder
116+
renderLabel nm l = trace "renderLabel" $
117+
(byteString $ prepareName nm)
118+
<> charUtf8 ' '
119+
<> byteString (textToUtf8ByteString l)
120+
<> charUtf8 ' '
121+
<> charUtf8 '1'
122+
<> charUtf8 '\n'
108123
prepareName nm = encodeUtf8 $ T.filter (flip elem (['a'..'z']++['A'..'Z']++['_'])) $ T.replace " " "_" $ T.replace "-" "_" $ T.replace "." "_" nm
109124
isFloat v = case double v of
110125
Right (_n, "") -> True -- only floating point number parsed, no leftover
@@ -136,7 +151,8 @@ spawnPrometheus ekg host port prometheusOutput = Async.async $
136151
intMetric sk v =
137152
Metric { mName = maybe "" id $ T.stripPrefix (ns <> ".") sk
138153
, mType = "int" -- All values are Int64.
139-
, mValue = NumberInt (fromIntegral v)
154+
, mLabel = Nothing
155+
, mNumber = NumberInt (fromIntegral v)
140156
}
141157
142158
-- We cannot make any assumptions about the format of 'sk' in other samples,
@@ -146,26 +162,34 @@ spawnPrometheus ekg host port prometheusOutput = Async.async $
146162
{ namespace = "common"
147163
, metrics =
148164
[ case sv of
149-
Counter c -> mkMetric sk $ NumberInt (fromIntegral c)
150-
Gauge g -> mkMetric sk $ NumberInt (fromIntegral g)
165+
Counter c -> mkMetric sk Nothing $ NumberInt (fromIntegral c)
166+
Gauge g -> mkMetric sk Nothing $ NumberInt (fromIntegral g)
151167
Label l -> case double l of
152-
Left _ -> NoMetric
153-
Right (r, _) -> mkMetric sk $ NumberReal r
168+
Right (r, _) ->
169+
mkMetric sk Nothing $ NumberReal r
170+
Left _ ->
171+
case T.uncons l of
172+
Just ('{', _) -> mkMetric sk (Just l) (NumberInt 1)
173+
_ -> NoMetric
154174
_ -> NoMetric
155175
| (sk, sv) <- samples
156176
]
157177
}
158178
where
159-
mkMetric sk number =
179+
mkMetric sk condTxt number =
160180
let (withoutType, typeSuffix) = stripTypeSuffix sk number
161-
in Metric { mName = withoutType, mType = typeSuffix, mValue = number }
181+
in Metric { mName = withoutType, mType = typeSuffix, mLabel = condTxt, mNumber = number }
162182
stripTypeSuffix sk number =
163183
let types = ["us", "ns", "s", "B", "int", "real"]
164184
parts = T.splitOn "." sk
165185
typeSuffix = if not . null $ parts then last parts else ""
166186
in if typeSuffix `elem` types
167187
then (fromJust $ T.stripSuffix ("." <> typeSuffix) sk, typeSuffix)
168188
else case number of
169-
NumberInt _ -> (sk, "int")
170-
NumberReal _ -> (sk, "real")
189+
NumberInt _ -> (sk, "int")
190+
NumberReal _ -> (sk, "real")
191+
192+
textToUtf8ByteString :: Text -> ByteString
193+
textToUtf8ByteString txt = encodeUtf8 txt
194+
171195
\end{code}

0 commit comments

Comments
 (0)