> ## Documentation Index
> Fetch the complete documentation index at: https://docs.germainux.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Monitoring Config Reference

> Reference for GermainUX-Agent monitoring rules: which Windows application to monitor, which events to collect, and how data is buffered, sent and protected.

> [card] [Data Privacy and Exclusions](#data-privacy-masking-and-exclusions)
>
> Masking and suppressing fields

> [card] [Optional Features](#features-%E2%80%94-everything-else-is-opt-in)
>
> Enabling optional capabilities

> [card] [Thumbnail rule criteria](#thumbnail-rule-criteria)
>
> Matching rules for thumbnails

> [card] [Full example](#full-example)
>
> Sample configuration file

**GermainUX-Agent Monitoring Configuration Reference**

## Overview

A monitoring rule tells GermainUX-Agent:

| Item | Details |
| - | - |
| Which Windows application to monitor | Which Windows application to monitor |
| Events to collect | Which user, application, performance, and technical events to collect |
| Feature activation | Whether to activate RUM Windows, Code Profiler, and Session Replay |
| Buffering and transmission | How collected facts are buffered and transmitted |
| Data handling | Which sensitive values must be masked, anonymized, or excluded |

Monitoring rules are JSON documents. They are normally created and managed centrally in GermainUX Enterprise. This reference is primarily intended for advanced configuration, diagnostics, and locally managed deployments.

## How the Agent Receives a Rule

The Agent resolves monitoring configuration in the following order:

**1. It retrieves the list of monitored applications and rule names from GermainUX Enterprise**

**2. It downloads the JSON configuration associated with each rule**

**3. If the server request fails, it looks for:**

```text theme={null}
{Agent installation directory}\config\{ruleName}.json
```

1. If a local Registry rule exists for the executable, the Agent loads the JSON file specified by that rule.

A local rule takes precedence over a centrally provided rule for the same executable.

> [!NOTE]
>
> To inspect the configuration currently applied to an application, right-click the GermainUX-Agent system-tray icon and select **Configurations**.

## Top-level fields

```json theme={null}
{
  "application": "My Application",
  "version": "2026.1",
  "agentName": "MyApplication-Prod",
  "profileName": "Default",
  "correlationId": ""
}
```

| Field | Purpose |
| - | - |
| `application` | Free-text application name attached to every fact this rule produces. |
| `version` | Informational agent/rule version string. |
| `agentName` | Unique name identifying this monitoring rule instance; used for provenance and is the name the Agent uses when fetching this rule's config by name. |
| `profileName` | Name of the monitoring profile this rule belongs to; informational/provenance only. |
| `correlationId` | Normally left unset — the Agent mints one per monitored process automatically so the Worker and Profiler's facts for the same running instance can be joined together. |

## `monitorConfig`

```json theme={null}
"monitorConfig": {
  "winTitle": "My Application",
  "useImageSibling": false
}
```

| Field | Purpose |
| - | - |
| `winTitle` | Partial window title used to help identify the application's main window. |
| `useImageSibling` | When a click lands on an image control, also look for a sibling element to attribute the click to (useful for icon-only buttons where the clickable label lives in a neighboring element). |

## `queue` — how facts are sent

```json theme={null}
"queue": {
  "pushInterval": 30,
  "bufferSize": 1000,
  "batchSize": 100,
  "outputPath": "",
  "prettyOutput": false,
  "httpTimeoutMs": 5000
}
```

| Field | Default | Purpose |
| - | - | - |
| `pushInterval` | `30` | Seconds between pushes to GermainUX. |
| `bufferSize` | `1000` | Max facts held in memory before older ones are dropped. |
| `batchSize` | `100` | Max facts sent per HTTP request. |
| `outputPath` | *(none)* | When set, facts are written to this local file **instead of** sent over HTTP — useful for offline capture/testing. Leave unset for normal operation. |
| `prettyOutput` | `false` | Indent the JSON when writing to `outputPath`. |
| `httpTimeoutMs` | `5000` | Timeout for each data-upload HTTP request. Keep this well below the Agent's worker shutdown grace period so a final flush at shutdown has time to complete or fail cleanly rather than being force-killed mid-send. |

## `proxy`

```json theme={null}
"proxy": {
  "url": "http://localhost:",
  "delayInit": false,
  "excludedPorts": [ 443, 4225, 4226 ],
  "minPort": 10000
}
```

Configures an outbound proxy used for HTTP monitoring interception. `excludedPorts` keeps \
&#x20;the proxy from intercepting traffic on ports you don't want captured (commonly the \
&#x20;GermainUX ports themselves, to avoid the agent monitoring its own uploads).

## `debug`

```json theme={null}
"debug": {
  "walkSiblings": false,
  "walkTree": false,
  "dumpTree": false,
  "dumpSnapshot": false,
  "printCreateWinInfo": false
}
```

Verbose diagnostic logging switches for the UI Worker's own troubleshooting (dumping \
&#x20;control trees, sibling walks, snapshot contents, etc. to the log). All should stay `false` \
&#x20;in normal production use — they add log volume and are only useful when working with \
&#x20;support to diagnose a UI-capture issue.

## `logging`

```json theme={null}
"logging": {
  "level": "INFO",
  "name": "myapplication",
  "path": "C:/germainagent/"
}
```

Informational metadata carried with the rule. **This does not control where the Worker or** \
&#x20;**Profiler actually write their log files** — that's governed entirely by the \
&#x20;`LogPath`/`WorkerLogLevel`/`CLRLogLevel` registry settings described in \
&#x20;[Agent Settings](https://docs.germainux.com/main/germainux-agent-settings-registry.md). Leave this block as-is or omit it.

## `globalVariables` — context attached to every fact

```json theme={null}
"globalVariables": [
  {
    "name": "username",
    "filter": { "type": "text", "name": "UsernameControlAutomationId" },
    "lowerCase": true
  }
]
```

Each entry describes a value to read from the UI once and attach as context to every \
&#x20;fact emitted afterward (e.g. the logged-in username shown somewhere in the app's chrome). \
&#x20;See [Context variable fields](https://docs.germainux.com/main/monitoring-config-reference.md#context-variable-fields) below for the full field list — \
&#x20;`userClicks` selector `variables` use the exact same shape.

## Data privacy: masking and exclusions

Two related, independent settings control what raw values are allowed to leave the \
&#x20;machine:

```json theme={null}
"maskAll": false,
"exclusions": [
  {
    "name": "Suppress username from facts",
    "fieldName": "user.name",
    "type": 1,
    "factType": "",
    "pattern": "",
    "preserveLength": true,
    "preserveWhitespace": false
  }
]
```

| Field | Purpose |
| - | - |
| `maskAll` | When `true`, **every** text field is masked by default unless it has its own explicit rule below. Use this for applications where sensitive data could appear almost anywhere and you'd rather opt fields *in* to being sent raw (by not needing a rule for them, once excluded rules apply) than try to enumerate every sensitive field. |
| `exclusions[].name` | Descriptive label for the rule (not sent anywhere, just for your own reference). |
| `exclusions[].fieldName` | Dot-path of the fact field this rule applies to (e.g. `user.name`). |
| `exclusions[].factType` | Optional — restrict the rule to a specific fact `type` value; omit to apply to the field name across all fact types. |
| `exclusions[].type` | Which sanitization to apply — see table below. |
| `exclusions[].pattern` | Optional regular expression. When set, only the matched portion of the value is sanitized; when omitted, the entire value is sanitized. |
| `exclusions[].preserveLength` | Mask-only: replace each character with `*` (keeping the original length) rather than a fixed-length placeholder. Default `true`. |
| `exclusions[].preserveWhitespace` | Mask-only: leave whitespace characters unmasked so the text still "looks like" separate words. Default `false`. |

`type` values:

| `type` | Behavior |
| - | - |
| `0` — Mask | Replace the value (or matched portion) with `*` characters. |
| `1` — Anonymize | Replace the value with a one-way hash — irreversible, but two occurrences of the same original value hash identically, so equality-based analysis still works. |
| `2` — Exclude | Remove the value entirely. |

## `features` — everything else is opt-in

All monitoring capability beyond basic identification lives under `features`, one block \
&#x20;per capability, each independently `enabled`. This section is required to be present in \
&#x20;the rule JSON (even if every sub-feature inside it is left off).

### `processMetrics`

```json theme={null}
"processMetrics": {
  "enabled": true,
  "interval": 60,
  "clrFallbackEnabled": false,
  "threadDetailEnabled": true,
  "threadPoolEnabled": false,
  "resourceCountersEnabled": false
}
```

Periodic OS-level process metrics: CPU %, working-set memory, thread count/detail, and \
&#x20;(optionally) handle/GDI/USER object counts and disk I/O deltas — the classic native \
&#x20;resource-leak indicators for a long-running desktop app.

| Field | Purpose |
| - | - |
| `enabled` / `interval` | Turn on collection and set its interval (seconds). |
| `clrFallbackEnabled` | Only relevant for a **headless** .NET process with no UI Worker — makes the CLR Profiler collect these metrics itself instead. Leave `false` for normal WPF/WinForms applications, which are already covered by the UI Worker. |
| `threadDetailEnabled` | Emit a per-thread CPU/state sample (via WMI), not just a total thread count. |
| `threadPoolEnabled` | Also report a best-effort count of `.NET ThreadPool`-named threads (only meaningful on .NET 6+ targets; reads `0` on older runtimes). |
| `resourceCountersEnabled` | Also report process handle count, GDI object count, USER object count, and disk read/write byte deltas since the last sample. |

### `gcMetrics`

```json theme={null}
"gcMetrics": { "enabled": false, "interval": 60 }
```

.NET garbage-collection metrics: a fact per GC pause as it happens (with generation, \
&#x20;whether it was induced, and heap size before/after), plus periodic cumulative gen0/1/2 \
&#x20;collection counts every `interval` seconds. Requires the CLR Profiler to be attached.

### `freezeDetection`

```json theme={null}
"freezeDetection": { "enabled": false, "pollIntervalMs": 2000, "hangTimeoutMs": 2000 }
```

Periodically pings each monitored window (`pollIntervalMs`) to see if it's still \
&#x20;responding to messages, waiting up to `hangTimeoutMs` before considering it hung. A fact \
&#x20;is emitted when a previously-hung window recovers, reporting how long it was \
&#x20;unresponsive. This runs its own background thread independent of other UI monitoring, so \
&#x20;it has a real (small) always-on cost — weigh that against how important freeze detection \
&#x20;is for the target application.

### `profiler` — CPU sampling

```json theme={null}
"profiler": { "enabled": false, "interval": 1000, "inclusions": [], "exclusions": [] }
```

Stack-sampling CPU profiler (requires the CLR Profiler attached). `interval` is how often \
&#x20;(ms) a stack sample is taken. `inclusions`/`exclusions` are executable-name filters for \
&#x20;which modules' code should appear in samples (both empty = everything).

### `http` — outbound HTTP monitoring

```json theme={null}
"http": {
  "enabled": false,
  "sslEnabled": true,
  "sslPorts": [ 443 ],
  "excludedPorts": [ 4225, 4226 ],
  "collectRequestBody": true,
  "requestBodyExclusions": "",
  "collectResponseBody": true,
  "responseBodyExclusions": ".*(css|js|png|jpg|jpeg|gif|svg|mpg)",
  "collectHeaders": false
}
```

Captures outbound HTTP(S) calls made by the target process, broken into connect/wait/ \
&#x20;download timing phases.

| Field | Purpose |
| - | - |
| `sslEnabled` / `sslPorts` | Enable TLS interception on the listed ports, needed to see HTTPS request/response detail (not just timing). |
| `excludedPorts` | Ports never monitored — typically your own GermainUX ports, to avoid capturing the agent's own uploads. |
| `collectRequestBody` / `requestBodyExclusions` | Whether to capture request bodies, and a regex of URLs/content to skip (e.g. large binary uploads). |
| `collectResponseBody` / `responseBodyExclusions` | Same, for responses — the sample regex above skips static assets (CSS/JS/images) as noise. |
| `collectHeaders` | Also capture request/response headers, including parsed `Server-Timing` data. |

### `exception`

```json theme={null}
"exception": { "enabled": false }
```

Reports managed (.NET) exceptions as they're thrown, with a captured stack trace. \
&#x20;Requires the CLR Profiler.

### `monitor` — core UI activity

```json theme={null}
"monitor": {
  "enabled": true,
  "windowEventsEnabled": true,
  "mouseEnabled": false,
  "changeEnabled": false,
  "keyboardEnabled": false
}
```

The baseline UI Worker monitoring feature; everything below it in this section \
&#x20;(`clickMaps`, `userClicks`, `userSearches`, `userFacingErrors`) requires `enabled: true` \
&#x20;here as well.

| Field | Purpose |
| - | - |
| `enabled` | Master switch — when `false`, no monitoring facts are produced at all. |
| `windowEventsEnabled` | Report windows being created/destroyed, and the app's own startup. |
| `mouseEnabled` | Report every mouse click on a control (raw telemetry — not filtered to specific business actions; see `userClicks` for that). |
| `changeEnabled` | Report when an input control's value changes (text edits, checkbox/radio toggles). |
| `keyboardEnabled` | Report command-style key presses (Enter, Escape, function keys, Ctrl/Alt/Win combinations) — not general text typed into fields. |

### `clickMaps` / `mouseMaps` — heatmap overlays

```json theme={null}
"clickMaps": { "enabled": false },
"mouseMaps": { "enabled": false }
```

`clickMaps` reports one point per click (control + screen position) for click-heatmap \
&#x20;visualizations. `mouseMaps` buffers raw mouse movement and flushes it periodically (every \
&#x20;5 minutes, on view change, or at shutdown) for movement heatmaps. Both are tagged with \
&#x20;whichever "view" was most recently identified by a `userClicks` selector — see below.

### `userClicks` — business-level click tracking

```json theme={null}
"userClicks": {
  "enabled": false,
  "typeValue": "Native:User Click",
  "selectors": {
    "Button Click": {
      "prefix": "Click on",
      "filter": { "type": "button" },
      "variables": [
        {
          "name": "argument1",
          "contextScan": false,
          "filter": { "name": "hierarchy" },
          "childIndex": 0
        }
      ],
      "requireDoubleClick": false
    }
  }
}
```

Unlike `monitor.mouseEnabled` (which reports *every* click), `userClicks` only reports a \
&#x20;click when it matches one of your named selectors — intended for tracking specific \
&#x20;business actions ("clicked Submit", "opened a customer record") rather than raw UI noise.

| Field | Purpose |
| - | - |
| `typeValue` | The fact `type` string stamped on every match (e.g. `Native:User Click`). |
| `selectors.{name}.filter` | Which control this selector matches — see [Filter fields](https://docs.germainux.com/main/monitoring-config-reference.md#filter-fields). |
| `selectors.{name}.prefix` | Text prefix used when building a description of the click (default: "Click on \\\<control\\>"). |
| `selectors.{name}.labelExpression` / `nameExpression` | Optional regexes further constraining the match against the control's label/name. |
| `selectors.{name}.requireDoubleClick` | Only match when the click was paired as a double-click (e.g. a DataGrid row drill-down), not a single click. |
| `selectors.{name}.variables` | Extra [context variables](https://docs.germainux.com/main/monitoring-config-reference.md#context-variable-fields) captured from elsewhere in the UI and attached to this specific click's fact. |

### `userSearches`

```json theme={null}
"userSearches": {
  "enabled": false,
  "selectors": {
    "Search Button": {
      "trigger": { "type": "button", "name": "SearchButton" },
      "valueControl": { "name": "SearchBox" }
    }
  }
}
```

When the `trigger` control is clicked, the current value of the separate `valueControl` \
&#x20;is captured as the search term. Use this for search boxes where the meaningful value \
&#x20;lives in a different control than the one that was clicked.

### `userFacingErrors`

```json theme={null}
"userFacingErrors": {
  "enabled": false,
  "rules": [
    { "label": "Error Dialog", "pattern": "[Ee]rror|[Ff]ailed|[Ee]xception" }
  ]
}
```

Reports when a newly created window's title matches one of the given regular \
&#x20;expressions — a lightweight way to detect error/failure dialogs without needing to \
&#x20;identify their exact controls. `label` becomes the fact's `name` field on a match.

### `replay` — session replay

```json theme={null}
"replay": {
  "enabled": false,
  "pointerEnabled": true,
  "controlMutationEnabled": true,
  "structuralChangesEnabled": true,
  "windowLifecycleEnabled": true,
  "focusMonitoringEnabled": true,
  "scrollMonitoringEnabled": true,
  "scrollbarMonitoringEnabled": true,
  "fragmentMaxEvents": 1000,
  "fragmentMaxAge": 15,
  "snapshotInterval": 30,
  "iconWin32Enabled": false,
  "thumbnailRules": [],
  "colorSamplingEnabled": false,
  "colorSamplingTypes": [ "pane", "window", "group", "button" ],
  "selfHealEnabled": false,
  "selfHealBurstThreshold": 3
}
```

Captures enough of the UI tree over time to reconstruct a visual replay of the session, \
&#x20;independent of the plain monitoring facts above.

| Field | Purpose |
| - | - |
| `enabled` | Master switch for all replay capture. |
| `pointerEnabled` | Record mouse clicks/moves. |
| `controlMutationEnabled` | Record control property changes (label, bounds, visibility). |
| `structuralChangesEnabled` | Record controls being added/removed from the UI tree. |
| `windowLifecycleEnabled` | Record windows being created/destroyed. |
| `focusMonitoringEnabled` | Record focus changes between controls. |
| `scrollMonitoringEnabled` / `scrollbarMonitoringEnabled` | Record scroll position/size and scrollbar thumb/track position changes. |
| `fragmentMaxEvents` / `fragmentMaxAge` | Flush the current batch of replay events after this many events, or this many seconds, whichever comes first. |
| `snapshotInterval` | Emit a full state snapshot at least this often (seconds); `0` disables periodic snapshots (a snapshot is always still captured at startup). |
| `iconWin32Enabled` | Capture each monitored window's application icon (via `WM_GETICON`/executable resource) for display in the replay viewer. |
| `thumbnailRules` | Ordered rules selecting which child controls get a captured visual thumbnail, and when to re-capture one — see [Thumbnail rule criteria](https://docs.germainux.com/main/monitoring-config-reference.md#thumbnail-rule-criteria). |
| `colorSamplingEnabled` / `colorSamplingTypes` | Sample background/border colors of controls (restricted to the listed UIA control type names; empty = all types) so the replay viewer can approximate styling without a full screenshot. |
| `selfHealEnabled` / `selfHealBurstThreshold` | Periodically re-scan the live UI tree to correct any drift between it and the Worker's in-memory copy; a rescan is also triggered after this many consecutive forced/deadline flushes in a row. Leave off unless replay data has been observed to drift from the real UI. |

## Filter fields

Used by `userClicks`/`userSearches` selectors, `globalVariables`, and context variables, \
&#x20;to identify a specific control:

| Field | Matches on |
| - | - |
| `type` | UIA control type, as a lowercase name (`button`, `edit`, `combo box`, `data grid`, `check box`, `list item`, `tab item`, `tree item`, `hyperlink`, `image`, `menu item`, and other standard UIA control type names). |
| `name` | The control's UIA AutomationId. |
| `label` | The control's visible label/name text. |
| `classname` | The Win32 window class name. |

Any combination of these can be set; all specified fields must match (AND).

## Context variable fields

Used by both `globalVariables` and a `userClicks` selector's `variables`:

| Field | Purpose |
| - | - |
| `name` | The name this value is attached to the fact under. |
| `filter` | Which control to read the value from — see [Filter fields](https://docs.germainux.com/main/monitoring-config-reference.md#filter-fields) above. |
| `childIndex` | If ≥ 0, read from the Nth child of the matched element instead of the element itself. |
| `siblingIndex` | If non-zero, read from a sibling offset by this many positions instead. |
| `expression` | Optional regex applied to the raw value; if present, only the matched portion is kept. |
| `contextScan` | Whether to actively search the UI tree for this value (`true`, default) vs. only checking the element directly involved in the triggering event. |
| `defaultOnFailure` | If `expression` is set and doesn't match, fall back to a default value instead of omitting the variable. |
| `lowerCase` | Lowercase the captured value. |

## Thumbnail rule criteria

Each `replay.thumbnailRules[]` entry has a `method` (`"win32"` or `"screen"` capture) and \
&#x20;a `criteria` object of AND'd match conditions, evaluated against each control the Worker \
&#x20;encounters:

| Criteria field | Matches |
| - | - |
| `type` / `not_type` | UIA control type name(s) that must / must not match (see [Filter fields](https://docs.germainux.com/main/monitoring-config-reference.md#filter-fields) for the naming convention). |
| `aid` / `not_aid` | AutomationId(s) that must / must not match. |
| `classname` / `not_classname` | Exact Win32 class name(s) that must / must not match. |
| `classnameSplit` / `all_classnameSplit` / `not_classnameSplit` | Win32 class name, split on whitespace into tokens: "any of these tokens present" / "all of these tokens present" / "none of these tokens present". |
| `label` / `not_label` | Visible label(s) that must / must not match (use `""` to match/exclude an empty label). |
| `hasChildren` | `true`/`false` — require the control to have/not have children. |
| `hasRect` | `true`/`false` — require the control to have/not have a non-zero bounding rectangle (i.e. actually visible on screen). |

Each rule also takes a top-level `recaptureOn` array listing which attribute changes \
&#x20;(`label`, `visibility`, `bounds`, `value`, `selected`) should trigger re-capturing the \
&#x20;thumbnail for a matched control after its first capture; omit it (or leave it empty) to \
&#x20;capture once and never recapture.

## Full example

See `Config/agent-config-sample.json` in the agent source tree for a complete, valid \
&#x20;starting-point file combining every block above with realistic default values and a \
&#x20;`"description"` field explaining it's meant to be copied and customized per application.

## Get Help

> [card] [Contact GermainUX Support](https://docs.germainux.com/main/support.md)
>
> The GermainUX team helps you get up and running faster, empower your team, turn data into actionable insights, and optimize performance to deliver measurable business outcomes.

> [card] Can't find what you need?
>
> Search all GermainUX docs with **Ctrl + K**, or use the feedback buttons at the bottom of this page to tell us what is missing.

The content of this document is proprietary to GERMAIN SOFTWARE.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.