# How to Use the `exceptionSign` Method for Exception Statistics in Didi SDS

> Learn how to use the exceptionSign method in Didi SDS clients to validate classify and count exceptions for downgrade strategies. Optimize your exception handling now.

- Repository: [DiDi/sds](https://github.com/didi/sds)
- Tags: how-to-guide
- Published: 2026-02-28

---

**The `exceptionSign` method acts as the statistical entry point that SDS clients invoke within catch blocks to validate, classify, and count exceptions toward sliding-window counters that drive exception-rate and exception-quantity downgrade strategies.**

The `exceptionSign` method bridges runtime failures and degradation decisions in the Didi SDS (Service Degradation System) client library. When protecting business methods with SDS, developers call this method to ensure that caught exceptions are properly recorded and evaluated against configured thresholds. According to the didi/sds source code, the implementation in [`CommonSdsClient.java`](https://github.com/didi/sds/blob/main/CommonSdsClient.java) handles point validation, exception filtering, and atomic counter updates through a coordinated three-step process.

## What `exceptionSign` Does in the SDS Client

The `exceptionSign` method is defined in the `SdsClient` interface and implemented by `CommonSdsClient` at [`sds-client/src/main/java/com/didiglobal/sds/client/CommonSdsClient.java`](https://github.com/didi/sds/blob/main/sds-client/src/main/java/com/didiglobal/sds/client/CommonSdsClient.java). It serves as the primary API for recording that an exception occurred during the execution of a protected business method.

When you invoke `sdsClient.exceptionSign(point, e)`, the client performs three distinct operations: it validates the protection point name, determines whether the specific `Throwable` should be counted as a degradation exception, and updates the statistical counters for the current time window. This design ensures that only relevant exceptions contribute to downgrade decisions while maintaining thread-safe statistics.

## How `exceptionSign` Records Exception Statistics

The statistical recording process follows a precise pipeline that filters noise and updates counters atomically.

### Step 1: Point Name Validation

The method first validates inputs using `AssertUtil.notBlack(point, ...)` to ensure the protection point identifier is not empty. This validation prevents malformed statistics from polluting the counter service and ensures that every recorded exception maps to a valid configuration point.

### Step 2: Exception Classification

Next, the implementation delegates to `SdsDowngradeExceptionService.isDowngradeException(point, exception)` to determine if the caught exception should count toward degradation statistics. This service examines two configured lists for the point:

- **Downgrade exceptions**: Specific exception types that should trigger statistical counting
- **Except exceptions**: Exception types that should be explicitly excluded from counting

As implemented in [`sds-client/src/main/java/com/didiglobal/sds/client/service/SdsDowngradeExceptionService.java`](https://github.com/didi/sds/blob/main/sds-client/src/main/java/com/didiglobal/sds/client/service/SdsDowngradeExceptionService.java) (lines 78-94), if no explicit configuration exists for the point, **every non-`SdsException` is treated as a failure exception** by default. This means standard business exceptions automatically contribute to exception-rate calculations unless you explicitly whitelist them.

### Step 3: Counter and Delay Updates

Once classified as a relevant exception, the method performs two critical updates:

1. **Downgrade delay extension**: Calls `SdsDowngradeDelayService.continueDowngradeDelay(point, System.currentTimeMillis())` to extend any active degradation delay windows
2. **Exception counter increment**: Invokes `SdsPowerfulCounterService.exceptionInvokeAddAndGet(point, startTime)` to atomically increment the exception count for the current sliding window

The `startTime` parameter comes from a `ThreadLocal` variable set by `shouldDowngrade` at the beginning of the request, ensuring the exception is counted in the correct time bucket even if the exception occurs milliseconds later.

## Implementing `exceptionSign` in Your Code

The standard pattern places `exceptionSign` inside a catch block, followed by a re-throw to maintain the original error semantics. The test harness in [`AbstractDowngradeTest.java`](https://github.com/didi/sds/blob/main/AbstractDowngradeTest.java) (lines 68-86) demonstrates this pattern at [`sds-client/src/test/java/com/didiglobal/sds/client/test/AbstractDowngradeTest.java`](https://github.com/didi/sds/blob/main/sds-client/src/test/java/com/didiglobal/sds/client/test/AbstractDowngradeTest.java):

```java
public boolean callBusiness(String point) {
    try {
        if (sdsClient.shouldDowngrade(point)) {
            // Return fallback response when degraded
            return false;
        }

        // Execute real business logic
        doWork();

    } catch (Exception e) {
        // Record the exception for SDS statistics
        sdsClient.exceptionSign(point, e);
        // Re-throw so upstream callers see the failure
        throw e;
    } finally {
        // Always close the request in SDS
        sdsClient.downgradeFinally(point);
    }
    return true;
}

```

This pattern ensures that `exceptionSign` captures the error before the `finally` block executes, while `downgradeFinally` handles latency and visit statistics regardless of success or failure.

## Configuring Exception Filters

You control which exceptions contribute to statistics through `SdsPointStrategyConfig`. To specify that only `IllegalStateException` counts as a degradation trigger for the "orderCreate" point:

```java
SdsPointStrategyConfig.setDowngradeExceptions(
        "orderCreate",
        Arrays.asList(IllegalStateException.class),
        Collections.emptyList());

```

If you provide no configuration, the default behavior in `SdsDowngradeExceptionService` counts any exception except `SdsException` itself, effectively treating all business errors as potential degradation signals.

## How `exceptionSign` Drives Downgrade Decisions

The counters updated by `exceptionSign` are consumed by two strategy executors that evaluate degradation rules:

- **`ExceptionStrategyExecutor`**: Compares the raw exception count against the `exceptionThreshold` defined in `SdsStrategy`
- **`ExceptionRateStrategyExecutor`**: Calculates the ratio of exception count to total visits and compares it against the `exceptionRateThreshold`

Both executors read from `SdsPowerfulCounterService` using the same sliding-window mechanics that `exceptionSign` writes to, creating a closed feedback loop where runtime exceptions directly influence subsequent `shouldDowngrade` decisions.

## Summary

- **The `exceptionSign` method** in [`CommonSdsClient.java`](https://github.com/didi/sds/blob/main/CommonSdsClient.java) is the canonical API for recording exceptions in SDS-protected methods
- **Three-phase processing** includes point validation, exception classification via `SdsDowngradeExceptionService`, and counter updates via `SdsPowerfulCounterService`
- **Default classification** treats all non-`SdsException` throwables as degradation exceptions unless explicitly configured otherwise
- **Timing correlation** uses `ThreadLocal` data from `shouldDowngrade` to ensure exceptions land in the correct sliding-window bucket
- **Strategy integration** feeds exception counts to `ExceptionStrategyExecutor` and `ExceptionRateStrategyExecutor` for threshold-based downgrade decisions

## Frequently Asked Questions

### When should I call `exceptionSign` in my application?

Call `exceptionSign` inside a catch block immediately after catching an exception in any SDS-protected method, before any re-throw or error handling logic. According to the [`AbstractDowngradeTest.java`](https://github.com/didi/sds/blob/main/AbstractDowngradeTest.java) implementation (lines 83-86), the typical pattern is `catch (Exception e) { sdsClient.exceptionSign(point, e); throw e; }` to ensure statistics are recorded while preserving the original error propagation.

### What happens if I don't configure exception filters?

If you do not configure specific downgrade or except exceptions for a point, `SdsDowngradeExceptionService.isDowngradeException` defaults to counting every exception that is not an instance of `SdsException`. This conservative default ensures that business logic failures automatically contribute to exception-rate statistics and trigger protective degradation when thresholds are breached.

### How does `exceptionSign` relate to exception-rate downgrade strategies?

The `exceptionSign` method increments counters that `ExceptionRateStrategyExecutor` reads when evaluating the `exceptionRateThreshold` strategy. By updating `SdsPowerfulCounterService.exceptionInvokeAddAndGet`, `exceptionSign` provides the numerator (exception count) for the exception-rate calculation, which the strategy executor divides by total visits to determine if the current error rate exceeds the configured limit.

### Can I call `exceptionSign` without calling `shouldDowngrade` first?

While technically possible, calling `exceptionSign` without a preceding `shouldDowngrade` call is not recommended. The `startTime` parameter for counter updates comes from a `ThreadLocal` set by `shouldDowngrade`, so missing the initial call results in incorrect time-bucket alignment for your statistics. Always pair `exceptionSign` with the standard `shouldDowngrade`-`downgradeFinally` lifecycle to ensure accurate sliding-window accounting.