Skip to content

Commit 91f34f8

Browse files
committed
(PDB-5216) Support a query "origin"
Add support for an optional query "origin", which can be provided via a query parameters, and log it along with the query id. Change the formatting of the query id log entries to be a json map, e.g. 2021-08-16 11:14:37,723 INFO [qtp237850705-35] [p.p.query-eng] PDBQuery:6dd2a796-a4a3-44be-afb6-2a84459367f6: {"ast":["from","catalogs",["=","certname","host-3"]],"origin":"puppet:somewhere"} to avoid any ambiguity, or the need for restrictions or a bespoke encoding, with respect to the origin string contents.
1 parent 2014a7e commit 91f34f8

File tree

5 files changed

+69
-36
lines changed

5 files changed

+69
-36
lines changed

documentation/api/query/v4/index.markdown

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ general info about queries, see [our guide to query structure.][query]
3737
* `ast_only`: optional. A boolean value. When true, the query response will be the supplied
3838
`query` in AST, either exactly as supplied or translated from PQL. False by default.
3939

40+
* `origin`: optional. A string describing the source of the query. It
41+
can be anything, and will be reported in the log when PuppetDB is
42+
configured to log queries. Note that Puppet intends to use origin
43+
names beginning with `puppet:` for its own queries, so it is
44+
recommended that other clients choose something else.
45+
4046
### Response format
4147

4248
The response will be in `application/json`, and will contain a list of JSON

src/puppetlabs/puppetdb/http/handlers.clj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
(def global-engine-params
6969
"Parameters that should always be forwarded from the incoming query to
7070
the engine."
71-
[:optimize_drop_unused_joins :include_facts_expiration :explain])
71+
[:optimize_drop_unused_joins :include_facts_expiration :explain :origin])
7272

7373
(defn status-response
7474
"Executes `query` and if a result is found, calls `found-fn` with
@@ -148,7 +148,8 @@
148148
(def global-params {:optional ["optimize_drop_unused_joins"
149149
"include_facts_expiration"
150150
"include_package_inventory"
151-
"explain"]})
151+
"explain"
152+
"origin"]})
152153
(def paging-params {:optional paging/query-params})
153154
(def pretty-params {:optional ["pretty"]})
154155
(def typical-params (merge-param-specs global-params

src/puppetlabs/puppetdb/http/query.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
(s/optional-key :include_package_inventory) (s/maybe s/Bool)
4747
(s/optional-key :order_by) (s/maybe [[(s/one s/Keyword "field")
4848
(s/one (s/enum :ascending :descending) "order")]])
49+
(s/optional-key :origin) (s/maybe s/Str)
4950
(s/optional-key :distinct_resources) (s/maybe s/Bool)
5051
(s/optional-key :distinct_start_time) s/Any
5152
(s/optional-key :distinct_end_time) s/Any

src/puppetlabs/puppetdb/query_eng.clj

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -102,27 +102,32 @@
102102
:when (:queryable? projection-value)]
103103
(keyword projection-key))))
104104

