@@ -26,18 +26,26 @@ under the License.
26
26
27
27
# Debug Point
28
28
29
- Debug point is used in code test. When enabling a debug point, it can run related code.
29
+ Debug point is a piece of code, inserted into FE or BE code, when program running into this code,
30
30
31
- Both FE and BE support debug points.
31
+ it can change variables or behaviors of the program.
32
+
33
+ It is mainly used for unit test or regression test when it is impossible to trigger some exceptions through normal means.
34
+
35
+ Each debug point has a name, the name can be whatever you want, there are swithes to enable and disable debug points,
36
+
37
+ and you can also pass data to debug points.
38
+
39
+ Both FE and BE support debug point, and after inserting debug point code, recompilation of FE or BE is needed.
32
40
33
41
## Code Example
34
42
35
43
FE example
36
44
37
45
``` java
38
46
private Status foo() {
39
- // dbug_fe_foo_do_nothing is the debug point name.
40
- // When it's active, DebugPointUtil.isEnable("dbug_fe_foo_do_nothing") will return true.
47
+ // dbug_fe_foo_do_nothing is the debug point name
48
+ // when it's active, DebugPointUtil.isEnable("dbug_fe_foo_do_nothing") returns true
41
49
if (DebugPointUtil . isEnable(" dbug_fe_foo_do_nothing" )) {
42
50
return Status . Nothing ;
43
51
}
@@ -48,46 +56,50 @@ private Status foo() {
48
56
}
49
57
```
50
58
51
- BE 桩子示例代码
59
+ BE example
52
60
53
61
``` c++
54
62
void Status foo () {
55
- // dbug_be_foo_do_nothing is the debug point name.
56
- // When it's active,DEBUG_EXECUTE_IF will execute the code block.
57
- DEBUG_EXECUTE_IF ("dbug_be_foo_do_nothing", { return Status.Nothing; });
63
+ // dbug_be_foo_do_nothing is the debug point name
64
+ // when it's active, DBUG_EXECUTE_IF will execute the code block
65
+ DBUG_EXECUTE_IF ("dbug_be_foo_do_nothing", { return Status.Nothing; });
58
66
59
67
do_foo_action ();
60
68
61
69
return Status.Ok;
62
70
}
63
71
```
64
72
65
- ## Global config
66
73
67
- To activate debug points, need set ` enable_debug_points ` to true.
74
+ ## Global Config
75
+
76
+ To enable debug points globally, we need to set ` enable_debug_points ` to true,
77
+
78
+ ` enable_debug_points ` is located in FE's fe.conf and BE's be.conf.
68
79
69
- ` enable_debug_points ` was located in FE's fe.conf and BE's be.conf。
70
80
81
+ ## Activate A Specified Debug Point
71
82
72
- ## Enable Debug Point
83
+ After debug points are enabled globally, a http request with a debug point name should be send to FE or BE node, <br />
84
+ only after that, when the program running into the specified debug point, related code can be executed.
73
85
74
86
### API
75
87
76
88
```
77
- POST /api/debug_point/add/{debug_point_name}[?timeout=<int>&execute=<int>]
89
+ POST /api/debug_point/add/{debug_point_name}[?timeout=<int>&execute=<int>]
78
90
```
79
91
80
92
81
93
### Query Parameters
82
94
83
95
* ` debug_point_name `
84
- Debug point name. Require .
96
+ Debug point name. Required .
85
97
86
98
* ` timeout `
87
- Timeout in seconds. When timeout, the debug point will be disable . Default is -1, not timeout. Optional.
99
+ Timeout in seconds. When timeout, the debug point will be deactivated . Default is -1, never timeout. Optional.
88
100
89
101
* ` execute `
90
- Max active times。 Default is -1, unlimit active times. Optional.
102
+ After activating, the max times the debug point can be executed. Default is -1, unlimited times. Optional.
91
103
92
104
93
105
### Request body
@@ -96,24 +108,105 @@ None
96
108
97
109
### Response
98
110
99
- ```
100
- {
101
- msg: "OK",
102
- code: 0
103
- }
104
- ```
111
+ ```
112
+ {
113
+ msg: "OK",
114
+ code: 0
115
+ }
116
+ ```
105
117
106
118
### Examples
107
119
108
120
109
- Enable debug point ` foo ` , activate no more than five times.
121
+ After activating debug point ` foo ` , executed no more than five times.
110
122
111
123
112
- ```
113
- curl -X POST "http://127.0.0.1:8030/api/debug_point/add/foo?execute=5 "
124
+ ```
125
+ curl -X POST "http://127.0.0.1:8030/api/debug_point/add/foo?execute=5"
126
+
127
+ ```
128
+
129
+
130
+ ## Pass Custom Parameters
131
+ When activating debug point, besides "timeout" and "execute" mentioned above, passing custom parameters is also allowed.<br />
132
+ A parameter is a key-value pair in the form of "key=value" in url path, after debug point name glued by charactor '?'.<br />
133
+ See examples below.
134
+
135
+ ### API
136
+
137
+ ```
138
+ POST /api/debug_point/add/{debug_point_name}[?k1=v1&k2=v2&k3=v3...]
139
+ ```
140
+ * ` k1=v1 ` <br />
141
+ k1 is parameter name <br />
142
+ v1 is parameter value <br />
143
+ multiple key-value pairs are concatenated by ` & ` <br />
144
+
145
+
146
+
147
+ ### Request body
148
+
149
+ None
150
+
151
+ ### Response
152
+
153
+ ```
154
+ {
155
+ msg: "OK",
156
+ code: 0
157
+ }
158
+ ```
159
+
160
+ ### Examples
161
+ Assuming a FE node with configuration http_port=8030 in fe.conf, <br />
162
+ the following http request activates a debug point named ` foo ` in FE node and passe parameter ` percent ` and ` duration ` :
163
+ > NOTE: User name and password may be needed.
164
+ ```
165
+ curl -u root: -X POST "http://127.0.0.1:8030/api/debug_point/add/foo?percent=0.5&duration=3"
166
+ ```
167
+
168
+ ```
169
+ NOTE:
170
+ 1. Inside FE and BE code, names and values of parameters are taken as strings.
171
+ 2. Parameter names and values are case sensitive in http request and FE/BE code.
172
+ 3. FE and BE share same url paths of REST API, it's just their IPs and Ports are different.
173
+ ```
174
+
175
+ ### Use parameters in FE and BE code
176
+ Following request activates debug point ` OlapTableSink.write_random_choose_sink ` in FE and passes parameter ` needCatchUp ` and ` sinkNum ` :
177
+ ```
178
+ curl -u root: -X POST "http://127.0.0.1:8030/api/debug_point/add/OlapTableSink.write_random_choose_sink?needCatchUp=true&sinkNum=3"
179
+ ```
180
+
181
+ The code in FE checks debug point ` OlapTableSink.write_random_choose_sink ` and gets parameter values:
182
+ ``` java
183
+ private void debugWriteRandomChooseSink(Tablet tablet, long version, Multimap<Long , Long > bePathsMap) {
184
+ DebugPoint debugPoint = DebugPointUtil . getDebugPoint(" OlapTableSink.write_random_choose_sink" );
185
+ if (debugPoint == null ) {
186
+ return ;
187
+ }
188
+ boolean needCatchup = debugPoint. param(" needCatchUp" , false );
189
+ int sinkNum = debugPoint. param(" sinkNum" , 0 );
190
+ ...
191
+ }
192
+ ```
193
+
194
+ Following request activates debug point ` TxnManager.prepare_txn.random_failed ` in BE and passes parameter ` percent ` :
195
+ ```
196
+ curl -X POST "http://127.0.0.1:8040/api/debug_point/add/TxnManager.prepare_txn.random_failed?percent=0.7
197
+ ```
198
+
199
+ The code in BE checks debug point ` TxnManager.prepare_txn.random_failed ` and gets parameter value:
200
+ ``` c++
201
+ DBUG_EXECUTE_IF ("TxnManager.prepare_txn.random_failed",
202
+ {if (rand() % 100 < (100 * dp->param("percent", 0.5))) {
203
+ LOG_WARNING("TxnManager.prepare_txn.random_failed random failed");
204
+ return Status::InternalError("debug prepare txn random failed");
205
+ }}
206
+ );
207
+ ```
208
+
114
209
115
- ```
116
-
117
210
## Disable Debug Point
118
211
119
212
### API
@@ -137,10 +230,10 @@ None
137
230
### Response
138
231
139
232
```
140
- {
141
- msg: "OK",
142
- code: 0
143
- }
233
+ {
234
+ msg: "OK",
235
+ code: 0
236
+ }
144
237
```
145
238
146
239
### Examples
@@ -149,17 +242,17 @@ None
149
242
Disable debug point ` foo ` 。
150
243
151
244
152
- ```
153
- curl -X POST "http://127.0.0.1:8030/api/debug_point/remove/foo "
245
+ ```
246
+ curl -X POST "http://127.0.0.1:8030/api/debug_point/remove/foo"
154
247
155
- ```
248
+ ```
156
249
157
250
## Clear Debug Points
158
251
159
252
### API
160
253
161
254
```
162
- POST /api/debug_point/clear
255
+ POST /api/debug_point/clear
163
256
```
164
257
165
258
@@ -170,16 +263,78 @@ None
170
263
171
264
### Response
172
265
173
- ```
174
- {
175
- msg: "OK",
176
- code: 0
177
- }
178
- ```
266
+ ```
267
+ {
268
+ msg: "OK",
269
+ code: 0
270
+ }
271
+ ```
179
272
180
273
### Examples
181
274
182
275
183
- ```
184
- curl -X POST "http://127.0.0.1:8030/api/debug_point/clear"
185
- ```
276
+ ```
277
+ curl -X POST "http://127.0.0.1:8030/api/debug_point/clear"
278
+ ```
279
+
280
+ ## Debug Points in Regression Test
281
+
282
+ > In community's CI system, ` enable_debug_points ` configuration of FE and BE are true by default.
283
+
284
+ The Regression test framework also provides methods to activate and deactivate a particular debug point, <br />
285
+ they are declared as below:
286
+ ``` groovy
287
+ // "name" is the debug point to activate, "params" is a list of key-value pairs passed to debug point
288
+ def enableDebugPointForAllFEs(String name, Map<String, String> params = null);
289
+ def enableDebugPointForAllBEs(String name, Map<String, String> params = null);
290
+ // "name" is the debug point to deactivate
291
+ def disableDebugPointForAllFEs(String name);
292
+ def disableDebugPointForAllFEs(String name);
293
+ ```
294
+ ` enableDebugPointForAllFEs() ` or ` enableDebugPointForAllBEs() ` needs to be called before the test actions you want to generate error, <br />
295
+ and ` disableDebugPointForAllFEs() ` or ` disableDebugPointForAllBEs() ` needs to be called afterward.
296
+
297
+ ### Concurrent Issue
298
+
299
+ Enabled debug points affects FE or BE globally, which could cause other concurrent tests to fail unexpectly in your pull request. <br />
300
+ To avoid this, there's a convension that regression tests using debug points must be in directory regression-test/suites/fault_injection_p0, <br />
301
+ and their group name must be "nonConcurrent", as these regression tests will be executed serially by pull request workflow.
302
+
303
+ ### Examples
304
+
305
+ ``` groovy
306
+ // .groovy file of the test case must be in regression-test/suites/fault_injection_p0
307
+ // and the group name must be 'nonConcurrent'
308
+ suite('debugpoint_action', 'nonConcurrent') {
309
+ try {
310
+ // Activate debug point named "PublishVersionDaemon.stop_publish" in all FE
311
+ // and pass parameter "timeout"
312
+ // "execute" and "timeout" are pre-existing parameters, usage is mentioned above
313
+ GetDebugPoint().enableDebugPointForAllFEs('PublishVersionDaemon.stop_publish', [timeout:1])
314
+
315
+ // Activate debug point named "Tablet.build_tablet_report_info.version_miss" in all BE
316
+ // and pass parameter "tablet_id", "version_miss" and "timeout"
317
+ GetDebugPoint().enableDebugPointForAllBEs('Tablet.build_tablet_report_info.version_miss',
318
+ [tablet_id:'12345', version_miss:true, timeout:1])
319
+
320
+ // Test actions which will run into debug point and generate error
321
+ sql """CREATE TABLE tbl_1 (k1 INT, k2 INT)
322
+ DUPLICATE KEY (k1)
323
+ DISTRIBUTED BY HASH(k1)
324
+ BUCKETS 3
325
+ PROPERTIES ("replication_allocation" = "tag.location.default: 1");
326
+ """
327
+ sql "INSERT INTO tbl_1 VALUES (1, 10)"
328
+ sql "INSERT INTO tbl_1 VALUES (2, 20)"
329
+ order_qt_select_1_1 'SELECT * FROM tbl_1'
330
+
331
+ } finally {
332
+ // Deactivate debug points
333
+ GetDebugPoint().disableDebugPointForAllFEs('PublishVersionDaemon.stop_publish')
334
+ GetDebugPoint().disableDebugPointForAllBEs('Tablet.build_tablet_report_info.version_miss')
335
+ }
336
+ }
337
+ ```
338
+
339
+
340
+
0 commit comments