• Stars
    star
    119
  • Rank 297,930 (Top 6 %)
  • Language
    Clojure
  • License
    Mozilla Public Li...
  • Created over 5 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A ClojureScript logging library based on goog.log

Glögi

CircleCI cljdoc badge Clojars Project

A wrapper around goog.log inspired by pedestal.log.

For more info see the accompanying blog post: ClojureScript logging with goog.log, and Logging in Practice with Glögi and Pedestal.

Installation

WARNING: There are two packages with different artefact IDs published on clojars. One is com.lambdaisland/glogi and another is lambdaisland/glogi (without the com.). Please migrate your dependency to com.lambdaisland/glogi as this is the only one which recieves new updates. We apologise for this confusion, but we had to make some changes to stay in accordance with the clojars policy.

deps.edn

com.lambdaisland/glogi {:mvn/version "1.3.169"}

project.clj

[com.lambdaisland/glogi "1.3.169"]

Quickstart

It is recommended to initialize Glögi at the top of your main namespace, so that no log messages are lost.

(ns my.app
  (:require [lambdaisland.glogi :as log]
            [lambdaisland.glogi.console :as glogi-console]))

(glogi-console/install!)

(log/set-levels
  {:glogi/root   :info    ;; Set a root logger level, this will be inherited by all loggers
   'my.app.thing :trace   ;; Some namespaces you might want detailed logging
   'my.app.other :error   ;; or for others you only want to see errors.
   })

(log/info :hello {:message "Hello, world!"})

Result in your browser console (but pretty with colors):

[my.app] {:hello {:message "Hello, world!"}}

Before you can start logging you need to install a handler that knows where to output the log messages (browser console, in a div, ...). (glogi-console/install!) is recommended. It contains some smarts so that your Clojure data is logged nicely. When cljs-devtools is active then it will pass data structures unchanged to js/console.log so devtools can render them. If not then it will stringify and colorize them so you get pretty EDN in your console, instead of seeing the implementation details of ClojureScript persistent data structures.

Log functions take key/value pairs.

Loggers and log levels

In goog.log, which glogi is based on, loggers have hierarchical names, with segments separated by dots. If you use Glogi's logging macros then it will automatically get the logger based on the namespace name.

When you call a logging function it will check the log level of the logger to decide if the message should be output ot not. To find this level the logger will go up the hierarchy until it finds a logger with an explicit level set. This is usually the root logger, but it doesn't have to be.

So say you have these namespaces:

my.app.ui.subs
my.app.ui.events
my.app.api
my.app.api.routes
some.lib.config
some.lib.print

You can set the level for individual namespaces

(log/set-levels '{my.app.ui.subs :debug
                  my.app.ui.events :config
                  ...})

But you can also set the level for a subtree of namespaces. So say you're debugging the API, which uses some.lib.

(log/set-levels '{my.app.api :all
                  some.lib :debug
                  ...})

This is really convenient and powerful. By sprinkling your code with logging at various levels you can easily get insight in what a particular part is doing, on demand.

Instead of adding more and more print statements as you debug, and then deleting them afterwards, you can add increasingly detailed levels of logging instead. Later when you find yourself in the same waters you can dial the verbosity up or down as you see fit.

Glogi is based on goog.log, and so it understand the log levels that goog.log provides. Glogi also aims to be at least partially API compatible with pedestal.log, and so we provide extra log levels that internally map to goog.log levels.

pedestal goog.log value description
:off Infinity Special value to disable logging
:shout 1200 Critical error
:error :severe 1000 Serious failure
:warn :warning 900 Potential problem, but program continues
:info :info 800 Informational message, e.g. to make background tasks visible
:config 700 Configuration info
:debug :fine 500 Step-by-step debug messages
:trace :finer 400 More verbose, detailed tracing messages
:finest 300 Highly verbose and detailed tracing
:all 0 Special value to show all log messages

There are also two special levels, :all and :off, which you can use in set-levels to turn logging up to the maximum, or turn it off instead.

It is recommended to use a consistent set of logging methods, for instance to use only the pedestal version, possibly augmented by the goog.log levels that don't have a pedestal equivalent.

for instance:

(log/shout ,,,)
(log/severe ,,,)
(log/error ,,,)
(log/warn ,,,)
(log/info ,,,)
(log/config ,,,)
(log/debug ,,,)
(log/trace ,,,)
(log/finest ,,,)

