mirror of
https://github.com/taoensso/telemere.git
synced 2025-12-17 01:51:10 +00:00
[new] [#28] OpenTelemetry handler: support custom signal attrs
Thanks to @benalbrecht for assistance on this feature!
This commit is contained in:
parent
19548d3fac
commit
5ef4f12c6e
1 changed files with 54 additions and 25 deletions
|
|
@ -46,7 +46,7 @@
|
||||||
(comment (enc/qb 1e6 (attr-name :a.b/c-d) (attr-name :x.y/z :a.b/c-d))) ; [44.13 63.19]
|
(comment (enc/qb 1e6 (attr-name :a.b/c-d) (attr-name :x.y/z :a.b/c-d))) ; [44.13 63.19]
|
||||||
|
|
||||||
;; AttributeTypes: String, Long, Double, Boolean, and arrays
|
;; AttributeTypes: String, Long, Double, Boolean, and arrays
|
||||||
(defprotocol ^:private IAttributesBuilder (^:private -put-attr! ^AttributesBuilder [attr-val attr-name attr-builder]))
|
(defprotocol ^:private IAttributesBuilder (^:private -put-attr! ^AttributesBuilder [attr-val attr-name attrs-builder]))
|
||||||
(extend-protocol IAttributesBuilder
|
(extend-protocol IAttributesBuilder
|
||||||
;; nil (-put-attr! [v ^String k ^AttributesBuilder ab] (.put ab k "nil")) ; As pr-edn*
|
;; nil (-put-attr! [v ^String k ^AttributesBuilder ab] (.put ab k "nil")) ; As pr-edn*
|
||||||
nil (-put-attr! [v ^String k ^AttributesBuilder ab] ab ) ; Noop
|
nil (-put-attr! [v ^String k ^AttributesBuilder ab] ab ) ; Noop
|
||||||
|
|
@ -66,6 +66,7 @@
|
||||||
clojure.lang.IPersistentCollection
|
clojure.lang.IPersistentCollection
|
||||||
(-put-attr! [v ^String k ^AttributesBuilder ab]
|
(-put-attr! [v ^String k ^AttributesBuilder ab]
|
||||||
(when-some [v1 (if (indexed? v) (nth v 0 nil) (first v))]
|
(when-some [v1 (if (indexed? v) (nth v 0 nil) (first v))]
|
||||||
|
;; Ignores nested maps
|
||||||
(or
|
(or
|
||||||
(cond
|
(cond
|
||||||
(string? v1) (enc/catching :common (.put ab k ^"[Ljava.lang.String;" (into-array String v)))
|
(string? v1) (enc/catching :common (.put ab k ^"[Ljava.lang.String;" (into-array String v)))
|
||||||
|
|
@ -82,16 +83,26 @@
|
||||||
(when-let [^String s (enc/catching :common (enc/pr-edn* v))]
|
(when-let [^String s (enc/catching :common (enc/pr-edn* v))]
|
||||||
(.put ab k s))))
|
(.put ab k s))))
|
||||||
|
|
||||||
(defmacro ^:private put-attr! [attr-builder attr-name attr-val]
|
(defmacro ^:private put-attr! [attrs-builder attr-name attr-val]
|
||||||
`(-put-attr! ~attr-val ~attr-name ~attr-builder)) ; Fix arg order
|
`(-put-attr! ~attr-val ~attr-name ~attrs-builder)) ; Fix arg order
|
||||||
|
|
||||||
|
(defn- put-attrs!
|
||||||
|
[^AttributesBuilder attrs-builder attrs]
|
||||||
|
(cond
|
||||||
|
(map? attrs) (enc/run-kv! (fn [k v] (put-attr! attrs-builder (attr-name k) v)) attrs) ; Unprefixed
|
||||||
|
(instance? Attributes attrs) (.putAll attrs-builder ^Attributes attrs) ; Unprefixed
|
||||||
|
:else
|
||||||
|
(enc/unexpected-arg! attrs
|
||||||
|
{:context `put-attrs!
|
||||||
|
:expected #{nil map io.opentelemetry.api.common.Attributes}})))
|
||||||
|
|
||||||
(defn- merge-attrs!
|
(defn- merge-attrs!
|
||||||
"If given a map, merges prefixed key/values (~like `into`).
|
"If given a map, merges prefixed key/values (~like `into`).
|
||||||
Otherwise just puts single named value."
|
Otherwise just puts single named value."
|
||||||
[attr-builder name-or-prefix x]
|
[attrs-builder name-or-prefix x]
|
||||||
(if (map? x)
|
(if (map? x)
|
||||||
(enc/run-kv! (fn [k v] (put-attr! attr-builder (attr-name name-or-prefix k) v)) x)
|
(enc/run-kv! (fn [k v] (put-attr! attrs-builder (attr-name name-or-prefix k) v)) x)
|
||||||
(do (put-attr! attr-builder name-or-prefix x))))
|
(do (put-attr! attrs-builder name-or-prefix x))))
|
||||||
|
|
||||||
;;;; Handler
|
;;;; Handler
|
||||||
|
|
||||||
|
|
@ -171,16 +182,10 @@
|
||||||
(put-attr! ab "root.id" id)
|
(put-attr! ab "root.id" id)
|
||||||
(put-attr! ab "root.uid" uid))
|
(put-attr! ab "root.uid" uid))
|
||||||
|
|
||||||
(when-let [ctx (get signal :ctx)] (merge-attrs! ab "ctx" ctx))
|
(when-let [ctx (get signal :ctx)] (merge-attrs! ab "ctx" ctx))
|
||||||
(when-let [data (get signal :data)] (merge-attrs! ab "data" data))
|
(when-let [data (get signal :data)] (merge-attrs! ab "data" data))
|
||||||
(when-let [attrs (get signal :otel/attrs)] ; Undocumented
|
(when-let [attrs (get signal :otel/attrs)] (put-attrs! ab attrs))
|
||||||
(cond
|
(when-let [attrs (get signal :otel/log-attrs)] (put-attrs! ab attrs))
|
||||||
(map? attrs) (enc/run-kv! (fn [k v] (put-attr! ab (attr-name k) v)) attrs) ; Unprefixed
|
|
||||||
(instance? Attributes attrs) (.putAll ab ^Attributes attrs) ; Unprefixed
|
|
||||||
:else
|
|
||||||
(enc/unexpected-arg! attrs
|
|
||||||
{:context `signal->attrs!
|
|
||||||
:expected #{nil map io.opentelemetry.api.common.Attributes}})))
|
|
||||||
|
|
||||||
(.build ab)))
|
(.build ab)))
|
||||||
|
|
||||||
|
|
@ -193,15 +198,30 @@
|
||||||
(let [ak-ns (io.opentelemetry.api.common.AttributeKey/stringKey "ns")
|
(let [ak-ns (io.opentelemetry.api.common.AttributeKey/stringKey "ns")
|
||||||
ak-line (io.opentelemetry.api.common.AttributeKey/longKey "line")]
|
ak-line (io.opentelemetry.api.common.AttributeKey/longKey "line")]
|
||||||
|
|
||||||
(defn- basic-span-attrs
|
(defn- span-attrs
|
||||||
"Returns `?Attributes`."
|
"Returns `?Attributes`."
|
||||||
[signal]
|
[signal]
|
||||||
(when-let [ns (get signal :ns)]
|
(let [common-attrs (get signal :otel/attrs)
|
||||||
(if-let [line (get signal :line)]
|
trace-attrs (get signal :otel/trace-attrs)]
|
||||||
(Attributes/of ak-ns ns, ak-line (long line))
|
|
||||||
(Attributes/of ak-ns ns)))))
|
|
||||||
|
|
||||||
(comment (enc/qb 1e6 (basic-span-attrs {:ns "ns1" :line 495}))) ; 52.4
|
(if (or common-attrs trace-attrs)
|
||||||
|
(let [ab (Attributes/builder)]
|
||||||
|
(when-let [ns (get signal :ns)] (.put ab "ns" (str ns)))
|
||||||
|
(when-let [line (get signal :line)] (.put ab "line" (long line)))
|
||||||
|
(when-let [attrs common-attrs] (put-attrs! ab attrs))
|
||||||
|
(when-let [attrs trace-attrs] (put-attrs! ab attrs))
|
||||||
|
(.build ab))
|
||||||
|
|
||||||
|
;; Common case
|
||||||
|
(when-let [ns (get signal :ns)]
|
||||||
|
(if-let [line (get signal :line)]
|
||||||
|
(Attributes/of ak-ns ns, ak-line (long line))
|
||||||
|
(Attributes/of ak-ns ns)))))))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(enc/qb 1e6 (span-attrs {:ns "ns1" :line 495})) ; 54.31
|
||||||
|
(span-attrs {:ns "ns1", :otel/attrs {:foo :bar}})
|
||||||
|
(span-attrs {:ns "ns1", :otel/attrs {:foo [5 :a :b]}}))
|
||||||
|
|
||||||
(defn handler:open-telemetry
|
(defn handler:open-telemetry
|
||||||
"Highly experimental, possibly buggy, and subject to change!!
|
"Highly experimental, possibly buggy, and subject to change!!
|
||||||
|
|
@ -220,7 +240,16 @@
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
`:logger-provider` - nil or `io.opentelemetry.api.logs.LoggerProvider`,
|
`:logger-provider` - nil or `io.opentelemetry.api.logs.LoggerProvider`,
|
||||||
(see `telemere/otel-default-providers_` for default)."
|
(see `telemere/otel-default-providers_` for default).
|
||||||
|
|
||||||
|
Optional signal keys:
|
||||||
|
`:otel/attrs` - Attributes [1] to add to log records AND tracing spans/events
|
||||||
|
`:otel/log-attrs` - Attributes [1] to add to log records ONLY
|
||||||
|
`:otel/trace-attrs` - Attributes [1] to add to tracing spans/events ONLY
|
||||||
|
|
||||||
|
[1] `io.opentelemetry.api.common.Attributes` or Clojure map with str/kw keys and vals ∈
|
||||||
|
#{nil boolean keyword string UUID long double string-vec long-vec double-vec boolean-vec}.
|
||||||
|
(Nested) map vals will be ignored!"
|
||||||
|
|
||||||
;; Notes:
|
;; Notes:
|
||||||
;; - Multi-threaded handlers may see signals ~out of order
|
;; - Multi-threaded handlers may see signals ~out of order
|
||||||
|
|
@ -278,7 +307,7 @@
|
||||||
(enc/if-not [end-inst (get signal :end-inst)]
|
(enc/if-not [end-inst (get signal :end-inst)]
|
||||||
;; No end-inst => no run-form => add `Event` to span (parent)
|
;; No end-inst => no run-form => add `Event` to span (parent)
|
||||||
(let [{:keys [id ^java.time.Instant inst]} signal]
|
(let [{:keys [id ^java.time.Instant inst]} signal]
|
||||||
(if-let [^Attributes attrs (basic-span-attrs signal)]
|
(if-let [^Attributes attrs (span-attrs signal)]
|
||||||
(.addEvent span (impl/otel-name id) attrs inst)
|
(.addEvent span (impl/otel-name id) attrs inst)
|
||||||
(.addEvent span (impl/otel-name id) inst)))
|
(.addEvent span (impl/otel-name id) inst)))
|
||||||
|
|
||||||
|
|
@ -288,7 +317,7 @@
|
||||||
(.setStatus span io.opentelemetry.api.trace.StatusCode/ERROR)
|
(.setStatus span io.opentelemetry.api.trace.StatusCode/ERROR)
|
||||||
(.setStatus span io.opentelemetry.api.trace.StatusCode/OK))
|
(.setStatus span io.opentelemetry.api.trace.StatusCode/OK))
|
||||||
|
|
||||||
(when-let [^Attributes attrs (basic-span-attrs signal)]
|
(when-let [^Attributes attrs (span-attrs signal)]
|
||||||
(.setAllAttributes span attrs))
|
(.setAllAttributes span attrs))
|
||||||
|
|
||||||
;; Error stuff
|
;; Error stuff
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue