ScansorSensors
C# (.NET Framework 4.8) solution with PRTG custom sensors (EXE/advanced sensors). One project per sensor folder, all in ScansorSensors.sln.
Conventions
- Each sensor folder contains:
<Name>.cs,<Name>.csproj,<Name>.json(parameters),desc.json,<slug>.md(documentation),docs/*.html(one page per parameter), optional*.ovl(PRTG value lookups). - Base classes from the NuGet package
Itesys(Itesys.Models):SensorExe(generic) andRFCSensorExe(SAP RFC, providesRFCConnection).Parameters["..."],JSONResult.AddChannel(name, value, unit:, customUnit:, valueLookup:, limitMaxError:, limitMaxWarning:, ...),JSONResult.SetText(...),Error(msg, code)+Abort(),Trace(...).- Each sensor has a unique
protected override int SensorCode. Mainpattern:new Sensor(args); sensor.Execute(); Console.OutputEncoding = UTF8; Console.Write(sensor.PrintResult());
- RFC helpers (
RFCConnection):- Table read:
SetTable/SetFields/SetOptions+ExecuteDatabaseConnection()→List<Dictionary<string,string>>. - FM call:
SetFunction(name, Dictionary<string, dynamic>)+Execute()→IRfcFunction. Limitation (checked via IL of Itesys 2026.8.0.1): it only sets scalars and appends table rows with a single field. For structures or range tables (SIGN/OPTION/LOW) use NCo directly on the framework destination:RfcDestinationManager.GetDestination("SAP")→Repository.CreateFunction(...)→Invoke(destination). - Projects using NCo types need the
sapnco/sapnco_utilsreferences (copy fromSAP_WorkProcess_Monitor.csproj).
- Table read:
- Build (no Python on the dev machine; use PowerShell):
$vs = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -requires Microsoft.Component.MSBuild -find "MSBuild\**\Bin\MSBuild.exe" | Select-Object -First 1
& $vs "<Folder>\<Name>.csproj" /restore /p:Configuration=Release /p:Platform=x64 /v:minimal /nologo - Style: tabs/indentation as in the surrounding file, comments sparse, English.
Work in progress
SAP_BusinessObjects_MonitorV2 (branch TASK-1263)
Replacement for SAP_BusinessObjects_Monitor (old one does not work with BI 2025). SensorCode 106. Uses the BI RESTful web services (/biprws), base URL Protocol://Host:Port.
- Logon:
POST /biprws/logon/longwith XML<attrs xmlns="http://www.sap.com/rws/bip">(userName =SAPUsername, password =SAPPassword, auth =AuthMethod). Token from headerX-SAP-LogonToken(fallback: attrlogonTokenin body). Token is sent quoted inX-SAP-LogonToken. LogoffPOST /biprws/logoffinfinally. - Paged JSON lists (pagesize 50) follow
next.__deferred.uri; only path+query are used because the API returns its internal host (e.g.10.10.16.9:8443). - Channels: Login Status (lookup
itesys.sapbusinessobjectsmonitorv2.loginstatus: 0 OK, 1 not reachable, 2 logon rejected; on failure no other channels), Login Responsetime (ms), one channel per enabled server (lookupitesys.sapbusinessobjectsmonitorv2.serverstatus: 0 Running, 1 running with errors, 2 not running), Servers not running (error > 0), Servers running with errors (warning > 0), Servers disabled, Active User Sessions, System Sessions. - Data sources (verified against a BI 2025 system):
GET /biprws/bionbi/server/list→entries[]withtitle,kind,status_type("Running"/"Stopped"),disabled("Enabled"/"Disabled").GET /biprws/infostore/41/children(Logon Sessions) → entriestype: Connection,name= user; "System Account" = internal sessions; the sensor's own session is subtracted.
- InfoStore findings: detail views (
/biprws/infostore/<id>) only returncuid,name,description,id,type– no status, timestamps or expiry. Folder ids: 24 License Keys, 41 Logon Sessions, 59 Enterprise Nodes, 62 Server Intelligence, 64 Alert Notifications (~850 entries, sorted by name, e.g. "Consolidated Health Watch Caution Event"), 16 Servers. - Open:
- Test
POST /biprws/v1/cmsquery(or/biprws/infostore/cmsquery) on BI 2025. If it works: license expiry, node/SIA status, failed/running instances, recent Danger alerts become possible. Not tested yet. SAP_BusinessObjects_MonitorV2.json:RequiredParametersstill listsOSUsername/OSPassword, code usesSAPUsername/SAPPassword; defaultProtocol=httpvs defaultPort=8443(likely https).desc.jsonanddocs/*.htmlstill describe the old sensor (CMSQueryPort, HTTPPort, Username, Password)..mdis updated.- Not yet run against a real system.
- Test
SAP_AuditLog_Monitor
New sensor (copied from SAP_ApplicationLog_Monitor), reads the Security Audit Log via FM RSAU_API_GET_LOG_DATA (function group RSAU_LOG, SAP_BASIS ≥ 7.50, remote-enabled). SensorCode 107.
- FM interface:
IS_INTERVAL(fieldsDAT_FROM,TIM_FROM,DAT_TO,TIM_TO), range tablesIT_R_MSG,IT_R_MANDT,IT_R_USER,IT_R_TCD,IT_R_REPS,IT_R_INSTANCE; outputsET_LOG,ET_LOG_UTC,ET_FSTAT,ET_RETURN. - Parameters (
SAP_AuditLog_Monitor.json): Minutes (max 1440) →IS_INTERVAL;SAPClient→IT_R_MANDT; Events →IT_R_MSG, Users →IT_R_USER, Tcodes →IT_R_TCD, Programs →IT_R_REPS, Instances →IT_R_INSTANCE.*= no filter, value with*→CP, otherwiseEQ. - Channel: "Audit Log Events" (row count of
ET_LOG); sensor text lists distinct "event (user)". Error codes 051/052 (Minutes), 054 (ABAP exception), 055 (other), 056 (ET_RETURNtype E/A), 057 (preset/FILE: file not found), 058 (invalid preset line). - Presets: parameter
Preset(defaultNONE= no preset, because the framework rejects empty parameters) →SAP_AuditLog_Monitor\<name>[.preset]withkey=valuelines (Minutes, Events, Users, Tcodes, Programs, Instances;#///comments). A PRTG value that differs from its default (*,60) overrides the preset. Each filter also acceptsFILE:<file>(one value per line). Shipped: Failed_Logons, Emergency_Users, User_Admin, Audit_Config_Changes (event IDs from memory, verify in SM19/RSAU_CONFIG). Copied via its own step inazure-pipelines.yml. - Open:
ET_LOGcolumn names unconfirmed – candidates inEventFields/UserFieldsat the top of the class; get the real names from SE37.ET_RETURNassumed BAPIRET2-like (TYPE,MESSAGE).- Time window uses the probe's local time; consider
/SOMO/GET_TIMEZONEoffset likeSAP_Dump_MonitorV2. - Not yet run against a real system (also needs the Scansor runtime /
sensors.db, so no local runs).