Skip to content

Commit

Permalink
Merge pull request #1 from kirisaki/develop
Browse files Browse the repository at this point in the history
release 0.0.1.0
  • Loading branch information
kirisaki authored Apr 13, 2019
2 parents f530d85 + 9bfc580 commit c9a79d5
Show file tree
Hide file tree
Showing 6 changed files with 342 additions and 31 deletions.
99 changes: 99 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
version: 2

aliases:
- &cache_paths
paths:
- ~/.cabal/packagess
- ~/.cabal/store
- ~/.ghc/

jobs:
test-8.6.3:
docker:
- image: haskell:8.6.3
steps:
- checkout
- setup_remote_docker
- restore_cache:
name: Restore cache
keys:
- ghc-8.6.3-{{ checksum "caster.cabal" }}
- run:
name: Install dependencies
command: cabal new-update
- run:
name: Install dependencies
command: cabal new-install
- run:
name: Install tasty-discover
command: cabal new-install tasty-discover
- run:
name: Run tests
command: cabal new-test
- save_cache:
name: Save packagess
key: ghc-8.6.3-{{ checksum "caster.cabal" }}
<<: *cache_paths
test-8.4.4:
docker:
- image: haskell:8.4.4
steps:
- checkout
- setup_remote_docker
- restore_cache:
name: Restore cache
keys:
- ghc-8.4.4-{{ checksum "caster.cabal" }}
- run:
name: Install dependencies
command: cabal new-update
- run:
name: Install dependencies
command: cabal new-install
- run:
name: Install tasty-discover
command: cabal new-install tasty-discover
- run:
name: Run tests
command: cabal new-test
- save_cache:
name: Save packagess
key: ghc-8.4.4-{{ checksum "caster.cabal" }}
<<: *cache_paths
test-8.2.2:
docker:
- image: haskell:8.2.2
steps:
- checkout
- setup_remote_docker
- restore_cache:
name: Restore cache
keys:
- ghc-8.2.2-{{ checksum "caster.cabal" }}
- run:
name: Install dependencies
command: cabal new-update
- run:
name: Install dependencies
command: cabal new-install
- run:
name: Install tasty-discover
command: cabal new-install tasty-discover
- run:
name: Run tests
command: cabal new-test
- save_cache:
name: Save packagess
key: ghc-8.2.2-{{ checksum "caster.cabal" }}
<<: *cache_paths



workflows:
version: 2
test-check:
jobs:
- test-8.6.3
- test-8.4.4
- test-8.2.2

8 changes: 5 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Revision history for caster
# Change Log

## 0.0.1 -- YYYY-mm-dd
## [0.0.1 -- 2019-04-13]

* First version. Released on an unsuspecting world.
### Added

- Basic functions.
114 changes: 113 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,114 @@
# caster
Thread-safe, multicast, and not slow logger.
caster is a multicast, thread-safe and fast logger.
It's convenient when log towards multiple outputs,
for example, when you want to log to stdout and files same time.
It's possible to change format and log level each outputs.
Also, it converts text-like values and Show instances into log messages automatically.

## Usage

First, the logger requires concurrency.

```haskell
import Control.Concurrent
```

Then, prepare to use the logger.
In following code, make `LogQueue`, `LogChan` and `Listener`,
start threads which relay messages from `LogChan` to the outputs
and one which broadcasts messages to `LogChan`.
Be careful not to change the order of `relayLog` and `broadcastLog`.
It causes that messages at the first are not logged correctly.

```haskell
import System.IO
import System.Log.Caster

main = do
chan <- newLogChan
lq <- newLogQueue

-- log to a file..
handle <- openFile "./foo.log" "caster_test_0.log"
let FileListener = handleListener defaultFormatter handle
_ <- forkIO $ relayLog chan LogDebug fileListener

-- log to stdout.
_ <- forkIO $ relayLog chan LogInfo stdoutListener

-- start to broadcast.
_ <- forkIO $ broadcastLog lq chan

-- give the LogQueue to the function which you want to log in.
someFunc lq

```

Last, push a message into the `LogQueue` with given functions in order to log.

``` haskell

someFunc :: LogQueue -> IO ()
someFunc lq = do

-- log levels are matched to syslog.
-- if you use OverloadedStrings, need to add type annotation.
debug lq ("debug message" :: String)

-- or you can use helper operator or helper function.
info lq $: "info messages"
info lq $ fix "info messages"

-- if the type is obviously, need not to annotate.
let msg = Data.Text.pack "notice message"
notice lq msg

-- it's possible to give incetanse of Show.
warn lq True

-- there is the useful operator which concatrates text-like values.
-- the values are converted into byte string as utf-8.
let text = "foo" :: Data.Text.Text
let bs = "bar" :: Data.ByteString.Lazy.ByteString
err lq $ text <:> bs <:> fix "baz"

```

