create pedestal telmere logger

This commit is contained in:
Travis Shears 2025-08-12 11:38:33 +02:00
parent 46c6de9491
commit a480f98cca
5 changed files with 222 additions and 8 deletions

View file

@ -1,8 +1,10 @@
(ns micro-blog.api
(:require [io.pedestal.connector :as conn]
[io.pedestal.http.http-kit :as hk]))
[io.pedestal.http.http-kit :as hk]
[io.pedestal.log :as log]))
(defn greet-handler [_request]
(defn greet-handler [request]
;; (log/info :in 'greet-handler :method (:request-method request) :uri (:uri request))
{:status 200
:body "Hello, world!\n"})
@ -16,4 +18,5 @@
(hk/create-connector nil)))
(defn start []
;; (log/info :in 'start :msg "Starting Pedestal server with Telmere logging")
(conn/start! (create-connector)))

View file

@ -0,0 +1,154 @@
(ns micro-blog.example-usage
(:require [io.pedestal.log :as log]
[io.pedestal.connector :as conn]
[io.pedestal.http.http-kit :as hk]
[taoensso.telemere :as tel]
[micro-blog.pedestal-telmere :as pt]
[micro-blog.logging :as logging]))
;; Example handlers that demonstrate Pedestal logging with Telmere
(defn health-check-handler [request]
(log/info :in 'health-check-handler
:request-id (get-in request [:headers "x-request-id"])
:user-agent (get-in request [:headers "user-agent"]))
{:status 200
:headers {"Content-Type" "application/json"}
:body "{\"status\": \"healthy\", \"timestamp\": \"2024-01-01T12:00:00Z\"}"})
(defn error-handler [request]
(try
(throw (ex-info "Simulated error for demonstration"
{:error-type :simulation
:request-path (:uri request)}))
(catch Exception e
(log/error :in 'error-handler
:exception e
:request-method (:request-method request)
:uri (:uri request))
{:status 500
:headers {"Content-Type" "application/json"}
:body "{\"error\": \"Internal server error\"}"))))
(defn user-handler [request]
(let [user-id (get-in request [:path-params :user-id])]
(log/debug :in 'user-handler :user-id user-id :action "fetching user")
(if (= user-id "123")
(do
(log/info :in 'user-handler :user-id user-id :result "found")
{:status 200
:headers {"Content-Type" "application/json"}
:body (str "{\"user_id\": \"" user-id "\", \"name\": \"John Doe\"}")})
(do
(log/warn :in 'user-handler :user-id user-id :result "not-found")
{:status 404
:headers {"Content-Type" "application/json"}
:body "{\"error\": \"User not found\"}"})))))
;; Interceptor that adds request logging
(def request-logger-interceptor
{:name ::request-logger
:enter (fn [context]
(let [request (:request context)
start-time (System/currentTimeMillis)]
(log/debug :in 'request-logger-interceptor
:event :request-start
:method (:request-method request)
:uri (:uri request)
:start-time start-time)
(assoc context ::start-time start-time)))
:leave (fn [context]
(let [request (:request context)
response (:response context)
start-time (::start-time context)
duration (- (System/currentTimeMillis) start-time)]
(log/info :in 'request-logger-interceptor
:event :request-complete
:method (:request-method request)
:uri (:uri request)
:status (:status response)
:duration-ms duration)
context))})
;; Routes with logging examples
(def routes
#{["/health" :get health-check-handler :route-name :health-check]
["/error" :get error-handler :route-name :error-demo]
["/users/:user-id" :get user-handler :route-name :get-user]})
(defn create-example-connector []
(-> (conn/default-connector-map 8891)
(conn/with-default-interceptors)
(conn/with-interceptors [request-logger-interceptor])
(conn/with-routes routes)
(hk/create-connector nil)))
(defn start-example-server []
;; Setup Telmere logging first
(logging/setup-logging)
(log/info :in 'start-example-server
:msg "Starting example server with Pedestal + Telmere logging"
:port 8891)
;; Start the server
(conn/start! (create-example-connector)))
(defn demo-logging []
"Demonstrates various logging scenarios"
;; Setup logging first
(logging/setup-logging)
;; Direct Telmere logging
(tel/log! {:level :info :data {:source "telmere-direct"}}
"This is direct Telmere logging")
;; Pedestal logging (which goes through Telmere)
(log/trace :source "pedestal" :level "trace" :msg "Trace level message")
(log/debug :source "pedestal" :level "debug" :msg "Debug level message")
(log/info :source "pedestal" :level "info" :msg "Info level message")
(log/warn :source "pedestal" :level "warn" :msg "Warning level message")
(log/error :source "pedestal" :level "error" :msg "Error level message")
;; Logging with structured data
(log/info :in 'demo-function
:operation "data-processing"
:records-processed 150
:processing-time-ms 250
:success true)
;; Logging with exception
(try
(/ 1 0)
(catch Exception e
(log/error :in 'demo-function
:operation "division"
:exception e
:msg "Division by zero error")))
;; Using MDC context
(log/with-context {:user-id "user-123" :session-id "sess-456"}
(log/info :in 'demo-function :msg "Processing user request")
(log/debug :in 'demo-function :msg "Validating user permissions"))
(println "Demo logging complete - check your console output!"))
(comment
;; To test the integration:
;; 1. Start the example server
(start-example-server)
;; 2. Make some requests:
;; curl http://localhost:8891/health
;; curl http://localhost:8891/users/123
;; curl http://localhost:8891/users/999
;; curl http://localhost:8891/error
;; 3. Run logging demo
(demo-logging)
;; 4. Test just the logging setup
(logging/test-logging)
)

View file

@ -3,7 +3,8 @@
(:require
[taoensso.telemere :as tel]
[cheshire.core :as json]
[cheshire.generate :as gen]))
[cheshire.generate :as gen]
[micro-blog.pedestal-telmere :as pt]))
(def json-logging-handler
(tel/handler:console
@ -24,8 +25,13 @@
(defn setup-logging []
(tel/remove-handler! :default/console)
(tel/add-handler! ::json-logger json-logging-handler))
(tel/add-handler! ::json-logger json-logging-handler)
;; Also setup Pedestal integration
(pt/setup-pedestal-telmere-logging!))
(defn test-logging []
(setup-logging)
(tel/log! {:level :info :data {:thing "example"}} "This is a test log message"))
;; (defn test-logging []
;; (setup-logging)
;; (tel/log! {:level :info :data {:thing "example"}} "This is a test log message")
;; ;; Test Pedestal logging integration
;; (require '[io.pedestal.log :as log])
;; ((resolve 'log/info) :test true :message "Pedestal logging via Telmere works!"))

View file

@ -3,7 +3,8 @@
(:import [java.time Instant Duration])
(:require [chime.core :as chime]
[taoensso.telemere :as tel]
[micro-blog.logging]
micro-blog.logging
micro-blog.api
[micro-blog.blue-sky :as blue-sky]
[micro-blog.mastodon :as masto]))
@ -12,6 +13,8 @@
(defn -main []
(micro-blog.logging/setup-logging)
(tel/log! :info "Setting up API")
(micro-blog.api/start)
(tel/log! :info "Setting up crons")
(doseq [[i cron] (map-indexed vector crons)]
(let [start (.plus (Instant/now) (Duration/ofMinutes (* i 5)))]

View file

@ -0,0 +1,48 @@
(ns micro-blog.pedestal-telmere
(:require [io.pedestal.log :as pedestal-log]
[taoensso.telemere :as tel]))
(defrecord TelmereLogger [logger-name]
pedestal-log/LoggerSource
(-trace [this body]
(tel/log! {:level :trace :id logger-name} body))
(-trace [this body throwable]
(tel/log! {:level :trace :id logger-name :error throwable} body))
(-debug [this body]
(tel/log! {:level :debug :id logger-name} body))
(-debug [this body throwable]
(tel/log! {:level :debug :id logger-name :error throwable} body))
(-info [this body]
(tel/log! {:level :info :id logger-name} body))
(-info [this body throwable]
(tel/log! {:level :info :id logger-name :error throwable} body))
(-warn [this body]
(tel/log! {:level :warn :id logger-name} body))
(-warn [this body throwable]
(tel/log! {:level :warn :id logger-name :error throwable} body))
(-error [this body]
(tel/log! {:level :error :id logger-name} body))
(-error [this body throwable]
(tel/log! {:level :error :id logger-name :error throwable} body))
(-level-enabled? [this level-key]
;; Telmere doesn't have a direct level check, so we'll assume all levels are enabled
;; You can customize this based on your Telmere configuration
(contains? #{:trace :debug :info :warn :error} level-key)))
(defn make-telmere-logger
"Creates a TelmereLogger instance for the given logger name"
[logger-name]
(->TelmereLogger logger-name))
(defn setup-pedestal-telmere-logging!
"Sets up Telmere as the logger source for Pedestal.
Call this before starting your Pedestal service."
[]
;; Override the default logger creation function
(alter-var-root #'pedestal-log/make-logger
(constantly make-telmere-logger)))