Skip to content

Commit

Permalink
other tweaks (#2437)
Browse files Browse the repository at this point in the history
  • Loading branch information
brock-statsig authored Dec 24, 2024
1 parent 935fa2c commit 9af4358
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 62 deletions.
49 changes: 47 additions & 2 deletions docs/client/concepts/initialize.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Initializing a Client SDK
sidebar_label: Initializing your SDK
title: Initializing SDKs
sidebar_label: Initializing
---

One of the first steps in using a Statsig client SDK is to call the asynchronous `initialize()` method in the SDK language of your choice.
Expand Down Expand Up @@ -104,3 +104,48 @@ evaluated_keys: {
/** The hashing algorithm used */
hash_used: string;
```


## Bootstrapping Overview

Bootstrapping the Client SDKs is a pattern used to provide the precomputed user assignments directly to the SDK for initialization, rather than relying on the default SDK behavior of downloading the configurations over the network from Statsig servers. This approach is beneficial if you're looking to remove the network dependency on Statsig and consolidate the download of the payload into the initial load to reduce latency.

### Technical details

With this approach, your server will be responsible for serving the configuration payload to your client app on page load (for web implementations) or during app launch (for mobile implementations).

This architecture requires running a server SDK that supports the `getClientInitializeResponse` method.
Your server SDK will maintain a fresh configuration in memory and when a request hits your route handler, you should call `getClientInitializeResponse(<user>)`, passing in a StatsigUser Object to generate the configuration object that gets passed to the client SDK for synchronous initialization.

#### Additional Considerations

* You should pass the same user object on both the server and client side.
* The `initializeValues` option should be an Object.
* This approach allows the client SDK to initialize synchronously.

## NodeJS example

_Server-side Node express.js route_
```js
app.get('/', async (req, res) => {
const userObj = {
userID: user.id
}
const initializeValues = Statsig.getClientInitializeResponse(userObj, null, {hash: "djb2"});
// render page.hbs using two variables
res.render('page.hbs', {
initializeValues: JSON.stringify(initializeValues),
userObj: JSON.stringify(userObj),
});
});
```

_Client-side JS within page.hbs_
```js
// pass both the userObject and initializeValues payloads as Object.
// The triple curly-brace in handlebars will unescape the JSON string
const client = new StatsigClient('<CLIENT_SIDE_KEY>' userObj);
client.dataAdapter.setData(bootstrapObject, user);
client.initializeSync();
```

2 changes: 1 addition & 1 deletion docs/client/concepts/parameter-stores.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Parameter Stores
sidebar_label: Parameter Stores
sidebar_label: Using Parameter Stores
slug: /client/concepts/parameter-stores
---

Expand Down
3 changes: 2 additions & 1 deletion docs/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ For details on flushing, check the [Node.js Server SDK documentation](/server/no
---

### I don't see my client or server language listed. Can I still use Statsig?

If none of our current SDKs meet your needs, please let us know via our [Slack community](https://statsig.com/slack)!

---
Expand All @@ -77,7 +78,7 @@ If you need all hypothetical assignments, you can consider using the `getClientI

#### Example of capturing all assignments in Node

Note, this method is designed to [bootstrap](/client/concepts/bootstrapping) client SDKs, and as such, will hash the experiment and feature keys returned in the payload, obfuscating their names for security. You can provide an optional `hash` parameter, allowing you to disable hashing and capture all values in plain text: [Node](https://github.com/statsig-io/node-js-server-sdk/blob/ea116142221c1aa83b46eff8b5f2292c8f8e2d54/src/StatsigServer.ts#L597), [Python](https://github.com/statsig-io/node-js-server-sdk/blob/ea116142221c1aa83b46eff8b5f2292c8f8e2d54/src/StatsigServer.ts#L597), [Java](https://github.com/statsig-io/java-server-sdk/blob/7443c357c78616142de9257af9e4c55c877ca700/src/main/kotlin/com/statsig/sdk/StatsigServer.kt#L83), [Go](https://github.com/statsig-io/go-sdk/blob/3d7edcbe468efb0fc7a04b0d10202243403dce5f/client.go#L282).
Note, this method is designed to [bootstrap](/client/concepts/initialize#bootstrapping-overview) client SDKs, and as such, will hash the experiment and feature keys returned in the payload, obfuscating their names for security. You can provide an optional `hash` parameter, allowing you to disable hashing and capture all values in plain text: [Node](https://github.com/statsig-io/node-js-server-sdk/blob/ea116142221c1aa83b46eff8b5f2292c8f8e2d54/src/StatsigServer.ts#L597), [Python](https://github.com/statsig-io/node-js-server-sdk/blob/ea116142221c1aa83b46eff8b5f2292c8f8e2d54/src/StatsigServer.ts#L597), [Java](https://github.com/statsig-io/java-server-sdk/blob/7443c357c78616142de9257af9e4c55c877ca700/src/main/kotlin/com/statsig/sdk/StatsigServer.kt#L83), [Go](https://github.com/statsig-io/go-sdk/blob/3d7edcbe468efb0fc7a04b0d10202243403dce5f/client.go#L282).

```node
const assignments = statsig.getClientInitializeResponse(userObj, "client-key", {hash: "none"});
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/private-attributes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Evaluation happening locally to the server on `privateAttributes` in the `statsi
Don't just take our word for it - all of our SDKs are open source and [available on github](https://github.com/statsig-io). Feel free to dive in to the implementation of `privateAttributes` in the SDK you are using, or reach out to us on [slack](https://www.statsig.com/slack) and we can point you in the right direction.

:::info
To ensure that user PII is never transmitted over the network back to Statsig during Client SDK initialization, you should use [Client Boostrapping](/client/concepts/bootstrapping) and provide the `privateAttributes` as part of the user object on the server to the `getClientInitializeResponse(<user object>)` call. This will generate all of the assignments locally on your server, and these assignments can then be passed as `initializeValues` to the client SDK, negating the need to send any user attributes from the client device to Statsig.
To ensure that user PII is never transmitted over the network back to Statsig during Client SDK initialization, you should use [Client Boostrapping](/client/concepts/initialize#bootstrapping-overview) and provide the `privateAttributes` as part of the user object on the server to the `getClientInitializeResponse(<user object>)` call. This will generate all of the assignments locally on your server, and these assignments can then be passed as `initializeValues` to the client SDK, negating the need to send any user attributes from the client device to Statsig.
:::

## Event Logging
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/uptime.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Collected here are a set of best practices that help maximize your uptime - acro

6. Use **change management** on Statsig in production. Changes should be approved by a reviewer. For critical areas, you can enforce an Allowed Reviewer group that has enough context to decide. Statsig Feature Gates allow you to easily audit and roll back changes.

7. **Caching on client SDKs**: Initializing Statsig client SDKs requires them to connect to Statsig and download config. Client SDKs can cache and reuse config (for the same user) if they are offline. You can also choose to bootstrap your client from your own server (and remove the round trip to Statsig) by using [client SDK bootstrapping](/client/concepts/bootstrapping).
7. **Caching on client SDKs**: Initializing Statsig client SDKs requires them to connect to Statsig and download config. Client SDKs can cache and reuse config (for the same user) if they are offline. You can also choose to bootstrap your client from your own server (and remove the round trip to Statsig) by using [client SDK bootstrapping](/client/concepts/initialize#bootstrapping-overview).

8. **Caching on server SDKs**: Initializing Statsig server SDKs requires them to connect to Statsig and download config. If connectivity to Statsig fails, initialization fails (falling back to default values). Remove this dependency when connectivity fails by providing this config locally. Read more about [dataAdapter](/server/concepts/data_store#dataadapter-or-datastore)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,12 @@
---
title: Monitoring the SDK
sidebar_label: SDK Monitoring
slug: /server/concepts/sdk_monitoring
sidebar_label: SDK Monitoring Integrations
slug: /sdk_monitoring
---
Statsig SDKs provide two main ways of monitoring the SDK's behavior and performance:
1. **Logs**: The SDK logs important events and errors to help you understand event-by-event how Statsig is behaving in your application.
2. **Metrics**: The SDK emits metrics to help you understand the aggregate performance of the SDK its impact on your application.

**Supported SDKs**: Most SDKs have some level of logging, but our latest release of structured logging and metrics, is currently only [available by the Python SDK](/server/pythonSDK/#sdk-monitoring-).

## Logging Levels and Expected Information
The Statsig SDK uses multiple logging levels to communicate various information types. Here’s what each logging level represents and what kind of details you can expect:

- Debug: Detailed logs useful for new users onboarding with the SDK and for diagnosing potential issues, such as:
- Messages when a feature gate does not exist
- Tracking process flows within the SDK
- Info: General information about the SDK’s operation, typically relevant to regular usage, such as:
- Messages regarding SDK initialization, including source and version information
- Notifications when the configuration store is populated
- Warning: Logs about unusual events that may impact functionality but are automatically managed and recovered, such as:
- Messages on non critical errors caught by the SDK
- Notifications about reconnection attempts to gRPC services
- Error: Critical logs about issues that severely impact the SDK’s functionality, such as:
- Messages about initialization failures or timeouts
- Notifications indicating gRPC fallback, suggesting gRPC is unavailable or incorrect configuration

:::note
This latest release of structured logging and metrics, is currently only [available by the Python SDK](/server/pythonSDK/#sdk-monitoring-). Want it in another? Reach out in our [Support Slack](https://statsig.com/slack).
:::

## SDK Metrics
Some Statsig SDKs provide built-in metrics to help you monitor its performance and impact on your application. The specific implementation may vary by programming language, refer to the documentation for the language-specific SDK interface.
Expand Down
21 changes: 19 additions & 2 deletions docs/sdks/debugging.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Debugging
sidebar_label: Debugging your SDK
sidebar_label: Debugging
slug: /sdk/debugging
---

Expand All @@ -23,6 +23,23 @@ When debugging why a certain user got a certain value, there are a number of too

![Screen Shot 2023-04-27 at 11 20 14 AM](https://user-images.githubusercontent.com/74584483/234956317-e65f7fd3-d87d-4616-b905-ee4df097863e.png)

### Logging Levels and Expected Information
Log-line feedback is one of the simplest tools you have to understand how your SDK is behaving. Our SDKs have multiple log levels to decide what information you'd like to receive:

- Debug: Detailed logs useful for new users onboarding with the SDK and for diagnosing potential issues, such as:
- Messages when a feature gate does not exist
- Tracking process flows within the SDK
- Info: General information about the SDK’s operation, typically relevant to regular usage, such as:
- Messages regarding SDK initialization, including source and version information
- Notifications when the configuration store is populated
- Warning: Logs about unusual events that may impact functionality but are automatically managed and recovered, such as:
- Messages on non critical errors caught by the SDK
- Notifications about reconnection attempts to gRPC services
- Error: Critical logs about issues that severely impact the SDK’s functionality, such as:
- Messages about initialization failures or timeouts
- Notifications indicating gRPC fallback, suggesting gRPC is unavailable or incorrect configuration



## Evaluation Details

Expand Down Expand Up @@ -70,7 +87,7 @@ When debugging why a certain user got a certain value, there are a number of too

For example: `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 a config was not included (resulting in an "Unrecognized" source), it could be excluded due to [Target Apps](/sdk-keys/target-apps), or [Client Bootstrapping](/client/concepts/bootstrapping).
If you are not sure why a config was not included (resulting in an "Unrecognized" source), it could be excluded due to [Target Apps](/sdk-keys/target-apps), or [Client Bootstrapping](/client/concepts/initialize#bootstrapping-overview).
</TabItem>
<TabItem value="server" label="Server SDKS">

Expand Down
4 changes: 2 additions & 2 deletions docs/sdks/getting-started.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Getting Started with Statsig's SDKs
sidebar_label: Getting Started
title: SDK Overview
sidebar_label: SDK Overview
slug: /sdks/getting-started
---

Expand Down
2 changes: 1 addition & 1 deletion docs/server/concepts/all_assignments.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ For this use-case, we recommend using the `getClientInitializeResponse` server s

#### Example of capturing all assignments in Node

Note that this method is designed to [bootstrap](/client/concepts/bootstrapping) the client SDKs, and as such, will hash the experiment and feature keys returned in the payload, obfuscating their names to mitigate the possibility of end-users spoofing into features &amp; gates. You can now provide an optional `hash` parameter, allowing you to disable hashing and capture all group names and values in plain text — [Node](https://github.com/statsig-io/node-js-server-sdk/blob/ea116142221c1aa83b46eff8b5f2292c8f8e2d54/src/StatsigServer.ts#L597), [Python](https://github.com/statsig-io/node-js-server-sdk/blob/ea116142221c1aa83b46eff8b5f2292c8f8e2d54/src/StatsigServer.ts#L597), [Java](https://github.com/statsig-io/java-server-sdk/blob/7443c357c78616142de9257af9e4c55c877ca700/src/main/kotlin/com/statsig/sdk/StatsigServer.kt#L83), [Go](https://github.com/statsig-io/go-sdk/blob/3d7edcbe468efb0fc7a04b0d10202243403dce5f/client.go#L282).
Note that this method is designed to [bootstrap](/client/concepts/initialize#bootstrapping-overview) the client SDKs, and as such, will hash the experiment and feature keys returned in the payload, obfuscating their names to mitigate the possibility of end-users spoofing into features &amp; gates. You can now provide an optional `hash` parameter, allowing you to disable hashing and capture all group names and values in plain text — [Node](https://github.com/statsig-io/node-js-server-sdk/blob/ea116142221c1aa83b46eff8b5f2292c8f8e2d54/src/StatsigServer.ts#L597), [Python](https://github.com/statsig-io/node-js-server-sdk/blob/ea116142221c1aa83b46eff8b5f2292c8f8e2d54/src/StatsigServer.ts#L597), [Java](https://github.com/statsig-io/java-server-sdk/blob/7443c357c78616142de9257af9e4c55c877ca700/src/main/kotlin/com/statsig/sdk/StatsigServer.kt#L83), [Go](https://github.com/statsig-io/go-sdk/blob/3d7edcbe468efb0fc7a04b0d10202243403dce5f/client.go#L282).

```node
const assignments = statsig.getClientInitializeResponse(userObj, "client-key", {hash: "none"});
Expand Down
62 changes: 34 additions & 28 deletions sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const sidebars: SidebarsConfig = {
className: "lightbulb-icon sidebar-icon",
items: [
"understanding-platform",
"client/concepts/parameter-stores",
"guides/first-device-level-experiment",
"guides/experiment-on-custom-id-types",
"guides/using-environments",
Expand All @@ -55,23 +56,10 @@ const sidebars: SidebarsConfig = {
className: "doc-icon sidebar-icon",
items: [
"sdks/getting-started",
{
Concepts: [
"sdks/client-vs-server",
"server/concepts/user",
"client/concepts/initialize",
"sdks/debugging",
"server/concepts/monitoring",
"client/concepts/bootstrapping",
"client/concepts/persistent_assignment",
"client/concepts/parameter-stores",
"server/concepts/data_store",
"server/concepts/persistent_assignment",
"sdk-keys/api-keys",
"sdk-keys/target-apps",
"server/deprecation-notices",
],
},
"sdks/client-vs-server",
"server/concepts/user",
"client/concepts/initialize",
"sdks/debugging",
{
className: "html-icon sidebar-icon sdk-sidebar-icon",
type: "doc",
Expand Down Expand Up @@ -239,16 +227,7 @@ const sidebars: SidebarsConfig = {
]

},
{
type: "category",
label: "Other Frameworks",
items: [
"guides/node-express-feature-flags",
"guides/node-express-abtests",
"guides/python-flask-feature-flags",
"guides/python-flask-abtests",
],
},

{
type: "category",
label: "Azure AI",
Expand All @@ -265,6 +244,28 @@ const sidebars: SidebarsConfig = {
"azureai/running-experiments",
],
},
{
type: "category",
label: "Advanced SDK Methods",
items: [
{
type: "category",
label: "Other Frameworks",
items: [
"guides/node-express-feature-flags",
"guides/node-express-abtests",
"guides/python-flask-feature-flags",
"guides/python-flask-abtests",
],
},
"client/concepts/persistent_assignment",
"server/concepts/persistent_assignment",
"server/concepts/data_store",
"sdk-keys/target-apps",

]
},
"server/deprecation-notices",
],
},
{
Expand Down Expand Up @@ -936,6 +937,7 @@ const sidebars: SidebarsConfig = {
label: "Workspace Management",
items: [
"access-management/introduction",
"sdk-keys/api-keys",
{
Workspace: [
"access-management/organizations",
Expand Down Expand Up @@ -1049,7 +1051,11 @@ const sidebars: SidebarsConfig = {
],
},
{
Reliability: ["infrastructure/reliability-faq", "guides/uptime"],
Reliability: [
"infrastructure/reliability-faq",
"guides/uptime",
"infrastructure/monitoring",
],
},
],
},
Expand Down

0 comments on commit 9af4358

Please sign in to comment.