network-carbon (empty) → 1.0.0
raw patch · 5 files changed
+165/−0 lines, 5 filesdep +basedep +bytestringdep +networksetup-changed
Dependencies added: base, bytestring, network, text, time, vector
Files
- Changelog.md +3/−0
- LICENSE +30/−0
- Setup.hs +2/−0
- network-carbon.cabal +28/−0
- src/Network/Carbon/Plaintext.hs +102/−0
+ Changelog.md view
@@ -0,0 +1,3 @@+## 1.0.0++* Initial release.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Oliver Charles++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Oliver Charles nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ network-carbon.cabal view
@@ -0,0 +1,28 @@+name: network-carbon+version: 1.0.0+synopsis: A Haskell implementation of the Carbon protocol (part of the Graphite monitoring tools)+homepage: http://github.com/ocharles/network-carbon+license: BSD3+license-file: LICENSE+author: Oliver Charles+maintainer: ollie@ocharles.org.uk+build-type: Simple+cabal-version: >=1.10+extra-source-files: Changelog.md++library+ exposed-modules:+ Network.Carbon.Plaintext++ build-depends:+ base >=4.6 && <4.8,+ bytestring >=0.10.2.0 && <0.11,+ network >= 2.5.0.0 && < 2.6,+ text >= 1.1.1.3 && < 1.2,+ time >= 1.4.2 && < 1.5,+ vector >= 0.10.11.0 && < 0.11++ hs-source-dirs: src+ default-language: Haskell2010++ ghc-options: -Wall -O2 -fwarn-incomplete-uni-patterns
+ src/Network/Carbon/Plaintext.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE OverloadedStrings #-}+module Network.Carbon.Plaintext+ ( -- * Interacting with Carbon+ -- ** Connections+ Connection(..)+ , connect+ , disconnect++ -- ** Metrics+ , sendMetrics+ , sendMetric+ , Metric(..)++ -- * Protocol details+ , encodeMetric+ )+ where++import Control.Monad (unless)+import Data.Monoid ((<>), mempty, mappend)+import Data.Typeable (Typeable)++import qualified Data.ByteString.Builder as Builder+import qualified Data.Time as Time+import qualified Data.Time.Clock.POSIX as Time+import qualified Data.Vector as V+import qualified Data.Text as Text+import qualified Data.Text.Encoding as Text+import qualified Network.Socket as Network+import qualified Network.Socket.ByteString.Lazy as Network++--------------------------------------------------------------------------------+-- | Low-level representation of a Carbon connection. It's suggested that you+-- construct this via 'connect'. It is henceforth assumed that+-- 'Network.getPeerName' will return something useful, which usually means+-- 'connectionSocket' should have been 'Network.connect'ed at least once.+data Connection = Connection+ { connectionSocket :: !Network.Socket+ -- ^ The connection socket to Carbon.+ }+ deriving (Eq, Show, Typeable)+++--------------------------------------------------------------------------------+-- | Connect to Carbon.+connect :: Network.SockAddr -> IO Connection+connect sockAddr = fmap Connection $ do+ s <- Network.socket Network.AF_INET Network.Stream Network.defaultProtocol+ Network.connect s sockAddr+ return s+++--------------------------------------------------------------------------------+-- | Disconnect from Carbon. Note that it's still valid to 'sendMetrics' to this+-- 'Connection', and it will result in a reconnection.+disconnect :: Connection -> IO ()+disconnect (Connection s) = Network.close s+++--------------------------------------------------------------------------------+reconnect :: Connection -> IO ()+reconnect (Connection s) = do+ peer <- Network.getPeerName s+ Network.connect s peer+++--------------------------------------------------------------------------------+-- | A single data point. A metric has a path that names it, a value, and the+-- time the metric was sampled.+data Metric = Metric+ { metricPath :: !Text.Text+ , metricValue :: !Double+ , metricTimeStamp :: !Time.UTCTime+ }+ deriving (Eq, Show, Typeable)+++--------------------------------------------------------------------------------+-- | Send a collection of metrics to Carbon.+sendMetrics :: Connection -> V.Vector Metric -> IO ()+sendMetrics c ms = do+ let socket = connectionSocket c++ do isWritable <- Network.isWritable socket+ unless isWritable (reconnect c)++ Network.sendAll socket (Builder.toLazyByteString (V.foldl' mappend mempty (V.map encodeMetric ms)))++--------------------------------------------------------------------------------+-- | Send a single metric.+sendMetric :: Connection -> Text.Text -> Double -> Time.UTCTime -> IO ()+sendMetric c k v t = sendMetrics c (V.singleton (Metric k v t))+++--------------------------------------------------------------------------------+-- | Encode a 'Metric' for transmission over the plain text protocol.+encodeMetric :: Metric -> Builder.Builder+encodeMetric (Metric k v t) =+ Builder.byteString (Text.encodeUtf8 k) <> " " <>+ Builder.stringUtf8 (show v) <> " " <>+ Builder.stringUtf8 (show (round (Time.utcTimeToPOSIXSeconds t) :: Int)) <> "\n"