nagios-check 0.1.0.0 → 0.2.0
raw patch · 4 files changed
+256/−216 lines, 4 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
- System.Nagios.Plugin: instance Applicative NagiosPlugin
- System.Nagios.Plugin: instance Enum CheckStatus
- System.Nagios.Plugin: instance Eq CheckResult
- System.Nagios.Plugin: instance Eq CheckStatus
- System.Nagios.Plugin: instance Eq PerfDatum
- System.Nagios.Plugin: instance Eq PerfValue
- System.Nagios.Plugin: instance Functor NagiosPlugin
- System.Nagios.Plugin: instance Monad NagiosPlugin
- System.Nagios.Plugin: instance MonadCatch NagiosPlugin
- System.Nagios.Plugin: instance MonadIO NagiosPlugin
- System.Nagios.Plugin: instance MonadState CheckState NagiosPlugin
- System.Nagios.Plugin: instance MonadThrow NagiosPlugin
- System.Nagios.Plugin: instance Ord CheckResult
- System.Nagios.Plugin: instance Ord CheckStatus
- System.Nagios.Plugin: instance Show CheckResult
- System.Nagios.Plugin: instance Show CheckStatus
- System.Nagios.Plugin: instance Show PerfDatum
- System.Nagios.Plugin: instance Show PerfValue
+ System.Nagios.Plugin: addBarePerfDatum :: Text -> PerfValue -> UOM -> NagiosPlugin ()
+ System.Nagios.Plugin: data Range
Files
- lib/System/Nagios/Plugin.hs +5/−214
- lib/System/Nagios/Plugin/Check.hs +230/−0
- lib/System/Nagios/Plugin/Range.hs +17/−0
- nagios-check.cabal +4/−2
lib/System/Nagios/Plugin.hs view
@@ -5,219 +5,10 @@ module System.Nagios.Plugin (- CheckStatus(..),- CheckResult,- UOM(..),- PerfValue(..),- NagiosPlugin,- runNagiosPlugin,- runNagiosPlugin',- addPerfDatum,- addResult,- checkStatus,- checkInfo,- worstResult,- PerfDatum,- finishState-) where--import Control.Applicative-import Control.Monad.Catch-import Control.Monad.State.Lazy-import Data.Bifunctor-import Data.Int-import Data.Monoid-import Data.Nagios.Perfdata.Metric (UOM (..))-import Data.Text (Text)-import qualified Data.Text as T-import qualified Data.Text.IO as T-import System.Exit---- | Nagios plugin exit statuses. Ordered by priority ---- OK < Warning < Critical < Unknown, which correspond to plugin exit--- statuses of 0, 1, 2, and 3 respectively.-data CheckStatus = OK -- ^ Check executed successfully and- -- detected no service problems.- | Warning -- ^ Nothing's actually broken but this- -- should be followed up.- | Critical -- ^ Check executed successfully and detected- -- a service failure.- | Unknown -- ^ Check unable to determine service- -- status.- deriving (Enum, Eq, Ord)--instance Show CheckStatus where- show OK = "OK"- show Warning = "WARNING"- show Critical = "CRITICAL"- show Unknown = "UNKNOWN"---- | A CheckResult is the exit status of the plugin combined with the--- plugin's info text. A `NagiosPlugin` which exits with------ > CheckResult (Critical "entropy decreasing in closed system")------ as its peak-badness CheckResult (and no 'PerfDatum's) will a) exit with--- status 2 and b) output the text "CRITICAL: entropy decreasing in closed--- system".-newtype CheckResult = CheckResult- { unCheckResult :: (CheckStatus, Text) }- deriving (Eq, Ord, Show)---- | Extract the return status from a 'CheckResult'-checkStatus :: CheckResult -> CheckStatus-checkStatus = fst . unCheckResult---- | Extract the infotext from a 'CheckResult'.-checkInfo :: CheckResult -> Text-checkInfo = snd . unCheckResult---- | Value of a performance metric.-data PerfValue = RealValue Double | IntegralValue Int64- deriving Eq--instance Show PerfValue where- show (RealValue x) = show x- show (IntegralValue x) = show x---- | One performance metric. A plugin will output zero or more of these,--- whereupon Nagios generally passes them off to an external system such--- as <http://oss.oetiker.ch/rrdtool/ RRDTool> or--- <https://github.com/anchor/vaultaire Vaultaire>.--- The thresholds are purely informative (designed to be graphed), and--- do not affect alerting; likewise with `_min` and `_max`.-data PerfDatum = PerfDatum- { _label :: Text -- ^ Name of quantity being measured.- , _value :: PerfValue -- ^ Measured value, integral or real.- , _uom :: UOM -- ^ Unit of measure; 'NullUOM' is fine here.- , _min :: Maybe PerfValue -- ^ Measured quantity cannot be lower than this.- , _max :: Maybe PerfValue -- ^ Measured quantity cannot be higher than this.- , _warn :: Maybe PerfValue -- ^ Warning threshold for graphing.- , _crit :: Maybe PerfValue -- ^ Critical threshold for graphing.- }- deriving (Eq, Show)---- | Current check results/perfdata. If the check suddenly dies, the--- 'worst' of the CheckResults (and all the PerfDatums) will be used--- to determine the exit state.-type CheckState = ([CheckResult], [PerfDatum])--newtype NagiosPlugin a = NagiosPlugin- {- unNagiosPlugin :: StateT CheckState IO a- } deriving (Functor, Applicative, Monad, MonadIO, MonadState CheckState, MonadCatch, MonadThrow)---- | Execute a Nagios check. The program will terminate at the check's--- completion. A default status will provided if none is given.-runNagiosPlugin :: NagiosPlugin a -> IO ()-runNagiosPlugin check = do- (_, st) <- runNagiosPlugin' $ catch check panic- finishWith st- where- panic :: SomeException -> NagiosPlugin a- panic = liftIO . finishWith . panicState---- | Execute a Nagios check as with 'runNagiosPlugin', but return its--- final state rather than terminating.-runNagiosPlugin' :: NagiosPlugin a -> IO (a, CheckState)-runNagiosPlugin' a = runStateT (unNagiosPlugin a) mempty---- | Insert a result. Only the 'CheckStatus' with the most 'badness'--- will determine the check's exit status.-addResult :: CheckStatus -> Text -> NagiosPlugin ()-addResult s t =- modify (first (CheckResult (s, t) :))---- | Insert a performance metric into the list the check will output.-addPerfDatum ::- Text -- ^ Name of the quantity being measured.- -> PerfValue -- ^ Measured value.- -> UOM -- ^ Unit of the measured value.- -> Maybe PerfValue -- ^ Minimum threshold.- -> Maybe PerfValue -- ^ Maximum threshold.- -> Maybe PerfValue -- ^ Warning threshold.- -> Maybe PerfValue -- ^ Critical threshold.- -> NagiosPlugin ()-addPerfDatum info val uom min' max' warn crit =- addPerfDatum' $ PerfDatum info val uom min' max' warn crit- where- addPerfDatum' pd = do- (rs, pds) <- get- put (rs, pd : pds)---- | The result which will be used if no other results have been--- provided.-defaultResult :: CheckResult-defaultResult = CheckResult (Unknown, T.pack "no check result specified")---- | The state the plugin will exit with if an uncaught exception occurs.--- within the plugin.-panicState :: SomeException -> CheckState-panicState = (,[]) . return . CheckResult . panicResult- where- panicResult e = (Critical,- T.pack ("unhandled exception: " ++ show e))---- | Returns result with greatest badness, or a default UNKNOWN result--- if no results have been specified.-worstResult :: [CheckResult] -> CheckResult-worstResult rs- | null rs = defaultResult- | otherwise = maximum rs---- | Render a plugin's performance data according to the--- <https://nagios-plugins.org/doc/guidelines.html Nagios plugin development guidelines>.-fmtPerfData :: [PerfDatum] -> Text-fmtPerfData = T.intercalate " " . map fmtPerfDatum- where- fmtPerfDatum PerfDatum{..} = T.concat- [ _label- , "="- , T.pack (show _value)- , T.pack (show _uom)- , fmtThreshold _min- , fmtThreshold _max- , fmtThreshold _warn- , fmtThreshold _crit- ]-- fmtThreshold Nothing = ";"- fmtThreshold (Just t) = T.pack $ ";" <> show t---- | Render a plugin's result according to the--- <https://nagios-plugins.org/doc/guidelines.html Nagios plugin development guidelines>.------ FIXME: not actually true yet, need to implement verbose output.-fmtResults :: [CheckResult] -> Text-fmtResults = fmtResult . worstResult- where- fmtResult (CheckResult (s,t)) =- T.pack (show s) <> ": " <> t---- | Given a check's final state, return the status and output it would--- exit with.-finishState :: CheckState -> (CheckStatus, Text)-finishState (rs, pds) =- let worst = worstResult rs- output = fmtResults rs <> perfdataPart pds- in (checkStatus worst, output)- where- perfdataPart [] = ""- perfdataPart xs = " | " <> fmtPerfData xs---- | Calculate our final result, print output and then exit with the--- appropriate status.-finishWith :: MonadIO m => CheckState -> m a-finishWith = liftIO . exitWithStatus . finishState+ module System.Nagios.Plugin.Check,+ module System.Nagios.Plugin.Range --- | Output the final check result to stdout and then terminate the--- check program with the appropriate exit status.-exitWithStatus :: (CheckStatus, Text) -> IO a-exitWithStatus (OK, t) = T.putStrLn t >> exitSuccess-exitWithStatus (r, t) = T.putStrLn t >> exitWith (ExitFailure $ fromEnum r)+) where --- | A 'Range' is a combination of a lower boundary and an upper boundary (x,y).--- An 'AcceptableRange' asserts that measured values between x and y--- imply that nothing is wrong; an UnacceptableRange implies the inverse.-data Range = AcceptableRange PerfValue PerfValue- | UnacceptableRange PerfValue PerfValue+import System.Nagios.Plugin.Check+import System.Nagios.Plugin.Range
+ lib/System/Nagios/Plugin/Check.hs view
@@ -0,0 +1,230 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}++module System.Nagios.Plugin.Check+(+ CheckStatus(..),+ CheckResult,+ UOM(..),+ PerfValue(..),+ NagiosPlugin,+ runNagiosPlugin,+ runNagiosPlugin',+ addPerfDatum,+ addBarePerfDatum,+ addResult,+ checkStatus,+ checkInfo,+ worstResult,+ PerfDatum,+ finishState+) where++import Control.Applicative+import Control.Monad.Catch+import Control.Monad.State.Lazy+import Data.Bifunctor+import Data.Int+import Data.Monoid+import Data.Nagios.Perfdata.Metric (UOM (..))+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Text.IO as T+import System.Exit++-- | Nagios plugin exit statuses. Ordered by priority -+-- OK < Warning < Critical < Unknown, which correspond to plugin exit+-- statuses of 0, 1, 2, and 3 respectively.+data CheckStatus = OK -- ^ Check executed successfully and+ -- detected no service problems.+ | Warning -- ^ Nothing's actually broken but this+ -- should be followed up.+ | Critical -- ^ Check executed successfully and detected+ -- a service failure.+ | Unknown -- ^ Check unable to determine service+ -- status.+ deriving (Enum, Eq, Ord)++instance Show CheckStatus where+ show OK = "OK"+ show Warning = "WARNING"+ show Critical = "CRITICAL"+ show Unknown = "UNKNOWN"++-- | A CheckResult is the exit status of the plugin combined with the+-- plugin's info text. A `NagiosPlugin` which exits with+--+-- > CheckResult (Critical "entropy decreasing in closed system")+--+-- as its peak-badness CheckResult (and no 'PerfDatum's) will a) exit with+-- status 2 and b) output the text "CRITICAL: entropy decreasing in closed+-- system".+newtype CheckResult = CheckResult+ { unCheckResult :: (CheckStatus, Text) }+ deriving (Eq, Ord, Show)++-- | Extract the return status from a 'CheckResult'+checkStatus :: CheckResult -> CheckStatus+checkStatus = fst . unCheckResult++-- | Extract the infotext from a 'CheckResult'.+checkInfo :: CheckResult -> Text+checkInfo = snd . unCheckResult++-- | Value of a performance metric.+data PerfValue = RealValue Double | IntegralValue Int64+ deriving Eq++instance Show PerfValue where+ show (RealValue x) = show x+ show (IntegralValue x) = show x++-- | One performance metric. A plugin will output zero or more of these,+-- whereupon Nagios generally passes them off to an external system such+-- as <http://oss.oetiker.ch/rrdtool/ RRDTool> or+-- <https://github.com/anchor/vaultaire Vaultaire>.+-- The thresholds are purely informative (designed to be graphed), and+-- do not affect alerting; likewise with `_min` and `_max`.+data PerfDatum = PerfDatum+ { _label :: Text -- ^ Name of quantity being measured.+ , _value :: PerfValue -- ^ Measured value, integral or real.+ , _uom :: UOM -- ^ Unit of measure; 'NullUOM' is fine here.+ , _min :: Maybe PerfValue -- ^ Measured quantity cannot be lower than this.+ , _max :: Maybe PerfValue -- ^ Measured quantity cannot be higher than this.+ , _warn :: Maybe PerfValue -- ^ Warning threshold for graphing.+ , _crit :: Maybe PerfValue -- ^ Critical threshold for graphing.+ }+ deriving (Eq, Show)++-- | Current check results/perfdata. If the check suddenly dies, the+-- 'worst' of the CheckResults (and all the PerfDatums) will be used+-- to determine the exit state.+type CheckState = ([CheckResult], [PerfDatum])++newtype NagiosPlugin a = NagiosPlugin+ {+ unNagiosPlugin :: StateT CheckState IO a+ } deriving (Functor, Applicative, Monad, MonadIO, MonadState CheckState, MonadCatch, MonadThrow)++-- | Execute a Nagios check. The program will terminate at the check's+-- completion. A default status will provided if none is given.+runNagiosPlugin :: NagiosPlugin a -> IO ()+runNagiosPlugin check = do+ (_, st) <- runNagiosPlugin' $ catch check panic+ finishWith st+ where+ panic :: SomeException -> NagiosPlugin a+ panic = liftIO . finishWith . panicState++-- | Execute a Nagios check as with 'runNagiosPlugin', but return its+-- final state rather than terminating.+runNagiosPlugin' :: NagiosPlugin a -> IO (a, CheckState)+runNagiosPlugin' a = runStateT (unNagiosPlugin a) mempty++-- | Insert a result. Only the 'CheckStatus' with the most 'badness'+-- will determine the check's exit status.+addResult :: CheckStatus -> Text -> NagiosPlugin ()+addResult s t =+ modify (first (CheckResult (s, t) :))++-- | Insert a performance metric into the list the check will output.+addPerfDatum ::+ Text -- ^ Name of the quantity being measured.+ -> PerfValue -- ^ Measured value.+ -> UOM -- ^ Unit of the measured value.+ -> Maybe PerfValue -- ^ Minimum threshold.+ -> Maybe PerfValue -- ^ Maximum threshold.+ -> Maybe PerfValue -- ^ Warning threshold.+ -> Maybe PerfValue -- ^ Critical threshold.+ -> NagiosPlugin ()+addPerfDatum info val uom min' max' warn crit =+ modify (second (PerfDatum info val uom min' max' warn crit :))++-- | Convenience function to insert a perfdatum without thresholds for+-- min, max, warn or crit. Note that unless the range of the metric is+-- actually unbounded, specifying explicit thresholds is considered+-- good practice (it makes life easier for authors of graphing+-- packages).+--+-- FIXME: implement thresholds properly and default to negative and+-- positive infinity for min and max here.+addBarePerfDatum ::+ Text -- ^ Name of the quantity being measured.+ -> PerfValue -- ^ Measured value.+ -> UOM -- ^ Unit of the measured value.+ -> NagiosPlugin ()+addBarePerfDatum info val uom =+ addPerfDatum info val uom Nothing Nothing Nothing Nothing++-- | The result which will be used if no other results have been+-- provided.+defaultResult :: CheckResult+defaultResult = CheckResult (Unknown, T.pack "no check result specified")++-- | The state the plugin will exit with if an uncaught exception occurs.+-- within the plugin.+panicState :: SomeException -> CheckState+panicState = (,[]) . return . CheckResult . panicResult+ where+ panicResult e = (Critical,+ T.pack ("unhandled exception: " ++ show e))++-- | Returns result with greatest badness, or a default UNKNOWN result+-- if no results have been specified.+worstResult :: [CheckResult] -> CheckResult+worstResult rs+ | null rs = defaultResult+ | otherwise = maximum rs++-- | Render a plugin's performance data according to the+-- <https://nagios-plugins.org/doc/guidelines.html Nagios plugin development guidelines>.+fmtPerfData :: [PerfDatum] -> Text+fmtPerfData = T.intercalate " " . map fmtPerfDatum+ where+ fmtPerfDatum PerfDatum{..} = T.concat+ [ _label+ , "="+ , T.pack (show _value)+ , T.pack (show _uom)+ , fmtThreshold _min+ , fmtThreshold _max+ , fmtThreshold _warn+ , fmtThreshold _crit+ ]++ fmtThreshold Nothing = ";"+ fmtThreshold (Just t) = T.pack $ ";" <> show t++-- | Render a plugin's result according to the+-- <https://nagios-plugins.org/doc/guidelines.html Nagios plugin development guidelines>.+--+-- FIXME: not actually true yet, need to implement verbose output.+fmtResults :: [CheckResult] -> Text+fmtResults = fmtResult . worstResult+ where+ fmtResult (CheckResult (s,t)) =+ T.pack (show s) <> ": " <> t++-- | Given a check's final state, return the status and output it would+-- exit with.+finishState :: CheckState -> (CheckStatus, Text)+finishState (rs, pds) =+ let worst = worstResult rs+ output = fmtResults rs <> perfdataPart pds+ in (checkStatus worst, output)+ where+ perfdataPart [] = ""+ perfdataPart xs = " | " <> fmtPerfData xs++-- | Calculate our final result, print output and then exit with the+-- appropriate status.+finishWith :: MonadIO m => CheckState -> m a+finishWith = liftIO . exitWithStatus . finishState++-- | Output the final check result to stdout and then terminate the+-- check program with the appropriate exit status.+exitWithStatus :: (CheckStatus, Text) -> IO a+exitWithStatus (OK, t) = T.putStrLn t >> exitSuccess+exitWithStatus (r, t) = T.putStrLn t >> exitWith (ExitFailure $ fromEnum r)
+ lib/System/Nagios/Plugin/Range.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE TupleSections #-}++module System.Nagios.Plugin.Range+(+ Range+) where++import System.Nagios.Plugin.Check (PerfValue)++-- | A 'Range' is a combination of a lower boundary and an upper boundary (x,y).+-- An 'AcceptableRange' asserts that measured values between x and y+-- imply that nothing is wrong; an UnacceptableRange implies the inverse.+data Range = AcceptableRange PerfValue PerfValue+ | UnacceptableRange PerfValue PerfValue
nagios-check.cabal view
@@ -1,5 +1,5 @@ name: nagios-check-version: 0.1.0.0+version: 0.2.0 synopsis: Package for writing monitoring plugins description: Implements Nagios plugin development guidelines within a Haskell framework for writing Nagios@@ -21,7 +21,9 @@ library exposed-modules: System.Nagios.Plugin- build-depends: base >=4.7 && <5,+ other-modules: System.Nagios.Plugin.Check+ System.Nagios.Plugin.Range+ build-depends: base >=4.5 && <5, mtl, text, bifunctors,