Skip to content

RUM Configuration

The Windows SDK collects the same View, Action, Resource, Error, and Long Task 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

Semantic .NET / C# Native C/C++ Default Range
General Session Sampling SampleRate sample_rate 1.0 0.01.0
Error Session Additional Sampling SessionErrorSampleRate session_error_sample_rate 0.0 0.01.0

The sampling decision remains consistent within the same session. It is recommended to first verify integration with 1.0, then adjust based on data volume.

Collection Boundaries

Capability .NET / C# Native C/C++
View WPF, WinForms automatic; WinUI 3 explicit Window association Invoke View C ABI within the window lifecycle
Action Common UI controls and app launch automatic collection App launch automatic collection; business operations invoke Action C ABI
Resource HttpClient automatic collection WinHTTP adapter or manual Resource C ABI
Error Unhandled exception automatic collection, supports manual Error Native crash recovery or manual Error
Long Task UI thread detection 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 collect WPF Windows and common controls.
EnableWinForms true Automatically collect WinForms Forms and common controls.
EnableWinUI true Enable WinUI 3 control collection; Windows still require explicit association.
EnableWebView true Automatically discover supported WebView2 controls.
EnableHttpClient true Collect Resources via .NET HTTP diagnostic events.
EnableUnhandledException true Collect unhandled exceptions in the application domain and UI framework.
EnableUiThreadBlock true Monitor UI thread blocking.
EnableAppLaunch true Collect the application launch phase.
UiThreadBlockThreshold 500 ms Long Task threshold.
UiThreadProbeInterval 250 ms UI thread probe interval.
UiThreadLongTaskCooldown 5 s Cooldown interval for merging consecutive blocking reports.

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

After initialization, the Native SDK automatically collects cold and hot launches by default, generating Actions with action_type=launch_cold and action_type=launch_hot respectively. guance_sdk_config_init() initializes enable_app_launch_tracking to 1; if the automatic launch Action is 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 top-level window of the current process and the first composited frame. The cold launch Action includes three phases: before application code runs, application initialization, and the first frame. When the application returns from the background to the foreground, a hot launch Action is generated. The application can still use guance_rum_add_launch_action() to report launch phases measured by the host; after manually reporting a cold launch, the SDK will not generate a duplicate automatic cold launch 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 and must be initialized by calling 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 next-launch crash recovery.
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 interval for persistent hang reports.
crash_cache_path SDK default directory Local directory for crash envelopes and optional dumps.
enable_minidump 0 Whether to retain 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 to let the host-side adapter correctly install and restore the std::terminate handler. The crashing process does not execute network or queue writes; the next initialization converts the limited crash envelope into a RUM Error.

Network Resources

With EnableHttpClient = true, the URL, method, status code, total duration, request/response size, and HTTP protocol are automatically recorded. When an explicit handler is required:

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 Header and RUM association, refer to Trace Configuration.

The application should only record DNS, TCP, TLS, or TTFB when the actual network phase timing is available; it should not estimate missing phases.

RUM Manual Instrumentation

When automatic collection cannot express business semantics, you can manually report Actions, Views, Errors, Long Tasks, and Resources. .NET / C# uses GuanceSdk, Native C/C++ uses the C ABI in guance_rum.h; both integration methods 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 automatically collected by windows, controls, HttpClient, WinHTTP, or WebView2.

Action

Auto-Terminated Action

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 the 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 the high-frequency protection.
}

The normal mode behaves consistently with the Android SDK: only one active Action is kept at a time; consecutive calls to StartAction within 100 ms will ignore the new call; after 100 ms, a subsequent call will end the previous Action and start a new one. An Action ends when the View changes and has a maximum duration of approximately 5 seconds.

Action Waiting for Business Completion

When a business operation must cover asynchronous logic, enable the needWait mode. Only this mode requires pairing 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 operation completes.

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 will not be replaced by a new Action until it is explicitly ended, but it is still subject to the approximate 5-second maximum duration and View change restrictions. If an empty ID is returned when starting an Action, it means the call was not accepted, and StopAction should not be called.

Action 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 an independent Action that has already ended with a known duration. It is not subject to the 100 ms high-frequency protection or the 5-second limit, nor does it associate subsequent 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 current active View. View names should describe stable pages and should 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 non-Exception errors, you can use GuanceSdk.AddError(stack, message, errorType, source). When automatic unhandled exception collection is enabled, if the same exception is manually reported and then re-thrown, eventually causing the process to terminate, an additional windows_crash will 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, 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 from within a crash handler. For complete type and field descriptions, refer to 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 already enabled, do not manually report the same blocking 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 measured DNS, TCP, TLS, and TTFB, you can use RumResourceTiming.FromPhases() to write phase timings; only write the total duration when reliable data is unavailable.

C++ applications can use ResourceScope to ensure the Resource is still ended 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);

For pure C applications, pair guance_rum_start_resource() and guance_rum_stop_resource(); use guance_rum_stop_resource_ext() when writing trace_id, span_id, request size, or HTTP protocol.

The Resource still needs to be ended on request failure, with the status code set to 0. After enabling HttpClient or WinHTTP automatic Resources, do not call the manual API for the same request again.

Flush

Manual events are first placed in a local queue. To attempt an immediate upload after a critical flow:

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

The application should still call ShutdownAsync() or guance_sdk_shutdown() on normal exit. For HTTP Trace propagation and application logging, refer to Trace Configuration and Log Configuration respectively.

Session Replay

Experimental Capability

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

Enable explicitly during 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
    }
});

The range for SampleRate and OnErrorSampleRate is 0.01.0. After initialization, recording can be controlled manually:

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

Manual start cannot bypass Enabled = false; it must be enabled in the initialization configuration. For element-level privacy APIs, refer to Windows Session Replay Privacy Override.

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 persisted queue and the v1/write/rum/replay upload channel. guance_rum_start_session_replay() and guance_rum_stop_session_replay() can manually control recording, but the start call will not override the disabled initialization configuration.

WebView2 and Electron page recording enters the same native session, segment, queue, and upload channel via the native Bridge. Refer to WebView2 Monitoring and Electron Monitoring respectively.

Feedback

Is this page helpful?