Created
August 16, 2018 04:42
-
-
Save shirren/332523d2f455eafc18a9ec931cc6f12f to your computer and use it in GitHub Desktop.
Haskell example to retrieve metrics from Keen.io via its rest interface
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# OPTIONS -Wno-unused-top-binds #-} | |
{-# OPTIONS -Wname-shadowing #-} | |
module Analysis.Keen where | |
import Data.Aeson | |
import qualified Data.ByteString.Char8 as BC | |
import Data.Text (Text) | |
import Data.Semigroup | |
import Network.HTTP.Simple | |
( Request | |
, defaultRequest | |
, getResponseBody | |
, httpJSON | |
, setRequestBodyJSON | |
, setRequestHeader | |
, setRequestHost | |
, setRequestMethod | |
, setRequestPath | |
, setRequestPort | |
, setRequestSecure | |
) | |
-- Keen api read key. | |
-- TODO: Read this value from the evironment. | |
readKey :: BC.ByteString | |
readKey = "INSERT_KEEN_READ_KEY" | |
-- Keen base url. | |
keenHost :: BC.ByteString | |
keenHost = "api.keen.io" | |
-- ADT to represent a Keen result | |
newtype KeenResult = KeenResult { | |
keenResult :: Int | |
} deriving Show | |
instance FromJSON KeenResult | |
where | |
parseJSON (Object o) = KeenResult <$> (o .: "result") | |
instance Semigroup KeenResult | |
where | |
(<>) (KeenResult result1) (KeenResult result2) = KeenResult $ result1 + result2 | |
-- A Keen request can be a filtered request in which case it is also | |
-- built from the Filter ADT. | |
data KeenFilter = KeenInFilter { | |
propertyName :: Text, | |
operator :: Text, | |
propertyValue :: [Text] | |
} | |
instance ToJSON KeenFilter | |
where | |
toJSON (KeenInFilter prop op val) = object | |
[ "property_name" .= prop | |
, "operator" .= op | |
, "property_value" .= val | |
] | |
-- Simple function to set default value on operator. | |
keenInFilter :: Text -> [Text] -> KeenFilter | |
keenInFilter name = KeenInFilter name "in" | |
-- Definition of Keen request ADT which is a sum type of either just an | |
-- event and time frame, or event, timeframe and a list of filters. | |
data KeenRequest = KeenRequest Text Text Text | | |
KeenFilterRequest { | |
event :: Text, | |
timeframe :: Text, | |
timezone :: Text, | |
filters :: [KeenFilter] | |
} | | |
KeenGroupByFilterRequest { | |
event :: Text, | |
groupBy :: Text, | |
timeframe :: Text, | |
timezone :: Text, | |
filters :: [KeenFilter] | |
} | |
instance ToJSON KeenRequest | |
where | |
toJSON (KeenRequest event timeframe timezone) = object | |
[ "event_collection" .= event | |
, "timeframe" .= timeframe | |
, "timezone" .= timezone | |
] | |
toJSON (KeenFilterRequest event timeframe timezone filters) = object | |
[ "event_collection" .= event | |
, "timeframe" .= timeframe | |
, "timezone" .= timezone | |
, "filters" .= filters | |
] | |
toJSON (KeenGroupByFilterRequest event groupBy timeframe timezone filters) = object | |
[ "event_collection" .= event | |
, "group_by" .= groupBy | |
, "timeframe" .= timeframe | |
, "timezone" .= timezone | |
, "filters" .= filters | |
] | |
-- Build a secure keen request. | |
buildRequest :: BC.ByteString -> BC.ByteString -> KeenRequest -> Request | |
buildRequest method path body = setRequestMethod method | |
$ setRequestHost keenHost | |
$ setRequestHeader "Authorization" [readKey] | |
$ setRequestPath completePath | |
$ setRequestBodyJSON body | |
$ setRequestSecure True | |
$ setRequestPort 443 defaultRequest | |
where | |
completePath = mconcat [apiPath, "/", projectId, "/queries/", path] | |
apiPath = "/3.0/projects" | |
projectId = "your_project_id" | |
-- Send a keen request to the Keen server and obtain the response. As we | |
-- are making a Http request, the response is of type IO. | |
sendKeenRequest :: Request -> IO KeenResult | |
sendKeenRequest request = getResponseBody <$> response | |
where | |
response = httpJSON request | |
-- Utility to generate a generic count request. | |
buildCountRequest :: KeenRequest -> Request | |
buildCountRequest = buildRequest "POST" "count" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment