
Hi all, Hot on the heels of the decision to remove logging from WAI, I would like to add it to Yesod. I think (at least to start with), we really need two modifications: a new method in the Yesod typeclass that specifies what to do with log messages, and a function living in the Handler monad that calls that method. I do not have any strong opinions on this topic, so I would appreciate input. Here's a strawman proposal: data LogLevel = LevelInfo | LevelWarn | LevelError | LevelOther Text class Yesod a where messageLogger :: a -> LogLevel -> Text -> IO () messageLogger _ level msg = formatLogMessage level msg >>= Data.Text.Lazy.IO.hPutStrLn System.IO.stderr formatLogMessage :: LogLevel -> Text -> IO Text formatLogMessage = ... -- print timestamp, log level, message, maybe process ID? to stderr -- make sure to expose the logInfo :: MonadIO m => Text -> GGHandler sub master m () logInfo t = do y < getYesod liftIO $ messageLogger y LevelInfo t ... and so on and so forth This should give completely flexibility to users to send their logs anywhere (database, printer, missiles) and in whatever format they want. Other ideas: * It would be nice to include file/line number information, but I'm not sure how easy/possible that will be without requiring the user to manually enter CPP macros. * Actually, that was my only other idea :) Michael

Hello, I would add a log level "Debug" which only gets printed to the log when in development mode. I also found the log output of SQL queries generated by the database layer quite helpful in development. Another thing is performance measurements, the time it takes to answer an request. These ideas are all coming from the way RoR does logging, but I found it very helpful when developing with Rails, so it should be a nice feature in Yesod, too. Here is an example: Instrument Load (0.4ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 86) ORDER BY LOWER(instruments.name) Rendered overview/_notification (2.1ms) CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 86) ORDER BY LOWER(instruments.name) Rendered overview/_notification (1.5ms) CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 90) ORDER BY LOWER(instruments.name) Rendered overview/_notification (1.4ms) CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 62) ORDER BY LOWER(instruments.name) Rendered overview/_notification (1.5ms) DepotGroup Load (27.2ms) SELECT * FROM "depot_groups" ORDER BY ordinal Completed in 3530ms (View: 166, DB: 2051) | 200 OK [http://localhost/] Sven On 04/01/2011 08:20 AM, Michael Snoyman wrote:
Hi all,
Hot on the heels of the decision to remove logging from WAI, I would like to add it to Yesod. I think (at least to start with), we really need two modifications: a new method in the Yesod typeclass that specifies what to do with log messages, and a function living in the Handler monad that calls that method. I do not have any strong opinions on this topic, so I would appreciate input. Here's a strawman proposal:
data LogLevel = LevelInfo | LevelWarn | LevelError | LevelOther Text
class Yesod a where messageLogger :: a -> LogLevel -> Text -> IO () messageLogger _ level msg = formatLogMessage level msg>>= Data.Text.Lazy.IO.hPutStrLn System.IO.stderr
formatLogMessage :: LogLevel -> Text -> IO Text formatLogMessage = ... -- print timestamp, log level, message, maybe process ID? to stderr -- make sure to expose the
logInfo :: MonadIO m => Text -> GGHandler sub master m () logInfo t = do y< getYesod liftIO $ messageLogger y LevelInfo t
... and so on and so forth
This should give completely flexibility to users to send their logs anywhere (database, printer, missiles) and in whatever format they want.
Other ideas:
* It would be nice to include file/line number information, but I'm not sure how easy/possible that will be without requiring the user to manually enter CPP macros. * Actually, that was my only other idea :)
Michael
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel

Take a look at hslogger. I know that another dependency is low on the "things we want" list, but its pretty decent. max On Apr 1, 2011, at 3:18 PM, Sven Koschnicke (GFXpro) wrote:
Hello,
I would add a log level "Debug" which only gets printed to the log when in development mode. I also found the log output of SQL queries generated by the database layer quite helpful in development. Another thing is performance measurements, the time it takes to answer an request. These ideas are all coming from the way RoR does logging, but I found it very helpful when developing with Rails, so it should be a nice feature in Yesod, too. Here is an example:
Instrument Load (0.4ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 86) ORDER BY LOWER(instruments.name) Rendered overview/_notification (2.1ms) CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 86) ORDER BY LOWER(instruments.name) Rendered overview/_notification (1.5ms) CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 90) ORDER BY LOWER(instruments.name) Rendered overview/_notification (1.4ms) CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 62) ORDER BY LOWER(instruments.name) Rendered overview/_notification (1.5ms) DepotGroup Load (27.2ms) SELECT * FROM "depot_groups" ORDER BY ordinal Completed in 3530ms (View: 166, DB: 2051) | 200 OK [http://localhost/]
Sven
On 04/01/2011 08:20 AM, Michael Snoyman wrote:
Hi all,
Hot on the heels of the decision to remove logging from WAI, I would like to add it to Yesod. I think (at least to start with), we really need two modifications: a new method in the Yesod typeclass that specifies what to do with log messages, and a function living in the Handler monad that calls that method. I do not have any strong opinions on this topic, so I would appreciate input. Here's a strawman proposal:
data LogLevel = LevelInfo | LevelWarn | LevelError | LevelOther Text
class Yesod a where messageLogger :: a -> LogLevel -> Text -> IO () messageLogger _ level msg = formatLogMessage level msg>>= Data.Text.Lazy.IO.hPutStrLn System.IO.stderr
formatLogMessage :: LogLevel -> Text -> IO Text formatLogMessage = ... -- print timestamp, log level, message, maybe process ID? to stderr -- make sure to expose the
logInfo :: MonadIO m => Text -> GGHandler sub master m () logInfo t = do y< getYesod liftIO $ messageLogger y LevelInfo t
... and so on and so forth
This should give completely flexibility to users to send their logs anywhere (database, printer, missiles) and in whatever format they want.
Other ideas:
* It would be nice to include file/line number information, but I'm not sure how easy/possible that will be without requiring the user to manually enter CPP macros. * Actually, that was my only other idea :)
Michael
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel

I like Michael's straw man. The only missing aspect I see is specifying a source. hslogger has this capability. This is useful for a web framework to differentiate between database logging and request logging, etc. It can be useful for an application when it grows in size. Does logging need to be in the typeclass or does it make send to just import it? On Sat, Apr 2, 2011 at 3:22 AM, Max Cantorwrote: > Take a look at hslogger. I know that another dependency is low on the > "things we want" list, but its pretty decent. > > max > > On Apr 1, 2011, at 3:18 PM, Sven Koschnicke (GFXpro) wrote: > > > Hello, > > > > I would add a log level "Debug" which only gets printed to the log when > in development mode. I also found the log output of SQL queries generated by > the database layer quite helpful in development. Another thing is > performance measurements, the time it takes to answer an request. These > ideas are all coming from the way RoR does logging, but I found it very > helpful when developing with Rails, so it should be a nice feature in Yesod, > too. Here is an example: > > > > Instrument Load (0.4ms) SELECT * FROM "instruments" WHERE > ("instruments"."id" = 86) ORDER BY LOWER(instruments.name) > > Rendered overview/_notification (2.1ms) > > CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = > 86) ORDER BY LOWER(instruments.name) > > Rendered overview/_notification (1.5ms) > > CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = > 90) ORDER BY LOWER(instruments.name) > > Rendered overview/_notification (1.4ms) > > CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = > 62) ORDER BY LOWER(instruments.name) > > Rendered overview/_notification (1.5ms) > > DepotGroup Load (27.2ms) SELECT * FROM "depot_groups" ORDER BY ordinal > > Completed in 3530ms (View: 166, DB: 2051) | 200 OK [http://localhost/] > > > > > > Sven > > > > On 04/01/2011 08:20 AM, Michael Snoyman wrote: > >> Hi all, > >> > >> Hot on the heels of the decision to remove logging from WAI, I would > >> like to add it to Yesod. I think (at least to start with), we really > >> need two modifications: a new method in the Yesod typeclass that > >> specifies what to do with log messages, and a function living in the > >> Handler monad that calls that method. I do not have any strong > >> opinions on this topic, so I would appreciate input. Here's a strawman > >> proposal: > >> > >> data LogLevel = LevelInfo | LevelWarn | LevelError | LevelOther Text > >> > >> class Yesod a where > >> messageLogger :: a -> LogLevel -> Text -> IO () > >> messageLogger _ level msg = formatLogMessage level msg>>= > >> Data.Text.Lazy.IO.hPutStrLn System.IO.stderr > >> > >> formatLogMessage :: LogLevel -> Text -> IO Text > >> formatLogMessage = ... > >> -- print timestamp, log level, message, maybe process ID? to stderr > >> -- make sure to expose the > >> > >> logInfo :: MonadIO m => Text -> GGHandler sub master m () > >> logInfo t = do > >> y< getYesod > >> liftIO $ messageLogger y LevelInfo t > >> > >> ... and so on and so forth > >> > >> This should give completely flexibility to users to send their logs > >> anywhere (database, printer, missiles) and in whatever format they > >> want. > >> > >> Other ideas: > >> > >> * It would be nice to include file/line number information, but I'm > >> not sure how easy/possible that will be without requiring the user to > >> manually enter CPP macros. > >> * Actually, that was my only other idea :) > >> > >> Michael > >> > >> _______________________________________________ > >> web-devel mailing list > >> web-devel@haskell.org > >> http://www.haskell.org/mailman/listinfo/web-devel > > > > > > _______________________________________________ > > web-devel mailing list > > web-devel@haskell.org > > http://www.haskell.org/mailman/listinfo/web-devel > > > _______________________________________________ > web-devel mailing list > web-devel@haskell.org > http://www.haskell.org/mailman/listinfo/web-devel >

@Sven: I agree, database level logging is a *very* nice idea. Timing
could also be very useful. The former will require modifications to
persistent; let's try to think about how that would work (I don't have
any clear ideas immediately). For timing: we could add a nice
combinator on top of the main logging functions:
logTimed :: MonadIO m => (normal params) -> m a -> m a
logTimed (normal params) action = do
begin <- getCurrentTime
a <- action
end <- getCurrentTime
log (normal params) ++ "; operation took: " ++ show (end - begin)
return a
@Max: I'm not planning on adding a specific backend like hslogger. I'd
rather make a system that is flexible enough to allow a user to plug
in whatever backend he/she wants. Plus, hslogger in LGPL, which I'm
trying to avoid in yesod-core.
@Greg: I like the idea of adding source. How would you see this, just
another Text argument? As for typeclass/not typeclass: the advantage
to the former is that all subsites will get to piggy-back on what the
master site defines. So I *definitely* think it's worthwhile.
Michael
On Sat, Apr 2, 2011 at 5:48 PM, Greg Weber
I like Michael's straw man. The only missing aspect I see is specifying a source. hslogger has this capability. This is useful for a web framework to differentiate between database logging and request logging, etc. It can be useful for an application when it grows in size. Does logging need to be in the typeclass or does it make send to just import it? On Sat, Apr 2, 2011 at 3:22 AM, Max Cantor
wrote: Take a look at hslogger. I know that another dependency is low on the "things we want" list, but its pretty decent.
max
On Apr 1, 2011, at 3:18 PM, Sven Koschnicke (GFXpro) wrote:
Hello,
I would add a log level "Debug" which only gets printed to the log when in development mode. I also found the log output of SQL queries generated by the database layer quite helpful in development. Another thing is performance measurements, the time it takes to answer an request. These ideas are all coming from the way RoR does logging, but I found it very helpful when developing with Rails, so it should be a nice feature in Yesod, too. Here is an example:
Instrument Load (0.4ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 86) ORDER BY LOWER(instruments.name) Rendered overview/_notification (2.1ms) CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 86) ORDER BY LOWER(instruments.name) Rendered overview/_notification (1.5ms) CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 90) ORDER BY LOWER(instruments.name) Rendered overview/_notification (1.4ms) CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 62) ORDER BY LOWER(instruments.name) Rendered overview/_notification (1.5ms) DepotGroup Load (27.2ms) SELECT * FROM "depot_groups" ORDER BY ordinal Completed in 3530ms (View: 166, DB: 2051) | 200 OK [http://localhost/]
Sven
On 04/01/2011 08:20 AM, Michael Snoyman wrote:
Hi all,
Hot on the heels of the decision to remove logging from WAI, I would like to add it to Yesod. I think (at least to start with), we really need two modifications: a new method in the Yesod typeclass that specifies what to do with log messages, and a function living in the Handler monad that calls that method. I do not have any strong opinions on this topic, so I would appreciate input. Here's a strawman proposal:
data LogLevel = LevelInfo | LevelWarn | LevelError | LevelOther Text
class Yesod a where messageLogger :: a -> LogLevel -> Text -> IO () messageLogger _ level msg = formatLogMessage level msg>>= Data.Text.Lazy.IO.hPutStrLn System.IO.stderr
formatLogMessage :: LogLevel -> Text -> IO Text formatLogMessage = ... -- print timestamp, log level, message, maybe process ID? to stderr -- make sure to expose the
logInfo :: MonadIO m => Text -> GGHandler sub master m () logInfo t = do y< getYesod liftIO $ messageLogger y LevelInfo t
... and so on and so forth
This should give completely flexibility to users to send their logs anywhere (database, printer, missiles) and in whatever format they want.
Other ideas:
* It would be nice to include file/line number information, but I'm not sure how easy/possible that will be without requiring the user to manually enter CPP macros. * Actually, that was my only other idea :)
Michael
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel

On Sat, Apr 2, 2011 at 11:10 AM, Michael Snoyman
@Sven: I agree, database level logging is a *very* nice idea. Timing could also be very useful. The former will require modifications to persistent; let's try to think about how that would work (I don't have any clear ideas immediately). For timing: we could add a nice combinator on top of the main logging functions:
logTimed :: MonadIO m => (normal params) -> m a -> m a logTimed (normal params) action = do begin <- getCurrentTime a <- action end <- getCurrentTime log (normal params) ++ "; operation took: " ++ show (end - begin) return a
@Max: I'm not planning on adding a specific backend like hslogger. I'd rather make a system that is flexible enough to allow a user to plug in whatever backend he/she wants. Plus, hslogger in LGPL, which I'm trying to avoid in yesod-core.
@Greg: I like the idea of adding source. How would you see this, just another Text argument? As for typeclass/not typeclass: the advantage to the former is that all subsites will get to piggy-back on what the master site defines. So I *definitely* think it's worthwhile.
in hslogger the source is just another string. That makes it easily extensible, but the lack of type safety worries me a bit. Maybe we just need to trust everyone to use a single canonical (Text) string for their sources. I imagine that for any source one would create a helper function that applies the source Text argument. Likewise, the default logging function for Yesod users wouldn't have a source argument. Michael
On Sat, Apr 2, 2011 at 5:48 PM, Greg Weber
wrote: I like Michael's straw man. The only missing aspect I see is specifying a source. hslogger has this capability. This is useful for a web framework to differentiate between database logging and request logging, etc. It can be useful for an application when it grows in size. Does logging need to be in the typeclass or does it make send to just import it? On Sat, Apr 2, 2011 at 3:22 AM, Max Cantor
wrote: Take a look at hslogger. I know that another dependency is low on the "things we want" list, but its pretty decent.
max
On Apr 1, 2011, at 3:18 PM, Sven Koschnicke (GFXpro) wrote:
Hello,
I would add a log level "Debug" which only gets printed to the log
when
in development mode. I also found the log output of SQL queries generated by the database layer quite helpful in development. Another thing is performance measurements, the time it takes to answer an request. These ideas are all coming from the way RoR does logging, but I found it very helpful when developing with Rails, so it should be a nice feature in Yesod, too. Here is an example:
Instrument Load (0.4ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 86) ORDER BY LOWER(instruments.name) Rendered overview/_notification (2.1ms) CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 86) ORDER BY LOWER(instruments.name) Rendered overview/_notification (1.5ms) CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 90) ORDER BY LOWER(instruments.name) Rendered overview/_notification (1.4ms) CACHE (0.0ms) SELECT * FROM "instruments" WHERE ("instruments"."id" = 62) ORDER BY LOWER(instruments.name) Rendered overview/_notification (1.5ms) DepotGroup Load (27.2ms) SELECT * FROM "depot_groups" ORDER BY ordinal Completed in 3530ms (View: 166, DB: 2051) | 200 OK [http://localhost/ ]
Sven
On 04/01/2011 08:20 AM, Michael Snoyman wrote:
Hi all,
Hot on the heels of the decision to remove logging from WAI, I would like to add it to Yesod. I think (at least to start with), we really need two modifications: a new method in the Yesod typeclass that specifies what to do with log messages, and a function living in the Handler monad that calls that method. I do not have any strong opinions on this topic, so I would appreciate input. Here's a strawman proposal:
data LogLevel = LevelInfo | LevelWarn | LevelError | LevelOther Text
class Yesod a where messageLogger :: a -> LogLevel -> Text -> IO () messageLogger _ level msg = formatLogMessage level msg>>= Data.Text.Lazy.IO.hPutStrLn System.IO.stderr
formatLogMessage :: LogLevel -> Text -> IO Text formatLogMessage = ... -- print timestamp, log level, message, maybe process ID? to stderr -- make sure to expose the
logInfo :: MonadIO m => Text -> GGHandler sub master m () logInfo t = do y< getYesod liftIO $ messageLogger y LevelInfo t
... and so on and so forth
This should give completely flexibility to users to send their logs anywhere (database, printer, missiles) and in whatever format they want.
Other ideas:
* It would be nice to include file/line number information, but I'm not sure how easy/possible that will be without requiring the user to manually enter CPP macros. * Actually, that was my only other idea :)
Michael
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel
_______________________________________________ web-devel mailing list web-devel@haskell.org http://www.haskell.org/mailman/listinfo/web-devel
participants (4)
-
Greg Weber
-
Max Cantor
-
Michael Snoyman
-
Sven Koschnicke (GFXpro)