Code Monkey home page Code Monkey logo

co-log-core's Introduction

co-log

GitHub CI MPL-2.0 license

co-log is a composable and configurable logging framework. It combines all the benefits of Haskell idioms to provide a reasonable and convenient interface. Although the library design uses some advanced concepts in its core, we are striving to provide beginner-friendly API. The library also provides the complete documentation with a lot of beginner-friendly examples, explanations and tutorials to guide users. The combination of a pragmatic approach to logging and fundamental Haskell abstractions allows us to create a highly composable and configurable logging framework.


If you're interested in how different Haskell typeclasses are used to implement core functions of co-log, you can read the following blog post which goes into detail about the internal implementation specifics:

Co-Log Family

Co-Log is a family of repositories for a composable and configurable logging framework co-log.

Here is the list of currently available repositories and libraries that you can check out:

co-log-core lightweight package with basic data types and general idea which depends only on base Hackage
co-log taggless final implementation of logging library based on co-log-core Hackage
co-log-polysemy implementation of logging library based on co-log-core and the polysemy extensible effects library. Hackage
co-log-benchmarks benchmarks of the co-log library -

co-log library

Logging library based on co-log-core package. Provides ready-to-go implementation of logging. This README contains How to tutorial on using this library. This tutorial explains step by step how to integrate co-log into small basic project, specifically how to replace putStrLn used for logging with library provided logging.

All code below can be compiled and run with the following commands:

$ cabal build
$ cabal exec readme

Preamble: imports and language extensions

Since this is a literate haskell file, we need to specify all our language extensions and imports up front.

{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE OverloadedStrings #-}

import Control.Monad.IO.Class (MonadIO, liftIO)

import Colog (Message, WithLog, cmap, fmtMessage, logDebug, logInfo, logTextStdout, logWarning,
              usingLoggerT)

import qualified Data.Text as Text
import qualified Data.Text.IO as TextIO

Simple IO function example

Consider the following function that reads lines from stdin and outputs different feedback depending on the line size.

processLinesBasic :: IO ()
processLinesBasic = do
    line <- TextIO.getLine
    case Text.length line of
        0 -> do
            -- here goes logging
            TextIO.putStrLn ">>>> Empty input"
            processLinesBasic
        n -> do
            TextIO.putStrLn ">>>> Correct input"
            TextIO.putStrLn $ "Line length: " <> Text.pack (show n)

This code mixes application logic with logging of the steps. It's convenient to have logging to observe behavior of the application. But putStrLn is very simple and primitive way to log things.

Using co-log library

In order to use co-log library, we need to refactor processLinesBasic function in the following way:

processLinesLog :: (WithLog env Message m, MonadIO m) => m ()
processLinesLog = do
    line <- liftIO TextIO.getLine
    case Text.length line of
        0 -> do
            -- here goes logging
            logWarning "Empty input"
            processLinesLog
        n -> do
            logDebug "Correct line"
            logInfo $ "Line length: " <> Text.pack (show n)

Let's summarize required changes:

  1. Make type more polymorphic: (WithLog env Message m, MonadIO m) => m ()
  2. Add liftIO to all IO functions.
  3. Replace putStrLn with proper log* function.

Running actions

Let's run both functions:

main :: IO ()
main = do
    processLinesBasic

    let action = cmap fmtMessage logTextStdout
    usingLoggerT action processLinesLog

And here is how output looks like:

screenshot from 2018-09-17 20-52-01

More Tutorials

To provide a more user-friendly introduction to the library, we've created the tutorial series which introduces the main concepts behind co-log smoothly, please check more details here.

co-log-core's People

Contributors

alaendle avatar alexfmpe avatar brandonhamilton avatar c37h40o9 avatar chshersh avatar cmdv avatar cronokirby avatar dependabot[bot] avatar gahag avatar gromakovsky avatar gutjuri avatar jiribenes avatar lucazulian avatar michaelpj avatar piq9117 avatar pranaysashank avatar qnikst avatar sanchayanmaity avatar sorki avatar sphaso avatar tfausak avatar udaycruise2903 avatar vekhir avatar vrom911 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

co-log-core's Issues

[RFC] Laws property-based tests for `LogAction`

It would be really nice to have tests for the logging functionality, especially property-based testing. However, it's not really clear how to test it. It would be really nice though to have property-based tests for laws for every data type. However, in order to do this, we need to implement the following two pieces:

  • Question 1: Some way to generate arbitrary LogAction
  • Question 2: Some way to compare LogAction

Question 1 is still open. For Question 2: instead of comparing LogActions we can compare results of PureLogger.

We have doctest for unit testing, so this should be enough in terms of unit tests (though, more functions always can be covered with doctest). But having property-based tests for laws would be really good.

Any thoughts are appreciated!

Severity "Success"

I wonder if a constructor Success would be useful for the Severity data type to distinguish critical operations that completed successfully in the log stream. Of course all of this can go into Info, but I feel an extra layer would help.

Green might be a fitting colour, if you're willing to consider this addition.

`WithSeverity`

I find myself wanting this type:

data WithSeverity a = WithSeverity a Severity

i.e. a message tagged with a severity. Then I can do something like this

data Log1 = ...
data Log2 = ALog1 Log1 | ...

adapt :: LogAction m (WithSeverity Log2) -> LogAction m (WithSeverity Log1)
adapt = cmap (fmap ALog1)

Given that co-log-core provides Severity, perhaps it would be nice to provide WithSeverity also?

[RFC] Surface of co-log-core

Our main goal in co-log-core is to create a minimal package with only base in dependencies and enabling more people to use co-log capabilities in a more flexible way.

As proposed by @dcoutts, it might be helpful for other people to:

maximise the ability to use the pattern in different applications by minimising the assumptions

and by moving some parts of co-log-core into co-log.

So let's start a discussion about possible changes in the co-log-core interface.

Minor documentation improvements

  • Fix Haddock with CPP for TypeErrors instance
  • Better docs for cmapMaybe
  • Fix hoistLogAction example of type performPureLogsInIO
  • Better top-level docs for Colog.Core.Action module
  • Typo in cfilterM docs

Severity Trace

It's not uncommon for logging systems to have a level below Debug, often called Trace. I do find this useful: often there's a distinction between "debugging information that's not useful during normal operation" (Debug) and "just vomit out everything" (Trace).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.