[isaacsim.core.telemetry] Isaac Sim Telemetry Framework#
Version: 2.0.0
Overview#
isaacsim.core.telemetry provides a centralized telemetry framework for Isaac Sim extensions, built on top of Carbonite’s omni.structuredlog Python bindings. It offers:
Pre-registered common events for extension activation tracking, feature usage, and error reporting — usable with a single function call.
Custom schema support for extensions that need domain-specific telemetry events (e.g. URDF import failure diagnostics).
Centralized enable/disable — all events no-op when structured logging is disabled.
Consistent error handling — failures are logged via
carb.log_warninstead of raising exceptions.
Quick Start#
Add "isaacsim.core.telemetry" = {} to your extension’s [dependencies] in extension.toml, then use the common helpers:
from isaacsim.core.telemetry import emit_extension_activated, emit_feature_used, emit_error
# Track extension lifecycle
emit_extension_activated(extension_id="isaacsim.my.extension", extension_version="1.0.0", action="enabled")
# Track feature usage
emit_feature_used(
extension_id="isaacsim.my.extension",
feature_name="create_sensor",
feature_type="command",
duration_ms=150,
)
# Track errors
emit_error(
extension_id="isaacsim.my.extension",
error_category="validation_error",
error_type="invalid_sensor_config",
operation="create_sensor",
)
No schema registration or setup is required for these common events.
Decorator-based instrumentation#
For functions where you want automatic timing and error tracking, use the decorator API:
from isaacsim.core.telemetry import telemetry, telemetry_usage, telemetry_error
# Full instrumentation: featureUsed on success, errorOccurred on exception
@telemetry(extension_id="isaacsim.sensors.experimental.rtx", feature_name="create_lidar_sensor")
def create_lidar_sensor(prim_path, config):
...
# Usage tracking only (no error events)
@telemetry_usage(extension_id="isaacsim.sensors.experimental.rtx", feature_name="query_sensor")
def query_sensor(sensor_id):
...
# Error tracking only (no usage events)
@telemetry_error(extension_id="isaacsim.app.setup", feature_name="app_startup")
def initialize():
...
Extension lifecycle instrumentation#
Apply @telemetry_extension to an IExt subclass to automatically emit extensionActivated events on startup and shutdown. The extension name and version are parsed from the ext_id that Kit passes to on_startup:
from isaacsim.core.telemetry import telemetry_extension
@telemetry_extension
class MyExtension(omni.ext.IExt):
def on_startup(self, ext_id):
...
def on_shutdown(self):
...
Common Event Reference#
extensionActivated#
Emitted when an Isaac Sim extension is enabled or disabled.
Property |
Type |
Description |
|---|---|---|
|
string |
Extension identifier (e.g. |
|
string |
Semantic version (e.g. |
|
string |
|
featureUsed#
Emitted when a user invokes a command, menu item, or significant API call.
Property |
Type |
Description |
|---|---|---|
|
string |
Extension that owns the feature |
|
string |
Short identifier (e.g. |
|
string |
|
|
integer |
Wall-clock duration in milliseconds, |
errorOccurred#
Emitted when an error occurs in an Isaac Sim extension.
Property |
Type |
Description |
|---|---|---|
|
string |
Extension where the error occurred |
|
string |
Broad classification (enum: |
|
string |
Extension-specific error code (e.g. |
|
string |
Feature/operation active when the error occurred (matches |
|
boolean |
|
Feature Type Guidance#
Use the featureType parameter to classify how the user triggered the feature:
"command"— Registered Kit commands (omni.kit.commands.execute)."menu_item"— Menu bar or context menu actions."api_call"— Significant programmatic operations (e.g.SimulationAppstartup, sensor creation via Python API).
Error Telemetry Patterns#
All error fields are structured identifiers — no free-form text is accepted, which eliminates PII risk by design.
from isaacsim.core.telemetry import emit_error
try:
parse_urdf(file_path)
except URDFParseError as exc:
emit_error(
extension_id="isaacsim.asset.importer.urdf",
error_category="import_failure",
error_type="urdf_joint_parse",
operation="import_urdf",
recoverable=False,
)
errorCategory values#
errorCategory |
When to use |
|---|---|
|
Asset or file import/parse failures |
|
Invalid configuration, parameters, or schema violations |
|
Unexpected failures during normal operation |
|
Missing or invalid settings/configuration |
|
Required extension, plugin, or library not available |
|
Operations that exceeded expected duration |
errorType guidelines#
Use a short, descriptive code that identifies the specific failure within the extension. It should be meaningful for drill-down analysis but never contain PII:
urdf_joint_parse— URDF joint element could not be parsedmissing_scan_rate_param— required sensor parameter was absentphysics_step_nan— physics simulation produced NaN valuesprim_not_found— expected USD prim was missing from the stage
Custom Schemas#
For domain-specific events that don’t fit the common schema, register a custom baked JSON schema:
from isaacsim.core.telemetry import get_telemetry_manager
MY_SCHEMA = {
"generated": "Custom schema for URDF importer diagnostics.",
"anyOf": [{"$ref": "#/definitions/events/com.nvidia.isaacsim.urdf.importResult"}],
"$schema": "http://json-schema.org/draft-07/schema#",
"schemaMeta": {
"clientName": "isaacsim.urdf.diagnostics",
"schemaVersion": "1.0",
"eventPrefix": "com.nvidia.isaacsim.urdf",
"definitionVersion": "1.0",
"omniverseFlags": ["fSchemaFlagAnonymizeEvents"],
"description": "URDF importer telemetry events.",
},
"definitions": {
"events": {
"com.nvidia.isaacsim.urdf.importResult": {
"eventMeta": {
"service": "telemetry",
"privacy": {"category": "usage", "description": "URDF import results"},
"omniverseFlags": [],
},
"type": "object",
"additionalProperties": False,
"required": ["filePath", "success", "jointCount"],
"properties": {
"filePath": {"type": "string", "description": "Path to the URDF file"},
"success": {"type": "boolean", "description": "Whether the import succeeded"},
"jointCount": {"type": "integer", "description": "Number of joints parsed"},
},
"description": "Emitted after a URDF import attempt.",
},
},
},
"description": "URDF importer telemetry events.",
}
class UrdfImporterExtension(omni.ext.IExt):
def on_startup(self, ext_id):
manager = get_telemetry_manager()
manager.register_schema(schema_name="isaacsim.urdf.diagnostics", schema=MY_SCHEMA)
def on_shutdown(self):
manager = get_telemetry_manager()
manager.unregister_schema(schema_name="isaacsim.urdf.diagnostics")
Send custom events via the raw API:
get_telemetry_manager().send_event(
schema_name="isaacsim.urdf.diagnostics",
event_name="importResult",
data={"filePath": "/path/to/robot.urdf", "success": True, "jointCount": 12},
)
Schema Versioning#
Every baked JSON schema contains two version fields in schemaMeta:
Field |
Purpose |
|---|---|
|
Version of the schema as a registered entity. Used by the telemetry transmitter and data servers to validate events. Once approved and published, a version is immutable. |
|
Version of the event definitions block ( |
Both use MAJOR.MINOR format and are kept in sync.
Minor bump (e.g.
1.0→1.1) — non-breaking changes: adding a new event, adding an optional property, adding a privacy category.Major bump (e.g.
1.1→2.0) — breaking changes: removing an event, removing/renaming a required property, changing a property’s type.
Published schema versions are immutable. Older versions remain approved so that older Isaac Sim builds continue to function. Bump versions only when event definitions actually change, not on every extension release.
Privacy and Configuration#
Telemetry behavior is controlled by a layered hierarchy. isaacsim.core.telemetry checks only the top-level switch; the remaining layers are enforced by omni.kit.telemetry and the Carbonite transmitter.
Control hierarchy#
Layer |
Setting |
Effect |
|---|---|---|
1. Master switch |
|
When |
2. Transmission |
|
When |
3. Mode |
|
Each mode applies different collection and transmission policies. Headless mode disables telemetry by default — pass |
4. Extension toggle |
Per-extension setting (e.g. |
Individual extensions can define their own toggle in |
5. Privacy consent |
|
Per-category consent ( |
Setting telemetry controls#
Command line:
# Disable all structured logging
--/structuredLog/enable=false
# Disable transmission only (local logging continues)
--/telemetry/enableAnonymousData=false
# Enable telemetry in headless mode
--/telemetry/mode=dev
Application .kit file:
[settings.telemetry]
enableAnonymousData = true
Runtime (Python):
import carb.settings
settings = carb.settings.get_settings()
settings.set("/structuredLog/enable", False) # disable everything
settings.set("/telemetry/enableAnonymousData", False) # disable transmission only
Privacy categories#
Carbonite defines three consent categories. Each event schema declares which category it belongs to; the transmitter only sends events whose category has user consent.
Category |
Description |
Used by this extension? |
|---|---|---|
|
App usage — startup, shutdown, feature adoption |
Yes — |
|
App performance — hardware info, timing, errors |
Yes — |
|
App customization by the user |
No — not currently collected in Omniverse apps |
Consent is set in ~/.nvidia-omniverse/config/privacy.toml:
[privacy]
usage = true
performance = true
personalization = true
For containers, use environment variables instead: OMNI_TELEMETRY_PRIVACY_USAGE, OMNI_TELEMETRY_PRIVACY_PERFORMANCE, OMNI_TELEMETRY_PRIVACY_PERSONALIZATION. If a category is missing and no environment variable is set, consent is denied by default.
Anonymization#
All common events use the
fSchemaFlagAnonymizeEventsflag, which strips personally identifiable information before transmission.Error events use only structured identifiers (enums and codes) — no free-form text fields — eliminating PII risk by design.
omni.kit.telemetry(a dependency of this extension) manages the structured log transmitter lifecycle.
Complete Integration Example#
A full extension combining common helpers and a custom schema:
import time
import omni.ext
from isaacsim.core.telemetry import (
emit_error,
emit_extension_activated,
emit_feature_used,
get_telemetry_manager,
)
CUSTOM_SCHEMA = {
# ... your baked JSON schema dict ...
}
class MyExtension(omni.ext.IExt):
def on_startup(self, ext_id):
ext_name = ext_id.split("-")[0]
version = ext_id.split("-")[1] if "-" in ext_id else "0.0.0"
# Track activation
emit_extension_activated(extension_id=ext_name, extension_version=version, action="enabled")
# Register domain-specific schema
get_telemetry_manager().register_schema(schema_name="my.custom.schema", schema=CUSTOM_SCHEMA)
def on_shutdown(self):
get_telemetry_manager().unregister_schema(schema_name="my.custom.schema")
def do_work(self):
start = time.perf_counter()
try:
result = self._perform_operation()
duration_ms = (time.perf_counter() - start) * 1000.0
emit_feature_used(
extension_id="isaacsim.my.extension",
feature_name="do_work",
feature_type="command",
duration_ms=duration_ms,
)
# Send domain-specific event
get_telemetry_manager().send_event(
schema_name="my.custom.schema", event_name="operationResult", data={"success": True}
)
except Exception:
emit_error(
extension_id="isaacsim.my.extension",
error_category="runtime_error",
error_type="operation_failed",
operation="do_work",
)
Enable Extension#
The extension can be enabled (if not already) in one of the following ways:
Define the next entry as an application argument from a terminal.
APP_SCRIPT.(sh|bat) --enable isaacsim.core.telemetry
Define the next entry under [dependencies] in an experience (.kit) file or an extension configuration (extension.toml) file.
[dependencies]
"isaacsim.core.telemetry" = {}
Open the Window > Extensions menu in a running application instance and search for isaacsim.core.telemetry.
Then, toggle the enable control button if it is not already active.
Python API#
- class TelemetryManager#
Bases:
objectSingleton that manages structured-log schema registration and event emission.
On first access the common Isaac Sim schema is automatically registered so that the typed helper functions (
emit_extension_activated(),emit_feature_used(),emit_error()) work without any setup.Extensions that need domain-specific telemetry can register additional schemas via
register_schema()and emit events viasend_event().- classmethod get_instance() TelemetryManager#
Return the singleton instance, creating it on first call.
- Returns:
The global TelemetryManager instance.
Example:
from isaacsim.core.telemetry import TelemetryManager manager = TelemetryManager.get_instance()
- is_enabled() bool#
Check whether structured logging is enabled.
- Returns:
True if the
/structuredLog/enablecarb setting is truthy.
Example:
manager = TelemetryManager.get_instance() if manager.is_enabled(): print("Telemetry is active")
- register_schema(
- schema_name: str,
- schema: dict,
Register a baked JSON schema with the structured-log system.
The schema dict must follow the Carbonite baked JSON Schema draft-07 format (with
schemaMeta,definitions/events,$schema,anyOf). See the Carbonite structured-log walkthrough for details.- Parameters:
schema_name – Unique key for later lookups (e.g. the schema’s
clientName).schema – Baked JSON schema dict passed directly to
omni.structuredlog.register_schema().
- Returns:
Dict mapping short event names to event handles, or None if registration failed or telemetry is disabled.
Example:
from isaacsim.core.telemetry import get_telemetry_manager events = get_telemetry_manager().register_schema(schema_name="my.schema", schema=my_schema_dict)
- send_event(
- schema_name: str,
- event_name: str,
- data: dict,
Emit a structured-log event.
- Parameters:
schema_name – Key used during
register_schema().event_name – Short event name within the schema.
data – Dict of event properties matching the schema definition.
- Returns:
True if the event was sent, False otherwise.
Example:
from isaacsim.core.telemetry import get_telemetry_manager get_telemetry_manager().send_event( schema_name="my.schema", event_name="myEvent", data={"key": "value"} )
- unregister_schema(schema_name: str) None#
Remove a previously registered schema from tracking.
This does not unregister the schema from the Carbonite structured-log system (schemas remain registered for the process lifetime), but it prevents further events from being sent through this manager for the given schema_name.
- Parameters:
schema_name – Key used during
register_schema().
Example:
from isaacsim.core.telemetry import get_telemetry_manager get_telemetry_manager().unregister_schema("my.schema")
- emit_error(
- extension_id: str,
- error_category: str,
- error_type: str,
- operation: str,
- recoverable: bool = True,
Emit an
errorOccurredevent.All parameters are structured identifiers — no free-form text is accepted, which eliminates PII risk by design.
- Parameters:
extension_id – Extension where the error occurred.
error_category – Broad classification. Must be one of
"import_failure","validation_error","runtime_error","configuration_error","dependency_error", or"timeout".error_type – Extension-specific error code for drill-down (e.g.
"urdf_joint_parse").operation – The feature/operation active when the error happened. Should match
featureNamevalues used infeatureUsedevents.recoverable –
Trueif the operation could continue or degrade gracefully,Falseif it aborted.
- Returns:
True if the event was sent successfully.
Example:
from isaacsim.core.telemetry import emit_error emit_error( "isaacsim.asset.importer.urdf", "import_failure", "urdf_joint_parse", "import_urdf", recoverable=False, )
- emit_extension_activated(
- extension_id: str,
- extension_version: str,
- action: str,
Emit an
extensionActivatedevent.- Parameters:
extension_id – Extension identifier (e.g.
"isaacsim.sensors.experimental.rtx").extension_version – Semantic version string (e.g.
"1.2.0").action –
"enabled"or"disabled".
- Returns:
True if the event was sent successfully.
Example:
from isaacsim.core.telemetry import emit_extension_activated emit_extension_activated( extension_id="isaacsim.sensors.experimental.rtx", extension_version="1.2.0", action="enabled" )
- emit_feature_used(
- extension_id: str,
- feature_name: str,
- feature_type: str,
- duration_ms: int = 0,
Emit a
featureUsedevent.- Parameters:
extension_id – Extension that owns the feature.
feature_name – Short identifier (e.g.
"import_urdf").feature_type – One of
"command","menu_item", or"api_call".duration_ms – Wall-clock duration in milliseconds.
- Returns:
True if the event was sent successfully.
Example:
from isaacsim.core.telemetry import emit_feature_used emit_feature_used( extension_id="isaacsim.asset.importer.urdf", feature_name="import_urdf", feature_type="command", duration_ms=1234, )
- get_telemetry_manager() TelemetryManager#
Return the global
TelemetryManagersingleton.- Returns:
The shared TelemetryManager instance.
Example:
from isaacsim.core.telemetry import get_telemetry_manager manager = get_telemetry_manager() manager.send_event(schema_name="my.schema", event_name="myEvent", data={"key": "value"})
- telemetry(
- extension_id: str,
- feature_name: str,
- feature_type: str = 'api_call',
- error_category: str = 'runtime_error',
Decorator that instruments a function with full telemetry.
On successful return a
featureUsedevent is emitted with the wall-clock duration. If the function raises, anerrorOccurredevent is emitted instead and the exception is re-raised unchanged.Works with both regular and
asyncfunctions.- Parameters:
extension_id – Extension that owns the feature.
feature_name – Short identifier (e.g.
"import_urdf").feature_type – One of
"command","menu_item", or"api_call".error_category – Category used in the
errorOccurredevent if the function raises.
- Returns:
A decorator that wraps the target function.
Example:
from isaacsim.core.telemetry import telemetry @telemetry(extension_id="isaacsim.sensors.experimental.rtx", feature_name="create_lidar_sensor") def create_lidar_sensor(prim_path, config): ... @telemetry(extension_id="isaacsim.asset.importer.urdf", feature_name="import_urdf", feature_type="command") async def import_urdf(file_path): ...
- telemetry_error(
- extension_id: str,
- feature_name: str,
- error_category: str = 'runtime_error',
Decorator that emits an
errorOccurredevent when the function raises.No
featureUsedevent is emitted on success. Use this for functions where you only care about failure tracking.Works with both regular and
asyncfunctions.- Parameters:
extension_id – Extension where the error would occur.
feature_name – Operation name used as the
operationfield in the error event.error_category – Broad error classification.
- Returns:
A decorator that wraps the target function.
Example:
from isaacsim.core.telemetry import telemetry_error @telemetry_error(extension_id="isaacsim.app.setup", feature_name="app_startup") def initialize(): ...
- telemetry_extension(
- cls: type[_T],
Class decorator that instruments an
omni.ext.IExtsubclass with lifecycle telemetry.Wraps
on_startupandon_shutdownto automatically emitextensionActivatedevents withaction="enabled"/"disabled". The extension name and version are parsed from theext_idargument that Kit passes toon_startup(format"ext.name-X.Y.Z").Handles both
on_startup(self, ext_id)andon_startup(self)signatures — Kit inspects the method signature to decide whether to passext_id.- Parameters:
cls – The
IExtsubclass to decorate.- Returns:
The same class with wrapped
on_startup/on_shutdown.
Example:
from isaacsim.core.telemetry import telemetry_extension @telemetry_extension class MyExtension(omni.ext.IExt): def on_startup(self, ext_id): ... def on_shutdown(self): ...
- telemetry_usage(
- extension_id: str,
- feature_name: str,
- feature_type: str = 'api_call',
Decorator that emits a
featureUsedevent on successful return.Exceptions are ignored (no
errorOccurredevent). Use this for functions where errors are expected or handled elsewhere.Works with both regular and
asyncfunctions.- Parameters:
extension_id – Extension that owns the feature.
feature_name – Short identifier (e.g.
"query_sensor").feature_type – One of
"command","menu_item", or"api_call".
- Returns:
A decorator that wraps the target function.
Example:
from isaacsim.core.telemetry import telemetry_usage @telemetry_usage(extension_id="isaacsim.sensors.experimental.rtx", feature_name="query_sensor") def query_sensor(sensor_id): ...