Code Monkey home page Code Monkey logo

telemere's Introduction

Taoensso open source
API | Wiki | Latest releases | Slack channel

Telemere logo

Structured telemetry library for Clojure/Script

Telemere is a next-generation replacement for Timbre. It handles structured and traditional logging, tracing, and basic performance monitoring with a simple unified API.

It helps enable Clojure/Script systems that are observable, robust, and debuggable - and it represents the refinement and culmination of ideas brewing over 12+ years in Timbre, Tufte, Truss, etc.

[Terminology] Telemetry derives from the Greek tele (remote) and metron (measure). It refers to the collection of in situ (in position) data, for transmission to other systems for monitoring/analysis. Logs are the most common form of software telemetry. So think of telemetry as the superset of logging-like activities that help monitor and understand (software) systems.

Latest release/s

Main tests Graal tests

See here for earlier releases.

Why Telemere?

Ergonomics

  • Elegant, lightweight API that's easy to use, easy to configure, and deeply flexible.
  • Sensible defaults to make getting started fast and easy.
  • Extensive beginner-oriented documentation, docstrings, and error messages.

Interop

Scaling

  • Hyper-optimized and blazing fast, see benchmarks.
  • An API that scales comfortably from the smallest disposable code, to the most massive and complex real-world production environments.

Flexibility

  • Config via plain Clojure vals and fns for easy customization, composition, and REPL debugging.
  • Unmatched environmental config support (JVM properties, environment variables, or classpath resources).
  • Expressive per-call and per-handler filtering at both runtime and compile-time.
  • Filter by namespace and id pattern, level, level by namespace pattern, etc.
  • Sampling, rate-limiting, and back-pressure monitoring.
  • Fully configurable a/sync dispatch (blocking, dropping, sliding, etc.).

Video demo

See for intro and usage:

Telemere demo video

Quick examples