105-
(defn maybe-log-sql [logging-options gen-sql]
106-
(if-let [log-id (:log-id logging-options)]
107-
(let [sql-output (gen-sql)]
108-
(log/infof "%s:%s:%s" "PDBQuery" log-id (:results-query sql-output))
109-
sql-output)
105+
(defn maybe-log-sql [options context gen-sql]
106+
(if-let [log-id (:log-id context)]
107+
(let [{[query & params] :results-query :as sql} (gen-sql)]
108+
(log/infof "PDBQuery:%s:%s"
109+
log-id (-> (sorted-map :origin (:origin options)
110+
:sql query
111+
:params (vec params))
112+
json/generate-string))
113+
sql)
110114
(gen-sql)))
111115

112116
(defn query->sql
113117
"Converts a vector-structured `query` to a corresponding SQL query which will
114118
return nodes matching the `query`."
115119
([query entity version options]
116120
(query->sql query entity version options {}))
117-
([query entity version options logging-options]
121+
([query entity version options context]
118122
{:pre [((some-fn nil? sequential?) query)]
119123
:post [(map? %)
120124
(jdbc/valid-jdbc-query? (:results-query %))
121125
(or (not (:include_total options))
122126
(jdbc/valid-jdbc-query? (:count-query %)))]}
123127

124128
(maybe-log-sql
125-
logging-options
129+
options
130+
context
126131
(fn []
127132
(cond
128133
(= :aggregate-event-counts entity)
@@ -214,8 +219,10 @@
214219
munge-fn (get-munge-fn entity version options url-prefix)]
215220

216221
(when log-queries
217-
;; log the AST of the incoming query
218-
(log/infof "%s:%s:%s" "PDBQuery" log-id query))
222+
;; Log origin and AST of incoming query
223+
(log/infof "PDBQuery:%s:%s"
224+
log-id (-> (sorted-map :origin (:origin options) :ast query)
225+
json/generate-string)))
219226

220227
(let [f #(let [{:keys [results-query]}
221228
(query->sql remaining-query entity version
@@ -367,8 +374,11 @@
367374
(user-query->engine-query version query-map query-config warn-experimental)]
368375

369376
(when log-queries
370-
;; log the AST of the incoming query
371-
(log/infof "%s:%s:%s" "PDBQuery" log-id (:query query-map)))
377+
;; Log origin and AST of incoming query
378+
(let [{:keys [origin query]} query-map]
379+
(log/infof "PDBQuery:%s:%s"
380+
log-id (-> (sorted-map :origin origin :ast query)
381+
json/generate-string))))
372382

373383
(try
374384
(let [munge-fn (get-munge-fn entity version query-options url-prefix)
@@ -407,8 +417,11 @@
407417
(user-query->engine-query version query-map query-config warn-experimental)]
408418

409419
(when log-queries
410-
;; log the AST of the incoming query
411-
(log/infof "%s:%s:%s" "PDBQuery" log-id (:query query-map)))
420+
;; Log origin and AST of incoming query
421+
(let [{:keys [origin query]} query-map]
422+
(log/infof "PDBQuery:%s:%s"
423+
log-id (-> (sorted-map :origin origin :ast query)
424+
json/generate-string))))
412425

413426
(try
414427
(jdbc/with-transacted-connection scf-read-db

test/puppetlabs/puppetdb/http/query_logging_test.clj

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,39 +54,51 @@
5454
(with-test-db
5555
(replace-catalog catalog-1)
5656
(with-http-app* #(assoc % :log-queries true)
57-
(doseq [[query ast-exp sql-exp]
57+
(doseq [[query exp-ast exp-sql exp-origin]
5858
;; produce-streaming-body
59-
[[["/v4" ["from" "nodes"]]
60-
"\"from\" \"nodes\""
61-
"latest_report_noop_pending"]
59+
[[["/v4" ["from" "nodes"] {:origin "foo"}]
60+
"\"from\",\"nodes\""
61+
"latest_report_noop_pending"
62+
"foo"]
6263
[["/v4" ["from" "facts"]]
63-
"\"from\" \"facts\""
64-
"(jsonb_each((stable||volatile)))"]
64+
"\"from\",\"facts\""
65+
"(jsonb_each((stable||volatile)))"
66+
nil]
6567
;; stream-query-result
66-
[["/v4/catalogs/myhost.localdomain" []]
67-
"\"from\" \"catalogs\""
68-
"row_to_json(edge_data)"]]]
68+
[["/v4/catalogs/myhost.localdomain" [] {:origin "bar"}]
69+
"\"from\",\"catalogs\""
70+
"row_to_json(edge_data)"
71+
"bar"]]]
6972
(with-logged-event-maps events
7073
(is (= 200 (:status (apply query-response :get query))))
7174

7275
(let [events @events
73-
uuid (some->> events
74-
(some #(->> % :message (re-find #"^PDBQuery:([^:]+):")))
75-
second)
76+
;; Returns [everything uuid query-info]
77+
parse-event-msg #(->> % :message (re-find #"^PDBQuery:([^:]+):(.*)"))
78+
parse-event-info #(-> % parse-event-msg (nth 2) json/parse-string)
79+
uuid (some->> events (some parse-event-msg) second)
7680
qev-matching (fn [expected]
7781
(fn [{:keys [message] :as event}]
7882
(and (str/starts-with? message (str "PDBQuery:" uuid ":"))
7983
(str/includes? message expected))))]
8084

8185
(is (uuid? (UUID/fromString uuid)))
8286

83-
(let [asts (filter (qev-matching ast-exp) events)]
84-
(when-not (is (= 1 (count asts)))
85-
(println-err "Unexpected log:" events)))
86-
87-
(let [sqls (filter (qev-matching sql-exp) events)]
88-
(when-not (is (= 1 (count sqls)))
89-
(println-err "Unexpected log:" events))))))))))
87+
(let [[ev & evs] (filter (qev-matching exp-ast) events)]
88+
(is (not (seq evs)))
89+
(when (seq evs)
90+
(println-err "Unexpected log:" events))
91+
(let [{:strs [ast origin] :as info} (parse-event-info ev)]
92+
(is ast)
93+
(is (= exp-origin origin))))
94+
95+
(let [[ev & evs] (filter (qev-matching exp-sql) events)]
96+
(is (not (seq evs)))
97+
(when (seq evs)
98+
(println-err "Unexpected log:" events))
99+
(let [{:strs [sql origin] :as info} (parse-event-info ev)]
100+
(is sql)
101+
(is (= exp-origin origin)))))))))))
90102

91103
(deftest no-queries-are-logged-when-log-queires-is-false
92104
(tk-log/with-logged-event-maps logs
@@ -119,11 +131,11 @@
119131

120132
(testing "AST/SQL is logged for both queries above"
121133
;; match the AST/SQL logs for nodes query
122-
(is (logs-include? logs "\"from\" \"nodes\""))
134+
(is (logs-include? logs "\"from\",\"nodes\""))
123135
(is (logs-include? logs "latest_report_noop_pending"))
124136

125137
;; match the AST/SQL logs for facts query
126-
(is (logs-include? logs "\"from\" \"facts\""))
138+
(is (logs-include? logs "\"from\",\"facts\""))
127139
(is (logs-include? logs "(jsonb_each((stable||volatile)))")))))))))))
128140

129141
(deftest no-PuppetDBServer-tk-service-queries-are-logged-when-log-queries-is-false

0 commit comments

Comments
 (0)