AppApptypeAn application you deploy and use, installed into a system or loaded into an application as a component, rather than a library whose functions you call.See every one →What this type is →by a community orgby a community orgoriginPublished by a community organisation, so it outlives any one maintainer.See every one →

admin-cockpit

An abap2UI5 app that shows usage, errors, response times, the draft table and a security traffic light of an abap2UI5 installation.

An abap2UI5 installation keeps no record of how much it is used, which apps fail and whether it is configured safely. The Admin Cockpit records that itself: one line in the installation's own HTTP handler (z2ui5_cl_cockpit_wire=>run( server )) replaces abap2UI5's call and records every roundtrip per app and event into the cockpit's Z2UI5_T_CK_* tables, with its duration, its size and the exception where it failed, and on an abap2UI5 that carries the monitor hook z2ui5_if_ui5_monitor the phases load, main and render come with them. Errors arrive grouped by app, event and exception class, and the drafts of one browser session are followed backwards into a session an administrator can step through roundtrip by roundtrip. The Installation & Security and Drafts & Housekeeping tabs need no recording at all: they read the configuration the framework computes and the abap2UI5 draft table, so the traffic light and the draft housekeeping work straight after the abapGit pull.

Facts

Last pushLicenceMIT

Where it sits

Lives in
Provides
TelemetryABAPTelemetrycapabilitySeeing what a running service did — traces across handlers and database calls, metrics, and correlation that survives an async boundary.
Add-on to
abap2UI5abap2UI5artifactOne ABAP class implementing z2ui5_if_app is the whole app: the browser loads a generic UI5 shell once, and every interaction after that is an HTTP roundtrip back into ABAP.
Requires
abap2UI5abap2UI5artifactThe cockpit is itself an abap2UI5 app and is installed next to the framework; branch main needs an abap2UI5 that carries the monitor hook z2ui5_if_ui5_monitor.abapGitabapGitartifactPulled into the system with abapGit, into a package of its own.
Optional
lock-managerlock-managerartifactshowing the lock-manager addon's own monitor on the Live tababap2UI5 headless frontendabap2UI5 headless frontendartifactre-running a failed roundtrip's app logic for the Reproduce feature

Who is behind it

abap2UI5-addonsabap2UI5-addonsOrganisationMaintains this
In the atlas: maintains 21
@abap2UI5-addons
maintaineroblomov-devPersonContributes to this
In the atlas: maintains 4, contributes to 44
@oblomov-dev
1 contributor

Before choosing this

Conditions

PracticalFunctional boundary

It sees abap2UI5 only: the figures come from the framework's HTTP handler, its monitor hook and its draft table, so nothing outside abap2UI5 appears in them. The usage, error and performance tabs stay empty until the handler line is in place or the user exit sets check_monitor_active. Recording which employee used which application, when and how fast, is subject to works council co-determination in Germany (§ 87 (1) no. 6 BetrVG); user tracking is HASH by default, NAME stores user names, and the request recorder keeps the complete request and response of every roundtrip for two days by default.

What it declares

Every artifact

Type
App
Origin
By a community org

As an app

Where it runs
does not say
Distributed through
abapGit

Connections5

admin-cockpit connectionsadmin-cockpitPROVIDES→ provides1provides stated Records every abap2UI5 POST roundtrip into its own aggregate and log tables (app, event, duration, request and response size, errors, and with the monitor hook the load, main and render phases) and shows usage per app, grouped errors and the slowest roundtrips with their phases. abap2UI5-addons/admin-cockpit — README: https://github.com/abap2ui5-addons/admin-cockpit abap2UI5-addons/admin-cockpit — README: https://github.com/abap2ui5-addons/admin-cockpitTelemetryNEEDS→ needs2needs stated The cockpit is itself an [abap2UI5](artifact:abap2ui5-abap2ui5) app and is installed next to the framework; branch `main` needs an abap2UI5 that carries the monitor hook `z2ui5_if_ui5_monitor`. abap2UI5-addons/admin-cockpit — AGENTS.md: https://raw.githubusercontent.com/abap2UI5-addons/admin-cockpit/main/AGENTS.md abap2UI5-addons/admin-cockpit — README: https://github.com/abap2ui5-addons/admin-cockpitabap2UI5needs stated Pulled into the system with [abapGit](artifact:abapgit-abapgit), into a package of its own. abap2UI5-addons/admin-cockpit — README: https://github.com/abap2ui5-addons/admin-cockpitabapGit→ optionally needs2optionally needs stated If: the headless frontend is installed re-running a failed roundtrip's app logic for the Reproduce feature admin-cockpit README: https://github.com/abap2ui5-addons/admin-cockpitabap2UI5 headless frontendifoptionally needs stated If: abap2UI5-addons/lock-manager is installed showing the lock-manager addon's own monitor on the Live tab admin-cockpit README: https://github.com/abap2ui5-addons/admin-cockpitlock-managerif

README

quoted from abap2UI5-addons/admin-cockpit under MIT, read
abap2UI5-addons/admin-cockpit/README.mdOn GitHub

admin-cockpit

abap2UI5-addons ABAP abap2UI5 License
ABAP Cloud ABAP Standard ABAP 7.02 ABAP Unit check-abap2UI5

See whether abap2UI5 is used, fast and safely configured - in one abap2UI5 app. The Admin Cockpit shows usage and errors per app, response times with their phases, the draft table and a security traffic light of the installation. It is itself an abap2UI5 app, installed with abapGit next to abap2UI5, for the administrators and IT leads who run it.

Part of abap2UI5-addons - addons and apps for abap2UI5, installed with abapGit.

Why