If you are using lambdaisland.glogi.console, then these levels will also influence with js/console method is used, as well as the color used to print the namespace name.

Spy

There is a convenience macro spy which you can use to have a quick look at a value. It outputs the form, the value, and returns the value so you can simply wrap any expression you want to see the value. Spy expressions are logged at the :debug level.

(let [x (spy (+ 1 1))
      y (spy (+ x x))]
  (+ x y))
;;=> 6
[my.ns] {:spy (+ 1 1) :=> 2}
[my.ns] {:spy (+ x x) :=> 4}

As you may have noticed, unlike js/console.log or prn, spy returns the value of the expression so you can wrap expressions with it without disrupting the flow of your program.

If you pass multiple values to spy, all will be printed:

(fn [{:keys [host port path protocol] :as config}]
  (spy host port)
  ;;...
  )
[my.ns] {:spy [host "localhost" port 8080]}

This will be logged slighly diferently on Clojure. This is because Pedestal doesn't directly support multiple values to spy, and Glogc tries to be a thin wrapper:

[my.ns] {:spy [host port] :value ["localhost" 8080]}

If you call spy on multiple values, the last value will be returned, analogous to do.

Special keys

Two keywords have a special meaning in logging calls.

  • :exception use this if you want to log an exception, this will make sure you get a proper stacktrace in the browser console
  • :lambdaisland.glogi/logger name of the logger to use, defaults to (str *ns*)

Controlling colorization

When using lambdaisland.glogi.console/install! it will try to detect what the best logging strategy is for your environment.

  • if cljs-devtools is detected then it will log ClojureScript objects directly
  • if it detects a browser that is not pre-chromium IE/Edge, then it will use console.log "%c" CSS-based colorization
  • all other cases it logs plain text

This behaviour can be changed by setting lambdaisland.glogi.console.colorize in :closure-defines in your compiler options.

  • "auto" the autodetect behavior described above (default)
  • "raw" always log ClojureScript objects directly
  • "true" format using CSS
  • "false" format as plain text

Logging in production

Production builds typically have goog.DEBUG set to false. This strips out some development checks, it also strips out logging. If you still want to see logs on production then add this to your ClojureScript compiler options:

:closure-defines {goog.DEBUG false
                  goog.debug.LOGGING_ENABLED true}

Use with Pedestal

The lambdaisland.glogc namespace provides a cross-platform (cljc) API, which uses Glogi on ClojureScript, and io.pedestal.log on Clojure. This way it's easy to do logging from cljc code, or just to have a consistent logging setup without having to wonder what kind of file you are in.

Note that the pedestal.log dependency is "BYO" (bring your own), you need to add it explicitly to your dependencies.

(ns my.ns
  (:require [lambdaisland.glogc :as log))

(log/debug :foo :bar)

goog.log has more distinct log levels than Pedestal. We provide macros for all of them, on Clojure they simply map to the nearest equivalent.

  • finest -> trace
  • finer -> trace
  • fine -> debug
  • config -> info

Supported by Nextjournal

Many thanks to Nextjournal for coming up with an interesting problem, and giving me the opportunity to explore and solve it.

Lambda Island Open Source

 

glogi is part of a growing collection of quality Clojure libraries created and maintained by the fine folks at Gaiwan.

Pay it forward by becoming a backer on our Open Collective, so that we may continue to enjoy a thriving Clojure ecosystem.

You can find an overview of our projects at lambdaisland/open-source.

 

 

Contributing

Everyone has a right to submit patches to glogi, and thus become a contributor.

Contributors MUST

  • adhere to the LambdaIsland Clojure Style Guide
  • write patches that solve a problem. Start by stating the problem, then supply a minimal solution. *
  • agree to license their contributions as MPL 2.0.
  • not break the contract with downstream consumers. **
  • not break the tests.

Contributors SHOULD

  • update the CHANGELOG and README.
  • add tests for new functionality.

If you submit a pull request that adheres to these rules, then it will almost certainly be merged immediately. However some things may require more consideration. If you add new dependencies, or significantly increase the API surface, then we need to decide if these changes are in line with the project's goals. In this case you can start by writing a pitch, and collecting feedback on it.

* This goes for features too, a feature needs to solve a problem. State the problem it solves, then supply a minimal solution.

** As long as this project has not seen a public release (i.e. is not on Clojars) we may still consider making breaking changes, if there is consensus that the changes are justified.

License

Copyright © 2019-2021 Arne Brasseur and Contributors

Licensed under the term of the Mozilla Public License 2.0, see LICENSE.

More Repositories

1

kaocha

Full featured next gen Clojure test runner
Clojure
792
star
2

regal

Royally reified regular expressions
Clojure
326
star
3

deep-diff2

Deep diff Clojure data structures and pretty print the result
Clojure
295
star
4

uri

A pure Clojure/ClojureScript URI library
Clojure
243
star
5

trikl

Terminal UI library for Clojure
Clojure
145
star
6

witchcraft

Clojure API for manipulating Minecraft, based on Bukkit
Clojure
135
star
7

fetch

ClojureScript wrapper for the JavaScript fetch API
Clojure
122
star
8

ornament

Clojure Styled Components
Clojure
118
star
9

uniontypes

Union Types (ADTs, sum types) built on clojure.spec
Clojure
115
star
10

launchpad

Clojure/nREPL launcher
Clojure
87
star
11

classpath

Classpath/classloader/deps.edn related utilities
Clojure
84
star
12

corgi

Emacs Lisp
75
star
13

metabase-datomic

Datomic driver for Metabase
Clojure
65
star
14

chui

Clojure
62
star
15

npmdemo

Demo of using Node+Express with ClojureScript
Clojure
60
star
16

funnel

Transit-over-WebSocket Message Relay
Clojure
58
star
17

deja-fu

ClojureScript local time/date library with a delightful API
Clojure
48
star
18

facai

Factories for fun and profit. 恭喜發財!
Clojure
45
star
19

open-source

A collection of Clojure/ClojureScript tools and libraries
Clojure
43
star
20

witchcraft-workshop

materials and code for the ClojureD 2022 workshop on Minecraft+Clojure
Clojure
40
star
21

kaocha-cljs

ClojureScript support for Kaocha
Clojure
40
star
22

cljbox2d

Clojure
40
star
23

thirdpartyjs

Demonstration of how to use third party JS in ClojureScript
Clojure
38
star
24

kaocha-cucumber

Cucumber support for Kaocha
Clojure
37
star
25

dom-types

Implement ClojureScript print handlers, as well Datify/Navigable for various built-in browser types.
Clojure
36
star
26

kaocha-cloverage

Code coverage analysis for Kaocha
Clojure
32
star
27

ansi

Parse ANSI color escape sequences to Hiccup syntax
Clojure
31
star
28

embedkit

Metabase as a Dashboard Engine
Clojure
30
star
29

plenish

Clojure
30
star
30

pennon

A feature flag library for Clojure
Clojure
30
star
31

hiccup

Enlive-backed Hiccup implementation (clj-only)
Clojure
28
star
32

edn-lines

Library for dealing with newline separated EDN files
Shell
27
star
33

kaocha-cljs2

Run ClojureScript tests from Kaocha (major rewrite)
Clojure
26
star
34

witchcraft-plugin

Add Clojure support (and an nREPL) to any Bukkit-based Minecraft server
Clojure
23
star
35

cli

Opinionated command line argument handling, with excellent support for subcommands
Clojure
22
star
36

garden-watcher

A component that watches-and-recompiles your Garden stylesheets.
Clojure
22
star
37

reitit-jaatya

Freeze your reitit routes and create a static site out of it
Clojure
21
star
38

nrepl-proxy

Proxy for debugging nREPL interactions
Clojure
18
star
39

data-printers

Quickly define print handlers for tagged literals across print/pprint implementations.
Clojure
18
star
40

lambdaisland-guides

In depth guides into Clojure and ClojureScript by Lambda Island
TeX
17
star
41

specmonstah-malli

Clojure
17
star
42

faker

Port of the Ruby Faker gem
Clojure
15
star
43

puck

ClojureScript wrapper around Pixi.js, plus other game dev utils
Clojure
15
star
44

kaocha-junit-xml

JUnit XML output for Kaocha
Clojure
11
star
45

aoc_2020

Advent of Code 2020
Clojure
11
star
46

harvest

Flexible factory library, successor to Facai
Clojure
11
star
47

gaiwan_co

Website for Gaiwan GmbH
Clojure
8
star
48

nrepl

Main namespace for starting an nREPL server with `clj`
Clojure
8
star
49

zipper-viz

Visualize Clojure zippers using Graphviz
Clojure
8
star
50

exoscale

Clojure/Babashka wrapper for the Exoscale HTTP API
Clojure
7
star
51

webstuff

The web as it was meant to be
Clojure
7
star
52

birch

A ClojureScript/Lumo version of the Unix "tree" command
Clojure
7
star
53

funnel-client

Websocket client for Funnel + examples
Clojure
7
star
54

corgi-packages

Emacs Packages developed as part of Corgi
Emacs Lisp
7
star
55

kanban

Episode 9. Reagent
Clojure
6
star
56

react-calculator

A calculator built with ClojureScript and React
JavaScript
6
star
57

souk

Clojure
6
star
58

logback-clojure-filter

Logback appender filter that takes a Clojure expression
Clojure
6
star
59

breakout

The retro game "Breakout". re-frame/Reagent/React/SVG.
Clojure
5
star
60

activities

Clojure
5
star
61

booklog

Keep track of the books you read (Auth with Buddy)
Clojure
5
star
62

li40-ultimate

Code from episode 40: The Ultimate Dev Setup
Shell
5
star
63

l33t

Demo ClojureScript+Node.js app
JavaScript
5
star
64

ep47-interceptors

Accompanying code to Lambda Island episode 47. Interceptors.
Clojure
5
star
65

daedalus

"Path finding and Delaunay triangulation in 2D, cljs wrapper for hxdaedalus-js"
Clojure
5
star
66

component_example

Example code for the Lambda Island episodes about Component
Clojure
4
star
67

ep43-data-science-kixi-stats

Clojure
4
star
68

lambwiki

A small wiki app to demonstrate Luminus
Clojure
4
star
69

new-project

Template for new projects
Emacs Lisp
3
star
70

kaocha-boot

Kaocha support for Boot
Clojure
3
star
71

datomic-quick-start

Datomic Quickstart sample code
Clojure
3
star
72

redolist

TodoMVC in re-frame
Clojure
3
star
73

rolodex-gui

Reagent app for testing the Rolodex API
Clojure
2
star
74

ep33testcljs

Testing ClojureScript with multiple backends
Clojure
2
star
75

elpa

Lambda Island Emacs Lisp Package Archive
Emacs Lisp
2
star
76

datalog-benchmarks

Clojure
2
star
77

kaocha-doctest

Doctest test type for Kaocha
Clojure
1
star
78

morf

Clojure
1
star
79

land-of-regal

Playground for Regal
Clojure
1
star
80

compobook

An example Compojure app
Clojure
1
star
81

ep41-react-components-reagent

Demo code from Episode 41, using React Components from Reagent
Clojure
1
star
82

repl-tools

Clojure
1
star
83

li45_polymorphism

Code for Lambda Island episode 45 and 46 about Polymorphism
Clojure
1
star
84

dotenv

Clojure
1
star
85

kaocha-midje

Midje integration for Kaocha
Clojure
1
star
86

rolodex

Clojure
1
star
87

laoban

Clojure
1
star
88

cookie-cutter

Auto-generate Clojure test namespaces in bulk.
Clojure
1
star
89

shellutils

Globbing and other shell/file utils
Clojure
1
star
90

kaocha-cljs2-demo

Example setups for kaocha-cljs2. WIP
Clojure
1
star
91

kaocha-demo

Clojure
1
star
92

kaocha-nauseam

Example project with a large (artificial) test suite
Clojure
1
star
93

li39-integrant

Accompanying code for Lambda Island episode 38 about Integrant
Clojure
1
star
94

webbing

Clojure
1
star
95

slack-backfill

Save Slack history to JSON files
Clojure
1
star
96

janus

Parser for Changelog files
Clojure
1
star
97

xdemo

Demo of xforms/redux/kixi.stats
Clojure
1
star
98

ep23deftype

Code for Lambda Island Episode 23, deftype and definterface
Clojure
1
star
99

ep24defrecord

Code for Lambda Island Episode 24, defrecord and defprotocol
Clojure
1
star
100

ep32testing

Code for Lambda Island Episode 32, Introduction to Clojure Testing
Clojure
1
star