Add audit selection group, audit report and event logger setup to CI-Eng-Sample

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Clio Liu 2026-10-01 17:15:27 +10:00
parent 668a1d2e31
commit 4b0f92b147
6 changed files with 99 additions and 3 deletions

View file

@ -0,0 +1,42 @@
@LANGUAGE
ENGLISH
@VERSION
1.03.00
! CI-Eng-Sample audit trail examples, CI Server R1.03.00. Load after 18_report_df.
! CIENG_ITEMS : AUDIT Service selection group = events on CI-Eng-Sample objects. Expressions
! have no LIKE: a name prefix is matched with >= "CI-Eng-Sample." and
! < "CI-Eng-Sample/" ('/' sorts right after '.'). COMPILE 1 compiles on load;
! the result is in LISTING and VALID_EXPRESSION.
! CIENG_AUDIT : ad-hoc report of the audit events on CI-Eng-Sample of the last hour.
@FIELDS
NAME,DESCRIPTION,EXPRESSION,COMPILE
@AUDIT_SELGRP_DF
"CIENG_ITEMS","Audit events on CI-Eng-Sample",@"
sbid >= "CI-Eng-Sample." and sbid < "CI-Eng-Sample/"
"@,1
@FIELDS
NAME,DESCRIPTION,PRIORITY,ADHOC_ENABLED,LIFE_TIME,ADHOC_DEST,QUERY
@REPORT_DF
"CIENG_AUDIT","CI-Eng-Sample audit trail, last hour",0,1,"1 Weeks","CIENG_FILE",@"
/* Who changed what on CI-Eng-Sample in the last hour */
set @width 160;
column t as 'DD-MM-YYYY hh:mm:ss' heading 'Time';
column grp as 'A12' heading 'Subject';
column attr as 'A16' heading 'Attribute';
column act as 'A8' heading 'Action';
column src as 'A12' heading 'Source';
column id as 'A32' heading 'Name';
column usr as 'A18' heading 'User';
column ov as 'A12' heading 'Old';
column nv as 'A12' heading 'New';
select action_time t, subject_group grp, subject_attribute attr, subject_action act,
subject_source src, subject_ident id, user_name usr, old_value ov, new_value nv
from audit_trail
where action_time > @date - 3600 and subject_ident like 'CI-Eng-Sample.%'
order by action_time;
"@

View file

@ -0,0 +1,19 @@
@LANGUAGE
ENGLISH
@VERSION
1.03.00
! Remove the CI-Eng-Sample audit report and selection group. Audit trail records themselves
! cannot be deleted (only whole units of storage group ADT, HISTORY Service).
@FIELDS
NAME
@REPORT_DF
"CIENG_AUDIT"
@FIELDS
NAME
@AUDIT_SELGRP_DF
"CIENG_ITEMS"

View file

