|
1 | 1 | (ns flamebin.processing |
2 | | - (:require [clj-async-profiler.post-processing :as pp] |
| 2 | + (:require [clojure.edn :as edn] |
3 | 3 | [clojure.java.io :as io] |
4 | 4 | [clojure.string :as str] |
5 | | - [taoensso.nippy :as nippy] |
6 | 5 | [flamebin.dto :refer [DenseProfile]] |
7 | 6 | [flamebin.util :refer [raise]] |
8 | 7 | [malli.core :as m] |
9 | | - [jsonista.core :as json] |
10 | | - [flamebin.util :refer [raise]] |
11 | | - [clojure.edn :as edn]) |
| 8 | + [taoensso.nippy :as nippy]) |
12 | 9 | (:import clj_async_profiler.Helpers |
13 | | - (java.io BufferedReader InputStream) |
14 | | - (java.util HashMap HashMap$Node Map$Entry) |
15 | | - (java.util.function Consumer Function) |
16 | | - java.io.PushbackReader)) |
| 10 | + (java.io BufferedReader InputStream PushbackReader) |
| 11 | + (java.util HashMap Map$Entry))) |
17 | 12 |
|
18 | 13 | ;; Collapsed stacks: |
19 | 14 | ;; a;b;c 10 |
|
88 | 83 | .stream |
89 | 84 | (.sorted (Map$Entry/comparingByKey)) |
90 | 85 | (.forEach |
91 | | - (reify Consumer |
92 | | - (accept [_ entry] |
93 | | - (let [stack (split-by-semicolon-and-transform-to-indices |
94 | | - (.getKey ^Map$Entry entry) frame->id-map) |
95 | | - value (.getValue ^Map$Entry entry) |
96 | | - same (count-same stack (aget last-stack 0)) |
97 | | - dense-stack (into [same] (drop same stack))] |
98 | | - (.add acc [dense-stack value]) |
99 | | - (aset last-stack 0 stack) |
100 | | - (aset total-samples 0 (+ (aget total-samples 0) ^long value))))))) |
| 86 | + (fn [^Map$Entry entry] |
| 87 | + (let [stack (split-by-semicolon-and-transform-to-indices |
| 88 | + (.getKey entry) frame->id-map) |
| 89 | + value (.getValue entry) |
| 90 | + same (count-same stack (aget last-stack 0)) |
| 91 | + dense-stack (into [same] (drop same stack))] |
| 92 | + (.add acc [dense-stack value]) |
| 93 | + (aset last-stack 0 stack) |
| 94 | + (aset total-samples 0 (+ (aget total-samples 0) ^long value)))))) |
101 | 95 | id->frame-arr (object-array (.size frame->id-map))] |
102 | 96 | (run! (fn [[k v]] (aset id->frame-arr v k)) frame->id-map) |
103 | 97 | {:stacks (vec acc) |
|
106 | 100 |
|
107 | 101 | (def ^:private nippy-compressor nippy/zstd-compressor) |
108 | 102 |
|
109 | | -(defn freeze [object] |
110 | | - (nippy/freeze object {:compressor nippy-compressor})) |
| 103 | +(defn freeze [object read-token] |
| 104 | + (nippy/freeze object {:compressor nippy-compressor |
| 105 | + :password (when read-token [:salted read-token])})) |
111 | 106 |
|
112 | 107 | (defn collapsed-stacks-stream->dense-profile [input-stream] |
113 | 108 | (-> input-stream |
|
122 | 117 | (update profile :total-samples |
123 | 118 | #(or % (transduce (map second) + 0 (:stacks profile))))))) |
124 | 119 |
|
125 | | -(defn read-compressed-profile [source-file] |
126 | | - (nippy/thaw-from-file source-file)) |
| 120 | +(defn read-compressed-profile [source-file read-token] |
| 121 | + (try (nippy/thaw-from-file source-file {:password (when read-token |
| 122 | + [:salted read-token])}) |
| 123 | + (catch clojure.lang.ExceptionInfo ex |
| 124 | + (if (str/includes? (ex-message ex) "decryption") |
| 125 | + (raise 403 "Failed to decrypt flamegraph, incorrect read-token.") |
| 126 | + (throw ex))))) |
127 | 127 |
|
128 | 128 | (comment |
129 | 129 | (defn file-as-gzip-input-stream [file] |
|
134 | 134 | (io/copy (io/file file) s)) |
135 | 135 | (.toByteArray baos))))) |
136 | 136 |
|
137 | | - (freeze |
138 | | - (intermediate-profile->dense-profile |
139 | | - (collapsed-stacks-stream->intermediate-profile |
140 | | - (file-as-gzip-input-stream "test/res/huge.txt")))) |
| 137 | + (nippy/thaw |
| 138 | + (freeze |
| 139 | + (intermediate-profile->dense-profile |
| 140 | + (collapsed-stacks-stream->intermediate-profile |
| 141 | + (file-as-gzip-input-stream "test/res/normal.txt"))) |
| 142 | + "key1") |
| 143 | + {:password [:salted "key2"]}) |
141 | 144 |
|
142 | 145 | (with-open [w (io/writer (io/file "test/res/huge.edn"))] |
143 | 146 | (binding [*out* w] |
|
0 commit comments