Repository: statsig-io/docs
Pull request #3035: Add templated sections for server core docs
Author: login: devin-ai-integration[bot]
Created: 2025-05-19T17:21:17Z | Merged: 2025-05-19T21:01:42Z

# Add templated sections for server core docs

Added new templated sections for persistent storage, data store, custom output logger, and observability client to the server core documentation.

These sections are dynamic based on the language and show 'coming soon' if the language doesn't support a particular interface.

## Changes

- Created template files for each interface in the Templates directory
- Added language-specific documentation for Python, Java, and Node.js
- Updated the core MDX files to include the new templates
- Documented the interfaces that users can customize and pass back to Statsig

Link to Devin run: https://app.devin.ai/sessions/f1912737a91e48459bfef3f3c403ee7d
Requested by: kat@statsig.com



Diff:
diff --git a/docs/server-core/Templates/_DataStore.mdx b/docs/server-core/Templates/_DataStore.mdx
new file mode 100644
index 000000000..0c8582e41
--- /dev/null
+++ b/docs/server-core/Templates/_DataStore.mdx
@@ -0,0 +1,15 @@
+import Admonition from '@theme/Admonition';
+
+## Data Store
+
+The Data Store interface allows you to implement custom storage for Statsig configurations. This enables advanced caching strategies and integration with your preferred storage systems.
+
+{props.content ? (
+  <div>{props.content}</div>
+) : (
+  <>
+    <Admonition type="note" title="Note">
+      Coming soon
+    </Admonition>
+  </>
+)}
diff --git a/docs/server-core/Templates/_ObservabilityClient.mdx b/docs/server-core/Templates/_ObservabilityClient.mdx
new file mode 100644
index 000000000..5c48ccd83
--- /dev/null
+++ b/docs/server-core/Templates/_ObservabilityClient.mdx
@@ -0,0 +1,13 @@
+import Admonition from '@theme/Admonition';
+
+## Observability Client
+
+The Observability Client interface allows you to monitor the health of the SDK by integrating with your own observability systems. This enables tracking metrics, errors, and performance data. For more information on the metrics emitted by Statsig SDKs, see the [Monitoring documentation](/sdk_monitoring).
+
+{props.content ? (
+  <div>{props.content}</div>
+) : (
+  <Admonition type="note" title="Note">
+    Coming soon
+  </Admonition>
+)}
diff --git a/docs/server-core/Templates/_OutputLogger.mdx b/docs/server-core/Templates/_OutputLogger.mdx
new file mode 100644
index 000000000..ad55118c2
--- /dev/null
+++ b/docs/server-core/Templates/_OutputLogger.mdx
@@ -0,0 +1,15 @@
+import Admonition from '@theme/Admonition';
+
+## Custom Output Logger
+
+The Output Logger interface allows you to customize how the SDK logs messages. This enables integration with your own logging system and control over log verbosity.
+
+{props.content ? (
+  <div>{props.content}</div>
+) : (
+  <>
+    <Admonition type="note" title="Note">
+      Coming soon
+    </Admonition>
+  </>
+)}
diff --git a/docs/server-core/Templates/_PersistentStorage.mdx b/docs/server-core/Templates/_PersistentStorage.mdx
new file mode 100644
index 000000000..223f053a6
--- /dev/null
+++ b/docs/server-core/Templates/_PersistentStorage.mdx
@@ -0,0 +1,15 @@
+import Admonition from '@theme/Admonition';
+
+## Persistent Storage
+
+The Persistent Storage interface allows you to implement custom storage for experiment assignments. This ensures consistent user experiences across sessions by persisting experiment assignments. For more information on persistent assignments, see the [Persistent Assignment documentation](/server/concepts/persistent_assignment).
+
+{props.content ? (
+  <div>{props.content}</div>
+) : (
+  <>
+    <Admonition type="note" title="Note">
+      Coming soon
+    </Admonition>
+  </>
+)}
diff --git a/docs/server-core/Templates/index.mdx b/docs/server-core/Templates/index.mdx
index cd2cf768e..ca532f471 100644
--- a/docs/server-core/Templates/index.mdx
+++ b/docs/server-core/Templates/index.mdx
@@ -39,3 +39,15 @@ export const SupportedCombinations = _SupportedCombinations;
 
 import * as _ExampleProgram from "./_ExampleProgram.mdx";
 export const ExampleProgram = _ExampleProgram;