@ -77,6 +77,8 @@ cmd /c "<repo>\examples\CI-Eng-Sample\remove.cmd"
| `CIENG_TANK1` | Report | Values of the `TANK1` items + last-hour statistics of one item (ad-hoc parameter chosen in an item browser, default `LEVEL`); daily 06:00 local time and ad hoc; output `CIENG_FILE`; lifetime 1 week | | `CIENG_TANK1` | Report | Values of the `TANK1` items + last-hour statistics of one item (ad-hoc parameter chosen in an item browser, default `LEVEL`); daily 06:00 local time and ad hoc; output `CIENG_FILE`; lifetime 1 week |
| `CIENG_INFLOW_HI` | Report | Generated 5 s after `TANK1.INFLOW` rises above 400; output `CIENG_FILE` | | `CIENG_INFLOW_HI` | Report | Generated 5 s after `TANK1.INFLOW` rises above 400; output `CIENG_FILE` |
| `CIENG_HTML` | Report | Ad hoc; `TANK1` values as an HTML table (cursor loop) plus the logbook text | | `CIENG_HTML` | Report | Ad hoc; `TANK1` values as an HTML table (cursor loop) plus the logbook text |
| `CIENG_AUDIT` | Report | Ad hoc; audit trail events on `CI-Eng-Sample.*` of the last hour |
| `CIENG_ITEMS` | Audit selection group | Expression `sbid >= "CI-Eng-Sample." and sbid < "CI-Eng-Sample/"`, compiled on load |
Items created by objects (`TANK1.CALC.VOLUME`, `TANK1.JFLOW.sPerMin`) and their sections are Items created by objects (`TANK1.CALC.VOLUME`, `TANK1.JFLOW.sPerMin`) and their sections are
deleted with the objects; they are not in `02_item_df.qli`. deleted with the objects; they are not in `02_item_df.qli`.
@ -102,9 +104,11 @@ New items start with status 13 (`NOT INIT`) until a value is written.
| `16_item_alarm_df.qli` | Switch on alarming for `TANK1.LEVEL` (loaded with `dssqld -m`) | | `16_item_alarm_df.qli` | Switch on alarming for `TANK1.LEVEL` (loaded with `dssqld -m`) |
| `17_printer_df.tpl`, `17_printer_df.ps1` | Report file device and destination; the script fills in this system's node name and `%TLS_LST_PATH%` and writes `17_printer_df.qli` (not in the repo) | | `17_printer_df.tpl`, `17_printer_df.ps1` | Report file device and destination; the script fills in this system's node name and `%TLS_LST_PATH%` and writes `17_printer_df.qli` (not in the repo) |
| `18_report_df.qli` | Reports (`REPORT_DF`, RQL in the `QUERY` memo) | | `18_report_df.qli` | Reports (`REPORT_DF`, RQL in the `QUERY` memo) |
| `19_audit_df.qli` | Audit selection group (`AUDIT_SELGRP_DF`) and audit report |
| `audit/adtlogci.sup` | Setup file for an extra audit event logger `ADTLOGCI` filtered on `CIENG_ITEMS` (copied to `tls\sup` by an administrator, not by `load.cmd`) |
| `83a_stop_report_df.qli` | Clears the schedule of `CIENG_TANK1` before removal (a scheduled report cannot be deleted) | | `83a_stop_report_df.qli` | Clears the schedule of `CIENG_TANK1` before removal (a scheduled report cannot be deleted) |
| `equipment/eqpciengslv_start.cmd`, `_stop.cmd` | Start/stop the Modbus slave mirror (copy to `tls\com`) | | `equipment/eqpciengslv_start.cmd`, `_stop.cmd` | Start/stop the Modbus slave mirror (copy to `tls\com`) |
| `76_`…`93_remove_*.qli` | Names to delete, in reverse order (reports and printer `83`/`84` first, alarm definitions last, `93`) | | `76_`…`93_remove_*.qli` | Names to delete, in reverse order (audit `79`, reports and printer `83`/`84` first, alarm definitions last, `93`) |
| `load.cmd`, `remove.cmd` | Run the steps in the right order | | `load.cmd`, `remove.cmd` | Run the steps in the right order |
| `displays/CIENG_Tank.xml` | Display (HTML mode): title, number field on `TANK1.LEVEL`, alarm overview, trend of `TANK1.LEVEL`, button *Operator layout* | | `displays/CIENG_Tank.xml` | Display (HTML mode): title, number field on `TANK1.LEVEL`, alarm overview, trend of `TANK1.LEVEL`, button *Operator layout* |
| `displays/CIENG_Menu.xml` | Navigation display (200 x 700): *Tank 1*, *Current Alarm* (main frame), *Tank 1 popup* (layout `popup`) | | `displays/CIENG_Menu.xml` | Navigation display (200 x 700): *Tank 1*, *Current Alarm* (main frame), *Tank 1 popup* (layout `popup`) |
@ -185,7 +189,8 @@ gets its own storage group of type *Report*. Try them (skill `reporting`, task `
- Ad hoc: `REPORT_DF` `NAME,PARAM_VALUE_1,GENERATE` = `"CIENG_TANK1","CI-Eng-Sample.TANK1.INFLOW",1` - Ad hoc: `REPORT_DF` `NAME,PARAM_VALUE_1,GENERATE` = `"CIENG_TANK1","CI-Eng-Sample.TANK1.INFLOW",1`
with `dssqld -m`, or in the Engineering Module *Configuration > Reporting > Reports* › right-click with `dssqld -m`, or in the Engineering Module *Configuration > Reporting > Reports* › right-click
› *Generate*. The output lands in `%TLS_LST_PATH%\cieng_report.txt` and in `REPORT_VAL`. › *Generate*. The output lands in `REPORT_VAL`; runs from the Engineering Module also print to
`%TLS_LST_PATH%\cieng_report.txt` (runs from `dssqld` do not print, ISS-045).
- Trigger: `itmval -p -n CI-Eng-Sample.TANK1.INFLOW -v 450` → `CIENG_INFLOW_HI` 5 s later; write a - Trigger: `itmval -p -n CI-Eng-Sample.TANK1.INFLOW -v 450` → `CIENG_INFLOW_HI` 5 s later; write a
value below 400 before the next test. value below 400 before the next test.
- `CIENG_TANK1` also runs every day at 06:00 (local time). - `CIENG_TANK1` also runs every day at 06:00 (local time).
@ -193,6 +198,22 @@ gets its own storage group of type *Report*. Try them (skill `reporting`, task `
`remove.cmd` clears the schedule, removes the reports (with their generated reports and logbook `remove.cmd` clears the schedule, removes the reports (with their generated reports and logbook
files), the destination and device, and deletes `cieng_report.txt`. files), the destination and device, and deletes `cieng_report.txt`.
## Audit trail
No admin rights needed for `19_audit_df.qli`. Every change made by `load.cmd`, `dssqld` or the
Engineering Module is in the audit trail (skill `audit-trail`):
- Generate `CIENG_AUDIT` (ad hoc, like the other reports) to list the last hour of changes on
`CI-Eng-Sample.*`: time, dataset, field, action, source, user, old and new value.
- Export: `dssqld -e audit.qlo -d AUDIT_TRAIL` (whole trail) or a qli with `@SELECT` (keep `NAME`
in `@FIELDS`).
- Event logger (optional, admin): copy `audit\adtlogci.sup` to `%TLS_ROOT_PATH%\tls\sup\`, then
run `adtlog -n adtlogci` in a console; it prints each new CI-Eng-Sample event on one line
(Ctrl+C to stop). Delete the file from `tls\sup` when the sample is removed.
Audit records themselves cannot be deleted; `remove.cmd` removes only the report and the
selection group.
## Planned additions ## Planned additions
| Phase | Adds | | Phase | Adds |

View file

@ -0,0 +1,11 @@
! CI-Eng-Sample: setup file for an extra AUDIT Service event logger (ADTLOG) named ADTLOGCI.
! A setup file is named after the process; copy this file to %TLS_ROOT_PATH%\tls\sup (admin)
! and start the logger with: adtlog -n adtlogci
! It prints only events of selection group CIENG_ITEMS (load 19_audit_df.qli first; the
! group must have compiled, else the logger exits). Output goes to stdout (no PRT_DEV).
! Keywords: see adtsys.sup (template) and knowledge/manuals/IM36K10L25-01EN.md.
SEL_GROUP = "CIENG_ITEMS"
TIMEFMT = "DD-MM-YYYY hh:mm:ss"
E_LAYOUT = ACTM,19,SBGP,12,SATR,14,SACT,8,SACS,12,SBID,32,USER,18,OVAL,12,NVAL,12
HEADER = "Time Subject Attribute Action Source Name User Old New"
HEADER_AFTER = 20

View file

@ -42,3 +42,5 @@ rem from 17_printer_df.tpl), then the report definitions.
powershell -NoProfile -ExecutionPolicy Bypass -File 17_printer_df.ps1 powershell -NoProfile -ExecutionPolicy Bypass -File 17_printer_df.ps1
dssqld -i 17_printer_df.qli -l 17_printer_df.qlo dssqld -i 17_printer_df.qli -l 17_printer_df.qlo
dssqld -i 18_report_df.qli -l 18_report_df.qlo dssqld -i 18_report_df.qli -l 18_report_df.qlo
rem Audit trail: selection group (compiled on load) and an ad-hoc audit report.
dssqld -i 19_audit_df.qli -l 19_audit_df.qlo

View file

@ -1,10 +1,11 @@
@echo off @echo off
rem Remove CI-Eng-Sample from a CI Server R1.03 TEST system (also deletes its history). rem Remove CI-Eng-Sample from a CI Server R1.03 TEST system (also deletes its history).
rem Run in an elevated prompt while CI Server is running; call this script by full path. rem Run in an elevated prompt while CI Server is running; call this script by full path.
rem Order: reports, printer, OPC UA, Modbus, auth group, object, class, trigger group, storage links, stop + delete storage groups, items, sections (children first). rem Order: audit report + selection group, reports, printer, OPC UA, Modbus, auth group, object, class, trigger group, storage links, stop + delete storage groups, items, sections (children first).
rem A storage group with an active unit cannot be deleted (HIS-E-GROUPHASUNT), so the rem A storage group with an active unit cannot be deleted (HIS-E-GROUPHASUNT), so the
rem group first gets a stop time one minute ahead; the script waits until it has passed. rem group first gets a stop time one minute ahead; the script waits until it has passed.
cd /d "%~dp0" cd /d "%~dp0"
dssqld -r 79_remove_audit_df.qli -l 79_remove_audit_df.qlo
rem Reports first (they refer to TANK1.INFLOW and the destination), then destination and device. rem Reports first (they refer to TANK1.INFLOW and the destination), then destination and device.
rem A scheduled report cannot be deleted, so its schedule is cleared first. rem A scheduled report cannot be deleted, so its schedule is cleared first.
dssqld -m 83a_stop_report_df.qli -l 83a_stop_report_df.qlo dssqld -m 83a_stop_report_df.qli -l 83a_stop_report_df.qlo