-
Notifications
You must be signed in to change notification settings - Fork 47
/
mbean_sampler.clj
140 lines (106 loc) · 4.58 KB
/
mbean_sampler.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
(ns com.brunobonacci.mulog.publishers.mbean-sampler
(:require [clojure.spec.alpha :as s]
[com.brunobonacci.mulog :as u]
[com.brunobonacci.mulog.buffer :as rb]
[com.brunobonacci.mulog.utils :as ut]
[clojure.java.jmx :as jmx]
[clojure.stacktrace :as stack]
[clojure.walk :as walk])
(:import [javax.management ObjectName]))
;;
;; Some values can be retrieved and an exception is thrown.
;; replacing those cases with `nil`
;;
(defn- sanitize-values
[value]
(as-> value $
;; Turns ObjectName into strings with canonical represtantion
(if (and (contains? $ :ObjectName) (instance? ObjectName (get $ :ObjectName)))
(update $ :ObjectName #(.getCanonicalName ^ObjectName %))
$)
;; remove exception
(walk/postwalk
(fn [v]
(if (instance? Exception v)
;; some values can't be retrieved
(if (instance? java.lang.UnsupportedOperationException
(stack/root-cause v))
nil
(ut/exception-stacktrace v))
v))
$)))
(defn mbeans-sample
"Returns list of MBeans that match the given `pattern`. For each
MBean it will returns the current value of each attribute/property.
- `*:type=Foo,name=Bar` to match names in any domain whose exact
set of keys is `type=Foo,name=Bar`.
- `d:type=Foo,name=Bar,*` to match names in the domain d that
have the keys `type=Foo,name=Bar` plus zero or more other keys.
- `*:type=Foo,name=Bar,*` to match names in any domain that has
the keys `type=Foo,name=Bar` plus zero or more other keys.
- `d:type=F?o,name=Bar` will match e.g. `d:type=Foo,name=Bar` and
`d:type=Fro,name=Bar`.
- `d:type=F*o,name=Bar` will match e.g. `d:type=Fo,name=Bar` and
`d:type=Frodo,name=Bar`.
- `d:type=Foo,name=\"B*\"` will match
e.g. `d:type=Foo,name=\"Bling\"`. Wildcards are recognized even inside
quotes, and like other special characters can be escaped with \\
"
[pattern]
(->> (jmx/mbean-names pattern)
(map (juxt (memfn ^ObjectName getCanonicalName) (memfn ^ObjectName getDomain)
(memfn ^ObjectName getKeyPropertyList) jmx/mbean))
(map (fn [[canonical-name domain keys attrs]]
{:canonical-name canonical-name
:domain domain
:keys (into {} keys)
:attributes (sanitize-values attrs)}))))
(defn sample-mbeans [mbeans-patterns transform-samples]
(doseq [pattern mbeans-patterns
mbean (transform-samples (mbeans-sample pattern))]
(u/log :mulog/mbean-sampled :search-pattern pattern :mbean mbean)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; ----==| P U B L I S H E R |==---- ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(deftype MBeanSamplerPublisher [config buffer]
com.brunobonacci.mulog.publisher.PPublisher
(agent-buffer [_]
buffer)
(publish-delay [_]
(:sampling-interval config 60000))
(publish [_ buffer]
;; sampling MBeans
(sample-mbeans (:mbeans-patterns config) (:transform-samples config))))
(def ^:const DEFAULT-CONFIG
{;; Interval in milliseconds between two samples
:sampling-interval 60000
;; list of MBean patterns to sample
:mbeans-patterns []
;; Transformation to apply to the samples before publishing.
;;
;; It is a function that takes a sequence of samples and
;; returns and updated sequence of samples:
;; `transform-samples -> sample-seq -> sample-seq`
:transform-samples identity})
(defn- apply-defaults
[{:keys [transform-samples transform] :as config}]
(as-> config $
(merge DEFAULT-CONFIG $)
(update $ :sampling-interval #(max (or % 1000) 1000))
(assoc $ :transform-samples (or transform-samples (and transform (partial map transform)) identity))))
(defn mbean-sampler-publisher
[{:keys [transform] :as config}]
(when transform
(println
"[μ/log] DEPRECATION WARNING: on `:mbean` sampler,"
"please update config key `:transform` to `:transform-samples`")
(println
"[μ/log] DEPRECATION WARNING: for more info: https://github.com/BrunoBonacci/mulog/issues/75"))
;; create the metrics publisher
(MBeanSamplerPublisher. (apply-defaults config) (rb/agent-buffer 100)))
(comment
(sample-mbeans ["java.lang:type=Memory"] identity)
(sample-mbeans ["java.nio:*"] identity)
)