Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 1 | Here I will write down some specifics of certain parts of the source, these are |
| 2 | just some of my thoughts and clues and they are probably not too important for |
| 3 | a wider audience. |
| 4 | |
| 5 | src/parser.c |
| 6 | ------------------------------------------------------------------------------ |
| 7 | The first thing to run when starting the HAProxy is the flt_ot_parse() function |
| 8 | which actually parses the filter configuration. |
| 9 | |
| 10 | In case of correct configuration, the function returns ERR_NONE (or 0), while |
| 11 | in case of incorrect configuration it returns the combination of ERR_* flags |
| 12 | (ERR_NONE here does not belong to that bit combination because its value is 0). |
| 13 | |
| 14 | One of the parameters of the function is <char **err> in which an error message |
| 15 | can be returned, if it exists. In that case the return value of the function |
| 16 | should have some of the ERR_* flags set. |
| 17 | |
| 18 | Let's look at an example of the following filter configuration what the function |
| 19 | call sequence looks like. |
| 20 | |
| 21 | Filter configuration line: |
| 22 | filter opentracing [id <id>] config <file> |
| 23 | |
| 24 | Function call sequence: |
| 25 | flt_ot_parse(<err>) { |
| 26 | /* Initialization of the filter configuration data. */ |
| 27 | flt_ot_conf_init() { |
| 28 | } |
| 29 | |
| 30 | /* Setting the filter name. */ |
| 31 | flt_ot_parse_keyword(<err>) { |
| 32 | flt_ot_parse_strdup(<err>) { |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | /* Setting the filter configuration file name. */ |
| 37 | flt_ot_parse_keyword(<err>) { |
| 38 | flt_ot_parse_strdup(<err>) { |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | /* Checking the configuration of the filter. */ |
| 43 | flt_ot_parse_cfg(<err>) { |
| 44 | flt_ot_parse_cfg_tracer() { |
| 45 | } |
| 46 | ... |
| 47 | flt_ot_post_parse_cfg_tracer() { |
| 48 | } |
| 49 | flt_ot_parse_cfg_group() { |
| 50 | } |
| 51 | ... |
| 52 | flt_ot_post_parse_cfg_group() { |
| 53 | } |
| 54 | flt_ot_parse_cfg_scope() { |
| 55 | } |
| 56 | ... |
| 57 | flt_ot_post_parse_cfg_scope() { |
| 58 | } |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | Checking the filter configuration is actually much more complicated, only the |
| 63 | name of the main function flt_ot_parse_cfg() that does it is listed here. |
| 64 | |
| 65 | All functions that use the <err> parameter should set the error status using |
| 66 | that pointer. All other functions (actually these are all functions called |
| 67 | by the flt_ot_parse_cfg() function) should set the error message using the |
| 68 | ha_warning()/ha_alert() HAProxy functions. Of course, the return value (the |
| 69 | mentioned combination of ERR_* bits) is set in all these functions and it |
| 70 | indicates whether the filter configuration is correct or not. |
| 71 | |
| 72 | |
| 73 | src/group.c |
| 74 | ------------------------------------------------------------------------------ |
| 75 | The OT filter allows the use of groups within which one or more 'ot-scope' |
| 76 | declarations can be found. These groups can be used using several HAProxy |
| 77 | rules, more precisely 'http-request', 'http-response', 'tcp-request', |
| 78 | 'tcp-response' and 'http-after-response' rules. |
| 79 | |
| 80 | Configuration example for the specified rules: |
| 81 | <rule> ot-group <filter-id> <group-name> [ { if | unless } <condition> ] |
| 82 | |
| 83 | Parsing each of these rules is performed by the flt_ot_group_parse() function. |
| 84 | After parsing the configuration, its verification is performed via the |
| 85 | flt_ot_group_check() function. One parsing function and one configuration |
| 86 | check function are called for each defined rule. |
| 87 | |
| 88 | flt_ot_group_parse(<err>) { |
| 89 | } |
| 90 | ... |
| 91 | flt_ot_group_check() { |
| 92 | } |
| 93 | ... |
| 94 | |
| 95 | |
| 96 | When deinitializing the module, the function flt_ot_group_release() is called |
| 97 | (which is actually an release_ptr callback function from one of the above |
| 98 | rules). One callback function is called for each defined rule. |
| 99 | |
| 100 | flt_ot_group_release() { |
| 101 | } |
| 102 | ... |
| 103 | |
| 104 | |
| 105 | src/filter.c |
| 106 | ------------------------------------------------------------------------------ |
| 107 | After parsing and checking the configuration, the flt_ot_check() function is |
| 108 | called which associates the 'ot-group' and 'ot-scope' definitions with their |
| 109 | declarations. This procedure concludes the configuration of the OT filter and |
| 110 | after that its initialization is possible. |
| 111 | |
| 112 | flt_ops.check = flt_ot_check; |
| 113 | flt_ot_check() { |
| 114 | } |
| 115 | |
| 116 | |
| 117 | The initialization of the OT filter is done via the flt_ot_init() callback |
| 118 | function. In this function the OpenTracing API library is also initialized. |
| 119 | It is also possible to initialize for each thread individually, but nothing |
| 120 | is being done here for now. |
| 121 | |
| 122 | flt_ops.init = flt_ot_init; |
| 123 | flt_ot_init() { |
| 124 | flt_ot_cli_init() { |
| 125 | } |
| 126 | /* Initialization of the OpenTracing API. */ |
| 127 | ot_init(<err>) { |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | flt_ops.init_per_thread = flt_ot_init_per_thread; |
| 132 | flt_ot_init_per_thread() { |
| 133 | } |
| 134 | ... |
| 135 | |
| 136 | |
| 137 | After the filter instance is created and attached to the stream, the |
| 138 | flt_ot_attach() function is called. In this function a new OT runtime |
| 139 | context is created, and flags are set that define which analyzers are used. |
| 140 | |
| 141 | flt_ops.attach = flt_ot_attach; |
| 142 | flt_ot_attach() { |
| 143 | /* In case OT is disabled, nothing is done on this stream further. */ |
| 144 | flt_ot_runtime_context_init(<err>) { |
| 145 | flt_ot_pool_alloc() { |
| 146 | } |
Miroslav Zagorac | 220a1ad | 2022-02-23 10:28:10 +0100 | [diff] [blame^] | 147 | /* Initializing and setting the variable 'sess.ot.uuid'. */ |
Miroslav Zagorac | 70230c6 | 2020-12-09 16:54:31 +0100 | [diff] [blame] | 148 | if (flt_ot_var_register(<err>) != -1) { |
| 149 | flt_ot_var_set(<err>) { |
| 150 | } |
| 151 | } |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | |
| 156 | When a stream is started, this function is called. At the moment, nothing |
| 157 | is being done in it. |
| 158 | |
| 159 | flt_ops.stream_start = flt_ot_stream_start; |
| 160 | flt_ot_stream_start() { |
| 161 | } |
| 162 | |
| 163 | |
| 164 | Channel analyzers are called when executing individual filter events. |
| 165 | For each of the four analyzer functions, the events associated with them |
| 166 | are listed. |
| 167 | |
| 168 | Events: |
| 169 | - 1 'on-client-session-start' |
| 170 | - 15 'on-server-session-start' |
| 171 | ------------------------------------------------------------------------ |
| 172 | flt_ops.channel_start_analyze = flt_ot_channel_start_analyze; |
| 173 | flt_ot_channel_start_analyze() { |
| 174 | flt_ot_event_run() { |
| 175 | /* Run event. */ |
| 176 | flt_ot_scope_run() { |
| 177 | /* Processing of all ot-scopes defined for the current event. */ |
| 178 | } |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | |
| 183 | Events: |
| 184 | - 2 'on-frontend-tcp-request' |
| 185 | - 4 'on-http-body-request' |
| 186 | - 5 'on-frontend-http-request' |
| 187 | - 6 'on-switching-rules-request' |
| 188 | - 7 'on-backend-tcp-request' |
| 189 | - 8 'on-backend-http-request' |
| 190 | - 9 'on-process-server-rules-request' |
| 191 | - 10 'on-http-process-request' |
| 192 | - 11 'on-tcp-rdp-cookie-request' |
| 193 | - 12 'on-process-sticking-rules-request |
| 194 | - 16 'on-tcp-response' |
| 195 | - 18 'on-process-store-rules-response' |
| 196 | - 19 'on-http-response' |
| 197 | ------------------------------------------------------------------------ |
| 198 | flt_ops.channel_pre_analyze = flt_ot_channel_pre_analyze; |
| 199 | flt_ot_channel_pre_analyze() { |
| 200 | flt_ot_event_run() { |
| 201 | /* Run event. */ |
| 202 | flt_ot_scope_run() { |
| 203 | /* Processing of all ot-scopes defined for the current event. */ |
| 204 | } |
| 205 | } |
| 206 | } |
| 207 | |
| 208 | |
| 209 | Events: |
| 210 | - 3 'on-http-wait-request' |
| 211 | - 17 'on-http-wait-response' |
| 212 | ------------------------------------------------------------------------ |
| 213 | flt_ops.channel_post_analyze = flt_ot_channel_post_analyze; |
| 214 | flt_ot_channel_post_analyze() { |
| 215 | flt_ot_event_run() { |
| 216 | /* Run event. */ |
| 217 | flt_ot_scope_run() { |
| 218 | /* Processing of all ot-scopes defined for the current event. */ |
| 219 | } |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | |
| 224 | Events: |
| 225 | - 13 'on-client-session-end' |
| 226 | - 14 'on-server-unavailable' |
| 227 | - 20 'on-server-session-end' |
| 228 | ------------------------------------------------------------------------ |
| 229 | flt_ops.channel_end_analyze = flt_ot_channel_end_analyze; |
| 230 | flt_ot_channel_end_analyze() { |
| 231 | flt_ot_event_run() { |
| 232 | /* Run event. */ |
| 233 | flt_ot_scope_run() { |
| 234 | /* Processing of all ot-scopes defined for the current event. */ |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | /* In case the backend server does not work, event 'on-server-unavailable' |
| 239 | is called here before event 'on-client-session-end'. */ |
| 240 | if ('on-server-unavailable') { |
| 241 | flt_ot_event_run() { |
| 242 | /* Run event. */ |
| 243 | flt_ot_scope_run() { |
| 244 | /* Processing of all ot-scopes defined for the current event. */ |
| 245 | } |
| 246 | } |
| 247 | } |
| 248 | } |
| 249 | |
| 250 | |
| 251 | After the stream has stopped, this function is called. At the moment, nothing |
| 252 | is being done in it. |
| 253 | |
| 254 | flt_ops.stream_stop = flt_ot_stream_stop; |
| 255 | flt_ot_stream_stop() { |
| 256 | } |
| 257 | |
| 258 | |
| 259 | Then, before the instance filter is detached from the stream, the following |
| 260 | function is called. It deallocates the runtime context of the OT filter. |
| 261 | |
| 262 | flt_ops.detach = flt_ot_detach; |
| 263 | flt_ot_detach() { |
| 264 | flt_ot_runtime_context_free() { |
| 265 | flt_ot_pool_free() { |
| 266 | } |
| 267 | } |
| 268 | } |
| 269 | |
| 270 | |
| 271 | Module deinitialization begins with deinitialization of individual threads |
| 272 | (as many threads as configured for the HAProxy process). Because nothing |
| 273 | special is connected to the process threads, nothing is done in this function. |
| 274 | |
| 275 | flt_ops.deinit_per_thread = flt_ot_deinit_per_thread; |
| 276 | flt_ot_deinit_per_thread() { |
| 277 | } |
| 278 | ... |
| 279 | |
| 280 | |
| 281 | For this function see the above description related to the src/group.c file. |
| 282 | |
| 283 | flt_ot_group_release() { |
| 284 | } |
| 285 | ... |
| 286 | |
| 287 | |
| 288 | Module deinitialization ends with the flt_ot_deinit() function, in which all |
| 289 | memory occupied by module operation (and OpenTracing API operation, of course) |
| 290 | is freed. |
| 291 | |
| 292 | flt_ops.deinit = flt_ot_deinit; |
| 293 | flt_ot_deinit() { |
| 294 | ot_close() { |
| 295 | } |
| 296 | flt_ot_conf_free() { |
| 297 | } |
| 298 | } |