Is abap2UI5 used? Is it fast? Is it safely configured? The three questions an IT lead asks before abap2UI5 goes to production. The cockpit answers them from the roundtrips it records, the abap2UI5 draft table and the configuration the framework computes - and the security and draft tabs need no logging at all: install, open, read the traffic light.

Good for:

  • IT leads and administrators deciding whether abap2UI5 is ready for production, and keeping an eye on it afterwards.
  • Finding errors - grouped by app and exception, with the user's steps up to the error and a replay of the failed event.
  • Performance - the slowest roundtrips, their phases and runtime hints.
  • Privacy by default - no user names unless you switch them on (see Privacy and the works council).

Installation

Requirements

  • ABAP Cloud or Standard ABAP 7.50 or higher, released APIs only; the 7.02 downport is linted in CI (ABAP_702). The UI runs on UI5 1.71 and later (OpenUI5 and SAPUI5): IconTabBar, GenericTile, sap.m tables - no SAPUI5-only micro charts.
  • abap2UI5 1.146.0 or later; for branch main an abap2UI5 with the monitor hook z2ui5_if_ui5_monitor (see the table below).
  • Optional: abap2UI5-addons/abap-agent-runtime for the Agents tab, the headless frontend for Reproduce, abap2UI5-addons/lock-manager for its monitor on the Live tab. All are found at run time - the cockpit activates without them.

Steps - with abapGit:

  1. abap2UI5 first - https://github.com/abap2UI5/abap2UI5.

  2. This repository with abapGit, into a package of its own (for example Z2UI5_COCKPIT; the folder logic is PREFIX, so src/01 and src/02 become Z2UI5_COCKPIT_01 and Z2UI5_COCKPIT_02). Pick the branch by your abap2UI5 release:

    Your abap2UI5BranchWhat you get
    has z2ui5_if_ui5_monitor (the release after 1.146.0)maineverything
    1.146.0 or later without the monitor hookstandaloneeverything with the handler line of step 4 - only the phases of a roundtrip (load, main, render) need the hook
  3. Start z2ui5_cl_cockpit_app right away: a cockpit without an administrator shows nothing but a Claim the administrator role screen - the first user who presses its button becomes the administrator (see Security of the cockpit itself).

  4. Hook the cockpit into your HTTP handler - one line, on every abap2UI5 release, once the pull is complete and every object is active. In your own handler class (SICF, the service, tab Handler List), method if_http_extension~handle_request, replace abap2UI5's call:

    METHOD if_http_extension~handle_request.
      z2ui5_cl_cockpit_wire=>run( server ).  " instead of z2ui5_cl_ui5_http_handler=>run( server )
    ENDMETHOD.

    It runs abap2UI5, takes the time and records the roundtrip - the usage, error and performance tabs and the recorder with one line. Details and ABAP Cloud: Where the line goes.

    Or the monitor hook (abap2UI5 with z2ui5_if_ui5_monitor, branch main) - it adds the phases of a roundtrip. Switch it on in your user exit; abap2UI5 calls no monitor until the exit says so, so a cockpit that does not activate cannot break your apps. With both, the hook counts and the handler line only records the bodies - nothing is counted twice:

    METHOD z2ui5_if_ui5_exit~set_config_http_post.
      cs_config-check_monitor_active = abap_true.
    ENDMETHOD.

    Until then the usage, error and performance tabs stay empty. Setting it back to abap_false stops the recording on the next roundtrip. The field exists in abap2UI5 releases that ship the opt-in. On an abap2UI5 that has the monitor hook but not the field yet, the monitor runs as soon as the cockpit is installed.

Once your abap2UI5 has the monitor hook, you can switch the abapGit repository from standalone to main and pull, and switch the hook on (step 4) for the phases - the handler line can stay.

Start - ?app_start=z2ui5_cl_cockpit_app. Claim the administrator role (step 3); Installation & Security and Drafts & Housekeeping work right away, the usage, error and performance tabs fill once step 4 is in place. What each tab shows: Usage.

Two packages, two branches
PackageContentActivates on
src/01The app, every tab, the tables, settings, authorization, housekeeping, the recorder z2ui5_cl_cockpit_rec, the request recorder z2ui5_cl_cockpit_wireevery abap2UI5 release with z2ui5_cl_ui5_view_builder
src/02z2ui5_cl_cockpit_monitor - the one class that implements the core's z2ui5_if_ui5_monitor and forwards to the recorderabap2UI5 with the monitor hook

The split sits exactly at the dependency: nothing in src/01 names the monitor interface or the monitor class (the app checks for both by name, at run time, and shows a "requires abap2UI5 with z2ui5_if_ui5_monitor" message where they are missing). Even the screens of Overview, Apps, Errors and Performance live in src/01 - they only read the cockpit's own tables.

Why a second branch instead of "just install src/01": abapGit always pulls a whole repository. On an abap2UI5 without the monitor interface the one class in src/02 would fail to activate - abapGit reports the error, leaves the class inactive and shows it as a diff on every pull. The standalone branch is main without src/02, generated by .github/workflows/publish-standalone.yaml on every push to main, after linting src/01 against the released abap2UI5 (the tag 1.146.0, pinned: main of abap2UI5 already carries the hook).

Usage

?app_start=z2ui5_cl_cockpit_app
TabWhat it showsNeeds
OverviewTiles: active users today, roundtrips today, p95 response time, error rate, draft table size, sessions with errors in the draft table (select it to step through them) - the last 30 days, one row per day - and the alerts: thresholds exceeded right now and the alert history (see Alerts)monitor
AppsPer app class: users, sessions, roundtrips, avg/p95 ms, response and model size, errors, last used - select one for its events, its sessions in the draft table and the business objects it works with (from its drafts, types only). Plus the unused apps: implementers of z2ui5_if_app without a roundtrip in N daysmonitor
ErrorsGrouped by app, event, exception class and first line, with count and first/last seen; the detail shows every occurrence, the full exception chain, the draft id and the user (pseudonymized by default), and what the user did afterwards - continued from the same screen, stopped there, still open (from the drafts) - Analyze failures: the values the failing cases share and other states of the app rarely have, and the business objects they concern - Open session: the user's steps up to the error (see Sessions) - and Reproduce: re-run the failed event on its draft (see Reproduce an error)monitor (Reproduce: headless-frontend)
PerformanceThe slowest roundtrips with their phase breakdown (load / main / render, plus the browser's own measure), and runtime hints: model larger than 1 MB, large responses, slow p95, growing app state, dominant phases, expired drafts nobody deletesmonitor
Drafts & HousekeepingRows, age, owners and expiry of the abap2UI5 draft table, size per app on demand; the sessions in it - step through what a user did, roundtrip by roundtrip (see Sessions); find a value (an order number, a customer) in all drafts; the navigation between apps; delete expired drafts (with confirmation), purge the cockpit's own log by retention - the same as a class for a background job-
Installation & Securityabap2UI5 version, platform, user exit, UI5 bootstrap and theme, the installed addons - and a security traffic light: CSRF origin check, hidden error details, CSP without 'unsafe-eval'/'unsafe-inline', security headers, reachable developer addons, the cockpit's own access. Every check with status, why it matters and how to fix it-
LiveWho is active now: drafts written in the last 5 minutes, apps in use from the monitor, the sessions active right now - open one to see what the user is doing - and a pointer to the lock-manager addon's monitor when it is installed(monitor)
AgentsWhat AI agents did through the agent addon's MCP endpoint: calls per day, per app and per MCP client, refusals by policy and by validation, the last calls, endpoint enabled yes/no (see Agents)agent addon
SettingsMonitor mode, slow threshold, retention, privacy mode, alert thresholds with a test notification, administrators, and the change log (claims, administrators, settings, deletions, reproductions, opened and exported sessions, draft searches, failure analyses, test notifications)-

The tabs marked - work without any logging - install, open, read the traffic light. That is the quick win.

Screenshots

Placeholder - screenshots of the Overview, Errors and Installation & Security tabs follow with the first release.

How the monitor works

Two ways feed the same statistics (z2ui5_cl_cockpit_rec): the handler line z2ui5_cl_cockpit_wire=>run( ) (installation step 4, every release - see Where the line goes), and the monitor hook below, which adds the phases of a roundtrip. With both, the hook counts and the handler line only records the bodies.

Once the user exit switches it on (check_monitor_active, installation step 4), abap2UI5 finds z2ui5_cl_cockpit_monitor on its own - the first class implementing z2ui5_if_ui5_monitor by name, looked up once per roll area, the way it finds the user exit - and calls on_roundtrip once per POST roundtrip, after the response is built, on success and on failure. The class maps the structure by name (MOVE-CORRESPONDING, so a field the core adds or renames never breaks the activation) and hands it to z2ui5_cl_cockpit_rec, which decides by the settings what is persisted:

TableWrittenContent
Z2UI5_T_CK_AGGevery recorded roundtrip, updated in place, lock-freeper UTC day, hour, app and event: count, app starts, errors, slow ones, sum and max of the total and of each phase, request/response KB, largest response and model, browser time, and a latency histogram of nine buckets (the p95 is interpolated from it)
Z2UI5_T_CK_USRonce per user, day and appthe user key (see privacy) - distinct users per day
Z2UI5_T_CK_ACTevery recorded roundtripuser key and app with the last-seen time - the Live tab
Z2UI5_T_CK_LOGerrors and slow roundtrips onlyone raw row: timings per phase, sizes, draft ids, exception class, first line and full chain
Z2UI5_T_CK_SETsettingsname/value
Z2UI5_T_CK_ADMadministratorsuser names
Z2UI5_T_CK_AUDevery change made in the cockpitchange log: time, user, action, details - kept as long as the aggregates
Z2UI5_T_CK_ALRby the housekeeping job, per raised or cleared alertalert history: rule, app, value, threshold, raised and cleared, what the notification answered - kept as long as the aggregates

Lock-free and overflow-safe. A roundtrip is added to the row of its hour with one UPDATE ... SET cnt = cnt + 1, ms_sum = ms_sum + n, ... - atomic on every database, so two work processes never lose each other's counts and nobody waits for a row lock (no SELECT ... FOR UPDATE, the same statement on ABAP Cloud). No row yet: INSERT; lost the race for it: the UPDATE once more. The maxima are conditional UPDATEs (... WHERE ms_max < n). The sum columns (milliseconds, KB) are DEC 15 - an INT4 overflows at 2.1 billion, which a busy hour of one app can reach in milliseconds; INT8 does not exist below 7.50, DEC 15 exists on every release and on ABAP Cloud. The increments are saturated at the largest DEC 15 before they are written, the counts stay INT4 per hour row, the read side adds days up in packed numbers and shows them saturated at the largest INT4 - and whatever a database still refuses, record( ) catches: the monitor never dumps.

It never breaks an app. Everything is caught; the core swallows anything a monitor raises anyway. A syntax error is the one thing no CATCH stops - a class that does not activate dumps whoever calls it - which is why the core calls no monitor until the exit switches it on. Commit semantics follow the interface: for an app that is not sticky the LUW is empty when the monitor runs (the framework committed its draft save, or rolled back a failed roundtrip right before the call), so the recorder writes its rows and issues COMMIT WORK itself - the core offers no commit helper. For a sticky (stateful) app the LUW belongs to the app (uncommitted work, update tasks, locks), so the recorder writes nothing then: the entry waits in the roll area, which a sticky session keeps, and is written with the first roundtrip of that roll area that is not sticky (at most 500 entries are buffered). A session that ends while still sticky loses its buffered entries - the price of never touching the app's LUW; a secondary database connection would avoid it, but exists on Standard ABAP only.

What it costs: a handful of single-row statements per roundtrip (settings and the daily salt are read once per roll area). Mode SAMPLE records errors fully and only a share of the rest - decided on the milliseconds of the start time - weighted so counts stay estimates of the totals; ERRORS records failed roundtrips only; OFF stops recording without uninstalling. The own tables purge themselves once per day on the first recorded roundtrip.

Only one monitor is called. If your installation has a monitor of its own that sorts before Z2UI5_CL_COCKPIT_MONITOR, the cockpit says so; call z2ui5_cl_cockpit_rec=>record( ) from your monitor to feed both.

Settings

SettingDefault
ModeALLALL, SAMPLE, ERRORS, OFF
Sample share10 %SAMPLE only
Slow roundtrip from2000 mslands in the raw log with its phases
Retention log, users, activity30 days
Retention aggregates400 days
User trackingHASHHASH, NONE, NAME - see below
App unused after90 daysApps tab
Hint thresholds500 KB response, 1024 KB modelPerformance tab
Alert: error rate from5 %0 switches the rule off - see Alerts
Alert: p95 from2000 ms0 switches the rule off
Alert: only with at least20 roundtripsper app, and over all apps
Alert: windowrunning UTC hour plus 10 to 23 hours before the running one
Recorder retention2 days0 stops the recorder

Privacy and the works council

Privacy mode is on by default: no user names are stored.

  • HASH (default) - users are counted under a SHA-256 pseudonym of a random salt and the user name. The salt is created per UTC day and the previous day's salt is deleted, so a pseudonym can neither be traced back to a name nor linked to the same user on another day - not even by an administrator with database access. Hence "users per day", never "users per month".
  • NONE - users are not counted at all; Live shows apps, not users.
  • NAME - user names are stored (raw log, user and activity tables) and shown in the error details.

The draft table of abap2UI5 itself carries the user name (the framework binds a draft to its owner). The cockpit shows its per-user statistics as "User 1, User 2, ..." unless user tracking is NAME, and the session list under today's pseudonym. The content of a session - the app's data after every step - is business data of that user: administrators only, every opened session in the change log (see Sessions). The recorder, once added to the handler, stores even more: what users typed and saw, for 2 days by default.

Germany (and similar elsewhere): recording which employee used which application, when and how fast, is a technical device suitable for monitoring behaviour or performance - introducing it is subject to works council co-determination (§ 87 (1) no. 6 BetrVG), regardless of whether anybody intends to evaluate individuals. HASH and NONE are designed to keep the cockpit on the side of aggregate system monitoring; agree NAME with your works council and your data protection officer before switching it on, and document the retention. This is not legal advice.

Security of the cockpit itself

The cockpit shows usage and configuration of the whole system and can delete drafts - it must be restricted. Like every abap2UI5 app it can be started by anybody who reaches the abap2UI5 ICF node, so it checks access itself, at the top of main( ):

  1. A class of your own implementing z2ui5_if_cockpit_auth decides, if there is one (found like the user exit, first implementer by name):

    CLASS zcl_my_cockpit_auth DEFINITION PUBLIC FINAL CREATE PUBLIC.
      PUBLIC SECTION.
        INTERFACES z2ui5_if_cockpit_auth.
    ENDCLASS.
    
    CLASS zcl_my_cockpit_auth IMPLEMENTATION.
      METHOD z2ui5_if_cockpit_auth~check.
        " standard ABAP, for example: basis administrators only
        AUTHORITY-CHECK OBJECT 'S_ADMI_FCD' ID 'S_ADMI_FCD' FIELD 'ST0R'.
        result = xsdbool( sy-subrc = 0 ).
      ENDMETHOD.
    ENDCLASS.

    action is DISPLAY (open the cockpit) or CHANGE (delete drafts, purge logs, change settings and administrators, reproduce errors). A class that cannot be created denies.

  2. Otherwise the administrator list on the Settings tab (Z2UI5_T_CK_ADM). Only the users on it get in; everybody else sees "No authorization".

  3. As long as that list is empty, the cockpit shows only the claim screen - one button, Claim the administrator role for , and nothing of the system. The first user who presses it becomes the administrator; the claim is a row with a fixed key, so of two users claiming at the same moment exactly one wins. The claim is written to the change log (Settings tab). Claim it right after the installation; the traffic light shows the unclaimed cockpit in red. The last administrator cannot be removed on the Settings tab.

The administrator has left? Reset the list with one class method - in a two-line report, an ABAP Cloud console class (if_oo_adt_classrun) or the test environment of SE24/ADT:

" hand the cockpit to a named user ...
z2ui5_cl_cockpit_auth=>reset_admins( 'NEW_ADMIN' ).
" ... or empty the list, so the next user who opens the cockpit can claim it
z2ui5_cl_cockpit_auth=>reset_admins( ).

Both commit and both are written to the change log.

The cockpit reads framework internals - the draft table Z2UI5_T_01, the user exit instance, the draft store, the class lookup - only by name, with dynamic SQL and dynamic calls, and read-only except for the draft cleanup. A later abap2UI5 release that renames one of them costs the cockpit that number, never its activation.

Reproduce an error

The detail of an error group offers Reproduce... for the selected occurrence when the headless frontend (z2ui5_cl_frontend_simulator) is installed. It resumes the draft the failed request came with (draft_id_prev of the log entry) and fires the same event again, through the simulator - the app runs exactly as it ran for the user, and the cockpit shows the exception chain, the messages the app showed and the view XML the roundtrip displayed.

It re-runs the app logic for real. Whatever the event writes, posts or sends happens again - as the administrator, with the administrator's authorizations, and committed if the app commits. The cockpit therefore asks first, offers it to administrators only (CHANGE) and writes every replay to the change log before it starts. Limits, all shown in the dialog:

  • draft-based apps only - a sticky (stateful) app keeps no draft;
  • only drafts that still exist - drafts expire (4 hours by default);
  • only your own drafts - abap2UI5 binds a draft to its owner. The cockpit knows the owner from the user name (user tracking NAME) or from today's pseudonym (HASH, same UTC day only); otherwise it tries, and the simulator says "no draft" when the draft is somebody else's;
  • the event, not the values - what the user typed in that roundtrip and the event's arguments are not recorded, so they are not replayed.

The simulator is called dynamically and named only in literals: the cockpit activates without it and simply does not offer the button.

Sessions - step through what a user did

Every POST roundtrip of abap2UI5 saves the app as it is afterwards into a new draft and names the draft it started from (ID_PREV), across app navigations too. Followed backwards, the drafts of one browser session form a chain - the session. The Drafts & Housekeeping tab lists the sessions in the draft table (Show sessions, newest activity first, searchable by app or user): user, app, number of steps, failed roundtrips the monitor logged in the session (With errors only keeps just those), first and last step, duration. The same list, limited to the last 5 minutes, is on the Live tab - who is working right now, and on what - and the app detail of the Apps tab opens it filtered to that app.

Open one and the viewer shows it step by step:

  • First / Back / Next / Last, or select any step in the list - time, seconds since the step before, app, size, and notes such as navigated to ZCL_..., continues step 3 (browser back or a second window) or the steps before it expired;
  • how many fields changed in the step - a step that changed nothing is marked no field changed, and when that happens twice or more in a row the viewer warns: the user pressed something again and again without effect (a button that does nothing, a check that refuses without a message);
  • the messages the app holds in its state when they appear - a BAPI return or a message table: a structure or row with a type E/A/X/W (TYPE, MSGTY, SEVERITY) and a text (MESSAGE, MSG, TEXT for errors). These are the business errors the user saw, which are no exception and never reach the Errors tab;
  • the business objects of the session - an order, a customer, a material - recognized by the field name (VBELN, KUNNR, MATNR, EBELN, BELNR, AUFNR, the flight and RAP demo keys, ORDER_ID, CUSTOMER, ..., also as the end of a name like MV_VBELN), each with the step it first appears in;
  • what the roundtrip monitor logged about a step, when it is active: the roundtrip that started from this step and failed (exception class, first line, event - the row is red), and the slow roundtrip that wrote it (event, milliseconds). The monitor logs only failed and slow roundtrips, so the event of an ordinary step stays empty;
  • the fields of the app after that step - every attribute of the app object and the objects it references, nested structures and table rows as paths (ZCL_ORDER-MT_ITEMS[2]-MATNR), references as an arrow to the class;
  • what changed since the step it continues - new, changed (with the value before) and removed, highlighted; Only changes (default) hides the rest, Framework objects adds abap2UI5's own container, the search narrows by field or value;
  • Compare with this step pins a step: every other step is then compared with it instead of with the step before - what differs between the screen that worked and the one that failed;
  • select a field for its history - its value in every step of the session, the steps where it changed highlighted, each one a jump target: when did the quantity become 0?
  • a warning when the app state grows: when the last step is twice the size of the first and above 20 KB, the viewer names the tables that grew most (ZCL_APP-MT_LOG 3 -> 1200 rows) - state that is serialized and read back on every roundtrip, and makes each one slower.

Analyze failures in the error detail looks for the cause in the data: it takes the states the failed roundtrips started from (as long as their drafts exist) and compares them with up to 300 other states of the same app. A value in at least 80 % of the failing states and at most 30 % of the others is listed - ZCL_ORDER-MS_HEAD-QTY = 0: in 5 of 5 failing, in 3 % of 120 other states - a correlation to check first, not a proof. Next to it the business objects of the failing states, counted: Customer 1000 in 4 of 5 - a data problem, not a code problem. Needs two failing states with drafts; written to the change log (ERROR_ANALYSIS).

The app detail of the Apps tab shows the business objects an app works with - per object type the number of its drafts it appears in. Types only, no values: an app understood in business terms without reading its code.

Find a value in all drafts answers the question a support call starts with - "I had a problem with order 4711": it searches every field of every draft (case-insensitive, at least 3 characters) and lists user, time, app, field and value; a hit opens its session at that step, the fields filtered to the value. Every search is written to the change log (DRAFTS_SEARCH), with the term.

Analyze navigation counts how users move between apps - the business process as users walk it: per pair of apps the navigations in the draft table, per app the sessions that start in it ((start)), and where sessions end - (end) after 30 minutes without a step, (end after an error) when a failed roundtrip started from the last step: where users give up. Only class names are read, no content.

Export writes the whole session into a text file - every field of the first step, then per step what changed, with events and monitor notes - to attach to a ticket for the app's developer. Every export is written to the change log.

From an error, Open session in the error detail jumps straight to the step the failing roundtrip started from - the screen the user was on, with the values the user had typed. That complements Reproduce, which replays the event but not the values.

What it is and is not:

  • The state after each roundtrip, not the event. A step is the app's attributes once the roundtrip finished; the event the user pressed is not in the draft (the Errors tab has it for failed roundtrips; the recorder adds it to every step).
  • As long as the drafts live - 4 hours by default, see the expiry on the tab. Sticky (stateful) apps write no drafts while sticky.
  • Read as text. The serialized state (asXML) is taken apart without loading a class from it - an app class that no longer activates cannot break the cockpit. Generic data references of an app are kept in the framework's own objects; Framework objects shows them.
  • Limits: the newest 50,000 drafts, 100 sessions per list, the newest 500 steps of a session, 1,000 fields per step (narrow them with the search).

Drafts hold business data of other users. The sessions are offered to administrators only (CHANGE), and every opened or exported session is written to the change log (SESSION_VIEW, SESSION_EXPORT), with the session's first draft, its app and the user as the list shows it; so is every search in the drafts (DRAFTS_SEARCH) and every failure analysis (ERROR_ANALYSIS). Agree it with your works council like the rest of the monitoring (see Privacy).

Recorder - replay what the user saw

The drafts show what an app held after each step. What the user saw and did - the screen, the button, the error box - never reaches a draft. The recorder takes it where it passes anyway: the HTTP handler. The one line that hooks the cockpit in there (z2ui5_cl_cockpit_wire=>run( server ), installation step 4) stores the complete request and response of every roundtrip, untouched.

Where the line goes

In your own HTTP handler class - the one the abap2UI5 service calls, not a class of the abap2UI5 repository (a pull would overwrite it):

  • Standard ABAP: transaction SICF, the service of your installation (e.g. /sap/bc/z2ui5), tab Handler List - that class, method if_http_extension~handle_request.
  • ABAP Cloud: the HTTP service of your installation, its handler class, method if_http_service_extension~handle_request.

There the call of abap2UI5 already stands. Replace it with the cockpit's, which calls it - the one place the cockpit hooks in:

" Standard ABAP
METHOD if_http_extension~handle_request.
  z2ui5_cl_cockpit_wire=>run( server ).
ENDMETHOD.

" ABAP Cloud
METHOD if_http_service_extension~handle_request.
  z2ui5_cl_cockpit_wire=>run( req = request res = response ).
ENDMETHOD.

run( ) calls z2ui5_cl_ui5_http_handler=>run( ), takes the time around it, and then, from the request and response it reads back:

  • records both bodies (the recorder, while its retention is not 0);
  • feeds the roundtrip statistics as the monitor hook would - app, event, drafts, duration, sizes, the browser time of the roundtrip before, and for a failure the error text and the innermost exception class of the 500 body; the app of a failed roundtrip from the draft it started from. Only the phases (load, main, render) stay 0 - they need the hook;
  • counts nothing twice: when the monitor hook recorded the roundtrip already, it only records the bodies.

An older installation calls z2ui5_cl_http_handler=>run( server ) - the deprecated name that forwards to z2ui5_cl_ui5_http_handler; replace it the same way. To keep abap2UI5's own line, add z2ui5_cl_cockpit_wire=>record( server ) right after it instead - the recorder only, without statistics (a line after the call cannot take its time).

Change it only once the cockpit is pulled and active: the line runs on every request of every abap2UI5 app, and a class that does not activate is a short dump no CATCH stops - in all apps. The cockpit's own part never raises; only what abap2UI5 raises leaves run( ), as before.

To check it: click through any app, then open the Installation tab - the row Recorder of requests and responses counts today's recordings.

It needs no abap2UI5 API beyond the handler (the bodies are read as they went over the wire, and taken apart only when someone looks), never raises, records only POST roundtrips, and never commits inside a sticky app's LUW - those wait in the roll area like the monitor's entries.

What it gives you, in the session viewer:

  • "User did" per step - the control pressed, by its label (pressed Button "Save" (SAVE)), and the fields typed before it (typed Input "Customer" = 4712).

  • "Shown" per step - the message boxes, toasts and popups the response opened, error boxes highlighted.

  • Screen - the screen of the step rebuilt from the recorded view XML and the model as the responses and inputs left it: the values in the fields, the rows of the tables (50 each), the popup on top with its buttons. Every event handler is emptied, a press in the copy fires nothing - and nothing runs by itself: an HTML control shows its content sanitized, XHTML/SVG elements and abap2UI5's helper controls (z2ui5.cc: storage, history, timer, websocket, ...) are left out. The control the user pressed next is outlined in orange - on the popup when one was open. Previous screen / Next screen step through the session like a film, each screen with what the user did on it next - or that the next click failed.

  • Request / Response - the raw bodies, the inputs, the view XML, and for a step whose next click ended in an HTTP 500 the failed request itself.

  • Story - the session told line by line, ready for a ticket, with a copy button:

    10:02:11  [ZORDER] started
    10:02:40  pressed Button "Save" (SAVE) -> error box: Date invalid (1.2 s server, 6.2 s waited)
    10:03:20  [ZDELIVERY] event GO - next click failed: event SHIP
    
  • Signs of trouble - in the session viewer, and as a column of the session lists (Drafts & Housekeeping, Live) to find the sessions worth a look: the same button three times within seconds, the same error box again, a failed click, the same button again after a wait of 5 s or more, a session that ended on an error. The lists read only ids and events of the recordings, the viewer also the error boxes.

  • Time per step (with run( )) - the server's time for the roundtrip and how long the user waited for it in the browser (the frontend sends it with the next request), orange from the slow roundtrip setting: "1.4 s server, 6.2 s waited" right before the same button is pressed again explains the double click.

The Errors tab adds "Messages users saw": the error and warning boxes and toasts of the last days, per app and text, how often and for how many users. Search it for the text from a ticket ("Material not found") - selecting a message opens the session where it was shown last, at that step.

Inputs right before an error (Errors tab) - the fields users typed in a roundtrip that answered with an error box or failed, how often that happened when they typed them, the last message and the values typed when it failed. Rows of a table count as one field:

ZORDER  MS_HEAD/DATE     2 errors of 3 typed  66 %  Date invalid   "31.02.2026", "30.02."
ZORDER  MT_ITEM/*/QTY    3 errors of 3 typed 100 %  Date invalid

A field with a high rate is where a process stumbles - a format users do not expect, a check that tells them too late.

Process variants (Drafts & Housekeeping, and per app in the Apps tab detail) - process mining on the recordings: every run from the start of a session to where nothing continued it, written as its events in order and counted. Runs of the same way are one variant:

ZORDER: (start) -> CREATE -> SAVE (failed) -> SAVE => ZDELIVERY: SHIP   12 runs  40 %
ZORDER: (start) -> CREATE -> SAVE (failed)                               5 runs  red
ZORDER: (start) -> SEARCH -> NEXT (repeated) -> DISPLAY                  9 runs
  • an event is counted on the app whose screen it was pressed on, => is an app change;
  • a click that failed and was tried again stands in place (orange row), a run that ended in a failed click is red - the ways into an error, with how often each happens;
  • (repeated) is the same event several times in a row, so paging through ten pages and through two is one way;
  • reads no body, only ids and event names - up to 20,000 recordings;
  • selecting a variant opens its newest run in the session viewer (administrators).

Retention: 2 days by default (Settings, Recorder retention; 0 stops recording, the line in the handler can stay). The Installation tab shows whether it records and warns above 7 days. Housekeeping purges it.

Privacy: the bodies are the business data the user typed and saw - everything a screen shows. Recordings are read by administrators only and only inside a session that is already written to the change log; the user is stored under the pseudonym unless user tracking is NAME. Keep the retention short and agree it with your works council like the rest of the monitoring.

Agents

When the agent addon is installed (detected by its class z2ui5_cl_agent_settings or its audit table Z2UI5_T_AG_LOG), the Agents tab reads its audit log and settings - with dynamic SQL inside TRY, so there is no dependency either way:

  • endpoint enabled yes/no, with the opted-in apps (implementers of z2ui5_if_agent_app), the APP rules and the agent administrators;
  • calls per day, per app and per MCP client (name and version from initialize), each split into refused by policy (endpoint disabled, app not enabled for agents, event forbidden or reserved for a human) and refused or failed otherwise (validation - wrong field or value, unknown or expired session, the app raised);
  • the last calls with operation, event, outcome and text; the user only with user tracking NAME.

The traffic light gets an agent line: disabled is green; enabled without an agent administrator is red; enabled with an APP * allow rule (every app class, not only the opted-in ones) or with no reachable app at all is yellow.

Alerts

Two rules, both on the Settings tab: an error rate and a p95 response time, each "from" a threshold. They are evaluated on the aggregates of the monitor, in a window of the UTC hour running now plus a number of full hours before it (default: 1, so 60 to 120 minutes), per app and over all apps:

  • an app with fewer roundtrips in the window than the minimum (default 20) raises nothing - three failures out of four are no alert;
  • the line over all apps raises a rule only when no single app raises it already - it is there for the many small apps that stay below the minimum one by one, and one broken app is not reported twice.

The Overview tab evaluates the rules live: what is exceeded right now, and the history. The housekeeping job z2ui5_cl_cockpit_job=>run( ) keeps that history in Z2UI5_T_CK_ALR: an alert is raised by the first run that finds the threshold exceeded and cleared by the first run that no longer finds it - so a broken app costs one notification when it breaks and one when it is fine again, not one per run. Schedule the job every 15 minutes (see Housekeeping and background jobs); without it the Overview still shows what is exceeded, but nothing is kept or sent.

Notifications go to a class of your own implementing z2ui5_if_cockpit_notify (found like the user exit, first implementer by name). It gets one structure per raised or cleared alert - rule, app, value, threshold, roundtrips, time, <SID>/<client> and a ready sentence - and is called inside the job's LUW: the job commits after it, so a mail queued with the released mail API is sent with that commit.

CLASS zcl_my_cockpit_notify DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES z2ui5_if_cockpit_notify.
ENDCLASS.

CLASS zcl_my_cockpit_notify IMPLEMENTATION.
  METHOD z2ui5_if_cockpit_notify~notify.
    " ABAP Cloud - on Standard ABAP cl_bcs, or your chat webhook, or a ticket.
    " notify( ) may raise any cx_static_check: the cockpit notes it in the
    " alert history and goes on.
    DATA(lo_mail) = cl_bcs_mail_message=>create_instance( ).
    lo_mail->set_sender( 'abap2ui5@example.com' ).
    lo_mail->add_recipient( 'basis-team@example.com' ).
    lo_mail->set_subject( CONV #( |[{ alert-system }] { alert-event }: { alert-text }| ) ).
    lo_mail->set_main( cl_bcs_mail_textpart=>create_instance(
      iv_content      = alert-text
      iv_content_type = 'text/plain' ) ).
    lo_mail->send( ).
  ENDMETHOD.
ENDCLASS.

Whatever the class raises is caught and noted in the alert history ("Notification" column) - a failing notification never stops the job. The button Send a test notification on the Settings tab calls the class with event TEST (administrators only, written to the change log). Without a class, alerts are still evaluated, kept and shown - only nobody is told, and the Overview says so.

Housekeeping and background jobs

The Drafts & Housekeeping tab deletes expired drafts (older than the expiry the framework computes - 4 hours by default, or what your user exit sets) through the framework's own draft store, and purges the cockpit's rows past their retention. For a job, call z2ui5_cl_cockpit_job=>run( ) - it also evaluates the alerts, so schedule it every 15 minutes when you want to be notified:

  • Standard ABAP - a two-line report, scheduled in SM36:

    REPORT z2ui5_cockpit_job.
    z2ui5_cl_cockpit_job=>run( ).
  • ABAP Cloud - an application job: a class of your own implementing if_apj_dt_exec_object / if_apj_rt_exec_object whose execute calls z2ui5_cl_cockpit_job=>run( ), plus the job catalog entry and template.

Roadmap

  • Export of the aggregates to OpenTelemetry / SAP Cloud ALM, so abap2UI5 shows up next to the rest of the landscape.
  • Reproduce with the user's input - record the model delta and the event arguments of a failed roundtrip (opt-in, privacy!) so the replay sends them too.
  • Per-app authorization overview: which roles may start which app classes.

Development

npm ci
npm run lint            # abaplint, Standard ABAP 7.50, both packages
npm run lint:cloud      # ABAP Cloud
npm run lint:standalone # package 01 against the released abap2UI5
npm run lint:702        # after npm run downport (rewrites src/ - CI only)
npm run check:abap2ui5  # the abap2UI5 linter: views, bindings, chain layout
npm run unit            # the ABAP Unit tests on abap2UI5's transpiled runtime

Unit tests. The pure logic has ABAP Unit tests (*.clas.testclasses.abap): p95 from the histogram, the runtime hint rules, error grouping, unused apps, the privacy modes and the daily salt rotation, the recorder's aggregation, the security traffic light and the agent check from given structures, the access decision, the Agents figures, when an error can be reproduced, and the alert rules with what a run raises and clears. The classes that touch the database (ltcl_salt, ltcl_rec) are RISK LEVEL DANGEROUS: they write rows of the test app ZZ_COCKPIT_UNIT_TEST on days in 2099, never commit, and delete and roll back in teardown. Without a system they run on abap2UI5's transpiled runtime (SQLite behind the database statements, so the DANGEROUS classes run too): npm run unit runs every Z2UI5_CL_COCKPIT* test, UNIT_FILTER=ltcl_rec npm run unit only those whose OBJECT: class->method contains the text. .github/scripts/unit.mjs is the whole recipe, and the ABAP_UNIT workflow runs the same script on every push and pull request: a checkout of abap2UI5 (the branch with z2ui5_if_ui5_monitor) in .unit/abap2UI5 (git-ignored; cloned on the first run, refreshed on every later one), npm ci there, src/01 and src/02 copied in as one more package, npm run downport && npm run auto_transpile, then the generated tests - each one printed, exit code 1 on any failure or when none ran. The first run takes a few minutes.

Temporary state: until @abap2ui5/linter releases its list with the monitor interface (abap2UI5/linter#140, merged), abap2ui5lint.jsonc waives non-released-api for the monitor class.

Contributing

Issues and pull requests are welcome. See AGENTS.md for the conventions of this repository.

License

MIT - see LICENSE.

MIT, read
Telemetry
  1. abap-metrics-providerExposes ABAP stack metrics to a monitoring toolfrom ABAP
  2. SAP Cloud LoggingOpenSearch-based store for logs, metrics and tracesfrom BTP/BAIP
  3. Agent Activation for Dynatrace Service for SAP BTPInjects the Dynatrace agent into Java applications on SAP BTPfrom BTP/BAIP
  4. SAP Monitoring Service for SAP BTPMetrics, availability checks and alerts for apps in Neo regionsfrom BTP/BAIP
  5. com.sap.cds:cds-services-bomMaven bill of materials pinning CAP Java module versionsfrom CAP
  6. @cap-js-community/business-metricsBusiness-level metrics from CDS annotations via @cap-js/telemetryfrom CAP
  7. @cap-js/telemetryOpenTelemetry instrumentation for CAP servicesfrom CAP
  8. cds-cachingCAP caching plugin for query results and remote service responsesfrom CAP
  9. cap-mcp-guardPolicy enforcement and field masking for MCP-enabled CAP appsfrom CAP
  10. abap-opentelemetryOTLP serialisation of traces, metrics and logs in ABAPfrom ABAP
  11. abap-prometheusPrometheus client for ABAP, installed with abapGitfrom ABAP
  12. @sanjay-sde/cap-js-log-controlCAP plugin controlling CDS logger and OpenTelemetry log verbosityfrom CAP
  13. @sap/e2e-traceSAP Passport handling for Node.js componentsfrom BTP/BAIP
  14. @sap-ux/telemetryLibrary for sending usage telemetry datafrom CAP
  15. @saptools/cf-metricsRead-only query tool for metrics in SAP Cloud Loggingfrom BTP/BAIP
  16. @saptools/cf-otelRead-only query tool for OpenTelemetry spans in SAP Cloud Loggingfrom BTP/BAIP
  17. cap-ui-telemetryUI5 frontend performance and error capture for CAPfrom CAP
  18. opentelemetry-cdsOpenTelemetry support for the CDS Node.js runtimefrom CAP

Details

Sources3
GitHub APIdiscovered herechecked
github.com/abap2UI5-addons/admin-cockpittree, pushes, contributors, CIchecked
README.mdquoted, and what the entry declareschecked

Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.

Compatibility and provenance
discovered viaGitHub API
first seen in the atlas
ecosystem and domainabap, operations-and-runtime
Flavors2
Standard ABAP
“ABAP Cloud or Standard ABAP 7.50 or higher, released APIs only” — abap2UI5-addons/admin-cockpit — READMEchecked
ABAP Cloud
“ABAP Cloud or Standard ABAP 7.50 or higher, released APIs only” — abap2UI5-addons/admin-cockpit — READMEchecked
Contributors1

From the repository’s contributor list, .

History in the atlas1
  1. First seen.
For your agent
Ref
artifact:abap2ui5-addons-admin-cockpit
JSON
/artifacts/abap2ui5-addons-admin-cockpit.json
MCP
Connecting an agent