Skip to content

Commit

Permalink
Merge pull request #173 from mbehr1/feat/ecu_apid_ctid_regex
Browse files Browse the repository at this point in the history
feat: regex support for ecu, apid, ctid
  • Loading branch information
mbehr1 authored Nov 11, 2023
2 parents 922f70e + edda8f1 commit 8ae507c
Show file tree
Hide file tree
Showing 7 changed files with 969 additions and 470 deletions.
17 changes: 16 additions & 1 deletion docs/dlt-logs/docs/filterReference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ attribute name | expected type | default value | description
`type`| number | none | Mandatory type. Use `0` for positive, `1` for negative, `2` for marker and `3` for event based filter.
`mstp`| number | undefined | Message type. `0` for `TYPE_LOG`, `1`for `TYPE_APP_TRACE`, `2` for `TYPE_NW_TRACE`, `3` for `TYPE_CONTROL`.
`ecu`| string | undefined| ECU identifier / ECU. Up to 4 characters.
`ecuIsRegex` | boolean | no value = 'autodetect' | Optional. See `apidIsRegex`.
`apid`| string | undefined| Application identifier / APID . Up to 4 characters.
`apidIsRegex` | boolean | no value = 'autodetect' | Optional. If provided the apid is treated according to the value as true:regex, false:no regex. If not provided the apid is treated as regex if it contains any special regex characters: `^$*+?()[]{}|.-\=!<,`
`ctid`| string | undefined| Context identifier / CTID. Up to 4 characters.
`ctidIsRegex` | boolean | no value = 'autodetect' | Optional. See `apidIsRegex`.
`logLevelMin`| number | undefined| Minimum log-level. I.e. log-level of the message has to be >= to match. If specified `mstp`is automatically set to 0. See [Log levels](#log-levels) for values and examples.
`logLevelMax`| number | undefined| Same as `logLevelMin`but for the maximum log-level, i.e. log-level of the message has to be <= `logLevelMax` to match. See [Log levels](#log-levels) for values and examples.
`verbose`| boolean | undefined| `verbose` or `non-verbose` messages. Verbose flag is part of the extended header of a DLT msg and defaults to false if the ext. header doesn't exist.
Expand All @@ -64,6 +67,8 @@ To speed up the match-comparision it's usually a good practice to specify as man

`ecu` should only be used in cases when you deal with DLT-files that have multiple ECUs logs in the same file. See [configs](configsReference) for an alternative way to quickly disable filters not relevant for the current ECU.

For `apid` and `ctid` the regular expressions are roughly 6 times slower (e.g. 35ns vs 6ns) and should only be used if necessary.

Payload text checks should use `payloadRegex` instead of `payload` except for the cases where you really do want to search simply for substring somewhere in the payload. The amount of necessary steps during regex comparision are nicely shown on pages like [regex101](https://regex101.com).

E.g. to match for messages with
Expand All @@ -73,6 +78,16 @@ E.g. to match for messages with
`^Operation .*? failed` (53 steps) is faster than `Operation .* failed` (70 steps for 3 test strings).
:::

:::tip ecu, apid, ctid regular expressions
In general the filter for ecu, apid, ctid expect 4 characters. If less characters are used the regex search is different that the default/non-regex ones:
e.g.
version | example | description
------- | ------- | -----------
default | `"apid":"ECU"` | default/non-regex matches against `apid ECU\0`. So starting with ECU and then (null byte).
`"apidIsRegex":true`| `"apid":"ECU"` | regex matches against 'ECU' within apid. So e.g. "ECU1" or "AECU" or "ECU" all match.
regex | `"apid":"^ECU"` | autodetected regex matches against starting with 'ECU'. So e.g. "ECU" or "ECU1" match but not "AECU".
:::

:::warning
Especially the `payloadRegex` consists frequently of characters that need to be escaped in JSON.
If using the DLT filter assistant to create filters this is done automatically. If you modify the JSON settings manually please keep this in mind and escape the strings properly.
Expand Down Expand Up @@ -173,4 +188,4 @@ Example:
"overviewRulerLane":1, // left
"overviewRulerColor":"yellow"
}
```
```
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -943,7 +943,7 @@
"ws": "^8.13.0"
},
"optionalDependencies": {
"node-adlt": "0.42.1"
"node-adlt": "0.43.0"
},
"commitlint": {
"extends": [
Expand Down
31 changes: 28 additions & 3 deletions src/dltAddEditFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,9 @@ export function editFilter(doc: FilterableDocument & ReportDocument, newFilter:
}

let stepInput = new MultiStepInput(`${isAdd ? 'add' : 'edit'} filter...`, [
{ title: `filter on ECU?`, items: ecus, initialValue: () => { return newFilter.ecu; }, placeholder: 'enter or select the ECU to filter (if any)', onValue: (v) => { newFilter.ecu = v.length ? v : undefined; }, isValid: (v => (v.length <= 4)) },
{ title: `filter on APID?`, items: apids, initialValue: () => { return newFilter.apid; }, onValue: (v) => { newFilter.apid = v.length ? v : undefined; }, isValid: (v => (v.length <= 4)) },
{ title: `filter on CTID?`, items: () => ctids.filter(v => { return newFilter.apid !== undefined ? v.data.apids.includes(newFilter.apid) : true; }), initialValue: () => { return newFilter.ctid; }, onValue: (v) => { newFilter.ctid = v.length ? v : undefined; }, isValid: (v => (v.length <= 4)) },
{ title: `filter on ECU?`, items: ecus, initialValue: () => { return newFilter.ecu instanceof RegExp ? newFilter.ecu.source : newFilter.ecu; }, placeholder: 'enter or select the ECU to filter (if any)', onValue: (v) => { newFilter.ecu = onValueChar4OrRegex(newFilter.ecu, v); }, isValid: (v => (v.length <= 4 || util.containsRegexChars(v))) },
{ title: `filter on APID?`, items: apids, initialValue: () => { return newFilter.apid instanceof RegExp ? newFilter.apid.source : newFilter.apid; }, onValue: (v) => { newFilter.apid = onValueChar4OrRegex(newFilter.apid, v); }, isValid: (v => (v.length <= 4 || util.containsRegexChars(v))) },
{ title: `filter on CTID?`, items: () => ctids.filter(v => { return ctidFilter(newFilter.apid, v.data.apids); }), initialValue: () => { return newFilter.ctid instanceof RegExp ? newFilter.ctid.source : newFilter.ctid; }, onValue: (v) => { newFilter.ctid = onValueChar4OrRegex(newFilter.ctid, v); }, isValid: (v => (v.length <= 4 || util.containsRegexChars(v))) },
{ title: `filter on payload?`, items: optArgs !== undefined && optArgs.payload !== undefined ? [new PickItem(optArgs.payload)] : [], initialValue: () => { return newFilter.payload; }, onValue: (v) => { newFilter.payload = v.length ? v : undefined; } },
{ title: `filter on payloadRegex?`, items: optArgs !== undefined && optArgs.payload !== undefined ? [new PickItem(optArgs.payload)] : [], initialValue: () => { return newFilter.payloadRegex?.source; }, onValue: (v) => { newFilter.payloadRegex = v.length ? new RegExp(v) : undefined; }, isValid: (v => { try { let r = new RegExp(v); return true; } catch (err) { return false; } }) },
{ title: `filter type?`, items: [new PickItem(filterTypesByNumber.get(0)!), new PickItem(filterTypesByNumber.get(1)!), new PickItem(filterTypesByNumber.get(2)!)], initialValue: () => { return filterTypesByNumber.get(newFilter.type); }, onValue: (v) => { let t = filterTypesByName.get(v); if (t !== undefined) { newFilter.type = t; } }, isValid: (v => (filterTypesByName.has(v))) },
Expand All @@ -211,6 +211,31 @@ export function editFilter(doc: FilterableDocument & ReportDocument, newFilter:
});
}

function ctidFilter(apid: string|RegExp|undefined, apids:string[]):boolean {
if (apid === undefined){
return true; // no apid -> all ctids
}
if (apid instanceof RegExp){
return apids.some(a => apid.test(a));
} else {
return apids.includes(apid);
}
}

function onValueChar4OrRegex(oldValue: string | RegExp | undefined, newValue: string): string | RegExp | undefined {
if (newValue.length) {
const oldWasRegEx = oldValue instanceof RegExp;
const lastValue = oldWasRegEx ? (oldValue as RegExp).source : oldValue;
if (newValue === lastValue) {
return oldValue; // we keep the type
} else {
return util.containsRegexChars(newValue) ? new RegExp(newValue) : newValue;
}
} else {
return undefined;
}
}

// from npm color-names: (import of 2.0 module does export as single elements and not as one object with all keys)
const colors = {
aliceblue: [240, 248, 255],
Expand Down
Loading

0 comments on commit 8ae507c

Please sign in to comment.