statement-logging.td 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. # Copyright Materialize, Inc. and contributors. All rights reserved.
  2. #
  3. # Use of this software is governed by the Business Source License
  4. # included in the LICENSE file at the root of this repository.
  5. #
  6. # As of the Change Date specified in that file, in accordance with
  7. # the Business Source License, use of this software will be governed
  8. # by the Apache License, Version 2.0.
  9. # These just test that statement
  10. # logging is set up in CI. The values
  11. # in prod won't necessarily be the same.
  12. > SHOW statement_logging_max_sample_rate
  13. statement_logging_max_sample_rate
  14. ----
  15. 1.0
  16. > SHOW statement_logging_sample_rate
  17. statement_logging_sample_rate
  18. ----
  19. 1.0
  20. $ postgres-execute connection=postgres://mz_system:materialize@${testdrive.materialize-internal-sql-addr}
  21. ALTER SYSTEM SET enable_statement_lifecycle_logging = true
  22. # Verify that we can get application names
  23. # that are set after session initialization
  24. > SET application_name TO my_app
  25. # Later, we need to ignore everything
  26. # that happened before the real test started. Sleep here,
  27. # so we can be sure that their `began_at` is different.
  28. $ sleep-is-probably-flaky-i-have-justified-my-need-with-a-comment duration="1s"
  29. # Make it so we can query the tables later
  30. $ postgres-execute connection=postgres://mz_system:materialize@${testdrive.materialize-internal-sql-addr}
  31. ALTER SYSTEM SET enable_rbac_checks = false
  32. # No peek result stash for large results, so that result sizes match the expectations below.
  33. $ postgres-execute connection=postgres://mz_system:materialize@${testdrive.materialize-internal-sql-addr}
  34. ALTER SYSTEM SET enable_compute_peek_response_stash = false
  35. # Now the real test begins
  36. # This will be executed on `mz_catalog_server`, due to auto-routing of "simple" queries.
  37. > SELECT 'beginning real test!'
  38. "beginning real test!"
  39. > PREPARE p AS values ($1)
  40. > EXECUTE p('hello world')
  41. "hello world"
  42. > CREATE TABLE t(f int)
  43. > INSERT INTO t VALUES (1)
  44. ! SELECT f/0 FROM t
  45. contains: division by zero
  46. > CREATE DEFAULT INDEX i ON t
  47. > SELECT * FROM t
  48. 1
  49. > SELECT count(*) FROM t
  50. 1
  51. # This one does not show up in the results. See
  52. # point "(2)" in the comment below.
  53. ! SELECT f_nonexistent FROM t
  54. contains: column "f_nonexistent" does not exist
  55. > BEGIN
  56. > DECLARE c CURSOR FOR VALUES (1), (2)
  57. > FETCH c
  58. 1
  59. > FETCH c
  60. 2
  61. > FETCH c
  62. > COMMIT
  63. # Create a cluster, run a query on it, and drop it to ensure that we retain the cluster name
  64. > CREATE CLUSTER c REPLICAS (r1 (size '1'))
  65. > SET cluster TO c
  66. > SELECT count(*) FROM t
  67. 1
  68. > DROP CLUSTER c
  69. # This will be executed on mz_catalog_server, due to auto-routing of catalog queries.
  70. > SELECT count(*) > 0 FROM mz_internal.mz_cluster_replica_metrics
  71. true
  72. # Test that we're correctly recording transaction isolation
  73. > SET transaction_isolation TO serializable
  74. > SELECT 'serializable'
  75. serializable
  76. # Assumptions encoded here:
  77. # (1) "Inner" statement executions are not logged. For example,
  78. # if SQL-level `PREPARE` and `EXECUTE` are used, those statements will
  79. # be logged, but not the statements they reference.
  80. # (2) We don't have a way to log errors that happen during statement preparation,
  81. # but only during statement execution.
  82. # (3) SQL-level statements always use a prepared statement with a useless name beginning with 's'
  83. # (4) `FETCH` has the somewhat confusing behavior of reporting the `result_size` and `rows_returned`
  84. # of the *total* result set in the first `FETCH`, and null thereafter.
  85. #
  86. # All of these (except (3), which is just how the postgres library TD uses works) are working as designed.
  87. # However, we recognize that they are confusing, so we will work on making them
  88. # less confusing as follow-ups.
  89. #
  90. # When we do so, we will need to change this test to encode the improved behavior.
  91. > WITH all_stmts AS (SELECT mseh.*, mpsh.*, mst.sql, mst.redacted_sql FROM mz_internal.mz_statement_execution_history mseh RIGHT JOIN mz_internal.mz_prepared_statement_history mpsh ON mseh.prepared_statement_id = mpsh.id RIGHT JOIN (SELECT DISTINCT sql_hash, sql, redacted_sql FROM mz_internal.mz_sql_text) mst ON mpsh.sql_hash = mst.sql_hash),
  92. test_begin AS (SELECT began_at FROM all_stmts WHERE sql = 'SELECT ''beginning real test!''' ORDER BY began_at DESC LIMIT 1)
  93. SELECT c.name, all_stmts.cluster_name, all_stmts.application_name, all_stmts.sample_rate, all_stmts.params, all_stmts.finished_status, all_stmts.error_message, all_stmts.result_size, all_stmts.rows_returned, all_stmts.execution_strategy, all_stmts.name LIKE 's%', all_stmts.sql, all_stmts.transaction_isolation, all_stmts.transient_index_id ~ '^t[0-9]+$',
  94. all_stmts.database_name, all_stmts.search_path::text
  95. FROM all_stmts, test_begin LEFT JOIN mz_clusters c ON c.id = all_stmts.cluster_id WHERE all_stmts.began_at >= test_begin.began_at AND all_stmts.sql NOT LIKE '%sduiahsdfuoiahsdf%'
  96. <null> <null> my_app 1 {} success <null> <null> <null> <null> true "SET transaction_isolation TO serializable" "strict serializable" <null> materialize {public}
  97. <null> c my_app 1 {} success <null> 18 1 standard true "SELECT count(*) FROM t" "strict serializable" true materialize {public}
  98. <null> c my_app 1 {} success <null> <null> <null> <null> true "DROP CLUSTER c" "strict serializable" <null> materialize {public}
  99. quickstart quickstart my_app 1 {} error "Evaluation error: division by zero" <null> <null> <null> true "SELECT f/0 FROM t" "strict serializable" true materialize {public}
  100. quickstart quickstart my_app 1 {} success <null> 13 1 constant true "EXECUTE p ('<REDACTED>')" "strict serializable" <null> materialize {public}
  101. quickstart quickstart my_app 1 {} success <null> 18 1 fast-path true "SELECT * FROM t" "strict serializable" <null> materialize {public}
  102. quickstart quickstart my_app 1 {} success <null> 18 1 standard true "SELECT count(*) FROM t" "strict serializable" true materialize {public}
  103. quickstart quickstart my_app 1 {} success <null> 4 2 constant true "FETCH c" "strict serializable" <null> materialize {public}
  104. quickstart quickstart my_app 1 {} success <null> <null> <null> <null> true BEGIN "strict serializable" <null> materialize {public}
  105. quickstart quickstart my_app 1 {} success <null> <null> <null> <null> true COMMIT "strict serializable" <null> materialize {public}
  106. quickstart quickstart my_app 1 {} success <null> <null> <null> <null> true "CREATE CLUSTER c REPLICAS (r1 (size '1'))" "strict serializable" <null> materialize {public}
  107. quickstart quickstart my_app 1 {} success <null> <null> <null> <null> true "CREATE DEFAULT INDEX i ON t" "strict serializable" <null> materialize {public}
  108. quickstart quickstart my_app 1 {} success <null> <null> <null> <null> true "CREATE TABLE t(f int)" "strict serializable" <null> materialize {public}
  109. quickstart quickstart my_app 1 {} success <null> <null> <null> <null> true "DECLARE c CURSOR FOR VALUES (1), (2)" "strict serializable" <null> materialize {public}
  110. quickstart quickstart my_app 1 {} success <null> <null> <null> <null> true "FETCH c" "strict serializable" <null> materialize {public}
  111. quickstart quickstart my_app 1 {} success <null> <null> <null> <null> true "FETCH c" "strict serializable" <null> materialize {public}
  112. quickstart quickstart my_app 1 {} success <null> <null> <null> <null> true "INSERT INTO t VALUES ('<REDACTED>')" "strict serializable" <null> materialize {public}
  113. quickstart quickstart my_app 1 {} success <null> <null> <null> <null> true "PREPARE p AS values ($1)" "strict serializable" <null> materialize {public}
  114. quickstart quickstart my_app 1 {} success <null> <null> <null> <null> true "SET cluster TO c" "strict serializable" <null> materialize {public}
  115. mz_catalog_server mz_catalog_server my_app 1 {} success <null> 22 1 constant true "SELECT 'beginning real test!'" "strict serializable" <null> materialize {public}
  116. mz_catalog_server mz_catalog_server my_app 1 {} success <null> 14 1 constant true "SELECT 'serializable'" serializable <null> materialize {public}
  117. mz_catalog_server mz_catalog_server my_app 1 {} success <null> 17 1 standard true "SELECT count(*) > 0 FROM mz_internal.mz_cluster_replica_metrics" "strict serializable" true materialize {public}
  118. > WITH all_stmts AS (SELECT mseh.id, mseh.began_at, mst.sql FROM mz_internal.mz_statement_execution_history mseh JOIN mz_internal.mz_prepared_statement_history mpsh ON mseh.prepared_statement_id = mpsh.id JOIN (SELECT DISTINCT sql, sql_hash, redacted_sql FROM mz_internal.mz_sql_text) mst ON mpsh.sql_hash = mst.sql_hash),
  119. test_begin AS (SELECT began_at FROM all_stmts WHERE sql = 'SELECT ''beginning real test!''' ORDER BY began_at DESC LIMIT 1)
  120. SELECT sql, event_type FROM test_begin, mz_internal.mz_statement_lifecycle_history mslh
  121. JOIN all_stmts ON mslh.statement_id = all_stmts.id
  122. WHERE all_stmts.began_at >= test_begin.began_at AND all_stmts.sql NOT LIKE '%sduiahsdfuoiahsdf%'
  123. BEGIN execution-began
  124. BEGIN execution-finished
  125. COMMIT execution-began
  126. COMMIT execution-finished
  127. "CREATE CLUSTER c REPLICAS (r1 (size '1'))" execution-began
  128. "CREATE CLUSTER c REPLICAS (r1 (size '1'))" execution-finished
  129. "CREATE DEFAULT INDEX i ON t" execution-began
  130. "CREATE DEFAULT INDEX i ON t" execution-finished
  131. "CREATE TABLE t(f int)" execution-began
  132. "CREATE TABLE t(f int)" execution-finished
  133. "DECLARE c CURSOR FOR VALUES (1), (2)" execution-began
  134. "DECLARE c CURSOR FOR VALUES (1), (2)" execution-finished
  135. "DROP CLUSTER c" execution-began
  136. "DROP CLUSTER c" execution-finished
  137. "EXECUTE p ('<REDACTED>')" compute-dependencies-finished
  138. "EXECUTE p ('<REDACTED>')" execution-began
  139. "EXECUTE p ('<REDACTED>')" execution-finished
  140. "EXECUTE p ('<REDACTED>')" optimization-finished
  141. "EXECUTE p ('<REDACTED>')" storage-dependencies-finished
  142. "FETCH c" compute-dependencies-finished
  143. "FETCH c" execution-began
  144. "FETCH c" execution-began
  145. "FETCH c" execution-began
  146. "FETCH c" execution-finished
  147. "FETCH c" execution-finished
  148. "FETCH c" execution-finished
  149. "FETCH c" optimization-finished
  150. "FETCH c" storage-dependencies-finished
  151. "INSERT INTO t VALUES ('<REDACTED>')" execution-began
  152. "INSERT INTO t VALUES ('<REDACTED>')" execution-finished
  153. "PREPARE p AS values ($1)" execution-began
  154. "PREPARE p AS values ($1)" execution-finished
  155. "SELECT 'beginning real test!'" compute-dependencies-finished
  156. "SELECT 'beginning real test!'" execution-began
  157. "SELECT 'beginning real test!'" execution-finished
  158. "SELECT 'beginning real test!'" optimization-finished
  159. "SELECT 'beginning real test!'" storage-dependencies-finished
  160. "SELECT 'serializable'" compute-dependencies-finished
  161. "SELECT 'serializable'" execution-began
  162. "SELECT 'serializable'" execution-finished
  163. "SELECT 'serializable'" optimization-finished
  164. "SELECT 'serializable'" storage-dependencies-finished
  165. "SELECT * FROM t" compute-dependencies-finished
  166. "SELECT * FROM t" execution-began
  167. "SELECT * FROM t" execution-finished
  168. "SELECT * FROM t" optimization-finished
  169. "SELECT * FROM t" storage-dependencies-finished
  170. "SELECT count(*) > 0 FROM mz_internal.mz_cluster_replica_metrics" compute-dependencies-finished
  171. "SELECT count(*) > 0 FROM mz_internal.mz_cluster_replica_metrics" execution-began
  172. "SELECT count(*) > 0 FROM mz_internal.mz_cluster_replica_metrics" execution-finished
  173. "SELECT count(*) > 0 FROM mz_internal.mz_cluster_replica_metrics" optimization-finished
  174. "SELECT count(*) FROM t" compute-dependencies-finished
  175. "SELECT count(*) FROM t" compute-dependencies-finished
  176. "SELECT count(*) FROM t" execution-began
  177. "SELECT count(*) FROM t" execution-began
  178. "SELECT count(*) FROM t" execution-finished
  179. "SELECT count(*) FROM t" execution-finished
  180. "SELECT count(*) FROM t" optimization-finished
  181. "SELECT count(*) FROM t" optimization-finished
  182. "SELECT count(*) FROM t" storage-dependencies-finished
  183. "SELECT count(*) FROM t" storage-dependencies-finished
  184. "SELECT f/0 FROM t" compute-dependencies-finished
  185. "SELECT f/0 FROM t" execution-began
  186. "SELECT f/0 FROM t" execution-finished
  187. "SELECT f/0 FROM t" optimization-finished
  188. "SELECT f/0 FROM t" storage-dependencies-finished
  189. "SET cluster TO c" execution-began
  190. "SET cluster TO c" execution-finished
  191. "SET transaction_isolation TO serializable" execution-began
  192. "SET transaction_isolation TO serializable" execution-finished
  193. # Test that everything in a transaction has the same transaction ID
  194. > BEGIN --hello
  195. > SELECT 'transaction statement 1'
  196. "transaction statement 1"
  197. > SELECT 'transaction statement 2'
  198. "transaction statement 2"
  199. > ROLLBACK
  200. > WITH begin_tid AS
  201. (SELECT transaction_id FROM mz_internal.mz_statement_execution_history mseh, mz_internal.mz_prepared_statement_history mpsh, mz_internal.mz_sql_text mst
  202. WHERE mseh.prepared_statement_id = mpsh.id
  203. AND mpsh.sql_hash = mst.sql_hash
  204. AND mst.sql = 'BEGIN --hello')
  205. SELECT sql FROM mz_internal.mz_statement_execution_history mseh, mz_internal.mz_prepared_statement_history mpsh, begin_tid, mz_internal.mz_sql_text mst
  206. WHERE mseh.prepared_statement_id = mpsh.id
  207. AND mseh.transaction_id = begin_tid.transaction_id
  208. AND mpsh.sql_hash = mst.sql_hash
  209. AND mseh.application_name = 'my_app'
  210. "BEGIN --hello"
  211. "SELECT 'transaction statement 1'"
  212. "SELECT 'transaction statement 2'"
  213. ROLLBACK
  214. # Test that SECRETs have their values redacted.
  215. > CREATE SECRET my_super_secret AS '123';
  216. > SELECT redacted_sql FROM mz_internal.mz_recent_activity_log_redacted WHERE statement_type = 'create_secret';
  217. "CREATE SECRET my_super_secret AS '<REDACTED>'"
  218. > SELECT sql FROM mz_internal.mz_recent_activity_log WHERE statement_type = 'create_secret';
  219. "CREATE SECRET my_super_secret AS '<REDACTED>'"
  220. > ALTER SECRET my_super_secret AS '456';
  221. > SELECT redacted_sql FROM mz_internal.mz_recent_activity_log_redacted WHERE statement_type = 'alter_secret';
  222. "ALTER SECRET my_super_secret AS '<REDACTED>'"
  223. > SELECT sql FROM mz_internal.mz_recent_activity_log WHERE statement_type = 'alter_secret';
  224. "ALTER SECRET my_super_secret AS '<REDACTED>'"
  225. # Test that UPDATE redacts values.
  226. > RESET cluster
  227. > CREATE TABLE redacted_test (a TEXT);
  228. > INSERT INTO redacted_test VALUES ('should be redacted');
  229. > SELECT sql FROM mz_internal.mz_recent_activity_log WHERE statement_type = 'insert' AND sql like '%redacted_test%';
  230. "INSERT INTO redacted_test VALUES ('<REDACTED>')"
  231. > UPDATE redacted_test SET a = 'also redacted' WHERE a = 'should be redacted';
  232. > SELECT sql FROM mz_internal.mz_recent_activity_log WHERE statement_type = 'update';
  233. "UPDATE redacted_test SET a = '<REDACTED>' WHERE a = '<REDACTED>'"
  234. # Test that the number of rows returned in query history respects OFFSET and LIMIT.
  235. > CREATE TABLE t_offset_limit (a int);
  236. > INSERT INTO t_offset_limit SELECT generate_series(1, 5);
  237. # Make sure the table has its data already, otherwise Testdrive might execute it multiple times
  238. > SELECT COUNT(*) FROM t_offset_limit
  239. 5
  240. > SELECT * FROM t_offset_limit ORDER BY a DESC OFFSET 4;
  241. 1
  242. > SELECT * FROM t_offset_limit ORDER BY a DESC LIMIT 2;
  243. 5
  244. 4
  245. > SELECT * FROM t_offset_limit ORDER BY a DESC OFFSET 100;
  246. > SELECT * FROM t_offset_limit ORDER BY a DESC LIMIT 0;
  247. > SELECT result_size, rows_returned FROM mz_internal.mz_recent_activity_log WHERE sql = 'SELECT * FROM t_offset_limit ORDER BY a DESC OFFSET 4';
  248. 90 1
  249. > SELECT result_size, rows_returned FROM mz_internal.mz_recent_activity_log WHERE sql = 'SELECT * FROM t_offset_limit ORDER BY a DESC LIMIT 2';
  250. 54 2
  251. > SELECT result_size, rows_returned FROM mz_internal.mz_recent_activity_log WHERE sql = 'SELECT * FROM t_offset_limit ORDER BY a DESC OFFSET 100';
  252. 90 0
  253. > SELECT result_size, rows_returned FROM mz_internal.mz_recent_activity_log WHERE sql = 'SELECT * FROM t_offset_limit ORDER BY a DESC LIMIT 0';
  254. 0 0
  255. > SELECT mseh.began_at, mslh.occurred_at
  256. FROM mz_internal.mz_statement_execution_history mseh JOIN mz_internal.mz_statement_lifecycle_history mslh ON (mseh.id = mslh.statement_id)
  257. WHERE mslh.event_type = 'execution-began' AND mseh.began_at != mslh.occurred_at;