diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # Changelog
 
+## v0.3.0
+
+ - Added addPerfData function and ToPerfData typeclass for more convenient
+   generation of perfdata from complex data structures.
+
 ## v0.2.1
 
  - Support for GHC 7.4 (Justin S. Leitgeib, @jsl).
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,2 +1,2 @@
-import Distribution.Simple
+import           Distribution.Simple
 main = defaultMain
diff --git a/lib/System/Nagios/Plugin.hs b/lib/System/Nagios/Plugin.hs
--- a/lib/System/Nagios/Plugin.hs
+++ b/lib/System/Nagios/Plugin.hs
@@ -6,9 +6,10 @@
 module System.Nagios.Plugin
 (
     module System.Nagios.Plugin.Check,
-    module System.Nagios.Plugin.Range
-
+    module System.Nagios.Plugin.Range,
+    module System.Nagios.Plugin.PerfData
 ) where
 
 import           System.Nagios.Plugin.Check
+import           System.Nagios.Plugin.PerfData
 import           System.Nagios.Plugin.Range
diff --git a/lib/System/Nagios/Plugin/Check.hs b/lib/System/Nagios/Plugin/Check.hs
--- a/lib/System/Nagios/Plugin/Check.hs
+++ b/lib/System/Nagios/Plugin/Check.hs
@@ -7,33 +7,31 @@
 (
     CheckStatus(..),
     CheckResult,
-    UOM(..),
-    PerfValue(..),
     NagiosPlugin,
     runNagiosPlugin,
     runNagiosPlugin',
     addPerfDatum,
+    addPerfData,
     addBarePerfDatum,
     addResult,
     checkStatus,
     checkInfo,
     worstResult,
-    PerfDatum,
     finishState
 ) where
 
 import           Control.Applicative
-import qualified Control.Monad.Catch as E
+import qualified Control.Monad.Catch           as E
 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           Data.Text                     (Text)
+import qualified Data.Text                     as T
+import qualified Data.Text.IO                  as T
 import           System.Exit
 
+import           System.Nagios.Plugin.PerfData
+
 -- | Nagios plugin exit statuses. Ordered by priority -
 --   'OK' < 'Warning' < 'Critical' < 'Unknown', which correspond to plugin exit
 --   statuses of 0, 1, 2, and 3 respectively.
@@ -73,31 +71,6 @@
 checkInfo :: CheckResult -> Text
 checkInfo = snd . unCheckResult
 
--- | Value of a performance metric.
-data PerfValue = RealValue Double | IntegralValue Int64
-  deriving (Eq, Ord)
-
-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.
@@ -157,6 +130,14 @@
     -> NagiosPlugin ()
 addBarePerfDatum info val uom =
     addPerfDatum info val uom Nothing Nothing Nothing Nothing
+
+-- | Alternative mechanism for adding perfdata generated from complex
+--   types; just implement the 'toPerfData' typeclass.
+addPerfData ::
+       ToPerfData a
+    => a
+    -> NagiosPlugin ()
+addPerfData pd = modify (second (++ toPerfData pd))
 
 -- | The result which will be used if no other results have been
 --   provided.
diff --git a/lib/System/Nagios/Plugin/PerfData.hs b/lib/System/Nagios/Plugin/PerfData.hs
new file mode 100644
--- /dev/null
+++ b/lib/System/Nagios/Plugin/PerfData.hs
@@ -0,0 +1,55 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE RecordWildCards            #-}
+{-# LANGUAGE TupleSections              #-}
+
+module System.Nagios.Plugin.PerfData
+(
+    UOM(..),
+    PerfValue(..),
+    PerfDatum(..),
+    ToPerfData,
+    toPerfData,
+    barePerfDatum
+) where
+
+import           Data.Int
+import           Data.Nagios.Perfdata.Metric (UOM (..))
+import           Data.Text                   (Text)
+
+-- | Value of a performance metric.
+data PerfValue = RealValue Double | IntegralValue Int64
+  deriving (Eq, Ord)
+
+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)
+
+class ToPerfData a where
+    { toPerfData :: a -> [PerfDatum] }
+
+-- | Create a PerfDatum from only the required values, using Nothing
+--   for all the others.
+barePerfDatum ::
+       Text
+    -> PerfValue
+    -> UOM
+    -> PerfDatum
+barePerfDatum info val uom = PerfDatum info val uom Nothing Nothing Nothing Nothing
diff --git a/lib/System/Nagios/Plugin/Range.hs b/lib/System/Nagios/Plugin/Range.hs
--- a/lib/System/Nagios/Plugin/Range.hs
+++ b/lib/System/Nagios/Plugin/Range.hs
@@ -8,7 +8,7 @@
     Range
 ) where
 
-import           System.Nagios.Plugin.Check (PerfValue)
+import           System.Nagios.Plugin.PerfData (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
diff --git a/nagios-check.cabal b/nagios-check.cabal
--- a/nagios-check.cabal
+++ b/nagios-check.cabal
@@ -1,5 +1,5 @@
 name:                nagios-check
-version:             0.2.1
+version:             0.3.0
 synopsis:            Package for writing monitoring plugins
 description:         Implements Nagios plugin development guidelines
                      within a Haskell framework for writing Nagios
@@ -24,6 +24,7 @@
   exposed-modules:     System.Nagios.Plugin
   other-modules:       System.Nagios.Plugin.Check
                        System.Nagios.Plugin.Range
+                       System.Nagios.Plugin.PerfData
   build-depends:       base >=4.5 && <5,
                        mtl,
                        text,
