> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/lens/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/lens/_mcp/server.

# Custom Export Strategies

NeMo Lens picks which ranks export by name: `NemoLensConfig.export_strategy` selects a callable from a process-wide registry. The four built-in strategies cover the common cases (see [Sampling](/nemo/lens/user-guide/sampling)); the registry is the extension point for everything else, including fleet-aware sampling, locality-aware selection, and anything that needs more context than the built-in strategies expose.

## Built-In Strategies

These strategies are registered automatically at import time and exposed as the frozenset `nemo.lens.strategies.BUILTIN_STRATEGIES` (this symbol lives on the submodule and is not a top-level `nemo.lens` export, so import it as `from nemo.lens.strategies import BUILTIN_STRATEGIES`):

* `single_rank` (default): a single rank exports (`config.export_rank`, where `-1` means the last rank).
* `all_ranks`: every rank exports.
* `sampled`: a deterministic hash-based fraction of ranks, controlled by `config.export_sample_rate`.
* `first_rank_per_node`: the rank with `LOCAL_RANK=0` on each node. This reads `LOCAL_RANK` from the environment (set by torchrun, deepspeed, etc.); a missing value is treated as `"0"`.

These built-in strategies cannot be unregistered, and replacing them requires `allow_override=True`.

## Select a Strategy

Select a strategy by name, through the config or env var:

```python
from nemo.lens import NemoLensConfig, setup_telemetry

cfg = NemoLensConfig(enabled=True, export_strategy="first_rank_per_node")
handle = setup_telemetry(cfg, rank=rank, world_size=world_size)
```

```bash
NEMO_LENS_EXPORT_STRATEGY=first_rank_per_node
```

Alternatively, pass the callable directly to `setup_telemetry` as an ad-hoc, one-off strategy:

```python
handle = setup_telemetry(
    cfg,
    rank=rank,
    world_size=world_size,
    export_strategy=lambda config, rank, world_size: rank in {0, 7, 42},
)
```

The `export_strategy=` argument bypasses the registry, which is useful when you want a one-line strategy without polluting a process-wide name.

## Register a Custom Strategy

```python
from nemo.lens import register_export_strategy, NemoLensConfig, setup_telemetry

def first_two_ranks(config, rank, world_size):
    return rank < 2

register_export_strategy("first_two_ranks", first_two_ranks)

cfg = NemoLensConfig(enabled=True, export_strategy="first_two_ranks")
handle = setup_telemetry(cfg, rank=rank, world_size=world_size)
```

* Register the strategy before calling `setup_telemetry`. Validation is lazy, so unknown names raise a `ValueError` at `setup_telemetry` time, not during `NemoLensConfig` construction.
* The registry is process-wide. Call `register_export_strategy` exactly once per process, typically near the import-time setup.
* `allow_override` is **keyword-only**. Pass `allow_override=True` only when you intentionally replace an existing entry. Without it, re-registering an already-registered name raises a `ValueError`. An empty `name` also raises a `ValueError`. Built-in strategies can only be replaced with `allow_override=True`, and they can never be unregistered.

## Strategy Callable Signature

```python
ExportStrategy = Callable[[NemoLensConfig, int, int], bool]
```

A strategy receives the resolved `NemoLensConfig`, the global `rank`, and the `world_size`. It returns `True` if **this** rank should export, `False` otherwise. The decision runs once per process at `setup_telemetry` time.

Strategies can read environment variables to obtain context omitted from function arguments, such as `LOCAL_RANK`, `NODE_RANK`, `SLURM_PROCID`, or other launcher-specific variables. The built-in `first_rank_per_node` strategy demonstrates this approach.

## Discovery and Introspection

```python
from nemo.lens import registered_strategies, unregister_export_strategy

registered_strategies()
# ['all_ranks', 'first_rank_per_node', 'first_two_ranks', 'sampled', 'single_rank']

unregister_export_strategy("first_two_ranks")
```

`registered_strategies()` returns a sorted list of every name currently in the registry. `unregister_export_strategy(name)` removes a custom entry; it raises a `ValueError` if `name` refers to a built-in strategy or is not registered.

`register_export_strategy`, `registered_strategies`, `unregister_export_strategy`, and `ExportStrategy` are top-level exports (`from nemo.lens import ...`). The lower-level `get_export_strategy(name)` lookup, like `BUILTIN_STRATEGIES`, is **not** a top-level export and must be imported from `nemo.lens.strategies`.

## Why This API

Name-based dispatch lets the same env var (`NEMO_LENS_EXPORT_STRATEGY`) route to user code without touching NeMo Lens internals, allowing production runs and CI to pick a strategy from outside the program. The `setup_telemetry(export_strategy=)` argument is the lower-level escape hatch: pass any callable, skip the registry, and never name it. This parallels the `span_exporter=` argument documented in [Custom Exporters](/nemo/lens/user-guide/custom-exporters), both of which keep the core surface small while staying open at the bottom for callers that need it.