1
1
mirror of https://github.com/github/semantic.git synced 2024-12-28 09:21:35 +03:00

Continue to refine config API

This commit is contained in:
Timothy Clem 2018-06-13 16:42:04 -07:00
parent 5ad2b64769
commit 7970999463
5 changed files with 52 additions and 46 deletions

View File

@ -1,5 +1,4 @@
{-# OPTIONS_GHC -fforce-recomp #-} -- So that gitHash is correct. {-# LANGUAGE ApplicativeDo, RankNTypes #-}
{-# LANGUAGE ApplicativeDo, RankNTypes, TemplateHaskell #-}
module Semantic.CLI module Semantic.CLI
( main ( main
-- Testing -- Testing
@ -11,10 +10,7 @@ import Data.Language (ensureLanguage)
import Data.List (intercalate) import Data.List (intercalate)
import Data.List.Split (splitWhen) import Data.List.Split (splitWhen)
import Data.Project import Data.Project
import Data.Version (showVersion)
import Development.GitRev
import Options.Applicative hiding (style) import Options.Applicative hiding (style)
import qualified Paths_semantic as Library (version)
import Prologue import Prologue
import Rendering.Renderer import Rendering.Renderer
import qualified Semantic.AST as AST import qualified Semantic.AST as AST
@ -25,6 +21,7 @@ import Semantic.IO as IO
import qualified Semantic.Parse as Parse import qualified Semantic.Parse as Parse
import qualified Semantic.Task as Task import qualified Semantic.Task as Task
import qualified Semantic.Telemetry.Log as Log import qualified Semantic.Telemetry.Log as Log
import Semantic.Version
import Serializing.Format hiding (Options) import Serializing.Format hiding (Options)
import Text.Read import Text.Read
@ -38,9 +35,9 @@ arguments :: ParserInfo (Options, Task.TaskEff ())
arguments = info (version <*> helper <*> ((,) <$> optionsParser <*> argumentsParser)) description arguments = info (version <*> helper <*> ((,) <$> optionsParser <*> argumentsParser)) description
where where
version = infoOption versionString (long "version" <> short 'v' <> help "Output the version of the program") version = infoOption versionString (long "version" <> short 'v' <> help "Output the version of the program")
versionString = "semantic version " <> showVersion Library.version <> " (" <> $(gitHash) <> ")" versionString = "semantic version " <> buildVersion <> " (" <> buildSHA <> ")"
description = fullDesc <> header "semantic -- Parse and diff semantically" description = fullDesc <> header "semantic -- Parse and diff semantically"
optionsParser = do optionsParser = do
logLevel <- options [ ("error", Just Log.Error) , ("warning", Just Log.Warning) , ("info", Just Log.Info) , ("debug", Just Log.Debug) , ("none", Nothing)] logLevel <- options [ ("error", Just Log.Error) , ("warning", Just Log.Warning) , ("info", Just Log.Info) , ("debug", Just Log.Debug) , ("none", Nothing)]
(long "log-level" <> value (Just Log.Warning) <> help "Log messages at or above this level, or disable logging entirely.") (long "log-level" <> value (Just Log.Warning) <> help "Log messages at or above this level, or disable logging entirely.")

View File

@ -1,19 +1,23 @@
{-# OPTIONS_GHC -fforce-recomp #-} -- So that gitHash is correct.
{-# LANGUAGE TemplateHaskell #-}
module Semantic.Config where module Semantic.Config where
import Control.Exception import Control.Exception
import Network.BSD import Network.BSD
import Network.HTTP.Client.TLS import Network.HTTP.Client.TLS
import Network.URI import Network.URI
import Prologue import Prologue
import Semantic.Telemetry import Semantic.Env
import Semantic.Telemetry.AsyncQueue import Semantic.Telemetry
import qualified Semantic.Telemetry.Stat as Stat import Semantic.Telemetry.AsyncQueue
import qualified Semantic.Telemetry.Haystack as Haystack
import qualified Semantic.Telemetry.Log as Log import qualified Semantic.Telemetry.Log as Log
import Semantic.Env import qualified Semantic.Telemetry.Stat as Stat
import System.Environment import Semantic.Version
import System.IO (hIsTerminalDevice, stderr) import System.Environment
import System.Posix.Process import System.IO (hIsTerminalDevice, stderr)
import System.Posix.Types import System.Posix.Process
import System.Posix.Types
data Config data Config
= Config = Config
@ -65,13 +69,17 @@ defaultConfig' options@Options{..} = do
, configMaxTelemetyQueueSize = size , configMaxTelemetyQueueSize = size
, configIsTerminal = isTerminal , configIsTerminal = isTerminal
, configLogPrintSource = isTerminal , configLogPrintSource = isTerminal
, configLogFormatter = logfmtFormatter , configLogFormatter = if isTerminal then terminalFormatter else logfmtFormatter
, configOptions = options , configOptions = options
} }
defaultHaystackFromConfig :: Config -> Haystack.ErrorLogger IO -> IO HaystackQueue
defaultHaystackFromConfig c@Config{..} logError = haystackClientFromConfig c >>= newAsyncQueue configMaxTelemetyQueueSize (Haystack.reportError logError)
haystackClientFromConfig :: Config -> IO HaystackClient haystackClientFromConfig :: Config -> IO HaystackClient
haystackClientFromConfig Config{..} = haystackClient configHaystackURL tlsManagerSettings configHostName configAppName haystackClientFromConfig Config{..} = haystackClient configHaystackURL tlsManagerSettings configAppName
withLogger :: Config -> (LogQueue -> IO c) -> IO c withLogger :: Config -> (LogQueue -> IO c) -> IO c
@ -79,12 +87,21 @@ withLogger c = bracket (defaultLoggerFromConfig c) closeAsyncQueue
defaultLoggerFromConfig :: Config -> IO LogQueue defaultLoggerFromConfig :: Config -> IO LogQueue
defaultLoggerFromConfig Config{..} = defaultLoggerFromConfig Config{..} =
newAsyncQueue configMaxTelemetyQueueSize Log.writeLogMessage LogOptions{ newAsyncQueue configMaxTelemetyQueueSize Log.writeLogMessage LogOptions {
optionsLevel = optionsLogLevel configOptions logOptionsLevel = optionsLogLevel configOptions
, optionsFormatter = configLogFormatter , logOptionsFormatter = configLogFormatter
, optionsLogContext = [("app", configAppName), ("process_id", show configProcessID)] <> [("request_id", x) | x <- toList (optionsRequestID configOptions) ] , logOptionsContext =
[ ("app", configAppName)
, ("pid", show configProcessID)
, ("hostname", configHostName)
, ("sha", buildSHA)
] <> [("request_id", x) | x <- toList (optionsRequestID configOptions) ]
} }
withStatter :: Config -> (StatQueue -> IO c) -> IO c
withStatter c = bracket (defaultStatterFromConfig c) $ \statter -> do
closeAsyncQueue statter
Stat.closeStatClient (asyncQueueExtra statter)
defaultStatterFromConfig :: Config -> IO StatQueue defaultStatterFromConfig :: Config -> IO StatQueue
defaultStatterFromConfig c@Config{..} = statsClientFromConfig c >>= newAsyncQueue configMaxTelemetyQueueSize Stat.sendStat defaultStatterFromConfig c@Config{..} = statsClientFromConfig c >>= newAsyncQueue configMaxTelemetyQueueSize Stat.sendStat

View File

@ -73,14 +73,11 @@ import Prologue hiding (MonadError (..), project)
import Semantic.Config import Semantic.Config
import Semantic.Distribute import Semantic.Distribute
import qualified Semantic.IO as IO import qualified Semantic.IO as IO
-- import Semantic.Log
-- import Semantic.Queue
import Semantic.Resolution import Semantic.Resolution
import Semantic.Telemetry.Stat as Stat
import Semantic.Telemetry import Semantic.Telemetry
import Semantic.Telemetry.Stat as Stat
import Serializing.Format hiding (Options) import Serializing.Format hiding (Options)
import System.Exit (die) import System.Exit (die)
import System.IO (stderr)
-- | A high-level task producing some result, e.g. parsing, diffing, rendering. 'Task's can also specify explicit concurrency via 'distribute', 'distributeFor', and 'distributeFoldMap' -- | A high-level task producing some result, e.g. parsing, diffing, rendering. 'Task's can also specify explicit concurrency via 'distribute', 'distributeFor', and 'distributeFoldMap'
type TaskEff = Eff '[Distribute WrappedTask type TaskEff = Eff '[Distribute WrappedTask
@ -129,21 +126,16 @@ serialize format = send . Serialize format
runTask :: TaskEff a -> IO a runTask :: TaskEff a -> IO a
runTask = runTaskWithOptions defaultOptions runTask = runTaskWithOptions defaultOptions
-- | Execute a 'TaskEff' with the passed 'Config', yielding its result value in 'IO'. -- | Execute a 'TaskEff' with the passed 'Options', yielding its result value in 'IO'.
runTaskWithOptions :: Options -> TaskEff a -> IO a runTaskWithOptions :: Options -> TaskEff a -> IO a
runTaskWithOptions opts task = do runTaskWithOptions opts task = do
config <- defaultConfig' opts config <- defaultConfig' opts
statter <- defaultStatterFromConfig config
-- logger <- defaultLoggerFromConfig c
result <- withLogger config $ \logger -> result <- withLogger config $ \logger ->
runTaskWithConfig config logger statter task withStatter config $ \statter ->
runTaskWithConfig config logger statter task
-- closeQueue statter
-- closeStatClient (asyncQueueExtra statter)
-- closeQueue logger
either (die . displayException) pure result either (die . displayException) pure result
-- | Execute a 'TaskEff' yielding its result value in 'IO'.
runTaskWithConfig :: Config -> LogQueue -> StatQueue -> TaskEff a -> IO (Either SomeException a) runTaskWithConfig :: Config -> LogQueue -> StatQueue -> TaskEff a -> IO (Either SomeException a)
runTaskWithConfig options logger statter task = do runTaskWithConfig options logger statter task = do
(result, stat) <- withTiming "run" [] $ do (result, stat) <- withTiming "run" [] $ do

View File

@ -55,7 +55,7 @@ type HaystackQueue = AsyncQueue ErrorReport HaystackClient
-- | Queue a message to be logged. -- | Queue a message to be logged.
queueLogMessage :: MonadIO io => LogQueue -> Level -> String -> [(String, String)] -> io () queueLogMessage :: MonadIO io => LogQueue -> Level -> String -> [(String, String)] -> io ()
queueLogMessage q@AsyncQueue{..} level message pairs queueLogMessage q@AsyncQueue{..} level message pairs
| Just logLevel <- optionsLevel asyncQueueExtra | Just logLevel <- logOptionsLevel asyncQueueExtra
, level <= logLevel = liftIO Time.getCurrentTime >>= liftIO . LocalTime.utcToLocalZonedTime >>= liftIO . writeAsyncQueue q . Message level message pairs , level <= logLevel = liftIO Time.getCurrentTime >>= liftIO . LocalTime.utcToLocalZonedTime >>= liftIO . writeAsyncQueue q . Message level message pairs
| otherwise = pure () | otherwise = pure ()

View File

@ -27,14 +27,14 @@ data Level
-- | Options for controlling logging -- | Options for controlling logging
data LogOptions = LogOptions data LogOptions = LogOptions
{ optionsLevel :: Maybe Level -- ^ What level of messages to log. 'Nothing' disabled logging. { logOptionsLevel :: Maybe Level -- ^ What level of messages to log. 'Nothing' disabled logging.
, optionsFormatter :: LogFormatter -- ^ Log formatter to use. , logOptionsFormatter :: LogFormatter -- ^ Log formatter to use.
, optionsLogContext :: [(String, String)] , logOptionsContext :: [(String, String)]
} }
-- | Write a log a message to stderr. -- | Write a log a message to stderr.
writeLogMessage :: MonadIO io => LogOptions -> Message -> io () writeLogMessage :: MonadIO io => LogOptions -> Message -> io ()
writeLogMessage options@LogOptions{..} = liftIO . hPutStr stderr . optionsFormatter options writeLogMessage options@LogOptions{..} = liftIO . hPutStr stderr . logOptionsFormatter options
-- | Format log messaging using "logfmt". -- | Format log messaging using "logfmt".
-- --
@ -49,7 +49,7 @@ logfmtFormatter LogOptions{..} (Message level message pairs time) =
( kv "time" (showTime time) ( kv "time" (showTime time)
: kv "msg" (shows message) : kv "msg" (shows message)
: kv "level" (shows level) : kv "level" (shows level)
: (uncurry kv . second shows <$> (pairs <> optionsLogContext))) : (uncurry kv . second shows <$> (pairs <> logOptionsContext)))
. showChar '\n' $ "" . showChar '\n' $ ""
where where
kv k v = showString k . showChar '=' . v kv k v = showString k . showChar '=' . v
@ -65,7 +65,7 @@ terminalFormatter LogOptions{..} (Message level message pairs time) =
showChar '[' . showTime time . showString "] " showChar '[' . showTime time . showString "] "
. showLevel level . showChar ' ' . showLevel level . showChar ' '
. showString (printf "%-20s " message) . showString (printf "%-20s " message)
. showPairs pairs . showPairs (pairs <> logOptionsContext)
. showChar '\n' $ "" . showChar '\n' $ ""
where where
colourize = True colourize = True