From 160caf38b6e936b6541b31b3c9bbe952ba0a4b15 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 22 Dec 2013 13:18:18 -0500 Subject: [PATCH] Disable syslog by default. Allow log_file and syslog to coexist. --- doc/htsnrc.example | 27 ++++++++++--------- src/CommandLine.hs | 7 +++-- src/Configuration.hs | 12 ++++++--- src/Logging.hs | 50 +++++++++++++++++++++++------------- src/OptionalConfiguration.hs | 35 +++++++++++++------------ 5 files changed, 77 insertions(+), 54 deletions(-) diff --git a/doc/htsnrc.example b/doc/htsnrc.example index 0c26557..8af5398 100644 --- a/doc/htsnrc.example +++ b/doc/htsnrc.example @@ -10,23 +10,24 @@ # username = "whoever" -# The password used to connect to the feed. +# The password associated with your TSN username. # # Default: none (required) # # password = "whatever" -# By default, htsn will output the XML files to the current working +# By default, XML files will be written to the current working # directory. Often this is not desirable, and you would rather save # them to a specific location. Specify it here. # -# Default: "." (here) +# Default: "." # # output-directory = "/var/lib/htsn" -# A list of hostnames that supply the feed. +# A list of hostnames that supply the feed. You probably don't need to +# change this, but you can. # # Default: ["feed1.sportsnetwork.com", # "feed2.sportsnetwork.com", @@ -35,19 +36,21 @@ # feed-hosts = [ "hostname1", "hostname2", ... ] -# Do you want to log to syslog? If so, the log_file option below will -# be ignored. This will log to the event log on Windows. +# Do you want to log to syslog? On Windows this will attempt to +# communicate (over UDP) with a syslog daemon on localhost, which will +# most likely not work. # -# Default: True +# Default: False # -# syslog = False +# syslog = True -# If syslog = False, which file should we use for a log? Can be either -# a relative or absolute path. It will not be auto-rotated; use -# something log logrotate for that. +# If you specify a file path here, logs will be written to it +# (possibly in addition to syslog). Can be either a relative or +# absolute path. It will not be auto-rotated; use something like +# logrotate for that. # -# Default: htsn.log +# Default: empty # # log_file = /var/log/htsn/htsn.log diff --git a/src/CommandLine.hs b/src/CommandLine.hs index ad4f867..c96fb6b 100644 --- a/src/CommandLine.hs +++ b/src/CommandLine.hs @@ -22,7 +22,6 @@ import Paths_htsn (version) import Data.Version (showVersion) import OptionalConfiguration ( OptionalConfiguration(..) ) -import TSN.FeedHosts ( FeedHosts(..) ) -- | The description of the program, displayed as part of the help. description :: String @@ -40,7 +39,7 @@ my_summary = program_name ++ "-" ++ (showVersion version) -- | A description of the "log_file" option. log_file_help :: String log_file_help = - "If syslog == False, log to the given file." + "Log to the given file." log_level_help :: String log_level_help = @@ -59,7 +58,7 @@ output_directory_help = -- | A description of the "syslog" option. syslog_help :: String syslog_help = - "Enable (default) or disable logging to syslog." + "Enable logging to syslog." -- | A description of the "username" option. username_help :: String @@ -75,7 +74,7 @@ arg_spec = -- Use an empty list for feed_hosts since cmdargs will appends to -- the default when the user supplies feed hosts. If he specifies -- any, those are all we should use. - feed_hosts = FeedHosts [] &= typ "HOSTNAMES" &= args, + feed_hosts = def &= typ "HOSTNAMES" &= args, log_file = def &= typFile &= help log_file_help, log_level = def &= typ "LEVEL" &= help log_level_help, password = def &= typ "PASSWORD" &= help password_help, diff --git a/src/Configuration.hs b/src/Configuration.hs index a9d5463..a90af38 100644 --- a/src/Configuration.hs +++ b/src/Configuration.hs @@ -10,13 +10,15 @@ where import System.Console.CmdArgs.Default ( Default(..) ) import System.Log ( Priority( INFO ) ) -import qualified OptionalConfiguration as OC (OptionalConfiguration(..)) +import qualified OptionalConfiguration as OC ( + OptionalConfiguration(..), + merge_maybes ) import TSN.FeedHosts (FeedHosts(..)) data Configuration = Configuration { feed_hosts :: FeedHosts, - log_file :: FilePath, + log_file :: Maybe FilePath, log_level :: Priority, password :: String, output_directory :: FilePath, @@ -27,7 +29,7 @@ data Configuration = -- | A Configuration with all of its fields set to their default -- values. instance Default Configuration where - def = Configuration def "htsn.log" INFO def "." True def + def = Configuration def def INFO def "." def def -- | Merge a Configuration with an OptionalConfiguration. This is more @@ -39,13 +41,15 @@ merge_optional :: Configuration merge_optional cfg opt_cfg = Configuration all_feed_hosts - (merge (log_file cfg) (OC.log_file opt_cfg)) + (OC.merge_maybes (log_file cfg) (OC.log_file opt_cfg)) (merge (log_level cfg) (OC.log_level opt_cfg)) (merge (password cfg) (OC.password opt_cfg)) (merge (output_directory cfg) (OC.output_directory opt_cfg)) (merge (syslog cfg) (OC.syslog opt_cfg)) (merge (username cfg) (OC.username opt_cfg)) where + -- | If the thing on the right is Just something, return that + -- something, otherwise return the thing on the left. merge :: a -> Maybe a -> a merge x Nothing = x merge _ (Just y) = y diff --git a/src/Logging.hs b/src/Logging.hs index fb1bfc6..8e80ac9 100644 --- a/src/Logging.hs +++ b/src/Logging.hs @@ -6,14 +6,16 @@ module Logging ( log_warning ) where +import Control.Monad ( when ) import System.Log.Formatter ( simpleLogFormatter ) import System.Log.Handler ( setFormatter ) -import System.Log.Handler.Simple ( fileHandler ) +import System.Log.Handler.Simple ( GenericHandler, fileHandler ) import System.Log.Handler.Syslog ( Facility ( USER ), openlog ) import System.Log.Logger ( - Priority ( DEBUG, INFO ), + Priority ( INFO ), + addHandler, debugM, errorM, infoM, @@ -39,19 +41,31 @@ log_warning = warningM rootLoggerName -- | Why don't we take a Configuration as an argument? Because it -- would create circular imports! -init_logging :: FilePath -> Priority -> Bool -> IO () -init_logging log_file log_level syslog - | syslog == True = do - handler' <- openlog rootLoggerName [] USER level - -- Syslog should output the date by itself. - let slf = simpleLogFormatter "htsn[$pid] $prio: $msg" - let handler = setFormatter handler' slf - updateGlobalLogger rootLoggerName (setLevel level . setHandlers [handler]) - | otherwise = do - handler' <- fileHandler log_file level - let slf = simpleLogFormatter "$time: htsn[$pid] $prio: $msg" - let handler = setFormatter handler' slf - updateGlobalLogger rootLoggerName (setLevel level . setHandlers [handler]) - where - min_level = if syslog then INFO else DEBUG - level = if log_level < min_level then min_level else log_level +init_logging :: Maybe FilePath -> Priority -> Bool -> IO () +init_logging log_file log_level syslog = do + -- First set the global log level and clear the default handler. + let no_handlers = [] :: [GenericHandler a] + updateGlobalLogger rootLoggerName (setLevel log_level . + setHandlers no_handlers) + + when syslog $ do + let min_level = INFO + let sl_level = if log_level < min_level then min_level else log_level + + -- The syslog handle gets its own level which will cowardly refuse + -- to log all debug info (i.e. the entire feed) to syslog. + sl_handler' <- openlog rootLoggerName [] USER sl_level + + -- Syslog should output the date by itself. + let sl_formatter = simpleLogFormatter "htsn[$pid] $prio: $msg" + let sl_handler = setFormatter sl_handler' sl_formatter + + updateGlobalLogger rootLoggerName (addHandler sl_handler) + + case log_file of + Nothing -> return () + Just lf -> do + lf_handler' <- fileHandler lf log_level + let lf_formatter = simpleLogFormatter "$time: htsn[$pid] $prio: $msg" + let lf_handler = setFormatter lf_handler' lf_formatter + updateGlobalLogger rootLoggerName (addHandler lf_handler) diff --git a/src/OptionalConfiguration.hs b/src/OptionalConfiguration.hs index d133432..0913864 100644 --- a/src/OptionalConfiguration.hs +++ b/src/OptionalConfiguration.hs @@ -12,7 +12,8 @@ module OptionalConfiguration ( OptionalConfiguration(..), - from_rc ) + from_rc, + merge_maybes ) where import qualified Data.Configurator as DC ( @@ -31,6 +32,7 @@ import System.Directory ( getHomeDirectory ) import System.FilePath ( () ) import System.IO.Error ( catchIOError ) import System.Log ( Priority(..) ) + import Logging ( log_error ) import TSN.FeedHosts ( FeedHosts(..) ) @@ -58,15 +60,22 @@ data OptionalConfiguration = deriving (Show, Data, Typeable) +-- | Combine two Maybes into one, essentially mashing them +-- together. We give precedence to the second argument when both are +-- Justs. +merge_maybes :: (Maybe a) -> (Maybe a) -> (Maybe a) +merge_maybes Nothing Nothing = Nothing +merge_maybes (Just x) Nothing = Just x +merge_maybes Nothing (Just x) = Just x +merge_maybes (Just _) (Just y) = Just y + + -- | The Monoid instance for these lets us "combine" two -- OptionalConfigurations. The "combine" operation that we'd like to -- perform is, essentially, to mash them together. So if we have two -- OptionalConfigurations, each half full, we could combine them -- into one big one. -- --- One of the two must take precedence during this mashing, and we --- choose the second one for no reason. --- -- This is used to merge command-line and config-file settings. -- instance Monoid OptionalConfiguration where @@ -85,19 +94,13 @@ instance Monoid OptionalConfiguration where cfg1 `mappend` cfg2 = OptionalConfiguration all_feed_hosts - (merge (log_file cfg1) (log_file cfg2)) - (merge (log_level cfg1) (log_level cfg2)) - (merge (password cfg1) (password cfg2)) - (merge (output_directory cfg1) (output_directory cfg2)) - (merge (syslog cfg1) (syslog cfg2)) - (merge (username cfg1) (username cfg2)) + (merge_maybes (log_file cfg1) (log_file cfg2)) + (merge_maybes (log_level cfg1) (log_level cfg2)) + (merge_maybes (password cfg1) (password cfg2)) + (merge_maybes (output_directory cfg1) (output_directory cfg2)) + (merge_maybes (syslog cfg1) (syslog cfg2)) + (merge_maybes (username cfg1) (username cfg2)) where - merge :: (Maybe a) -> (Maybe a) -> (Maybe a) - merge Nothing Nothing = Nothing - merge (Just x) Nothing = Just x - merge Nothing (Just x) = Just x - merge (Just _) (Just y) = Just y - -- Use only the latter feed_hosts if there are any. all_feed_hosts = feed_hosts $ if (null (get_feed_hosts (feed_hosts cfg2))) -- 2.43.2