module Handler.Health where import Import import qualified Data.Aeson.Encode.Pretty as Aeson import qualified Data.Text.Lazy.Builder as Builder import qualified Data.UUID as UUID import qualified Data.Set as Set import Control.Concurrent.STM.Delay getHealthR :: Handler TypedContent getHealthR = do reportStore <- getsYesod appHealthReport healthReports' <- liftIO $ readTVarIO reportStore interval <- getsYesod $ view _appHealthCheckInterval case fromNullable healthReports' of Nothing -> do let Min (NTop minInterval) = ofoldMap1 (Min . NTop) $ impureNonNull interval delay <- for minInterval $ \minInterval' -> liftIO . newDelay . round $ toRational minInterval' * 1e6 waitResult <- atomically $ maybe (pure $ Left False) (fmap (const $ Left True) . waitDelay) delay <|> (fmap Right . assertM (not. Set.null) $ readTVar reportStore) case waitResult of Left False -> sendResponseStatus noContent204 () Left True -> sendResponseStatus internalServerError500 ("System is not generating HealthReports" :: Text) Right _ -> redirect HealthR Just healthReports -> do let (Max lastUpdated, Min status) = ofoldMap1 (Max *** Min . healthReportStatus) healthReports reportNextUpdate (lastCheck, classifyHealthReport -> kind) = fromMaybe 0 (interval kind) `addUTCTime` lastCheck Max nextUpdate = ofoldMap1 (Max . reportNextUpdate) healthReports instanceId <- getsYesod appInstanceID setWeakEtagHashable (instanceId, lastUpdated) expiresAt nextUpdate setLastModified lastUpdated let status' | HealthSuccess <- status = ok200 | otherwise = internalServerError500 sendResponseStatus status' <=< selectRep $ do provideRep . siteLayoutMsg MsgHealthReport $ do setTitleI MsgHealthReport [whamlet| $newline never
$forall (_, report) <- healthReports' $case report $of HealthMatchingClusterConfig passed
_{MsgHealthMatchingClusterConfig}
#{boolSymbol passed} $of HealthHTTPReachable (Just passed)
_{MsgHealthHTTPReachable}
#{boolSymbol passed} $of HealthLDAPAdmins (Just found)
_{MsgHealthLDAPAdmins}
#{textPercent found 1} $of HealthSMTPConnect (Just passed)
_{MsgHealthSMTPConnect}
#{boolSymbol passed} $of HealthWidgetMemcached (Just passed)
_{MsgHealthWidgetMemcached}
#{boolSymbol passed} $of HealthActiveJobExecutors (Just active)
_{MsgHealthActiveJobExecutors}
#{textPercent active 1} $of _ |] provideJson healthReports provideRep . return . Builder.toLazyText $ Aeson.encodePrettyToTextBuilder healthReports getInstanceR :: Handler TypedContent getInstanceR = do instanceInfo@(clusterId, instanceId) <- getsYesod $ (,) <$> appClusterID <*> appInstanceID setWeakEtagHashable (clusterId, instanceId) selectRep $ do provideRep $ siteLayoutMsg MsgInstanceIdentification $ do setTitleI MsgInstanceIdentification [whamlet| $newline never
_{MsgClusterId}
#{UUID.toText clusterId}
_{MsgInstanceId}
#{UUID.toText instanceId} |] provideJson instanceInfo provideRep . return $ tshow instanceInfo