From 8dead73e7af9321426b662050c0bade8d4bcf762 Mon Sep 17 00:00:00 2001 From: Eric Dallo Date: Mon, 12 Jan 2026 09:20:34 -0300 Subject: [PATCH 1/4] Fix middlwares metric --- src/metrepl/metrics.clj | 7 +++---- src/metrepl/middleware/op_metrics.clj | 21 +++++++++++++++++++-- test/metrepl/metrics_test.clj | 9 +++------ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/metrepl/metrics.clj b/src/metrepl/metrics.clj index cb65fea..aa7ba71 100644 --- a/src/metrepl/metrics.clj +++ b/src/metrepl/metrics.clj @@ -5,8 +5,7 @@ [clojure.string :as string] [metrepl.config :as config] [metrepl.exporters :as exporters] - [metrepl.transport :as m.transport] - [nrepl.middleware.dynamic-loader :as nrepl.dynamic-loader]) + [metrepl.transport :as m.transport]) (:import [java.lang.management ManagementFactory] [java.util.jar JarFile])) @@ -64,7 +63,7 @@ "build.gradle" "gradle" "build.gradle.kts" "gradle"}) -(defn metrify-repl-ready [startup-time-ms] +(defn metrify-repl-ready [startup-time-ms middlewares] (metrify* :info/repl-ready (fn [] (let [project-types (vec (keep @@ -78,5 +77,5 @@ (classpath/classpath-jarfiles))] {:startup-time-ms startup-time-ms :project-types project-types - :middlewares (some->> nrepl.dynamic-loader/*state* deref :stack (mapv #(subs (str %) 2))) + :middlewares middlewares :dependencies dependencies})))) diff --git a/src/metrepl/middleware/op_metrics.clj b/src/metrepl/middleware/op_metrics.clj index 24b2207..efae5b4 100644 --- a/src/metrepl/middleware/op_metrics.clj +++ b/src/metrepl/middleware/op_metrics.clj @@ -1,12 +1,27 @@ (ns metrepl.middleware.op-metrics (:require [metrepl.metrics :as metrics] + [metrepl.transport :as m.transport] [nrepl.middleware :as middleware] [nrepl.middleware.session]) (:import [java.lang.management ManagementFactory])) (defonce first-op-received?* (atom false)) +(defonce middlewares* (atom nil)) + +(defn ^:private capture-middlewares-from-describe + "Wraps the message to capture middlewares from describe op response." + [msg] + (if (= "describe" (:op msg)) + (m.transport/wrap + msg + {:on-before-send + (fn [response] + (when-let [auxs (:aux response)] + (when-let [mws (get auxs "middleware")] + (reset! middlewares* (vec mws)))))}) + msg)) (defn wrap-op-metrics "Wrap all ops metrifying each one, emmiting these events: @@ -17,8 +32,10 @@ (fn [msg] (when-not @first-op-received?* (reset! first-op-received?* true) - (metrics/metrify-repl-ready (.getUptime (ManagementFactory/getRuntimeMXBean)))) - (handler (metrics/metrify-op-task msg)))) + (metrics/metrify-repl-ready (.getUptime (ManagementFactory/getRuntimeMXBean)) @middlewares*)) + (handler (-> msg + capture-middlewares-from-describe + metrics/metrify-op-task)))) (middleware/set-descriptor! #'wrap-op-metrics diff --git a/test/metrepl/metrics_test.clj b/test/metrepl/metrics_test.clj index 0e0cbf9..46f1b37 100644 --- a/test/metrepl/metrics_test.clj +++ b/test/metrepl/metrics_test.clj @@ -5,8 +5,6 @@ [matcher-combinators.test :refer [match?]] [metrepl.exporters :as exporters] [metrepl.metrics :as metrics] - [metrepl.middleware.op-metrics :as op-metrics] - [nrepl.middleware.dynamic-loader :as nrepl.dynamic-loader] [nrepl.transport :refer [Transport]])) (def mock-transport @@ -137,13 +135,12 @@ (.send {:status #{:done}}))))) (deftest metrify-repl-ready-test - (with-redefs [nrepl.dynamic-loader/*state* (atom {:stack [#'op-metrics/wrap-op-metrics]}) - exporters/export! (fn [metric] + (with-redefs [exporters/export! (fn [metric] (case (:metric metric) :info/repl-ready (is (match? {:metric :info/repl-ready :payload {:startup-time-ms 123 :project-types (matchers/in-any-order ["deps" "babashka"]) - :middlewares (matchers/embeds ["metrepl.middleware.op-metrics/wrap-op-metrics"])}} + :middlewares ["metrepl.middleware.op-metrics/wrap-op-metrics"]}} metric))))] - (metrics/metrify-repl-ready 123))) + (metrics/metrify-repl-ready 123 ["metrepl.middleware.op-metrics/wrap-op-metrics"]))) From 9504169ca80ae61874905da70a1d76dafd7632fe Mon Sep 17 00:00:00 2001 From: Eric Dallo Date: Wed, 14 Jan 2026 15:06:28 -0300 Subject: [PATCH 2/4] Use middleware when available --- src/metrepl/metrics.clj | 4 ++-- src/metrepl/middleware/op_metrics.clj | 21 ++------------------- test/metrepl/metrics_test.clj | 9 ++++++--- 3 files changed, 10 insertions(+), 24 deletions(-) diff --git a/src/metrepl/metrics.clj b/src/metrepl/metrics.clj index aa7ba71..eb0671c 100644 --- a/src/metrepl/metrics.clj +++ b/src/metrepl/metrics.clj @@ -16,6 +16,7 @@ (merge {:op op} (case op "clone" (select-keys msg [:client-name :client-version]) + "describe" (select-keys msg [:middleware]) "load-file" (cond-> (select-keys msg [:file-name :file-path]) @first-load-file?* (assoc :first-time true)) "eval" (select-keys msg [:ns]) @@ -63,7 +64,7 @@ "build.gradle" "gradle" "build.gradle.kts" "gradle"}) -(defn metrify-repl-ready [startup-time-ms middlewares] +(defn metrify-repl-ready [startup-time-ms] (metrify* :info/repl-ready (fn [] (let [project-types (vec (keep @@ -77,5 +78,4 @@ (classpath/classpath-jarfiles))] {:startup-time-ms startup-time-ms :project-types project-types - :middlewares middlewares :dependencies dependencies})))) diff --git a/src/metrepl/middleware/op_metrics.clj b/src/metrepl/middleware/op_metrics.clj index efae5b4..24b2207 100644 --- a/src/metrepl/middleware/op_metrics.clj +++ b/src/metrepl/middleware/op_metrics.clj @@ -1,27 +1,12 @@ (ns metrepl.middleware.op-metrics (:require [metrepl.metrics :as metrics] - [metrepl.transport :as m.transport] [nrepl.middleware :as middleware] [nrepl.middleware.session]) (:import [java.lang.management ManagementFactory])) (defonce first-op-received?* (atom false)) -(defonce middlewares* (atom nil)) - -(defn ^:private capture-middlewares-from-describe - "Wraps the message to capture middlewares from describe op response." - [msg] - (if (= "describe" (:op msg)) - (m.transport/wrap - msg - {:on-before-send - (fn [response] - (when-let [auxs (:aux response)] - (when-let [mws (get auxs "middleware")] - (reset! middlewares* (vec mws)))))}) - msg)) (defn wrap-op-metrics "Wrap all ops metrifying each one, emmiting these events: @@ -32,10 +17,8 @@ (fn [msg] (when-not @first-op-received?* (reset! first-op-received?* true) - (metrics/metrify-repl-ready (.getUptime (ManagementFactory/getRuntimeMXBean)) @middlewares*)) - (handler (-> msg - capture-middlewares-from-describe - metrics/metrify-op-task)))) + (metrics/metrify-repl-ready (.getUptime (ManagementFactory/getRuntimeMXBean)))) + (handler (metrics/metrify-op-task msg)))) (middleware/set-descriptor! #'wrap-op-metrics diff --git a/test/metrepl/metrics_test.clj b/test/metrepl/metrics_test.clj index 46f1b37..0e0cbf9 100644 --- a/test/metrepl/metrics_test.clj +++ b/test/metrepl/metrics_test.clj @@ -5,6 +5,8 @@ [matcher-combinators.test :refer [match?]] [metrepl.exporters :as exporters] [metrepl.metrics :as metrics] + [metrepl.middleware.op-metrics :as op-metrics] + [nrepl.middleware.dynamic-loader :as nrepl.dynamic-loader] [nrepl.transport :refer [Transport]])) (def mock-transport @@ -135,12 +137,13 @@ (.send {:status #{:done}}))))) (deftest metrify-repl-ready-test - (with-redefs [exporters/export! (fn [metric] + (with-redefs [nrepl.dynamic-loader/*state* (atom {:stack [#'op-metrics/wrap-op-metrics]}) + exporters/export! (fn [metric] (case (:metric metric) :info/repl-ready (is (match? {:metric :info/repl-ready :payload {:startup-time-ms 123 :project-types (matchers/in-any-order ["deps" "babashka"]) - :middlewares ["metrepl.middleware.op-metrics/wrap-op-metrics"]}} + :middlewares (matchers/embeds ["metrepl.middleware.op-metrics/wrap-op-metrics"])}} metric))))] - (metrics/metrify-repl-ready 123 ["metrepl.middleware.op-metrics/wrap-op-metrics"]))) + (metrics/metrify-repl-ready 123))) From c5f35984edb672f1290f29db35907ccd1ec2016d Mon Sep 17 00:00:00 2001 From: Eric Dallo Date: Wed, 14 Jan 2026 15:09:37 -0300 Subject: [PATCH 3/4] Fix tests --- test/metrepl/metrics_test.clj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/metrepl/metrics_test.clj b/test/metrepl/metrics_test.clj index 0e0cbf9..1060c98 100644 --- a/test/metrepl/metrics_test.clj +++ b/test/metrepl/metrics_test.clj @@ -143,7 +143,6 @@ :info/repl-ready (is (match? {:metric :info/repl-ready :payload {:startup-time-ms 123 - :project-types (matchers/in-any-order ["deps" "babashka"]) - :middlewares (matchers/embeds ["metrepl.middleware.op-metrics/wrap-op-metrics"])}} + :project-types (matchers/in-any-order ["deps" "babashka"])}} metric))))] (metrics/metrify-repl-ready 123))) From c74db8588101f98caf2b3f679a1e897d774b1136 Mon Sep 17 00:00:00 2001 From: Eric Dallo Date: Wed, 14 Jan 2026 15:52:21 -0300 Subject: [PATCH 4/4] Check response instead of payload --- src/metrepl/metrics.clj | 21 +++++++++++++++------ test/metrepl/metrics_test.clj | 20 +++++++++++++++++++- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/metrepl/metrics.clj b/src/metrepl/metrics.clj index eb0671c..d91f300 100644 --- a/src/metrepl/metrics.clj +++ b/src/metrepl/metrics.clj @@ -12,11 +12,10 @@ (defonce first-load-file?* (atom true)) -(defn ^:private msg->payload [{:keys [op] :as msg}] +(defn ^:private msg->initial-payload [{:keys [op] :as msg}] (merge {:op op} (case op "clone" (select-keys msg [:client-name :client-version]) - "describe" (select-keys msg [:middleware]) "load-file" (cond-> (select-keys msg [:file-name :file-path]) @first-load-file?* (assoc :first-time true)) "eval" (select-keys msg [:ns]) @@ -24,6 +23,15 @@ "close" {:session-time-ms (.getUptime (ManagementFactory/getRuntimeMXBean))} nil))) +(defn ^:private initial-payload->final-payload [initial-payload response end-time] + (cond-> initial-payload + + (and (= "describe" (:op initial-payload)) (get response :middleware)) + (assoc :middleware (vec (get response :middleware))) + + :always + (assoc :time-ms end-time))) + (defn metrify* [metric content-fn] (try (exporters/export! {:metric metric @@ -40,8 +48,8 @@ (metrify* metric (constantly content))) (defn metrify-op-task [msg] - (let [payload (msg->payload msg) - _ (metrify :event/op-requested payload) + (let [initial-payload (msg->initial-payload msg) + _ (metrify :event/op-requested initial-payload) start-time (System/currentTimeMillis)] (when (and (= "load-file" (:op msg)) @first-load-file?*) @@ -51,8 +59,9 @@ {:on-before-send (fn [response] (when (contains? (:status response) :done) - (let [end-time (- (System/currentTimeMillis) start-time)] - (metrify :event/op-completed (assoc payload :time-ms end-time)))))}))) + (let [end-time (- (System/currentTimeMillis) start-time) + final-payload (initial-payload->final-payload initial-payload response end-time)] + (metrify :event/op-completed final-payload))))}))) (def ^:private type-by-file {"project.clj" "lein" diff --git a/test/metrepl/metrics_test.clj b/test/metrepl/metrics_test.clj index 1060c98..390f1bb 100644 --- a/test/metrepl/metrics_test.clj +++ b/test/metrepl/metrics_test.clj @@ -134,7 +134,25 @@ metric))))] (-> (metrics/metrify-op-task {:op "close" :transport mock-transport}) :transport - (.send {:status #{:done}}))))) + (.send {:status #{:done}})))) + (testing "describe op" + (with-redefs [exporters/export! (fn [metric] + (case (:metric metric) + :event/op-requested + (is (match? {:metric :event/op-requested + :payload {:op "describe"}} + metric)) + :event/op-completed + (is (match? {:metric :event/op-completed + :payload {:op "describe" + :middleware ["some-middleware"] + :time-ms int?}} + metric))))] + (-> (metrics/metrify-op-task {:op "describe" + :transport mock-transport}) + :transport + (.send {:status #{:done} + :middleware ["some-middleware"]}))))) (deftest metrify-repl-ready-test (with-redefs [nrepl.dynamic-loader/*state* (atom {:stack [#'op-metrics/wrap-op-metrics]})