+
+import * as _PersistentStorage from "./_PersistentStorage.mdx";
+export const PersistentStorage = _PersistentStorage;
+
+import * as _DataStore from "./_DataStore.mdx";
+export const DataStore = _DataStore;
+
+import * as _OutputLogger from "./_OutputLogger.mdx";
+export const OutputLogger = _OutputLogger;
+
+import * as _ObservabilityClient from "./_ObservabilityClient.mdx";
+export const ObservabilityClient = _ObservabilityClient;
diff --git a/docs/server-core/elixir-core.mdx b/docs/server-core/elixir-core.mdx
index 6506d1e94..121c64711 100644
--- a/docs/server-core/elixir-core.mdx
+++ b/docs/server-core/elixir-core.mdx
@@ -21,6 +21,10 @@ import {
   StatsigUser,
   ManualExposures,
   Shutdown,
+  PersistentStorage,
+  DataStore,
+  OutputLogger,
+  ObservabilityClient
 } from "./Templates/index.mdx";
 
 
@@ -68,6 +72,10 @@ export const Builder = SDKDocsBuilder({
     [StatsigUser, {}],
     [StatsigOptions, { options: <Options /> }],
     [Shutdown, { shutdown: <ShutdownSnippet /> }],
+    [PersistentStorage, { }],
+    [DataStore, { }],
+    [OutputLogger, { }],
+    [ObservabilityClient, { }],
     [FAQ, { faqs: <MoreFAQs /> }],
   ]
 })
diff --git a/docs/server-core/java-core.mdx b/docs/server-core/java-core.mdx
index 0c549dc5c..62d80419e 100644
--- a/docs/server-core/java-core.mdx
+++ b/docs/server-core/java-core.mdx
@@ -26,6 +26,10 @@ import {
   JavaCoreVsLegacy,
   SupportedCombinations,
   ExampleProgram,
+  PersistentStorage,
+  DataStore,
+  OutputLogger,
+  ObservabilityClient
 } from "./Templates/index.mdx";
 
 import Preamble from "./_preamble.mdx";
@@ -48,6 +52,7 @@ import { Snippets as ManualExposureSnippets } from "./java/_manualExposures.mdx"
 import CoreVsLegacyContent from "./java/_core_vs_legacy.mdx";
 import SupportedCombinationsContent from "./java/_supported_combinations.mdx";
 import ExampleProgramContent from "./java/_example.mdx";
