Skip to content

RUM Configuration

The Windows SDK collects the same View, Action, Resource, Error, and Long Task data in both C# and Native C/C++. C# provides automatic UI framework collection; Native uses an explicit C ABI and adapters for HWND and WinHTTP.

RUM Initialization Configuration

Sampling Configuration

Semantics .NET / C# Native C/C++ Default Range
Regular Session sampling SampleRate sample_rate 1.0 0.0–1.0
Additional Error Session sampling SessionErrorSampleRate session_error_sample_rate 0.0 0.0–1.0

The sampling decision remains consistent within the same Session. We recommend verifying integration with 1.0 first, then adjusting based on data volume.

Collection Boundaries

Capability .NET / C# Native C/C++
View WPF and WinForms automatic; WinUI 3 requires explicit Window association Call the View C ABI within the window lifecycle
Action Automatic collection for common UI controls and app launch Automatic collection for app launch; call the Action C ABI for business operations
Resource Automatic collection via HttpClient WinHTTP adapter or manual Resource C ABI
Error Automatic collection for unhandled exceptions; manual Error supported Native crash recovery or manual Error
Long Task UI thread probing or manual reporting HWND Watchdog or manual reporting

Enabling Collection

GuanceSdk.EnableAutomaticInstrumentation(new AutomaticInstrumentationOptions
{
    EnableWpf = true,
    EnableWinForms = true,
    EnableWinUI = true,
    EnableWebView = true,
    EnableHttpClient = true,
    EnableUnhandledException = true,
    EnableUiThreadBlock = true,
    EnableAppLaunch = true,
    UiThreadBlockThreshold = TimeSpan.FromMilliseconds(500),
    UiThreadProbeInterval = TimeSpan.FromMilliseconds(250),
    UiThreadLongTaskCooldown = TimeSpan.FromSeconds(5)
});

Automatic Collection Parameters

Parameter Default Description
EnableWpf true Automatically collects WPF Window and common controls.
EnableWinForms true Automatically collects WinForms Form and common controls.
EnableWinUI true Enables WinUI 3 control collection; Window still requires explicit association.
EnableWebView true Automatically discovers supported WebView2 controls.
EnableHttpClient true Collects Resources through .NET HTTP diagnostic events.
EnableUnhandledException true Collects unhandled exceptions from application domains and UI frameworks.
EnableUiThreadBlock true Monitors UI thread blocking.
EnableAppLaunch true Collects the app launch phase.
UiThreadBlockThreshold 500 ms Long Task threshold.
UiThreadProbeInterval 250 ms UI thread probe interval.
UiThreadLongTaskCooldown 5 s Cooldown for merging consecutive blocking reports.

Repeated calls do not re-register the same set of collectors, but the application should still call this only once during the startup flow.

After initialization, the Native SDK automatically collects cold and hot launches by default and generates Actions with action_type=launch_cold and action_type=launch_hot, respectively. guance_sdk_config_init() initializes enable_app_launch_tracking to 1; if automatic launch Actions are not needed, set it to 0 before calling guance_sdk_init():

guance_sdk_config config;
guance_sdk_config_init(&config);
config.enable_app_launch_tracking = 0;

Automatic collection observes the current process's top-level window and the first composed frame. A cold start Action includes three phases: before application code runs, application initialization, and the first frame; a hot start Action is generated when the application returns to the foreground from the background. The application can still use guance_rum_add_launch_action() to report a launch phase already measured by the host; once a cold start has been manually reported, the SDK will not generate a duplicate automatic cold start Action.

After creating the top-level window, you can enable the UI Watchdog and crash recovery:

guance_sdk_native_monitoring_config monitoring;
guance_sdk_native_monitoring_config_init(&monitoring);
monitoring.enable_ui_hang_monitoring = 1;
monitoring.main_window_handle = reinterpret_cast<uintptr_t>(main_window);
monitoring.enable_native_crash_reporting = 1;
monitoring.enable_minidump = 0;

if (!guance_sdk_enable_native_monitoring(rum, &monitoring)) {
    // Invalid HWND or configuration.
}

Native Monitoring Parameters

guance_sdk_native_monitoring_config is a versioned structure; you must call the initialization function first.

Field Default Description
enable_ui_hang_monitoring 0 Whether to enable the HWND UI Watchdog.
enable_native_crash_reporting 0 Whether to enable SEH and crash recovery on the next launch.
main_window_handle 0 A valid top-level HWND owned by the current process.
ui_probe_interval_ms 250 UI probe interval.
long_task_threshold_ms 500 Long Task threshold.
hang_threshold_ms 5000 Application Not Responding threshold.
hang_report_cooldown_ms 5000 Cooldown for continuous hang reports.
crash_cache_path SDK default directory Local directory for crash envelopes and optional dumps.
enable_minidump 0 Whether to keep a local minidump; dumps are not uploaded to RUM.
max_crash_files 3 Maximum number of crash files.
max_crash_file_bytes 32 MiB Maximum total bytes for crash files.

C++ applications should include guance_sdk.hpp so that the host-side adapter correctly installs and restores the std::terminate handler. The crashed process does not perform network or queue writes; the next initialization converts the limited crash envelope into a RUM Error.

Network Resources

When EnableHttpClient = true, the SDK automatically records the URL, method, status code, total duration, request/response sizes, and HTTP protocol. If you need an explicit handler:

using var http = new HttpClient(
    GuanceSdk.CreateHttpMessageHandler(new HttpClientHandler()));

C++ WinHTTP uses a scoped adapter:

guance::rum::WinHttpResource resource(
    rum,
    request,
    "https://api.example.com/items",
    "GET");
resource.send();
resource.receive();

For other network libraries, call guance_rum_start_resource() and guance_rum_stop_resource_ext(). For Trace headers and RUM correlation, see Trace Configuration.

Applications should record DNS, TCP, TLS, or TTFB only when real network phase timings are available; do not estimate missing phases.

RUM Manual Instrumentation

When automatic collection cannot express business semantics, you can manually report Action, View, Error, Long Task, and Resource. .NET / C# uses GuanceSdk, and Native C/C++ uses the C ABI in guance_rum.h; both integration approaches produce the same Windows RUM data types.

Avoid Duplicate Collection

Manual APIs and automatic collection write to the same Session. Do not manually report data that has already been collected automatically by windows, controls, HttpClient, WinHTTP, or WebView2.

Action

Auto-Ending Actions

Used to collect user operations and associate Resources, Errors, and Long Tasks generated during the operation:

var action = GuanceSdk.StartAction("SaveOrder", "click");
if (!action.IsAccepted)
{
    // This call was ignored by high-frequency protection.
}

In normal mode, calling StopAction is not required, and disposing the returned RumActionScope does not end the Action.

const char* action_id = guance_rum_start_action(rum, "SaveOrder", "click");
if (action_id[0] == '\0') {
    // This call was ignored by high-frequency protection.
}

Normal mode behaves like the Android SDK: only one active Action is kept at any time; consecutive StartAction calls within 100 ms ignore the new call, and a call after more than 100 ms ends the previous Action and starts a new one. An Action ends when the View changes and lasts for about 5 seconds at most.

Actions Waiting for Business Completion

When a business operation must cover a piece of asynchronous logic, enable needWait mode. Only this mode must be paired with StopAction:

using (GuanceSdk.StartAction("SaveOrder", "custom", needWait: true))
{
    await SaveOrderAsync();
}

You can also save the ActionId and call GuanceSdk.StopAction(actionId) when the business logic finishes.

const char* action_id = guance_rum_start_action_ext(
    rum,
    "SaveOrder",
    "custom",
    1);

save_order();

if (action_id[0] != '\0') {
    guance_rum_stop_action(rum, action_id);
}

A needWait Action is not replaced by a new Action until explicitly ended, but it is still subject to the approximately 5-second maximum duration and View switch restrictions. If starting an Action returns an empty ID, the call was not accepted, and you should not call StopAction.

Actions with Known Duration

GuanceSdk.AddAction(
    name: "ExportReport",
    type: "custom",
    duration: TimeSpan.FromMilliseconds(320),
    properties: new Dictionary<string, object?>
    {
        ["format"] = "csv"
    });
constexpr int64_t duration_ns = 320LL * 1000 * 1000;
guance_rum_add_action(rum, "ExportReport", "custom", duration_ns);

AddAction is used to directly report a standalone Action that has already finished and whose duration is known. It is not subject to the 100 ms high-frequency protection or the 5-second limit, and it does not associate with subsequently generated Resources, Errors, or Long Tasks.

View

GuanceSdk.StartView(
    "OrderDetail",
    new Dictionary<string, object?>
    {
        ["order_type"] = "subscription"
    });

// Execute when the page ends.
GuanceSdk.StopView();
guance_rum_start_view(rum, "OrderDetail");

// Execute when the page or window ends.
guance_rum_stop_view(rum);

Starting a new View automatically ends the currently active View. View names should describe stable pages and must not contain order numbers, user IDs, object addresses, or search terms.

Error

try
{
    await LoadOrdersAsync();
}
catch (Exception exception)
{
    GuanceSdk.AddError(
        exception,
        new Dictionary<string, object?>
        {
            ["operation"] = "load_orders"
        });
}

For errors that are not Exception, you can use GuanceSdk.AddError(stack, message, errorType, source). When automatic collection of unhandled exceptions is enabled, if the same exception is rethrown after manual reporting and eventually terminates the process, a windows_crash will also be generated; avoid duplicate reporting based on business semantics.

guance_rum_add_error(
    rum,
    "OrderRepository::load_orders",
    "Order request failed",
    "NetworkError",
    "custom");

Automatically collected .NET fatal exceptions use error_type=windows_crash, and Native SEH and C++ std::terminate use error_type=native_crash; the error_source for crashes is always logger. Native crash monitoring recovers crash Errors on the next launch; do not call the manual Error API inside a crash handler. For the complete type and field documentation, see Application Data Collection.

Long Task

GuanceSdk.AddLongTask(
    duration: TimeSpan.FromMilliseconds(850),
    stack: "ReportRenderer.Render");
constexpr int64_t duration_ns = 850LL * 1000 * 1000;
guance_rum_add_long_task(rum, duration_ns, "ReportRenderer::render");

When UI thread blocking monitoring is enabled, do not manually report the same blocking interval again.

Resource

var resourceId = GuanceSdk.StartResource(
    "https://api.example.com/orders",
    "GET");

GuanceSdk.StopResource(
    resourceId,
    statusCode: 200,
    timing: RumResourceTiming.FromTotalElapsed(
        TimeSpan.FromMilliseconds(120),
        source: "manual"),
    responseSize: 2048,
    requestSize: 0,
    resourceType: "http");

If the application has already measured DNS, TCP, TLS, and TTFB, you can use RumResourceTiming.FromPhases() to write phase timings; when no reliable data is available, write only the total elapsed time.

C++ applications can use ResourceScope to ensure the Resource is still completed on exceptions or early returns:

#include "guance_sdk.hpp"

guance::rum::ResourceScope resource(
    rum,
    "https://api.example.com/orders",
    "GET",
    "http");

const auto response = send_request();
resource.complete(
    response.status_code,
    response.body_size,
    response.request_size);

Pure C applications can pair guance_rum_start_resource() with guance_rum_stop_resource(); use guance_rum_stop_resource_ext() when you need to write trace_id, span_id, request size, or the HTTP protocol.

Even when the request fails, you still need to complete the Resource and set the status code to 0. After enabling automatic HttpClient or WinHTTP Resources, do not call the manual API again for the same request.

Flush

Manual events enter a local queue first. To attempt reporting immediately after a critical flow:

await GuanceSdk.FlushAsync();
guance_sdk_flush(rum);

On normal application exit, you should still call ShutdownAsync() or guance_sdk_shutdown(). For HTTP Trace propagation and application logs, see Trace Configuration and Log Configuration, respectively.

Session Replay

Experimental Capability

Windows Session Replay is disabled by default. It can be explicitly enabled and validated, but it is not yet in the stable release scope. Integrators must evaluate replay compatibility, privacy, performance, and data volume on their own, and current behavior should not be considered a stable compatibility commitment.

Explicitly enable it at initialization and set the Replay sampling and default privacy policy:

GuanceSdk.Init(new GuanceConfig
{
    // DatawayUrl / ClientToken / RumAppId ...
    SessionReplay = new RumSessionReplayConfig
    {
        Enabled = true,
        SampleRate = 1.0,
        OnErrorSampleRate = 0.0,
        TextAndInputPrivacy = SessionReplayTextAndInputPrivacy.MaskAll,
        TouchPrivacy = SessionReplayTouchPrivacy.Show,
        ImagePrivacy = SessionReplayImagePrivacy.MaskAll
    }
});

SampleRate and OnErrorSampleRate both range from 0.0 to 1.0. After initialization, recording can be controlled manually:

GuanceSdk.StartSessionReplayRecording();
GuanceSdk.StopSessionReplayRecording();

Manually starting recording cannot bypass Enabled = false; it must first be enabled in the initialization configuration. For element-level privacy APIs, see Windows Session Replay Privacy Overrides.

guance_sdk_config config;
guance_sdk_config_init(&config);
config.session_replay_enabled = 1;
config.session_replay_sample_rate = 1.0;
config.session_replay_on_error_sample_rate = 0.0;

guance_sdk_handle rum = guance_sdk_init(&config);
guance_rum_register_replay_window(
    rum,
    reinterpret_cast<uintptr_t>(main_window));

Native Replay uses a separate persistent queue and the v1/write/rum/replay upload channel. guance_rum_start_session_replay() and guance_rum_stop_session_replay() can control recording manually, but the start call likewise does not override a disabled initialization configuration.

Page recording from WebView2 and Electron enters the same native Session, segment, queue, and upload channel through the native Bridge. See WebView2 Monitoring and Electron Monitoring, respectively.

Feedback

Is this page helpful?