(require '[taoensso.telemere :as t])

(t/log! {:id ::my-id, :data {:x1 :x2}} "My message") %>

;; 2024-04-11T10:54:57.202869Z INFO LOG Schrebermann.local examples(56,1) ::my-id - My message
;;    data: {:x1 :x2}

(t/log! "This will send a `:log` signal to the Clj/s console")
(t/log! :info "This will do the same, but only when the current level is >= `:info`")

;; Easily construct messages
(let [x "constructed"] (t/log! :info ["Here's a" x "message!"]))

;; Attach an id
(t/log! {:level :info, :id ::my-id} "This signal has an id")

;; Attach arb user data
(t/log! {:level :info, :data {:x :y}} "This signal has structured data")

;; Capture for debug/testing
(t/with-signal (t/log! "This will be captured"))
;; => {:keys [location level id data msg_ ...]}

;; `:let` bindings available to `:data` and message, only paid for
;; when allowed by minimum level and other filtering criteria
(t/log!
  {:level :info
   :let [expensive-metric1 (last (for [x (range 100), y (range 100)] (* x y)))]
   :data {:metric1 expensive-metric1}}
  ["Message with metric value:" expensive-metric1])

;; With sampling 50% and 1/sec rate limiting
(t/log!
  {:sample-rate 0.5
   :rate-limit  {"1 per sec" [1 1000]}}
  "This signal will be sampled and rate limited")

;;; A quick taste of filtering...

(t/set-ns-filter! {:deny "taoensso.*" :allow "taoensso.sente.*"}) ; Set namespace filter
(t/set-id-filter! {:allow #{::my-particular-id "my-app/*"}})      ; Set id        filter

(t/set-min-level!       :warn) ; Set minimum level
(t/set-min-level! :log :debug) ; Set minimul level for `:log` signals

;; Set minimum level for `:event` signals originating in the "taoensso.sente.*" ns
(t/set-min-level! :event "taoensso.sente.*" :warn)

See examples.cljc for more REPL-ready snippets.

API overview

See relevant docstrings (links below) for usage info-

Signal creators

Name Signal kind Main arg Optional arg Returns
log! :log msg opts/level Signal allowed?
event! :event id opts/level Signal allowed?
error! :error error opts/id Given error
trace! :trace form opts/id Form result
spy! :spy form opts/level Form result
catch->error! :error form opts/id Form value or given fallback
signal! <arb> opts - Depends on opts

Signal filters

Global Dynamic Filters by
set-kind-filter! with-kind-filter Signal kind (:log, :event, etc.)
set-ns-filter! with-ns-filter Signal namespace
set-id-filter! with-id-filter Signal id
set-min-level with-min-level Signal level (minimum can be specified by kind and/or ns)

Internal help

Var Help with
help:signal-creators List of signal creators
help:signal-options Options for signal creators
help:signal-content Signal map content
help:signal-flow Ordered flow from signal creation to handling
help:signal-filters API for configuring signal filters
help:signal-handlers API for configuring signal handlers

Included handlers

See linked docstrings below for features and usage:

Name Platform Output target Output format
handler:console Clj *out* or *err* edn/JSON or human-readable
handler:console Cljs Browser console edn/JSON or human-readable
handler:console-raw Cljs Browser console Raw signals for cljs-devtools, etc.
handler:file Clj File/s on disk edn/JSON or human-readable
handler:open-telemetry-logger Clj OpenTelemetry Java client LogRecord
handler:postal Clj Email (via postal) edn/JSON or human-readable
handler:slack Clj Slack (via clj-slack) edn/JSON or human-readable
handler:tcp-socket Clj TCP socket edn/JSON or human-readable
handler:udp-socket Clj UDP socket edn/JSON or human-readable

See here for more/upcoming handlers, community handlers, info on writing your own handlers, etc.

Documentation

Benchmarks

Telemere is highly optimized and offers terrific performance at any scale:

Compile-time filtering? Runtime filtering? Time? Trace? nsecs
✓ (elide) - - - 0
- - - 200
- - 280
- 650

Measurements:

  • Are ~nanoseconds per signal call (= milliseconds per 1e6 calls)
  • Exclude handler runtime (which depends on handler/s, is usually async)
  • Taken on a 2020 Macbook Pro M1, running OpenJDK 21

Tip: Telemere offers extensive per-call and per-handler filtering, sampling, and rate-limiting. Use these to ensure that you're not capturing useless/low-value information in production. See here for more tips!

Funding

You can help support continued work on this project, thank you!! 🙏

License

Copyright © 2023-2024 Peter Taoussanis.
Licensed under EPL 1.0 (same as Clojure).

telemere's People

Contributors

ptaoussanis avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

Forkers

madis

telemere's Issues

Root stacktrace is missing

Dear @ptaoussanis,

Thank you so much for this great library. I would like to report the bug of stacktrace not being reported in the console as of 1.0.0-beta-7.

Here is a minimal reproduction:

(tm/log! {:level :info
               :error (ex-info "Some error message" {})}
               "Internal Server Error")

Output

; 2024-05-04T10:18:20.947134Z INFO LOG Macbook.local backend.core (130,1) - Internal Server Error
;
; <<< error <<<
;   Root: clojure.lang.ExceptionInfo - Some error message
;
; Root stack trace:
;
; >>> error >>>

Telemere v1.0.0-beta1

  • Core / fundamentals
  • SLF4J integration
  • Timbre migration tools
  • Initial handlers
  • Docstrings, help
  • Wiki docs
  • Demo video

Make configuring filtering via system vals easier

The current system is very flexible, but also intimidating - especially for beginners.

  • Document this better, including templates/examples
  • Maybe add a util to help serialize current config to env/prop/res?

Add key differences between telemere and mulog to doc section

Hello. First of all thx for the great tool.

I haven't had the opportunity to look into it in detail yet, but it all looks very interesting. Also, I couldn’t help but notice some parallels with mulog and I’m interested what key differences between telemere and mulog from your point of view. One of the things I was able to notice is clojure support, but i will be glad to read about another points.

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.