Summary
Add an optional trace mode to the interpretation engine that returns step-by-step details of how each rule in a RuleSet was evaluated against the input string. When enabled via ?trace=true on the HTTP API, the response includes a trace array alongside the existing results.
Example Response (trace enabled)
{
"rulesetId": "GS1_DATAMATRIX",
"input": "01034531200000111719112510ABC123",
"results": [
{ "targetField": "GTIN", "value": "03453120000011" },
{ "targetField": "EXPIRY_DATE", "value": "2019-11-25" },
{ "targetField": "BATCH", "value": "ABC123" }
],
"trace": {
"totalRules": 4,
"matchedRules": 3,
"steps": [
{
"step": 1,
"ruleId": "010",
"type": "MATCH",
"targetField": "GTIN",
"regex": "01(\\d{14})",
"offset": 0,
"matched": true,
"capturedGroup": "03453120000011",
"matchPosition": { "start": 0, "end": 16 },
"resultValue": "03453120000011"
},
{
"step": 2,
"ruleId": "020",
"type": "MATCH",
"targetField": "EXPIRY_RAW",
"regex": "17(\\d{6})",
"offset": 0,
"matched": true,
"capturedGroup": "191125",
"matchPosition": { "start": 16, "end": 24 },
"resultValue": "191125"
},
{
"step": 3,
"ruleId": "030",
"type": "REPLACE",
"targetField": "EXPIRY_DATE",
"regex": "(\\d{2})(\\d{2})(\\d{2})",
"replacePattern": "20$1-$2-$3",
"offset": 0,
"sourceValue": "191125",
"matched": true,
"resultValue": "2019-11-25"
},
{
"step": 4,
"ruleId": "040",
"type": "MATCH",
"targetField": "BATCH",
"regex": "10([A-Za-z0-9]{1,20})",
"offset": 0,
"matched": true,
"capturedGroup": "ABC123",
"matchPosition": { "start": 24, "end": 32 },
"resultValue": "ABC123"
}
]
}
}
Implementation Suggestions
Data Model (new objects)
| Object |
Type |
Description |
zasis_trace_step |
Structure |
Single trace entry: step#, rule_id, type, regex, target_field, matched, raw_match, position_start, position_end, result_value, source_value (for REPLACE), offset_pre, offset_post |
zasis_tt_trace |
Table Type |
Standard table of zasis_trace_step |
Changes to Existing Objects
| Object |
Change |
zasis_interpret_output |
Add optional field trace TYPE zasis_tt_trace |
zasis_if_interpreter~execute |
Add optional parameter with_trace TYPE abap_bool DEFAULT abap_false |
zasis_cl_interpreter |
Inside the rule LOOP, conditionally collect trace data; use FIND ... MATCH OFFSET ... MATCH LENGTH for position tracking in MATCH rules |
zasis_cl_http_handler_core |
Parse ?trace=true query parameter; pass to interpreter; serialize trace in JSON response |
Design Principles
- Zero overhead when off —
IF with_trace = abap_true guard around trace collection; no extra allocations or regex calls when disabled
- Same execution path — Trace observes existing logic, does not alter rule evaluation behavior
- Optional in response — JSON serializer skips empty
trace field; existing consumers see no change
- Position tracking — Replace
match() with FIND ... RESULTS to capture match offset/length (only when trace is active, or always if the overhead is negligible)
Affected Layers
- dm — New structure + table type
- bo — Interpreter interface + implementation
- srv — HTTP handler query param parsing + JSON serialization
- tests — Unit tests for trace output, ICF integration tests for
?trace=true endpoint
Summary
Add an optional trace mode to the interpretation engine that returns step-by-step details of how each rule in a RuleSet was evaluated against the input string. When enabled via
?trace=trueon the HTTP API, the response includes atracearray alongside the existingresults.Example Response (trace enabled)
{ "rulesetId": "GS1_DATAMATRIX", "input": "01034531200000111719112510ABC123", "results": [ { "targetField": "GTIN", "value": "03453120000011" }, { "targetField": "EXPIRY_DATE", "value": "2019-11-25" }, { "targetField": "BATCH", "value": "ABC123" } ], "trace": { "totalRules": 4, "matchedRules": 3, "steps": [ { "step": 1, "ruleId": "010", "type": "MATCH", "targetField": "GTIN", "regex": "01(\\d{14})", "offset": 0, "matched": true, "capturedGroup": "03453120000011", "matchPosition": { "start": 0, "end": 16 }, "resultValue": "03453120000011" }, { "step": 2, "ruleId": "020", "type": "MATCH", "targetField": "EXPIRY_RAW", "regex": "17(\\d{6})", "offset": 0, "matched": true, "capturedGroup": "191125", "matchPosition": { "start": 16, "end": 24 }, "resultValue": "191125" }, { "step": 3, "ruleId": "030", "type": "REPLACE", "targetField": "EXPIRY_DATE", "regex": "(\\d{2})(\\d{2})(\\d{2})", "replacePattern": "20$1-$2-$3", "offset": 0, "sourceValue": "191125", "matched": true, "resultValue": "2019-11-25" }, { "step": 4, "ruleId": "040", "type": "MATCH", "targetField": "BATCH", "regex": "10([A-Za-z0-9]{1,20})", "offset": 0, "matched": true, "capturedGroup": "ABC123", "matchPosition": { "start": 24, "end": 32 }, "resultValue": "ABC123" } ] } }Implementation Suggestions
Data Model (new objects)
zasis_trace_stepzasis_tt_tracezasis_trace_stepChanges to Existing Objects
zasis_interpret_outputtrace TYPE zasis_tt_tracezasis_if_interpreter~executewith_trace TYPE abap_bool DEFAULT abap_falsezasis_cl_interpreterFIND ... MATCH OFFSET ... MATCH LENGTHfor position tracking in MATCH ruleszasis_cl_http_handler_core?trace=truequery parameter; pass to interpreter; serialize trace in JSON responseDesign Principles
IF with_trace = abap_trueguard around trace collection; no extra allocations or regex calls when disabledtracefield; existing consumers see no changematch()withFIND ... RESULTSto capture match offset/length (only when trace is active, or always if the overhead is negligible)Affected Layers
?trace=trueendpoint