+import ObservabilityClientContent from "./java/_observability_client.mdx";
 
 
 export const Builder = SDKDocsBuilder({
@@ -84,6 +89,10 @@ export const Builder = SDKDocsBuilder({
     [StatsigOptions, { options: <Options /> }],
     [Shutdown, { shutdown: <ShutdownSnippet />, flush: <Flush /> }],
     [LocalOverrides, { snippet: <OverridesSnippet />,},],
+    [PersistentStorage, { }],
+    [DataStore, { }],
+    [OutputLogger, { }],
+    [ObservabilityClient, { content: <ObservabilityClientContent /> }],
     [FAQ, { 
       faqs: <>
         <MoreFAQs />
@@ -101,4 +110,4 @@ export const Builder = SDKDocsBuilder({
 
 export const toc = Builder.toc
 
-<>{Builder.result}</>
\ No newline at end of file
+<>{Builder.result}</>
diff --git a/docs/server-core/java/_observability_client.mdx b/docs/server-core/java/_observability_client.mdx
new file mode 100644
index 000000000..75629ea6e
--- /dev/null
+++ b/docs/server-core/java/_observability_client.mdx
@@ -0,0 +1,13 @@
+```java
+public interface ObservabilityClient {
+  void init();
+
+  void increment(String metricName, double value, Map<String, String> tags);
+
+  void gauge(String metricName, double value, Map<String, String> tags);
+
+  void dist(String metricName, double value, Map<String, String> tags);
+
+  void error(String tag, String errorMessage);
+}
+```
diff --git a/docs/server-core/node-core.mdx b/docs/server-core/node-core.mdx
index 42f92bf08..1b68b7a80 100644
--- a/docs/server-core/node-core.mdx
+++ b/docs/server-core/node-core.mdx
@@ -18,6 +18,10 @@ import {
   ManualExposures,
   Shutdown,
   LocalOverrides,
+  PersistentStorage,
+  DataStore,
+  OutputLogger,
+  ObservabilityClient
 } from "./Templates/index.mdx";
 
 import Preamble from "./_preamble.mdx";
@@ -35,6 +39,9 @@ import ShutdownSnippet from "./node/_shutdown.mdx";
 import { Snippets as ManualExposureSnippets } from "./node/_manualExposures.mdx";
 import OverridesSnippet from "./node/_localOverrides.mdx";
 import SharedInstanceSnippet from "./node/_sharedInstance.mdx";
+import DataStoreContent from "./node/_data_store.mdx";
+import ObservabilityClientContent from "./node/_observability_client.mdx";
+import PersistentStorageContent from "./node/_persistent_storage.mdx";
 
 
 export const Builder = SDKDocsBuilder({
@@ -72,6 +79,10 @@ export const Builder = SDKDocsBuilder({
     [StatsigOptions, { options: <Options /> }],
     [Shutdown, { shutdown: <ShutdownSnippet /> }],
     [LocalOverrides, { snippet: <OverridesSnippet />,},],
+    [PersistentStorage, { content: <PersistentStorageContent /> }],
+    [DataStore, { content: <DataStoreContent /> }],
+    [OutputLogger, { }],
+    [ObservabilityClient, { content: <ObservabilityClientContent /> }],
     [FAQ, { faqs: <MoreFAQs /> }],
   ]
 })
diff --git a/docs/server-core/node/_data_store.mdx b/docs/server-core/node/_data_store.mdx
new file mode 100644
index 000000000..e1639b720
--- /dev/null
+++ b/docs/server-core/node/_data_store.mdx
@@ -0,0 +1,14 @@
+```typescript
+export interface DataStore {
+  initialize?: () => Promise<void>;
+  shutdown?: () => Promise<void>;
+  get?: (key: string) => Promise<DataStoreResponse>;
+  set?: (key: string, value: string, time?: number) => Promise<void>;
+  supportPollingUpdatesFor?: (key: string) => Promise<boolean>;
+}
+
+export interface DataStoreResponse {
+  result?: string;
+  time?: number;
+}
+```
diff --git a/docs/server-core/node/_observability_client.mdx b/docs/server-core/node/_observability_client.mdx
new file mode 100644
index 000000000..3b07ebbd0
--- /dev/null
+++ b/docs/server-core/node/_observability_client.mdx
@@ -0,0 +1,9 @@
+```typescript
+export interface ObservabilityClient {
+  initialize?: () => void;
+  increment?: (metricName: string, value: number, tags: Record<string, string>) => void;
+  gauge?: (metricName: string, value: number, tags: Record<string, string>) => void;
+  dist?: (metricName: string, value: number, tags: Record<string, string>) => void;
+  error?: (tag: string, error: string) => void;
+}
+```
diff --git a/docs/server-core/node/_persistent_storage.mdx b/docs/server-core/node/_persistent_storage.mdx
new file mode 100644
index 000000000..121eff24a
--- /dev/null
+++ b/docs/server-core/node/_persistent_storage.mdx
@@ -0,0 +1,15 @@
+```typescript
+export interface PersistentStorage {
+  load?: (key: string) => Promise<Record<string, StickyValues>>;
+  save?: (key: string, configName: string, data: StickyValues) => Promise<void>;
+  delete?: (key: string, configName: string) => Promise<void>;
+}
+
+export interface StickyValues {
+  value: any;
+  ruleID: string;
+  groupName?: string;
+  secondaryExposures?: Array<Record<string, string>>;
+  undelegatedSecondaryExposures?: Array<Record<string, string>>;
+}
+```
diff --git a/docs/server-core/php-core.mdx b/docs/server-core/php-core.mdx
index 5d25f6ec3..f1659fcab 100644
--- a/docs/server-core/php-core.mdx
+++ b/docs/server-core/php-core.mdx
@@ -22,6 +22,10 @@ import {
   ManualExposures,
   Shutdown,
   Reference,
+  PersistentStorage,
+  DataStore,
+  OutputLogger,
+  ObservabilityClient
 } from "./Templates/index.mdx";
 
 import Preamble from "./_preamble.mdx";
@@ -67,6 +71,11 @@ export const Builder = SDKDocsBuilder({
     [StatsigUser, { }],
     [StatsigOptions, { options: <Options /> }],
     [Shutdown, { shutdown: <ShutdownSnippet />, flush: <Flush /> }],
+    [PersistentStorage, { }],
+    [DataStore, { }],
+    [OutputLogger, { }],
+    [ObservabilityClient, { }],
+    [FAQ, { }],
   ]
 })
 
diff --git a/docs/server-core/python-core.mdx b/docs/server-core/python-core.mdx
index ac2ab000d..8542897a9 100644
--- a/docs/server-core/python-core.mdx
+++ b/docs/server-core/python-core.mdx
@@ -22,7 +22,11 @@ import {
   ManualExposures,
   Shutdown,
   LocalOverrides,
-  ServerCore
+  ServerCore,
+  PersistentStorage,
+  DataStore,
+  OutputLogger,
+  ObservabilityClient
 } from "./Templates/index.mdx";
 
 
@@ -41,6 +45,10 @@ import ShutdownSnippet from "./python/_shutdown.mdx";
 import OverridesSnippet from "./python/_localOverrides.mdx";
 import { Snippets as ManualExposureSnippets } from "./python/_manualExposures.mdx";
 import SharedInstanceSnippet from "./python/_sharedInstance.mdx";
+import PersistentStorageContent from "./python/_persistent_storage.mdx";
+import DataStoreContent from "./python/_data_store.mdx";
+import OutputLoggerContent from "./python/_output_logger.mdx";
+import ObservabilityClientContent from "./python/_observability_client.mdx";
 
 
 
@@ -85,6 +93,10 @@ export const Builder = SDKDocsBuilder({
       },
     ],
     [ServerCore, { snippet: <Preamble /> }],
+    [PersistentStorage, { content: <PersistentStorageContent /> }],
+    [DataStore, { content: <DataStoreContent /> }],
+    [OutputLogger, { content: <OutputLoggerContent /> }],
+    [ObservabilityClient, { content: <ObservabilityClientContent /> }],
     [FAQ, { faqs: <MoreFAQs /> }],
   ]
 })
diff --git a/docs/server-core/python/_data_store.mdx b/docs/server-core/python/_data_store.mdx
new file mode 100644
index 000000000..d388ae743
--- /dev/null
+++ b/docs/server-core/python/_data_store.mdx
@@ -0,0 +1,49 @@
+```python
+class DataStore(DataStoreBase):
+    def initialize(self):
+        """
+        Initialize the data store. Called when the Statsig client initializes.
+        """
+        pass
+
+    def shutdown(self):
+        """
+        Clean up resources when the Statsig client shuts down.
+        """
+        pass
+
+    def get(self, key: str) -> Optional[DataStoreResponse]:
+        """
+        Retrieve value from the data store.
+        
+        Args:
+            key: The key to retrieve the value for
+            
+        Returns:
+            DataStoreResponse containing the result and time
+        """
+        pass
+
+    def set(self, key: str, value: str, time: Optional[int] = None):
+        """
+        Store a value in the data store.
+        
+        Args:
+            key: The key to store the value under
+            value: The value to store
+            time: Optional timestamp
+        """
+        pass
+
+    def support_polling_updates_for(self, key: str) -> bool:
+        """
+        Whether the data store supports polling for updates for the given key.
+        
+        Args:
+            key: The key to check
+            
+        Returns:
+            True if polling is supported, False otherwise
+        """
+        return False
+```
diff --git a/docs/server-core/python/_observability_client.mdx b/docs/server-core/python/_observability_client.mdx
new file mode 100644
index 000000000..ef7cb97d4
--- /dev/null
+++ b/docs/server-core/python/_observability_client.mdx
@@ -0,0 +1,63 @@
+```python
+class ObservabilityClient(ObservabilityClientBase):
+    def init(self):
+        """
+        Initialize the observability client. Called when the Statsig client initializes.
+        """
+        pass
+
+    def increment(self, metric_name: str, value: float, tags: Optional[Dict[str, str]] = None):
+        """
+        Report a counter metric.
+        
+        Args:
+            metric_name: The name of the metric
+            value: The amount to increment by
+            tags: Optional tags to associate with the metric
+        """
+        pass
+
+    def gauge(self, metric_name: str, value: float, tags: Optional[Dict[str, str]] = None):
+        """
+        Report a gauge metric.
+        
+        Args:
+            metric_name: The name of the metric
+            value: The current value
+            tags: Optional tags to associate with the metric
+        """
+        pass
+
+    def dist(self, metric_name: str, value: float, tags: Optional[Dict[str, str]] = None):
+        """
+        Report a distribution metric.
+        
+        Args:
+            metric_name: The name of the metric
+            value: The value to record
+            tags: Optional tags to associate with the metric
+        """
+        pass
+
+    def error(self, tag: str, error: str):
+        """
+        Report an error.
+        
+        Args:
+            tag: Category/component tag for the error
+            error: The error message
+        """
+        pass
+
+    def should_enable_high_cardinality_for_this_tag(self, tag: str) -> bool:
+        """
+        Determine if high cardinality should be enabled for a tag.
+        
+        Args:
+            tag: The tag to check
+            
+        Returns:
+            True if high cardinality should be enabled, False otherwise
+        """
+        pass
+```
diff --git a/docs/server-core/python/_output_logger.mdx b/docs/server-core/python/_output_logger.mdx
new file mode 100644
index 000000000..b9ada5da2
--- /dev/null
+++ b/docs/server-core/python/_output_logger.mdx
@@ -0,0 +1,54 @@
+```python
+class OutputLoggerProvider(OutputLoggerProviderBase):
+    def init(self):
+        """
+        Initialize the logger. Called when the Statsig client initializes.
+        """
+        pass
+
+    def debug(self, tag: str, msg: str):
+        """
+        Log a debug message.
+        
+        Args:
+            tag: Category/component tag for the message
+            msg: The message to log
+        """
+        pass
+
+    def info(self, tag: str, msg: str):
+        """
+        Log an info message.
+        
+        Args:
+            tag: Category/component tag for the message
+            msg: The message to log
+        """
+        pass
+
+    def warn(self, tag: str, msg: str):
+        """
+        Log a warning message.
+        
+        Args:
+            tag: Category/component tag for the message
+            msg: The message to log
+        """
+        pass
+
+    def error(self, tag: str, msg: str):
+        """
+        Log an error message.
+        
+        Args:
+            tag: Category/component tag for the message
+            msg: The message to log
+        """
+        pass
+
+    def shutdown(self):
+        """
+        Clean up resources when the Statsig client shuts down.
+        """
+        pass
+```
diff --git a/docs/server-core/python/_persistent_storage.mdx b/docs/server-core/python/_persistent_storage.mdx
new file mode 100644
index 000000000..6232dde8e
--- /dev/null
+++ b/docs/server-core/python/_persistent_storage.mdx
@@ -0,0 +1,35 @@
+```python
+class PersistentStorage(PersistentStorageBaseClass):
+    def load(self, key: str) -> Optional[UserPersistedValues]:
+        """
+        Load persisted values for a user from storage
+        
+        Args:
+            key: A string key that uniquely identifies a user
+
+        Returns:
+            Dictionary mapping config names to their persisted values
+        """
+        pass
+
+    def save(self, key: str, config_name: str, data: StickyValues):
+        """
+        Save a persistent value for a user
+        
+        Args:
+            key: A string key that uniquely identifies a user
+            config_name: The name of the config/experiment
+            data: The values to persist
+        """
+        pass
+
+    def delete(self, key: str, config_name: str):
+        """
+        Delete a persistent value for a user
+        
+        Args:
+            key: A string key that uniquely identifies a user
+            config_name: The name of the config/experiment to delete
+        """
+        pass
+```
diff --git a/docs/server-core/rust-core.mdx b/docs/server-core/rust-core.mdx
index b64158dea..f4d9ff08f 100644
--- a/docs/server-core/rust-core.mdx
+++ b/docs/server-core/rust-core.mdx
@@ -22,6 +22,10 @@ import {
   ManualExposures,
   Shutdown,
   LocalOverrides,
+  PersistentStorage,
+  DataStore,
+  OutputLogger,
+  ObservabilityClient
 } from "./Templates/index.mdx";
 
 
@@ -41,6 +45,10 @@ import ShutdownSnippet from "./rust/_shutdown.mdx";
 import OverridesSnippet from "./rust/_localOverrides.mdx";
 import { Snippets as ManualExposureSnippets } from "./java/_manualExposures.mdx";
 import SharedInstanceSnippet from "./rust/_sharedInstance.mdx";
+import DataStoreContent from "./rust/_data_store.mdx";
+import OutputLoggerContent from "./rust/_output_logger.mdx";
+import ObservabilityClientContent from "./rust/_observability_client.mdx";
+import PersistentStorageContent from "./rust/_persistent_storage.mdx";
 
 
 
@@ -78,6 +86,10 @@ export const Builder = SDKDocsBuilder({
     [StatsigUser, { statsigUser: <UserSnippet /> }],
     [StatsigOptions, { options: <Options /> }],
     [Shutdown, { shutdown: <ShutdownSnippet /> }],
+    [PersistentStorage, { content: <PersistentStorageContent /> }],
+    [DataStore, { content: <DataStoreContent /> }],
+    [OutputLogger, { content: <OutputLoggerContent /> }],
+    [ObservabilityClient, { content: <ObservabilityClientContent /> }],
     [FAQ, { faqs: <MoreFAQs /> }],
   ]
 })
diff --git a/docs/server-core/rust/_data_store.mdx b/docs/server-core/rust/_data_store.mdx
new file mode 100644
index 000000000..94acfb72a
--- /dev/null
+++ b/docs/server-core/rust/_data_store.mdx
@@ -0,0 +1,14 @@
+```rust
+pub trait DataStoreTrait: Send + Sync {
+    fn initialize(&self) -> Result<(), DataStoreErrorEnum>;
+    fn shutdown(&self) -> Result<(), DataStoreErrorEnum>;
+    fn get(&self, key: &str) -> Result<Option<DataStoreResponse>, DataStoreErrorEnum>;
+    fn set(&self, key: &str, value: &str, time: Option<u64>) -> Result<(), DataStoreErrorEnum>;
+    fn support_polling_updates_for(&self, key: &str) -> Result<bool, DataStoreErrorEnum>;
+}
+
+pub struct DataStoreResponse {
+    pub result: String,
+    pub time: Option<u64>,
+}
+```
diff --git a/docs/server-core/rust/_observability_client.mdx b/docs/server-core/rust/_observability_client.mdx
new file mode 100644
index 000000000..63813ac6a
--- /dev/null
+++ b/docs/server-core/rust/_observability_client.mdx
@@ -0,0 +1,9 @@
+```rust
+pub trait ObservabilityClient: Send + Sync {
+    fn init(&self);
+    fn increment(&self, metric_name: &str, value: f64, tags: &HashMap<String, String>);
+    fn gauge(&self, metric_name: &str, value: f64, tags: &HashMap<String, String>);
+    fn dist(&self, metric_name: &str, value: f64, tags: &HashMap<String, String>);
+    fn error(&self, tag: &str, error: &str);
+}
+```
diff --git a/docs/server-core/rust/_output_logger.mdx b/docs/server-core/rust/_output_logger.mdx
new file mode 100644
index 000000000..10ac57941
--- /dev/null
+++ b/docs/server-core/rust/_output_logger.mdx
@@ -0,0 +1,10 @@
+```rust
+pub trait OutputLogProvider: Send + Sync {
+    fn initialize(&self);
+    fn debug(&self, tag: &str, msg: String);
+    fn info(&self, tag: &str, msg: String);
+    fn warn(&self, tag: &str, msg: String);
+    fn error(&self, tag: &str, msg: String);
+    fn shutdown(&self);
+}
+```
diff --git a/docs/server-core/rust/_persistent_storage.mdx b/docs/server-core/rust/_persistent_storage.mdx
new file mode 100644
index 000000000..0d16fbb73
--- /dev/null
+++ b/docs/server-core/rust/_persistent_storage.mdx
@@ -0,0 +1,7 @@
+```rust
+pub trait PersistentStorageTrait: Send + Sync {
+    fn load(&self, key: &str) -> Result<Option<UserPersistedValues>, PersistentStorageErrorEnum>;
+    fn save(&self, key: &str, config_name: &str, data: &StickyValues) -> Result<(), PersistentStorageErrorEnum>;
+    fn delete(&self, key: &str, config_name: &str) -> Result<(), PersistentStorageErrorEnum>;
+}
+```


Reviews:
user: login: kat-statsig
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T17:49:21Z
user: login: kat-statsig
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T17:50:21Z
user: login: kat-statsig
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T17:52:53Z
user: login: kat-statsig
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T18:47:29Z
user: login: kat-statsig
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T18:47:55Z
user: login: kat-statsig
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T18:48:44Z
user: login: weihao-statsig
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T19:07:19Z
user: login: kat-statsig
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T19:29:53Z
user: login: kat-statsig
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T19:30:49Z
user: login: kat-statsig
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T19:44:57Z
user: login: kat-statsig
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T20:02:41Z
user: login: kat-statsig
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T20:13:45Z
user: login: kat-statsig
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T20:26:01Z
user: login: graphite-app[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T20:48:09Z

Review comments:
diff_hunk: @@ -0,0 +1,32 @@
+## Custom Output Logger
+
+The `OutputLogger` class provides logging capabilities for the Statsig SDK. You can control the verbosity of logs using the `LogLevel` enum.
+
+### LogLevel Enum
+
+```java
path: docs/server-core/java/_output_logger.mdx
user: login: kat-statsig
body: java doesn't have custom output logger
created_at: 2025-05-19T17:49:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,20 @@
+## Data Store Interface
path: docs/server-core/node/_data_store.mdx
user: login: kat-statsig
body: please remove all these headers and descrptions, they are duplicating with template headers
created_at: 2025-05-19T17:50:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,11 @@
+## Data Store
+
+The Data Store interface allows you to implement custom storage for Statsig configurations. This enables advanced caching strategies and integration with your preferred storage systems.
+
+<>
+  {props.content ? (
+    <div>{props.content}</div>
+  ) : (
+    <div>Coming soon</div>
path: docs/server-core/Templates/_DataStore.mdx
user: login: kat-statsig
body: Since all the templates default to Coming soon if there is no content, do not create the individual sections for each language for coming soon
created_at: 2025-05-19T17:52:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -84,6 +88,10 @@ export const Builder = SDKDocsBuilder({
     [StatsigOptions, { options: <Options /> }],
     [Shutdown, { shutdown: <ShutdownSnippet />, flush: <Flush /> }],
     [LocalOverrides, { snippet: <OverridesSnippet />,},],
+    [PersistentStorage, { }],
+    [DataStore, { }],
+    [OutputLogger, { }],
+    [ObservabilityClient, { }],
path: docs/server-core/java-core.mdx
user: login: kat-statsig
body: link to java observability client please
created_at: 2025-05-19T18:47:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -72,6 +76,10 @@ export const Builder = SDKDocsBuilder({
     [StatsigOptions, { options: <Options /> }],
     [Shutdown, { shutdown: <ShutdownSnippet /> }],
     [LocalOverrides, { snippet: <OverridesSnippet />,},],
+    [PersistentStorage, { }],
+    [DataStore, { }],
path: docs/server-core/node-core.mdx
user: login: kat-statsig
body: link to the appropriate snippets please
created_at: 2025-05-19T18:47:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -78,6 +85,10 @@ export const Builder = SDKDocsBuilder({
     [StatsigUser, { statsigUser: <UserSnippet /> }],
     [StatsigOptions, { options: <Options /> }],
     [Shutdown, { shutdown: <ShutdownSnippet /> }],
+    [PersistentStorage, { }],
path: docs/server-core/rust-core.mdx
user: login: kat-statsig
body: add persistent snippet and link to it
rust persistent storage is here https://github.com/statsig-io/statsig-server-core/blob/main/statsig-rust/src/persistent_storage/persistent_storage_trait.rs#L22
created_at: 2025-05-19T18:48:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,11 @@
+## Observability Client
+
+The Observability Client interface allows you to monitor the health of the SDK by integrating with your own observability systems. This enables tracking metrics, errors, and performance data.
path: docs/server-core/Templates/_ObservabilityClient.mdx
user: login: kat-statsig
body: can you link it to this page that expands on the metrics we emit https://github.com/statsig-io/docs/blob/a2c9a2d4a9ecb4e00b21ad6c5447e0011a3a0898/docs/infrastructure/monitoring.mdx#L4 
created_at: 2025-05-19T19:29:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,11 @@
+## Persistent Storage
+
+The Persistent Storage interface allows you to implement custom storage for experiment assignments. This ensures consistent user experiences across sessions by persisting experiment assignments.
path: docs/server-core/Templates/_PersistentStorage.mdx
user: login: kat-statsig
body: can you link to this concept page here https://github.com/statsig-io/docs/edit/main/docs/server/concepts/persistent_assignment.mdx

created_at: 2025-05-19T19:30:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,11 @@
+## Observability Client
+
+The Observability Client interface allows you to monitor the health of the SDK by integrating with your own observability systems. This enables tracking metrics, errors, and performance data. For more information on the metrics emitted by Statsig SDKs, see the [Monitoring documentation](/sdk_monitoring).
+
+<>
+  {props.content ? (
+    <div>{props.content}</div>
+  ) : (
+    <div>Coming soon</div>
path: docs/server-core/Templates/_ObservabilityClient.mdx
user: login: kat-statsig
body: can you give the coming soon blocks in these templates a little styling
created_at: 2025-05-19T19:44:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,23 @@
+## Data Store
+
+The Data Store interface allows you to implement custom storage for Statsig configurations. This enables advanced caching strategies and integration with your preferred storage systems.
+
+<>
+  {props.content ? (
+    <div>{props.content}</div>
+  ) : (
+    <div className="admonition admonition-note alert alert--secondary">
+      <div className="admonition-heading">
+        <h5>
+          <span className="admonition-icon">
+            <svg xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16">
+              <path fillRule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path>
path: docs/server-core/Templates/_DataStore.mdx
user: login: kat-statsig
body: use 
:::note

Some **content** with _Markdown_ `syntax`. Check [this `api`](#).

:::
instead
created_at: 2025-05-19T20:02:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,13 @@
+## Data Store
+
+The Data Store interface allows you to implement custom storage for Statsig configurations. This enables advanced caching strategies and integration with your preferred storage systems.
+
+{props.content ? (
+  <div>{props.content}</div>
+) : (
+  <>
+    :::note
+    Coming soon
path: docs/server-core/Templates/_DataStore.mdx
user: login: kat-statsig
body: update them to use
<div className="alert alert--info">
    <strong>Note:</strong> Coming soon
  </div>
created_at: 2025-05-19T20:13:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,11 @@
+## Data Store
+
+The Data Store interface allows you to implement custom storage for Statsig configurations. This enables advanced caching strategies and integration with your preferred storage systems.
+
+{props.content ? (
+  <div>{props.content}</div>
+) : (
+  <div className="alert alert--info">
path: docs/server-core/Templates/_DataStore.mdx
user: login: kat-statsig
body: can you use this for the templayes omsyead
```
import Admonition from '@theme/Admonition';

<Admonition type="note" title="Note">
  Coming soon
</Admonition>
```
created_at: 2025-05-19T20:26:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -72,6 +79,10 @@ export const Builder = SDKDocsBuilder({
     [StatsigOptions, { options: <Options /> }],
     [Shutdown, { shutdown: <ShutdownSnippet /> }],
     [LocalOverrides, { snippet: <OverridesSnippet />,},],
+    [PersistentStorage, { }],
path: docs/server-core/node-core.mdx
user: login: graphite-app[bot]
body: It appears there's an inconsistency in the Node.js implementation. The code imports `PersistentStorageContent` but doesn't use it in the component array. For consistency with the other interfaces, consider updating the line to:

```javascript
[PersistentStorage, { content: <PersistentStorageContent /> }],
```

This would display the Node.js-specific implementation details rather than showing the generic "Coming soon" message.
```suggestion
    [PersistentStorage, { content: <PersistentStorageContent /> }],
```
  

*Spotted by [Diamond](https://app.graphite.dev/diamond/?org=statsig-io&ref=ai-review-comment)*<i class='graphite__hidden'><br /><br />Is this helpful? React 👍 or 👎 to let us know.</i>
created_at: 2025-05-19T20:48:08Z
author_association: CONTRIBUTOR

PR comments:
user: login: devin-ai-integration[bot]
created_at: 2025-05-19T17:21:22Z
body: ### 🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:
- Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
- Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:
- [ ] Disable automatic comment and CI monitoring

author_association: CONTRIBUTOR
user: login: jasonwzm
created_at: 2025-05-19T17:24:08Z
body: <!-- NETLIFY DEPLOY COMMENT GENERATED BY ACTIONS_NETLIFY - APP ID SHA256: 0038af8fad421c48cf2dd5ee95e08d2d419533ec7208a507c5ccd1696cdf8b44 -->
🚀 Deployed on https://682b9c01806fb82a72242305--cozy-fox-0defec.netlify.app
author_association: MEMBER