The logger requires to be given `LogQueue`,
so functions which log need to take `LogQueue` as a parameter.
You can inject `LogQueue` with Reader Monad and so on,
but I recommend to use easily [Data\.Reflection](https://hackage.haskell.org/package/reflection).


```haskell
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}

import Control.Concurrent
import Control.Monad
import Data.Reflection
import System.Log.Caster

type UseLogger = Given LogQueue

useLogger :: UseLogger => LogQueue
useLogger = given

someIO :: UseLogger => IO ()
someIO = do
critical useLogger "critical message"
alert useLogger "alert message"
emergency useLogger "..."

inject :: (UseLogger => a) -> IO a
inject io = do
lq <- newLogQueue
give io lq

main :: IO ()
main = do
chan <- newLogChan
_ <- forkIO $ relayLog chan LogDebug stdoutListener
join $ inject someIO

```
50 changes: 30 additions & 20 deletions caster.cabal
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: caster
version: 0.0.1
synopsis: Multicast, thread-safe, and not slow logger.
version: 0.0.1.0
synopsis: Multicast, thread-safe, and fast logger.
description: Please see the README on GitHub at <https://github.com/kirisaki/caster#readme>
homepage: https://github.com/kirisaki/caster#readme
bug-reports: https://github.com/kirisaki/caster/issues
Expand All @@ -14,16 +14,19 @@ build-type: Simple
extra-source-files: CHANGELOG.md, README.md
cabal-version: >=1.10

source-repository head
type: git
location: https://github.com/kirisaki/caster

library
exposed-modules: System.Log.Caster
-- other-modules:
-- other-extensions:
build-depends: base >=4.11 && <4.12
, bytestring
, fast-builder
, stm
, text
, unix-time
build-depends: base >= 4.10
, bytestring >= 0.10.8.2
, fast-builder >= 0.1.0.0
, stm >= 2.5.0.0
, text >= 1.2.3.1
, unix-time >= 0.4.5
hs-source-dirs: src
default-language: Haskell2010
default-extensions: LambdaCase
Expand All @@ -35,16 +38,23 @@ library
, ExistentialQuantification

test-suite test
default-language:
Haskell2010
type:
exitcode-stdio-1.0
type: exitcode-stdio-1.0
main-is: Driver.hs
other-modules:
CasterTest
default-language: Haskell2010
hs-source-dirs:
test
main-is:
Driver.hs
test
build-depends:
base >= 4 && < 5
, tasty
, tasty-discover
, caster
base >= 4 && < 5
, caster
, bytestring
, directory
, text
, fast-builder
, QuickCheck
, quickcheck-instances
, tasty-hunit
, tasty
, tasty-discover
, tasty-quickcheck
12 changes: 7 additions & 5 deletions src/System/Log/Caster.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ Stability : experimental
{-# LANGUAGE UndecidableInstances #-}
module System.Log.Caster
( -- * Basics
LogMsg
LogMsg(..)
, broadcastLog
, LogQueue
, LogQueue(..)
, newLogQueue
, LogChan
, LogChan(..)
, newLogChan
, Formatter
, Listener
Expand All @@ -41,6 +41,7 @@ module System.Log.Caster
, ToBuilder(..)
, fix
, ($:)
, (<:>)
) where


Expand All @@ -51,6 +52,7 @@ import qualified Data.ByteString as SBS
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.FastBuilder as FB
import qualified Data.ByteString.Lazy as LBS
import Data.Semigroup
import qualified Data.Text as ST
import qualified Data.Text.Encoding as STE
import qualified Data.Text.Lazy as LT
Expand Down Expand Up @@ -104,7 +106,7 @@ infixr 6 <:>
(<:>) :: (ToBuilder a, ToBuilder b) => a -> b -> FB.Builder
a <:> b = toBuilder a <> toBuilder b

-- | Logging level. This is matched to syslog.
-- |Log levels. These are matched to syslog.
data LogLevel
= LogDebug
| LogInfo
Expand Down Expand Up @@ -193,7 +195,7 @@ logLevelToBuilder = \case
formatTime :: UnixTime -> FB.Builder
formatTime ut =
let
ut' = FB.byteString . unsafePerformIO $ formatUnixTime "%Y-%m-$d %T" ut
ut' = FB.byteString . unsafePerformIO $ formatUnixTime "%Y-%m-d %T" ut
utMilli = FB.string7 . tail . show $ utMicroSeconds ut `div` 1000 + 1000
in
ut' <> "." <> utMilli
Expand Down
Loading

0 comments on commit c9a79d5

Please sign in to comment.