Skip to main content

Debugging

When debugging why a certain user got a certain value, there are a number of tools at your disposal. First and foremost, every config in the Statsig ecosystem (meaning Feature Gates, Dynamic Configs, Experiments, and Layers) has a Setup tab and a Diagnostics tab.

The diagnostics tab is useful for seeing higher level pass/fail/bucketing population sizes over time, via the checks chart at the top.

Screen Shot 2023-04-27 at 11 17 08 AM

For debugging specific checks, the logstream at the bottom is useful and shows both production and non production exposures in near real time:

Screen Shot 2023-04-27 at 11 20 14 AM

If you click in to a specific exposure, there is even more detail to explain why a certain evaluation got a certain value. The rule is already specified in the exposure stream, but beyond that there are other considerations for why you got a certain value. We call this the evaluation Reason, which is only visible in the details view of an exposure. Click on any specific exposure to find it:

Screen Shot 2023-04-27 at 11 21 50 AM

For client SDKs, these reasons for the value you are seeing can be:

  • Network: fetched at SDK initialization time from the network
  • Bootstrap: derived from bootstrapping the client SDK with a set of values
  • InvalidBootstrap: the set of values was for a different user than the SDK was initialized with. These are discarded for analysis (See Fixing InvalidBootstrap)
  • Cache: loaded from the local storage cache for the current user, and a network result was not available
  • Prefetch: fetched from the prefetchUsers api (js-client only)
  • Sticky: persisted from a sticky evaluation previously
  • LocalOverride: from an override set locally on the SDK via an override API
  • Unrecognized: the sdk was initialized, but this config did not exist in the set of values
  • Error: an unknown error has occured, and was logged to statsig servers
  • NetworkNotModified: the network response came back, but the cached values were already up to date for this user

Newer versions of the sdk will contain two tags: one regarding the initialization state of the sdk, and the other qualifying different sources for that value.

So in addition to the reasons above, you may have:

  • Recognized: the value was recognized in the set of configs the client was operating with
  • Unrecognized: the value was not included in the set of configs the client was operating with
  • Sticky: the value is from keepDeviceValue = true on the method call
  • LocalOverride: the value is from a local override set on the sdk

So Network:Recognized means the sdk had up to date values from a successful initialization network request, and the gate/config/experiment you were checking was defined in the payload. If you are not sure why the config was not included in the payload, it could be excluded due to Target Apps, or Client Bootstrapping, for example.

For server SDKs, these reasons for the value you are seeing can be:

  • Network: fetched at SDK initialization time from the network
  • Bootstrap: derived from bootstrapping the server SDK with a set of values
  • DataAdapter: derived from the provided data adapter or data store
  • LocalOverride: from an override set locally on the SDK via an override API
  • Unrecognized: the sdk was initialized, but this config did not exist in the set of values
  • Uninitialized: the sdk was not yet successfully initialized

Newer versions fothe

In addition to these reasons, the most recent versions of server SDKs will also give you two times to watch: the time at which config definitions initialized the SDK, and the time at which the SDK was currently evaluating those definitions. When you change a gate/config/experiment, the project time will update and server SDKs will download the new definition. If you have not changed your project in two hours, and the evalation time is saying the SDK is up to date as of 2 hours ago, then you're evaluating the most up to date definition of that gate/experiment.

In this example, the project was last updated yesterday, and the SDK was initialized with those values. The project has not updated since that time, and the SDK is still using that same set of definitions which it fetched from the network. You can also see the SDK type and version associated with a given check.

Screen Shot 2023-04-27 at 11 15 50 AM

Fixing InvalidBootstrap

This can occur when you are Bootstrapping a Statsig Client SDK with your own prefetched or generated values. The InvalidBootstrap reason is signally that the current user the Client SDK is operating against is not the same as the one used to generate the bootstrap values.

The following pseudo code highlights how this can occur:

// Server Side

userA = { userID: 'user-a' };
bootstrapValues = Statsig.getClientInitializeResponse(userA);

// Client Side

bootstrapValues = fetchStatsigValuesFromMyServers(); // <- Network request that executes the above logic

userB = { userID: 'user-b' }; // <- This is not the same User
Statsig.initialize("client-key", userB, { initializeValues: bootstrapValues });

Users must also be a 1 to 1 match. The SDK will treat a user with slightly different values as a completely different user. For example, the following two user objects would also trigger InvalidBootstrap even though they have the same UserID.

userA = { userID: 'user-a' };
userAExt = { userID: 'user-a', customIDs: { employeeID: 'employee-a' }};

Client SDK Debugger

It can be useful to inspect the current values that a Client SDK is using internally. For this, we have a Client SDK Debugger. With this tool, you can see the current User object the SDK is using as well as the gate/config values associated with it.

Javascript/React: Via a Chrome Extension https://github.com/statsig-io/statsig-sdk-debugger-chrome-extension

iOS: Available with Statsig.openDebugView(). Available in v1.26.0 and above.

Android: Not yet supported.

LandingGates ListGate DetailsExperiment Details
client-debugger-landingclient-debugger-gates-listclient-debugger-gate-infoclient-debugger-experiment-details