From f3ce2b5c3f4c1daa0462f611c87097c56fe2d6e0 Mon Sep 17 00:00:00 2001 From: Dennis Schridde Date: Mon, 19 Jun 2023 13:57:08 +0200 Subject: [PATCH] [new] [#374] Add OpenTelemetry Protocol (OTLP) community appender (@devurandom) Once is implemented, the actual log emission should be replaced with clj-otel's API. --- project.clj | 3 +- .../timbre/appenders/community/otlp.clj | 102 ++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/taoensso/timbre/appenders/community/otlp.clj diff --git a/project.clj b/project.clj index c12de2b..8d73696 100644 --- a/project.clj +++ b/project.clj @@ -50,7 +50,8 @@ [congomongo "2.6.0"] [server-socket "1.0.0"] [org.zeromq/cljzmq "0.1.4"] - [cljs-node-io "1.1.2"] ; Node spit appender + [cljs-node-io "1.1.2"] ; `node-spit` appender + [com.github.steffan-westcott/clj-otel-api "0.2.6"] ; `otlp` appender ]} :dev [:dev+ :community #_:deploy] diff --git a/src/taoensso/timbre/appenders/community/otlp.clj b/src/taoensso/timbre/appenders/community/otlp.clj new file mode 100644 index 0000000..0ed0362 --- /dev/null +++ b/src/taoensso/timbre/appenders/community/otlp.clj @@ -0,0 +1,102 @@ +(ns taoensso.timbre.appenders.community.otlp + "OpenTelemetry Protocol (OTLP) appender. + Requires ." + {:author "Dennis Schridde (@devurandom)"} + (:require + [taoensso.encore :as enc] + [steffan-westcott.clj-otel.api.attributes :as attr]) + + (:import [io.opentelemetry.api.logs LoggerProvider Severity])) + +(comment (set! *warn-on-reflection* true)) + +(def ^:private default-severity Severity/INFO) +(def ^:private timbre->otlp-levels + {:trace Severity/TRACE + :debug Severity/DEBUG + :info Severity/INFO + :warn Severity/WARN + :error Severity/ERROR + :fatal Severity/FATAL + :report default-severity}) + +(defn- single-map [xs] + (let [[x & r] xs] + (when (and (map? x) (not r)) + x))) + +(defn- assoc-some-nx + ([m k v ] (if (contains? m k) m (enc/assoc-some m k v))) + ([m k v & kvs] (enc/reduce-kvs assoc-some-nx (enc/assoc-some m k v) kvs)) + ([m kvs] + (reduce-kv + (fn [m k v] (if (contains? m k) m (enc/assoc-some m k v))) + (if (nil? m) {} m) + kvs))) + +(defn appender + "Returns a `com.github.steffan-westcott/clj-otel-api` appender. + + For use WITH OpenTelemetry Java Agent- + + Setup a Java Agent appender, e.g.: + (otlp/appender {:logger-provider (.getLogsBridge (GlobalOpenTelemetry/get))}) + + For agent v1.x: enable the logs exporter with `OTEL_LOGS_EXPORTER=otlp`. + For agent v2.x: the logs exporter should be enabled by default [1]. + + For use WITHOUT OpenTelemetry Java Agent- + + Setup an \"autoconfiguration\" appender, e.g.: + (otlp/appender + {:logger-provider + (.getSdkLoggerProvider + (.getOpenTelemetrySdk + (.build (AutoConfiguredOpenTelemetrySdk/builder))))}) + + You'll need the following on your classpath: + `io.opentelemetry/opentelemetry-sdk-extension-autoconfigure`, + `io.opentelemetry/opentelemetry-exporter-otlp`. + + If you already have an instance of `GlobalOpenTelemetry` (e.g. created + by agent), you'll need to prevent setting the newly-created SDK as the + global default: + (.build + (doto (AutoConfiguredOpenTelemetrySdk/builder) + (.setResultAsGlobal false))) + + [1] Ref. " + [{:keys [^LoggerProvider logger-provider]}] + {:enabled? true + :async? true + :min-level nil + :rate-limit nil + :output-fn :inherit + :fn + (fn [{:keys [^java.util.Date instant level ^String ?ns-str + ?file ?line ?err vargs msg_ context]}] + + (let [logger (.get logger-provider ?ns-str) + timestamp (.toInstant instant) + severity (get timbre->otlp-levels level default-severity) + arg (single-map vargs) + message (if-let [msg (:msg arg)] msg (force msg_)) + ?ex-data (ex-data ?err) + extra + (assoc-some-nx context + :file ?file + :line ?line + :ex-data ?ex-data) + + event (merge (dissoc arg :msg) extra) + attributes (attr/->attributes event)] + + ;; TODO Use clj-otel once it supports the logs API, + ;; Ref. + (.emit + (doto (.logRecordBuilder logger) + (.setAllAttributes attributes) + (.setTimestamp timestamp) + (.setBody message) + (.setSeverity severity) + (.setSeverityText (.toString severity))))))})