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

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 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. 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 (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 (lines 68-86) demonstrates this pattern at sds-client/src/test/java/com/didiglobal/sds/client/test/AbstractDowngradeTest.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:

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 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →