From 6d13eed37d132ce71c93d5d7c85c70d88d05f19e Mon Sep 17 00:00:00 2001 From: "statsig-kong[bot]" Date: Mon, 18 Aug 2025 13:17:57 +0000 Subject: [PATCH 01/23] chore: bump version to 0.7.4-rc.2508181316 --- Cargo.lock | 12 ++++++------ Cargo.toml | 2 +- examples/rust/mem-bench/Cargo.lock | 2 +- statsig-dotnet/Directory.Build.props | 2 +- statsig-elixir/mix.exs | 2 +- statsig-go/cmd/post-install/main.go | 2 +- statsig-java/gradle.properties | 2 +- statsig-node/npm/aarch64-apple-darwin.package.json | 2 +- .../npm/aarch64-unknown-linux-gnu.package.json | 2 +- .../npm/aarch64-unknown-linux-musl.package.json | 2 +- statsig-node/npm/i686-pc-windows-msvc.package.json | 2 +- statsig-node/npm/x86_64-apple-darwin.package.json | 2 +- statsig-node/npm/x86_64-pc-windows-msvc.package.json | 2 +- .../npm/x86_64-unknown-linux-gnu.package.json | 2 +- .../npm/x86_64-unknown-linux-musl.package.json | 2 +- statsig-node/package.json | 2 +- statsig-php/post-install.php | 2 +- statsig-rust/Cargo.toml | 2 +- statsig-rust/src/statsig_metadata.rs | 2 +- 19 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d22b7019..704aecfcf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2373,7 +2373,7 @@ dependencies = [ [[package]] name = "sigstat-grpc" -version = "0.7.4-beta.2508160236" +version = "0.7.4-rc.2508181316" dependencies = [ "async-trait", "chrono", @@ -2437,7 +2437,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statsig-node" -version = "0.7.4-beta.2508160236" +version = "0.7.4-rc.2508181316" dependencies = [ "async-trait", "napi", @@ -2450,7 +2450,7 @@ dependencies = [ [[package]] name = "statsig-pyo3" -version = "0.7.4-beta.2508160236" +version = "0.7.4-rc.2508181316" dependencies = [ "async-trait", "lazy_static", @@ -2464,7 +2464,7 @@ dependencies = [ [[package]] name = "statsig-rust" -version = "0.7.4-beta.2508160236" +version = "0.7.4-rc.2508181316" dependencies = [ "ahash", "arc-swap", @@ -2504,7 +2504,7 @@ dependencies = [ [[package]] name = "statsig_elixir" -version = "0.7.4-beta.2508160236" +version = "0.7.4-rc.2508181316" dependencies = [ "parking_lot", "rustler", @@ -2516,7 +2516,7 @@ dependencies = [ [[package]] name = "statsig_ffi" -version = "0.7.4-beta.2508160236" +version = "0.7.4-rc.2508181316" dependencies = [ "async-trait", "cbindgen", diff --git a/Cargo.toml b/Cargo.toml index 4a1fa2f54..af70a5463 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ exclude = [ [workspace.package] edition = "2021" license = "ISC" -version = "0.7.4-beta.2508160236" +version = "0.7.4-rc.2508181316" homepage = "https://statsig.com/" authors = ["Statsig", "Daniel Loomb "] readme = "README.md" diff --git a/examples/rust/mem-bench/Cargo.lock b/examples/rust/mem-bench/Cargo.lock index 369baa1ed..9648c9379 100644 --- a/examples/rust/mem-bench/Cargo.lock +++ b/examples/rust/mem-bench/Cargo.lock @@ -1815,7 +1815,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statsig-rust" -version = "0.7.4-beta.2508160236" +version = "0.7.4-rc.2508181316" dependencies = [ "ahash", "arc-swap", diff --git a/statsig-dotnet/Directory.Build.props b/statsig-dotnet/Directory.Build.props index dacd9a592..99c21f39f 100644 --- a/statsig-dotnet/Directory.Build.props +++ b/statsig-dotnet/Directory.Build.props @@ -1,6 +1,6 @@ - 0.7.4-beta.2508160236 + 0.7.4-rc.2508181316 ISC \ No newline at end of file diff --git a/statsig-elixir/mix.exs b/statsig-elixir/mix.exs index 3cdf14eb2..d7dc2e7dc 100644 --- a/statsig-elixir/mix.exs +++ b/statsig-elixir/mix.exs @@ -4,7 +4,7 @@ defmodule Statsigelixir.MixProject do def project do [ app: :statsig_elixir, - version: "0.7.4-beta.2508160236", + version: "0.7.4-rc.2508181316", elixir: "~> 1.0", start_permanent: Mix.env() == :prod, description: description(), diff --git a/statsig-go/cmd/post-install/main.go b/statsig-go/cmd/post-install/main.go index 4115d1b78..b76703883 100644 --- a/statsig-go/cmd/post-install/main.go +++ b/statsig-go/cmd/post-install/main.go @@ -12,7 +12,7 @@ import ( ) const ( - version = "0.7.4-beta.2508160236" + version = "0.7.4-rc.2508181316" ) var output_dir string diff --git a/statsig-java/gradle.properties b/statsig-java/gradle.properties index 589f7af07..03d443c1f 100644 --- a/statsig-java/gradle.properties +++ b/statsig-java/gradle.properties @@ -1 +1 @@ -version=0.7.4-beta.2508160236 \ No newline at end of file +version=0.7.4-rc.2508181316 \ No newline at end of file diff --git a/statsig-node/npm/aarch64-apple-darwin.package.json b/statsig-node/npm/aarch64-apple-darwin.package.json index d19f2cca5..0dfae9e43 100644 --- a/statsig-node/npm/aarch64-apple-darwin.package.json +++ b/statsig-node/npm/aarch64-apple-darwin.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-darwin-arm64", - "version": "0.7.4-beta.2508160236", + "version": "0.7.4-rc.2508181316", "os": [ "darwin" ], diff --git a/statsig-node/npm/aarch64-unknown-linux-gnu.package.json b/statsig-node/npm/aarch64-unknown-linux-gnu.package.json index fec93babd..4ab1805ac 100644 --- a/statsig-node/npm/aarch64-unknown-linux-gnu.package.json +++ b/statsig-node/npm/aarch64-unknown-linux-gnu.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-arm64-gnu", - "version": "0.7.4-beta.2508160236", + "version": "0.7.4-rc.2508181316", "os": [ "linux" ], diff --git a/statsig-node/npm/aarch64-unknown-linux-musl.package.json b/statsig-node/npm/aarch64-unknown-linux-musl.package.json index a4f3b512f..dece5e189 100644 --- a/statsig-node/npm/aarch64-unknown-linux-musl.package.json +++ b/statsig-node/npm/aarch64-unknown-linux-musl.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-arm64-musl", - "version": "0.7.4-beta.2508160236", + "version": "0.7.4-rc.2508181316", "os": [ "linux" ], diff --git a/statsig-node/npm/i686-pc-windows-msvc.package.json b/statsig-node/npm/i686-pc-windows-msvc.package.json index 29a6d187a..e3bb3e9bb 100644 --- a/statsig-node/npm/i686-pc-windows-msvc.package.json +++ b/statsig-node/npm/i686-pc-windows-msvc.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-win32-ia32-msvc", - "version": "0.7.4-beta.2508160236", + "version": "0.7.4-rc.2508181316", "os": [ "win32" ], diff --git a/statsig-node/npm/x86_64-apple-darwin.package.json b/statsig-node/npm/x86_64-apple-darwin.package.json index 6c003e7bb..03c09aab9 100644 --- a/statsig-node/npm/x86_64-apple-darwin.package.json +++ b/statsig-node/npm/x86_64-apple-darwin.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-darwin-x64", - "version": "0.7.4-beta.2508160236", + "version": "0.7.4-rc.2508181316", "os": [ "darwin" ], diff --git a/statsig-node/npm/x86_64-pc-windows-msvc.package.json b/statsig-node/npm/x86_64-pc-windows-msvc.package.json index 9ae3ef930..1e83e71b1 100644 --- a/statsig-node/npm/x86_64-pc-windows-msvc.package.json +++ b/statsig-node/npm/x86_64-pc-windows-msvc.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-win32-x64-msvc", - "version": "0.7.4-beta.2508160236", + "version": "0.7.4-rc.2508181316", "os": [ "win32" ], diff --git a/statsig-node/npm/x86_64-unknown-linux-gnu.package.json b/statsig-node/npm/x86_64-unknown-linux-gnu.package.json index 1a0ce8aa2..15846c57a 100644 --- a/statsig-node/npm/x86_64-unknown-linux-gnu.package.json +++ b/statsig-node/npm/x86_64-unknown-linux-gnu.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-x64-gnu", - "version": "0.7.4-beta.2508160236", + "version": "0.7.4-rc.2508181316", "os": [ "linux" ], diff --git a/statsig-node/npm/x86_64-unknown-linux-musl.package.json b/statsig-node/npm/x86_64-unknown-linux-musl.package.json index cb509e4b8..b6df7119d 100644 --- a/statsig-node/npm/x86_64-unknown-linux-musl.package.json +++ b/statsig-node/npm/x86_64-unknown-linux-musl.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-x64-musl", - "version": "0.7.4-beta.2508160236", + "version": "0.7.4-rc.2508181316", "os": [ "linux" ], diff --git a/statsig-node/package.json b/statsig-node/package.json index b2209ddfa..c1850f6ff 100644 --- a/statsig-node/package.json +++ b/statsig-node/package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core", - "version": "0.7.4-beta.2508160236", + "version": "0.7.4-rc.2508181316", "main": "index.js", "scripts": { "test": "jest --colors" diff --git a/statsig-php/post-install.php b/statsig-php/post-install.php index 2c733b8ec..68038a7d8 100644 --- a/statsig-php/post-install.php +++ b/statsig-php/post-install.php @@ -1,7 +1,7 @@ Self { Self { - sdk_version: "0.7.4-beta.2508160236".to_string(), + sdk_version: "0.7.4-rc.2508181316".to_string(), sdk_type: "statsig-server-core".to_string(), session_id: Uuid::new_v4().to_string(), os: None, From 3281d76c4e9f6232e0d1bb2248218b5a046c47e3 Mon Sep 17 00:00:00 2001 From: Weihao Ding <158090588+weihao-statsig@users.noreply.github.com> Date: Mon, 18 Aug 2025 16:10:19 -0700 Subject: [PATCH 02/23] [Cherrypick][releases/0.7.4-rc.2508181316] chore: reuse tokio rt across napi-rs and statsig-node (#1642) [auto][cherrypick] f849beef0c20a5d002f16d16458584bb69c15f92 chore: reuse tokio rt across napi-rs and statsig-node (#1638) --- statsig-node/src/__tests__/NumThreads.test.ts | 33 +++++++++++++++++++ statsig-node/src/lib.rs | 5 ++- statsig-node/src/lib/statsig-generated.d.ts | 2 ++ statsig-node/src/statsig_napi.rs | 28 ++++++++-------- statsig-rust/src/lib.rs | 2 +- statsig-rust/src/statsig_runtime.rs | 20 ++++++----- 6 files changed, 66 insertions(+), 24 deletions(-) create mode 100644 statsig-node/src/__tests__/NumThreads.test.ts diff --git a/statsig-node/src/__tests__/NumThreads.test.ts b/statsig-node/src/__tests__/NumThreads.test.ts new file mode 100644 index 000000000..3c0eccc01 --- /dev/null +++ b/statsig-node/src/__tests__/NumThreads.test.ts @@ -0,0 +1,33 @@ +import { execSync } from 'node:child_process'; + +import { Statsig } from '../../build/index.js'; + +function getNumThreads() { + const pid = process.pid; + + try { + const threads = execSync(`ps -o nlwp ${pid}`) + .toString() + .split('\n')[1] + .trim(); + console.log(`Process owns ${threads} threads`); + return threads; + } catch (err) { + console.error('Failed to get thread count', err); + } +} + +test('Has correct number of threads', async () => { + const instances = []; + for (let i = 0; i < 10; i++) { + const statsig = new Statsig('secret-num-threads-test', { + disableNetwork: true, + }); + instances.push(statsig); + } + + await Promise.all(instances.map((statsig) => statsig.initialize())); + + const threads = getNumThreads(); + expect(threads).toBe('16'); +}); diff --git a/statsig-node/src/lib.rs b/statsig-node/src/lib.rs index 7acee8854..da83069f1 100644 --- a/statsig-node/src/lib.rs +++ b/statsig-node/src/lib.rs @@ -13,9 +13,12 @@ pub mod statsig_user_napi; mod statsig_metadata_napi; -use napi::module_init; +use napi::{bindgen_prelude::create_custom_tokio_runtime, module_init}; #[module_init] fn init() { statsig_metadata_napi::update_statsig_metadata(None); + + let rt = statsig_rust::statsig_runtime::create_new_runtime(); + create_custom_tokio_runtime(rt); } diff --git a/statsig-node/src/lib/statsig-generated.d.ts b/statsig-node/src/lib/statsig-generated.d.ts index 8c4a6d3f3..c7c3c8ce5 100644 --- a/statsig-node/src/lib/statsig-generated.d.ts +++ b/statsig-node/src/lib/statsig-generated.d.ts @@ -156,6 +156,7 @@ export interface EvaluationDetails { export interface ExperimentEvaluationOptions { disableExposureLogging?: boolean + userPersistedValues?: Record } export interface FeatureGate { @@ -171,6 +172,7 @@ export interface FeatureGateEvaluationOptions { export interface LayerEvaluationOptions { disableExposureLogging?: boolean + userPersistedValues?: Record } export interface NapiNetworkFuncResult { diff --git a/statsig-node/src/statsig_napi.rs b/statsig-node/src/statsig_napi.rs index a968cfbb0..959bb1afc 100644 --- a/statsig-node/src/statsig_napi.rs +++ b/statsig-node/src/statsig_napi.rs @@ -40,23 +40,25 @@ impl StatsigNapiInternal { sdk_key: String, options: Option, ) -> Self { - log_d!(TAG, "StatsigNapi new"); + within_runtime_if_available(|| { + log_d!(TAG, "StatsigNapi new"); - statsig_metadata_napi::update_statsig_metadata(Some(env)); + statsig_metadata_napi::update_statsig_metadata(Some(env)); - let (inner_opts, obs_client) = options - .map(|opts| opts.safe_convert_to_inner()) - .unwrap_or((None, None)); + let (inner_opts, obs_client) = options + .map(|opts| opts.safe_convert_to_inner()) + .unwrap_or((None, None)); - let network_provider: Arc = - Arc::new(NetworkProviderNapi { network_func }); - NetworkProviderGlobal::set(&network_provider); + let network_provider: Arc = + Arc::new(NetworkProviderNapi { network_func }); + NetworkProviderGlobal::set(&network_provider); - Self { - inner: Arc::new(StatsigActual::new(&sdk_key, inner_opts)), - observability_client: Mutex::new(obs_client), - network_provider: Mutex::new(Some(network_provider)), - } + Self { + inner: Arc::new(StatsigActual::new(&sdk_key, inner_opts)), + observability_client: Mutex::new(obs_client), + network_provider: Mutex::new(Some(network_provider)), + } + }) } #[napi] diff --git a/statsig-rust/src/lib.rs b/statsig-rust/src/lib.rs index 4c8e43f7f..350c95a5c 100644 --- a/statsig-rust/src/lib.rs +++ b/statsig-rust/src/lib.rs @@ -48,6 +48,7 @@ pub mod statsig_core_api_options; pub mod statsig_global; pub mod statsig_metadata; pub mod statsig_options; +pub mod statsig_runtime; pub mod statsig_types; pub mod user; @@ -64,6 +65,5 @@ mod spec_store; mod specs_adapter; mod statsig; mod statsig_err; -mod statsig_runtime; mod statsig_type_factories; mod utils; diff --git a/statsig-rust/src/statsig_runtime.rs b/statsig-rust/src/statsig_runtime.rs index 4cf9dfa7f..f822acfbd 100644 --- a/statsig-rust/src/statsig_runtime.rs +++ b/statsig-rust/src/statsig_runtime.rs @@ -8,7 +8,7 @@ use std::future::Future; use std::sync::atomic::AtomicBool; use std::sync::Arc; use std::time::Duration; -use tokio::runtime::{Builder, Handle}; +use tokio::runtime::{Builder, Handle, Runtime}; use tokio::sync::Notify; use tokio::task::JoinHandle; @@ -191,6 +191,15 @@ impl StatsigRuntime { } } +pub fn create_new_runtime() -> Runtime { + Builder::new_multi_thread() + .worker_threads(5) + .thread_name("statsig") + .enable_all() + .build() + .expect("Failed to create a tokio Runtime") +} + fn remove_join_handle_with_id( spawned_tasks: Arc>>>, tag: String, @@ -232,14 +241,7 @@ fn create_runtime_if_required() { } None => { log_d!(TAG, "Creating new tokio runtime for StatsigGlobal"); - let rt = Arc::new( - Builder::new_multi_thread() - .worker_threads(5) - .thread_name("statsig") - .enable_all() - .build() - .expect("Failed to find or create a tokio Runtime"), - ); + let rt = Arc::new(create_new_runtime()); lock.replace(rt); } From ebcd5a85be35e272ce22be736e01999cc479af80 Mon Sep 17 00:00:00 2001 From: "statsig-kong[bot]" Date: Mon, 18 Aug 2025 16:12:05 -0700 Subject: [PATCH 03/23] Bot: Updated File Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index af70a5463..a244bc1f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ exclude = [ [workspace.package] edition = "2021" license = "ISC" -version = "0.7.4-rc.2508181316" +version = "0.7.4-rc.2508182310" homepage = "https://statsig.com/" authors = ["Statsig", "Daniel Loomb "] readme = "README.md" From be3445b37a6a961ff27c88f2e8526f3a597f46ae Mon Sep 17 00:00:00 2001 From: "statsig-kong[bot]" Date: Mon, 18 Aug 2025 23:13:55 +0000 Subject: [PATCH 04/23] Bot: Version synchronized in 18 files --- Cargo.lock | 12 ++++++------ examples/rust/mem-bench/Cargo.lock | 2 +- statsig-dotnet/Directory.Build.props | 2 +- statsig-elixir/mix.exs | 2 +- statsig-go/cmd/post-install/main.go | 2 +- statsig-java/gradle.properties | 2 +- statsig-node/npm/aarch64-apple-darwin.package.json | 2 +- .../npm/aarch64-unknown-linux-gnu.package.json | 2 +- .../npm/aarch64-unknown-linux-musl.package.json | 2 +- statsig-node/npm/i686-pc-windows-msvc.package.json | 2 +- statsig-node/npm/x86_64-apple-darwin.package.json | 2 +- statsig-node/npm/x86_64-pc-windows-msvc.package.json | 2 +- .../npm/x86_64-unknown-linux-gnu.package.json | 2 +- .../npm/x86_64-unknown-linux-musl.package.json | 2 +- statsig-node/package.json | 2 +- statsig-php/post-install.php | 2 +- statsig-rust/Cargo.toml | 2 +- statsig-rust/src/statsig_metadata.rs | 2 +- 18 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 704aecfcf..04c61d77f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2373,7 +2373,7 @@ dependencies = [ [[package]] name = "sigstat-grpc" -version = "0.7.4-rc.2508181316" +version = "0.7.4-rc.2508182310" dependencies = [ "async-trait", "chrono", @@ -2437,7 +2437,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statsig-node" -version = "0.7.4-rc.2508181316" +version = "0.7.4-rc.2508182310" dependencies = [ "async-trait", "napi", @@ -2450,7 +2450,7 @@ dependencies = [ [[package]] name = "statsig-pyo3" -version = "0.7.4-rc.2508181316" +version = "0.7.4-rc.2508182310" dependencies = [ "async-trait", "lazy_static", @@ -2464,7 +2464,7 @@ dependencies = [ [[package]] name = "statsig-rust" -version = "0.7.4-rc.2508181316" +version = "0.7.4-rc.2508182310" dependencies = [ "ahash", "arc-swap", @@ -2504,7 +2504,7 @@ dependencies = [ [[package]] name = "statsig_elixir" -version = "0.7.4-rc.2508181316" +version = "0.7.4-rc.2508182310" dependencies = [ "parking_lot", "rustler", @@ -2516,7 +2516,7 @@ dependencies = [ [[package]] name = "statsig_ffi" -version = "0.7.4-rc.2508181316" +version = "0.7.4-rc.2508182310" dependencies = [ "async-trait", "cbindgen", diff --git a/examples/rust/mem-bench/Cargo.lock b/examples/rust/mem-bench/Cargo.lock index 9648c9379..eccb62413 100644 --- a/examples/rust/mem-bench/Cargo.lock +++ b/examples/rust/mem-bench/Cargo.lock @@ -1815,7 +1815,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statsig-rust" -version = "0.7.4-rc.2508181316" +version = "0.7.4-rc.2508182310" dependencies = [ "ahash", "arc-swap", diff --git a/statsig-dotnet/Directory.Build.props b/statsig-dotnet/Directory.Build.props index 99c21f39f..b35b6aebf 100644 --- a/statsig-dotnet/Directory.Build.props +++ b/statsig-dotnet/Directory.Build.props @@ -1,6 +1,6 @@ - 0.7.4-rc.2508181316 + 0.7.4-rc.2508182310 ISC \ No newline at end of file diff --git a/statsig-elixir/mix.exs b/statsig-elixir/mix.exs index d7dc2e7dc..58f474985 100644 --- a/statsig-elixir/mix.exs +++ b/statsig-elixir/mix.exs @@ -4,7 +4,7 @@ defmodule Statsigelixir.MixProject do def project do [ app: :statsig_elixir, - version: "0.7.4-rc.2508181316", + version: "0.7.4-rc.2508182310", elixir: "~> 1.0", start_permanent: Mix.env() == :prod, description: description(), diff --git a/statsig-go/cmd/post-install/main.go b/statsig-go/cmd/post-install/main.go index b76703883..7a68fb0db 100644 --- a/statsig-go/cmd/post-install/main.go +++ b/statsig-go/cmd/post-install/main.go @@ -12,7 +12,7 @@ import ( ) const ( - version = "0.7.4-rc.2508181316" + version = "0.7.4-rc.2508182310" ) var output_dir string diff --git a/statsig-java/gradle.properties b/statsig-java/gradle.properties index 03d443c1f..787be7762 100644 --- a/statsig-java/gradle.properties +++ b/statsig-java/gradle.properties @@ -1 +1 @@ -version=0.7.4-rc.2508181316 \ No newline at end of file +version=0.7.4-rc.2508182310 \ No newline at end of file diff --git a/statsig-node/npm/aarch64-apple-darwin.package.json b/statsig-node/npm/aarch64-apple-darwin.package.json index 0dfae9e43..7236e6101 100644 --- a/statsig-node/npm/aarch64-apple-darwin.package.json +++ b/statsig-node/npm/aarch64-apple-darwin.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-darwin-arm64", - "version": "0.7.4-rc.2508181316", + "version": "0.7.4-rc.2508182310", "os": [ "darwin" ], diff --git a/statsig-node/npm/aarch64-unknown-linux-gnu.package.json b/statsig-node/npm/aarch64-unknown-linux-gnu.package.json index 4ab1805ac..0282a644c 100644 --- a/statsig-node/npm/aarch64-unknown-linux-gnu.package.json +++ b/statsig-node/npm/aarch64-unknown-linux-gnu.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-arm64-gnu", - "version": "0.7.4-rc.2508181316", + "version": "0.7.4-rc.2508182310", "os": [ "linux" ], diff --git a/statsig-node/npm/aarch64-unknown-linux-musl.package.json b/statsig-node/npm/aarch64-unknown-linux-musl.package.json index dece5e189..17e9e9a04 100644 --- a/statsig-node/npm/aarch64-unknown-linux-musl.package.json +++ b/statsig-node/npm/aarch64-unknown-linux-musl.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-arm64-musl", - "version": "0.7.4-rc.2508181316", + "version": "0.7.4-rc.2508182310", "os": [ "linux" ], diff --git a/statsig-node/npm/i686-pc-windows-msvc.package.json b/statsig-node/npm/i686-pc-windows-msvc.package.json index e3bb3e9bb..31bb09c1b 100644 --- a/statsig-node/npm/i686-pc-windows-msvc.package.json +++ b/statsig-node/npm/i686-pc-windows-msvc.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-win32-ia32-msvc", - "version": "0.7.4-rc.2508181316", + "version": "0.7.4-rc.2508182310", "os": [ "win32" ], diff --git a/statsig-node/npm/x86_64-apple-darwin.package.json b/statsig-node/npm/x86_64-apple-darwin.package.json index 03c09aab9..317649d0c 100644 --- a/statsig-node/npm/x86_64-apple-darwin.package.json +++ b/statsig-node/npm/x86_64-apple-darwin.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-darwin-x64", - "version": "0.7.4-rc.2508181316", + "version": "0.7.4-rc.2508182310", "os": [ "darwin" ], diff --git a/statsig-node/npm/x86_64-pc-windows-msvc.package.json b/statsig-node/npm/x86_64-pc-windows-msvc.package.json index 1e83e71b1..44d0c6bcd 100644 --- a/statsig-node/npm/x86_64-pc-windows-msvc.package.json +++ b/statsig-node/npm/x86_64-pc-windows-msvc.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-win32-x64-msvc", - "version": "0.7.4-rc.2508181316", + "version": "0.7.4-rc.2508182310", "os": [ "win32" ], diff --git a/statsig-node/npm/x86_64-unknown-linux-gnu.package.json b/statsig-node/npm/x86_64-unknown-linux-gnu.package.json index 15846c57a..a38caafd3 100644 --- a/statsig-node/npm/x86_64-unknown-linux-gnu.package.json +++ b/statsig-node/npm/x86_64-unknown-linux-gnu.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-x64-gnu", - "version": "0.7.4-rc.2508181316", + "version": "0.7.4-rc.2508182310", "os": [ "linux" ], diff --git a/statsig-node/npm/x86_64-unknown-linux-musl.package.json b/statsig-node/npm/x86_64-unknown-linux-musl.package.json index b6df7119d..10387c06b 100644 --- a/statsig-node/npm/x86_64-unknown-linux-musl.package.json +++ b/statsig-node/npm/x86_64-unknown-linux-musl.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-x64-musl", - "version": "0.7.4-rc.2508181316", + "version": "0.7.4-rc.2508182310", "os": [ "linux" ], diff --git a/statsig-node/package.json b/statsig-node/package.json index c1850f6ff..e15dd6920 100644 --- a/statsig-node/package.json +++ b/statsig-node/package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core", - "version": "0.7.4-rc.2508181316", + "version": "0.7.4-rc.2508182310", "main": "index.js", "scripts": { "test": "jest --colors" diff --git a/statsig-php/post-install.php b/statsig-php/post-install.php index 68038a7d8..9ed3c8cae 100644 --- a/statsig-php/post-install.php +++ b/statsig-php/post-install.php @@ -1,7 +1,7 @@ Self { Self { - sdk_version: "0.7.4-rc.2508181316".to_string(), + sdk_version: "0.7.4-rc.2508182310".to_string(), sdk_type: "statsig-server-core".to_string(), session_id: Uuid::new_v4().to_string(), os: None, From c7c5d98365c0e22f522e61b658283d4909370696 Mon Sep 17 00:00:00 2001 From: Xin Li <137219293+xinlili-statsig@users.noreply.github.com> Date: Mon, 18 Aug 2025 18:02:48 -0700 Subject: [PATCH 05/23] [Cherrypick][releases/0.7.4-rc.2508182310] Fix elixir publish action + elixir: add gcir, make user_id or custom_id required, and some small fix (#1646) * [auto][cherrypick] 04582584ed3822663c849d9e7273b294aaf4fe47 Fix elixir publish action (#1640) * [auto][cherrypick] f1097f521c94e2fbb5364f3d9d0d9fecc18f5888 elixir: add gcir, make user_id or custom_id required, and some small fix (#1633) --- .../commands/publishers/elixir-publisher.ts | 38 +++++++------- statsig-elixir/lib/statsig.ex | 18 ++++++- statsig-elixir/lib/statsig/dynamic_config.ex | 4 +- statsig-elixir/lib/statsig/native_bindings.ex | 1 + statsig-elixir/lib/statsig/user.ex | 13 +++++ .../native/statsig_elixir/src/statsig_nfi.rs | 15 ++++++ .../statsig_elixir/src/statsig_types_nfi.rs | 2 + .../statsig_elixir/src/statsig_user_nfi.rs | 49 +++++++++++++------ 8 files changed, 104 insertions(+), 36 deletions(-) diff --git a/cli/src/commands/publishers/elixir-publisher.ts b/cli/src/commands/publishers/elixir-publisher.ts index 97efb5b62..ccfe9f9f9 100644 --- a/cli/src/commands/publishers/elixir-publisher.ts +++ b/cli/src/commands/publishers/elixir-publisher.ts @@ -1,4 +1,4 @@ -import { getRootedPath } from '@/utils/file_utils.js'; +import { BASE_DIR, getRootedPath } from '@/utils/file_utils.js'; import { GhRelease, createReleaseForVersion, @@ -19,7 +19,7 @@ import { PublisherOptions } from './publisher-options.js'; const ELIXIR_REPRO_NAME = 'statsig-elixir-core'; const EXPECTED_ZIPPED_FILES = 6; const COMPRESSED_DIR = 'artifacts/elixir_compressed_dir'; -const ELIXIR_DIR = 'statsig-elixir'; +const ELIXIR_DIR = `${BASE_DIR}/statsig-elixir`; export async function publishElixir(options: PublisherOptions) { const octokit = await getOctokit(); @@ -30,7 +30,7 @@ export async function publishElixir(options: PublisherOptions) { // step 2. zip path is **/target/**/release/libstatsig_elixir**.so const zippedFilesPath = await compressLibraries(); // step 3. upload - for (const path in zippedFilesPath) { + for (const path of zippedFilesPath) { await uploadRelease(octokit, release, path); } // step 4. run checksum @@ -40,23 +40,26 @@ export async function publishElixir(options: PublisherOptions) { } async function publishToHex() { - Log.stepBegin("Publish package to hex") - execSync(`mix hex.user auth ${process.env.HEX_API_KEY}`, { cwd: ELIXIR_DIR }) - execSync(`mix hex.publish`, { cwd: ELIXIR_DIR }) + Log.stepBegin('Publish package to hex'); + execSync(`HEX_API_KEY=${process.env.HEX_API_KEY} mix hex.publish --yes`, { cwd: ELIXIR_DIR, stdio: 'inherit' }); } async function runCheckSum() { Log.stepBegin('Setup elixir build environment'); - execSync('mix local.hex', { cwd: ELIXIR_DIR }); - execSync('mix local.rebar', { cwd: ELIXIR_DIR }); - execSync('mix deps.get', { cwd: ELIXIR_DIR }); + execSync('mix local.hex', { cwd: ELIXIR_DIR, stdio: 'inherit'}); + execSync('mix local.rebar', { cwd: ELIXIR_DIR, stdio: 'inherit'}); + execSync('mix deps.get', { cwd: ELIXIR_DIR, stdio: 'inherit'}); Log.stepEnd('Setup elixir build environment'); Log.stepBegin('Rerun checksum'); - execSync( - `FORCE_STATSIG_NATIVE_BUILD="true" mix rustler_precompiled.download NativeBindings --all --printls`, - { cwd: ELIXIR_DIR }, - ); + execSync('FORCE_STATSIG_NATIVE_BUILD="true" mix compile', { + cwd: ELIXIR_DIR, + stdio: 'inherit' + }); + execSync(`mix rustler_precompiled.download Statsig.NativeBindings --all --printls`, { + cwd: ELIXIR_DIR, + stdio: 'inherit' + }); Log.stepEnd('Rerun checksum'); } @@ -72,12 +75,11 @@ async function uploadRelease( } Log.stepProgress(`Release upload URL: ${uploadUrl}`); - const { result, error } = await uploadReleaseAsset( octokit, ELIXIR_REPRO_NAME, release.id, - COMPRESSED_DIR, + path, ); } @@ -105,13 +107,13 @@ async function compressLibraries() { const compressedPath = []; Log.stepBegin('Compressing: Create tar gz files'); const matches = await glob( - 'artifacts/**/target/**/release/libstatsig_elixir**.so', + '/tmp/statsig-server-core-publish/**/target/**/release/libstatsig_elixir**.so', { nodir: true, }, ); - if (matches.length != EXPECTED_ZIPPED_FILES) { + if (matches.length < EXPECTED_ZIPPED_FILES) { console.error('Found less binaries'); process.exit(1); @@ -131,7 +133,7 @@ async function compressLibraries() { compressedPath.push(tarName); } Log.stepEnd('Compressing: Create tar gz files'); - if (compressedPath.length != EXPECTED_ZIPPED_FILES) { + if (compressedPath.length <= EXPECTED_ZIPPED_FILES) { console.error('Found less zipped files'); process.exit(1); } diff --git a/statsig-elixir/lib/statsig.ex b/statsig-elixir/lib/statsig.ex index 3522f7522..4dfe30879 100644 --- a/statsig-elixir/lib/statsig.ex +++ b/statsig-elixir/lib/statsig.ex @@ -116,6 +116,22 @@ defmodule Statsig do end end + def get_client_init_response_as_string(statsig_user) do + try do + instance = get_statsig_instance() + + case NativeBindings.get_client_init_response_as_string(instance, statsig_user) do + {:error, e} -> {:error, e} + response -> {:ok, response} + end + rescue + exception -> {:error, Exception.message(exception)} + catch + :exit, reason -> {:error, {:exit, reason}} + exception -> {:error, Exception.message(exception)} + end + end + @spec log_event(%Statsig.User{}, String.t(), String.t() | number(), %{String.t() => String.t()}) :: any() def log_event(statsig_user, event_name, value, metadata) do @@ -123,7 +139,7 @@ defmodule Statsig do instance = get_statsig_instance() case value do - value when is_binary(value) -> + value when is_binary(value) or is_nil(value) -> NativeBindings.log_event(instance, statsig_user, event_name, value, metadata) value when is_number(value) -> diff --git a/statsig-elixir/lib/statsig/dynamic_config.ex b/statsig-elixir/lib/statsig/dynamic_config.ex index cace1c1fc..2c65d6a6d 100644 --- a/statsig-elixir/lib/statsig/dynamic_config.ex +++ b/statsig-elixir/lib/statsig/dynamic_config.ex @@ -3,14 +3,14 @@ defmodule Statsig.DynamicConfig do :name, :value, :rule_id, - :id_type + :id_type, ] @type t :: %__MODULE__{ name: String.t(), value: String.t(), rule_id: String.t(), - id_type: String.t() + id_type: String.t(), } def get_param_value(config, param_name) do diff --git a/statsig-elixir/lib/statsig/native_bindings.ex b/statsig-elixir/lib/statsig/native_bindings.ex index 88920caca..e2b18616d 100644 --- a/statsig-elixir/lib/statsig/native_bindings.ex +++ b/statsig-elixir/lib/statsig/native_bindings.ex @@ -21,6 +21,7 @@ defmodule Statsig.NativeBindings do def get_config(_statsig, _config_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_experiment(_statsig, _experiment_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_layer(_statsig, _layer_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) + def get_client_init_response_as_string(_statsig, _statsig_user), do: :erlang.nif_error(:nif_not_loaded) def log_event(_statsig, _statsig_user, _event_name,_value, _metadata), do: :erlang.nif_error(:nif_not_loaded) def log_event_with_number(_statsig, _statsig_user, _event_name,_value, _metadata), do: :erlang.nif_error(:nif_not_loaded) def flush(_statsig), do: :erlang.nif_error(:nif_not_loaded) diff --git a/statsig-elixir/lib/statsig/user.ex b/statsig-elixir/lib/statsig/user.ex index 77c98d5a7..9f1f17a80 100644 --- a/statsig-elixir/lib/statsig/user.ex +++ b/statsig-elixir/lib/statsig/user.ex @@ -12,6 +12,19 @@ defmodule Statsig.User do app_version: nil, ] + def new(attrs) when is_map(attrs) do + %__MODULE__{} + |> struct(attrs) + |> validate_presence_of_id() + end + + defp validate_presence_of_id(%__MODULE__{user_id: nil, custom_ids: nil}) do + raise ArgumentError, + "Either `user_id` or `custom_ids` must be set" + end + + defp validate_presence_of_id(struct), do: struct + @type custom_value :: String.t() | number() | boolean() | nil @type custom_attributes :: %{String.t() => custom_value()} diff --git a/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs b/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs index 2d9ec872c..409fb24c0 100644 --- a/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs +++ b/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs @@ -202,6 +202,20 @@ pub fn log_event_with_number( } } +#[rustler::nif(schedule = "DirtyCpu")] +pub fn get_client_init_response_as_string( + statsig: ResourceArc, + statsig_user: StatsigUser, +) -> Result { + match statsig.statsig_core.read() { + Ok(read_guard) => { + let response = read_guard.get_client_init_response_as_string(&statsig_user.into()); + Ok(response) + } + Err(_) => Err(Error::RaiseAtom("Failed to get Statsig")), + } +} + #[rustler::nif(schedule = "DirtyIo")] pub fn flush(statsig: ResourceArc) -> Result<(), Error> { match statsig.statsig_core.read() { @@ -280,6 +294,7 @@ pub fn layer_get_rule_id(layer: ResourceArc) -> Result) -> Result, Error> { + println!("get group name"); match layer.core.read() { Ok(read_guard) => Ok(read_guard.group_name.clone()), Err(_) => Err(Error::RaiseAtom("Failed to get Statsig")), diff --git a/statsig-elixir/native/statsig_elixir/src/statsig_types_nfi.rs b/statsig-elixir/native/statsig_elixir/src/statsig_types_nfi.rs index f93f366ed..aea339df0 100644 --- a/statsig-elixir/native/statsig_elixir/src/statsig_types_nfi.rs +++ b/statsig-elixir/native/statsig_elixir/src/statsig_types_nfi.rs @@ -90,6 +90,8 @@ impl<'a> Decoder<'a> for AllowedPrimitive { Ok(AllowedPrimitive::Str(s)) } else if let Ok(b) = bool::decode(term) { Ok(AllowedPrimitive::Bool(b)) + } else if let Ok(f) = f64::decode(term) { + Ok(AllowedPrimitive::Float(f)) } else { Err(rustler::Error::BadArg) } diff --git a/statsig-elixir/native/statsig_elixir/src/statsig_user_nfi.rs b/statsig-elixir/native/statsig_elixir/src/statsig_user_nfi.rs index af0f83b03..a2ce9489d 100644 --- a/statsig-elixir/native/statsig_elixir/src/statsig_user_nfi.rs +++ b/statsig-elixir/native/statsig_elixir/src/statsig_user_nfi.rs @@ -6,7 +6,13 @@ use std::collections::HashMap; macro_rules! to_value_with_dynamic { ($map:expr) => {{ $map.into_iter() - .map(|(key, value)| (key, value.into())) + .map(|(key, value)| { + let converted_value = match value { + Some(v) => v.into(), + None => DynamicValue::new(), + }; + (key, converted_value) + }) .collect::>() }}; } @@ -14,11 +20,11 @@ macro_rules! to_value_with_dynamic { #[derive(NifStruct)] #[module = "Statsig.User"] pub struct StatsigUser { - pub user_id: String, + pub user_id: Option, pub email: Option, - pub custom: Option>, + pub custom: Option>>, pub custom_ids: Option>, - pub private_attributes: Option>, + pub private_attributes: Option>>, pub ip: Option, pub user_agent: Option, pub country: Option, @@ -28,16 +34,29 @@ pub struct StatsigUser { impl From for StatsigUserActual { fn from(user: StatsigUser) -> Self { - StatsigUserBuilder::new_with_user_id(user.user_id) - .custom_ids(user.custom_ids) - .app_version(user.app_version) - .email(user.email) - .ip(user.ip) - .user_agent(user.user_agent) - .locale(user.locale) - .country(user.country) - .custom(user.custom.map(|m| to_value_with_dynamic!(m))) - .private_attributes(user.private_attributes.map(|m| to_value_with_dynamic!(m))) - .build() + // We enforce either user id or custom ids being set on elixir side, so making assumption if no user id there must be custom_id + match user.user_id { + Some(id) => StatsigUserBuilder::new_with_user_id(id) + .custom_ids(user.custom_ids) + .app_version(user.app_version) + .email(user.email) + .ip(user.ip) + .user_agent(user.user_agent) + .locale(user.locale) + .country(user.country) + .custom(user.custom.map(|m| to_value_with_dynamic!(m))) + .private_attributes(user.private_attributes.map(|m| to_value_with_dynamic!(m))) + .build(), + None => StatsigUserBuilder::new_with_custom_ids(user.custom_ids.unwrap_or_default()) + .app_version(user.app_version) + .email(user.email) + .ip(user.ip) + .user_agent(user.user_agent) + .locale(user.locale) + .country(user.country) + .custom(user.custom.map(|m| to_value_with_dynamic!(m))) + .private_attributes(user.private_attributes.map(|m| to_value_with_dynamic!(m))) + .build(), + } } } From eeb6da28f0019670f544b5a78a2a041553b322de Mon Sep 17 00:00:00 2001 From: Xin Li <137219293+xinlili-statsig@users.noreply.github.com> Date: Tue, 19 Aug 2025 11:29:21 -0700 Subject: [PATCH 06/23] [Cherrypick][releases/0.7.4-rc.2508182310] elixir: add gcir, make user_id or custom_id required, and some small fix + Fix elixir publish action (#1649) * [auto][cherrypick] f1097f521c94e2fbb5364f3d9d0d9fecc18f5888 elixir: add gcir, make user_id or custom_id required, and some small fix (#1633) * [auto][cherrypick] 04582584ed3822663c849d9e7273b294aaf4fe47 Fix elixir publish action (#1640) --- statsig-elixir/lib/statsig/native_bindings.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/statsig-elixir/lib/statsig/native_bindings.ex b/statsig-elixir/lib/statsig/native_bindings.ex index e2b18616d..9efc50447 100644 --- a/statsig-elixir/lib/statsig/native_bindings.ex +++ b/statsig-elixir/lib/statsig/native_bindings.ex @@ -4,7 +4,7 @@ defmodule Statsig.NativeBindings do otp_app: :statsig_elixir, crate: "statsig_elixir", version: version, - base_url: "https://github.com/statsig-io/statsig-server-core/releases/download/#{version}/", + base_url: "https://github.com/statsig-io/statsig-elixir-core/releases/download/#{version}/", force_build: System.get_env("FORCE_STATSIG_NATIVE_BUILD") in ["1", "true"], targets: [ "aarch64-apple-darwin", # Add other supported targets if needed From 6646ee7c428bd7a029ee7cf94882bc6d459c399f Mon Sep 17 00:00:00 2001 From: "statsig-kong[bot]" Date: Tue, 19 Aug 2025 11:30:10 -0700 Subject: [PATCH 07/23] Bot: Updated File Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a244bc1f1..a4f5c7f41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ exclude = [ [workspace.package] edition = "2021" license = "ISC" -version = "0.7.4-rc.2508182310" +version = "0.7.4-rc.2508191829" homepage = "https://statsig.com/" authors = ["Statsig", "Daniel Loomb "] readme = "README.md" From 5a37359eb6c650843062c4ef3b435148a999808a Mon Sep 17 00:00:00 2001 From: "statsig-kong[bot]" Date: Tue, 19 Aug 2025 18:31:57 +0000 Subject: [PATCH 08/23] Bot: Version synchronized in 18 files --- Cargo.lock | 12 ++++++------ examples/rust/mem-bench/Cargo.lock | 2 +- statsig-dotnet/Directory.Build.props | 2 +- statsig-elixir/mix.exs | 2 +- statsig-go/cmd/post-install/main.go | 2 +- statsig-java/gradle.properties | 2 +- statsig-node/npm/aarch64-apple-darwin.package.json | 2 +- .../npm/aarch64-unknown-linux-gnu.package.json | 2 +- .../npm/aarch64-unknown-linux-musl.package.json | 2 +- statsig-node/npm/i686-pc-windows-msvc.package.json | 2 +- statsig-node/npm/x86_64-apple-darwin.package.json | 2 +- statsig-node/npm/x86_64-pc-windows-msvc.package.json | 2 +- .../npm/x86_64-unknown-linux-gnu.package.json | 2 +- .../npm/x86_64-unknown-linux-musl.package.json | 2 +- statsig-node/package.json | 2 +- statsig-php/post-install.php | 2 +- statsig-rust/Cargo.toml | 2 +- statsig-rust/src/statsig_metadata.rs | 2 +- 18 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 04c61d77f..0505ca4f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2373,7 +2373,7 @@ dependencies = [ [[package]] name = "sigstat-grpc" -version = "0.7.4-rc.2508182310" +version = "0.7.4-rc.2508191829" dependencies = [ "async-trait", "chrono", @@ -2437,7 +2437,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statsig-node" -version = "0.7.4-rc.2508182310" +version = "0.7.4-rc.2508191829" dependencies = [ "async-trait", "napi", @@ -2450,7 +2450,7 @@ dependencies = [ [[package]] name = "statsig-pyo3" -version = "0.7.4-rc.2508182310" +version = "0.7.4-rc.2508191829" dependencies = [ "async-trait", "lazy_static", @@ -2464,7 +2464,7 @@ dependencies = [ [[package]] name = "statsig-rust" -version = "0.7.4-rc.2508182310" +version = "0.7.4-rc.2508191829" dependencies = [ "ahash", "arc-swap", @@ -2504,7 +2504,7 @@ dependencies = [ [[package]] name = "statsig_elixir" -version = "0.7.4-rc.2508182310" +version = "0.7.4-rc.2508191829" dependencies = [ "parking_lot", "rustler", @@ -2516,7 +2516,7 @@ dependencies = [ [[package]] name = "statsig_ffi" -version = "0.7.4-rc.2508182310" +version = "0.7.4-rc.2508191829" dependencies = [ "async-trait", "cbindgen", diff --git a/examples/rust/mem-bench/Cargo.lock b/examples/rust/mem-bench/Cargo.lock index eccb62413..a7498b42a 100644 --- a/examples/rust/mem-bench/Cargo.lock +++ b/examples/rust/mem-bench/Cargo.lock @@ -1815,7 +1815,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statsig-rust" -version = "0.7.4-rc.2508182310" +version = "0.7.4-rc.2508191829" dependencies = [ "ahash", "arc-swap", diff --git a/statsig-dotnet/Directory.Build.props b/statsig-dotnet/Directory.Build.props index b35b6aebf..6b496b977 100644 --- a/statsig-dotnet/Directory.Build.props +++ b/statsig-dotnet/Directory.Build.props @@ -1,6 +1,6 @@ - 0.7.4-rc.2508182310 + 0.7.4-rc.2508191829 ISC \ No newline at end of file diff --git a/statsig-elixir/mix.exs b/statsig-elixir/mix.exs index 58f474985..da370c170 100644 --- a/statsig-elixir/mix.exs +++ b/statsig-elixir/mix.exs @@ -4,7 +4,7 @@ defmodule Statsigelixir.MixProject do def project do [ app: :statsig_elixir, - version: "0.7.4-rc.2508182310", + version: "0.7.4-rc.2508191829", elixir: "~> 1.0", start_permanent: Mix.env() == :prod, description: description(), diff --git a/statsig-go/cmd/post-install/main.go b/statsig-go/cmd/post-install/main.go index 7a68fb0db..fe6ce131d 100644 --- a/statsig-go/cmd/post-install/main.go +++ b/statsig-go/cmd/post-install/main.go @@ -12,7 +12,7 @@ import ( ) const ( - version = "0.7.4-rc.2508182310" + version = "0.7.4-rc.2508191829" ) var output_dir string diff --git a/statsig-java/gradle.properties b/statsig-java/gradle.properties index 787be7762..5feadf140 100644 --- a/statsig-java/gradle.properties +++ b/statsig-java/gradle.properties @@ -1 +1 @@ -version=0.7.4-rc.2508182310 \ No newline at end of file +version=0.7.4-rc.2508191829 \ No newline at end of file diff --git a/statsig-node/npm/aarch64-apple-darwin.package.json b/statsig-node/npm/aarch64-apple-darwin.package.json index 7236e6101..4684be4ac 100644 --- a/statsig-node/npm/aarch64-apple-darwin.package.json +++ b/statsig-node/npm/aarch64-apple-darwin.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-darwin-arm64", - "version": "0.7.4-rc.2508182310", + "version": "0.7.4-rc.2508191829", "os": [ "darwin" ], diff --git a/statsig-node/npm/aarch64-unknown-linux-gnu.package.json b/statsig-node/npm/aarch64-unknown-linux-gnu.package.json index 0282a644c..3dd834e41 100644 --- a/statsig-node/npm/aarch64-unknown-linux-gnu.package.json +++ b/statsig-node/npm/aarch64-unknown-linux-gnu.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-arm64-gnu", - "version": "0.7.4-rc.2508182310", + "version": "0.7.4-rc.2508191829", "os": [ "linux" ], diff --git a/statsig-node/npm/aarch64-unknown-linux-musl.package.json b/statsig-node/npm/aarch64-unknown-linux-musl.package.json index 17e9e9a04..aa5edfea0 100644 --- a/statsig-node/npm/aarch64-unknown-linux-musl.package.json +++ b/statsig-node/npm/aarch64-unknown-linux-musl.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-arm64-musl", - "version": "0.7.4-rc.2508182310", + "version": "0.7.4-rc.2508191829", "os": [ "linux" ], diff --git a/statsig-node/npm/i686-pc-windows-msvc.package.json b/statsig-node/npm/i686-pc-windows-msvc.package.json index 31bb09c1b..03f363526 100644 --- a/statsig-node/npm/i686-pc-windows-msvc.package.json +++ b/statsig-node/npm/i686-pc-windows-msvc.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-win32-ia32-msvc", - "version": "0.7.4-rc.2508182310", + "version": "0.7.4-rc.2508191829", "os": [ "win32" ], diff --git a/statsig-node/npm/x86_64-apple-darwin.package.json b/statsig-node/npm/x86_64-apple-darwin.package.json index 317649d0c..e7ca36096 100644 --- a/statsig-node/npm/x86_64-apple-darwin.package.json +++ b/statsig-node/npm/x86_64-apple-darwin.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-darwin-x64", - "version": "0.7.4-rc.2508182310", + "version": "0.7.4-rc.2508191829", "os": [ "darwin" ], diff --git a/statsig-node/npm/x86_64-pc-windows-msvc.package.json b/statsig-node/npm/x86_64-pc-windows-msvc.package.json index 44d0c6bcd..f1786ba42 100644 --- a/statsig-node/npm/x86_64-pc-windows-msvc.package.json +++ b/statsig-node/npm/x86_64-pc-windows-msvc.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-win32-x64-msvc", - "version": "0.7.4-rc.2508182310", + "version": "0.7.4-rc.2508191829", "os": [ "win32" ], diff --git a/statsig-node/npm/x86_64-unknown-linux-gnu.package.json b/statsig-node/npm/x86_64-unknown-linux-gnu.package.json index a38caafd3..f59a8e24b 100644 --- a/statsig-node/npm/x86_64-unknown-linux-gnu.package.json +++ b/statsig-node/npm/x86_64-unknown-linux-gnu.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-x64-gnu", - "version": "0.7.4-rc.2508182310", + "version": "0.7.4-rc.2508191829", "os": [ "linux" ], diff --git a/statsig-node/npm/x86_64-unknown-linux-musl.package.json b/statsig-node/npm/x86_64-unknown-linux-musl.package.json index 10387c06b..b4deb88a1 100644 --- a/statsig-node/npm/x86_64-unknown-linux-musl.package.json +++ b/statsig-node/npm/x86_64-unknown-linux-musl.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-x64-musl", - "version": "0.7.4-rc.2508182310", + "version": "0.7.4-rc.2508191829", "os": [ "linux" ], diff --git a/statsig-node/package.json b/statsig-node/package.json index e15dd6920..5739aff66 100644 --- a/statsig-node/package.json +++ b/statsig-node/package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core", - "version": "0.7.4-rc.2508182310", + "version": "0.7.4-rc.2508191829", "main": "index.js", "scripts": { "test": "jest --colors" diff --git a/statsig-php/post-install.php b/statsig-php/post-install.php index 9ed3c8cae..2a1bb8383 100644 --- a/statsig-php/post-install.php +++ b/statsig-php/post-install.php @@ -1,7 +1,7 @@ Self { Self { - sdk_version: "0.7.4-rc.2508182310".to_string(), + sdk_version: "0.7.4-rc.2508191829".to_string(), sdk_type: "statsig-server-core".to_string(), session_id: Uuid::new_v4().to_string(), os: None, From 62b863a49a7c01ffd39f15dd107f9df2fb8d7d83 Mon Sep 17 00:00:00 2001 From: Xin Li <137219293+xinlili-statsig@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:02:25 -0700 Subject: [PATCH 09/23] [cherrypick][releases/0.7.4-rc.2508191829] elixir: statsigmetadata update (#1668) [auto][cherrypick] b6fd39e148b61427bb7ec755f0ebd0e18c4f74eb elixir: statsigmetadata update (#1655) --- statsig-elixir/lib/statsig.ex | 39 +++++++++++++++++- statsig-elixir/lib/statsig/native_bindings.ex | 3 +- .../native/statsig_elixir/src/statsig_nfi.rs | 40 ++++++++++++++++++- statsig-elixir/test/statsig_test.exs | 4 +- 4 files changed, 81 insertions(+), 5 deletions(-) diff --git a/statsig-elixir/lib/statsig.ex b/statsig-elixir/lib/statsig.ex index 4dfe30879..712f41171 100644 --- a/statsig-elixir/lib/statsig.ex +++ b/statsig-elixir/lib/statsig.ex @@ -9,7 +9,7 @@ defmodule Statsig do def init({sdk_key, statsig_options}) do try do - instance = NativeBindings.new(sdk_key, statsig_options) + instance = NativeBindings.new(sdk_key, statsig_options,get_system_info()) {:ok, instance} rescue exception -> {:error, Exception.message(exception)} @@ -116,6 +116,21 @@ defmodule Statsig do end end + def get_prompt(prompt_name, statsig_user, options \\nil) do + try do + instance = get_statsig_instance() + case NativeBindings.get_prompt(instance, prompt_name, statsig_user, options) do + {:error, e} -> {:error, e} + layer -> {:ok, layer} + end + rescue + exception -> {:error, Exception.message(exception)} + catch + :exit, reason -> {:error, {:exit, reason}} + exception -> {:error, Exception.message(exception)} + end + end + def get_client_init_response_as_string(statsig_user) do try do instance = get_statsig_instance() @@ -185,4 +200,26 @@ defmodule Statsig do exception -> {:error, Exception.message(exception)} end end + + def get_system_info do + try do + %{ + "os"=> :os.type() |> elem(0) |> Atom.to_string(), + "arch"=> :erlang.system_info(:system_architecture) |> List.to_string(), + "language_version"=> System.version() + } + rescue + _ -> %{ + "os"=> "unknown", + "arch"=> "unknown", + "language_version"=> "unknown" + } + catch + _, _ -> %{ + "os"=> "unknown", + "arch"=> "unknown", + "language_version"=> "unknown" + } + end + end end diff --git a/statsig-elixir/lib/statsig/native_bindings.ex b/statsig-elixir/lib/statsig/native_bindings.ex index 9efc50447..b0a8d516c 100644 --- a/statsig-elixir/lib/statsig/native_bindings.ex +++ b/statsig-elixir/lib/statsig/native_bindings.ex @@ -14,13 +14,14 @@ defmodule Statsig.NativeBindings do "x86_64-unknown-linux-musl", "aarch64-unknown-linux-musl", ] - def new(_key, _options), do: :erlang.nif_error(:nif_not_loaded) + def new(_key, _options, _system_metadata), do: :erlang.nif_error(:nif_not_loaded) def initialize(_statsig), do: :erlang.nif_error(:nif_not_loaded) def check_gate(_statsig, _gate_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_feature_gate(_statsig, _gate_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_config(_statsig, _config_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_experiment(_statsig, _experiment_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_layer(_statsig, _layer_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) + def get_prompt(_statsig, _prompt_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_client_init_response_as_string(_statsig, _statsig_user), do: :erlang.nif_error(:nif_not_loaded) def log_event(_statsig, _statsig_user, _event_name,_value, _metadata), do: :erlang.nif_error(:nif_not_loaded) def log_event_with_number(_statsig, _statsig_user, _event_name,_value, _metadata), do: :erlang.nif_error(:nif_not_loaded) diff --git a/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs b/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs index 409fb24c0..58cd3e680 100644 --- a/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs +++ b/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs @@ -1,5 +1,7 @@ use rustler::{Env, Error, ResourceArc, Term}; -use statsig_rust::{statsig_types::Layer as LayerActual, Statsig}; +use statsig_rust::{ + statsig_metadata::StatsigMetadata, statsig_types::Layer as LayerActual, Statsig, +}; use std::{ collections::HashMap, sync::{Arc, RwLock}, @@ -43,7 +45,9 @@ impl LayerResource { pub fn new( sdk_key: String, options: Option, + system_metadata: HashMap, ) -> Result, Error> { + update_metadata(system_metadata); let statsig = Statsig::new(&sdk_key, options.map(|op| Arc::new(op.into()))); Ok(ResourceArc::new(StatsigResource { statsig_core: RwLock::new(Arc::new(statsig)), @@ -163,6 +167,26 @@ pub fn get_layer( } } +#[rustler::nif] +pub fn get_prompt( + statsig: ResourceArc, + prompt_name: &str, + statsig_user: StatsigUser, + options: Option, +) -> Result, Error> { + match statsig.statsig_core.read() { + Ok(read_guard) => { + let layer = read_guard.get_prompt_with_options( + &statsig_user.into(), + prompt_name, + options.map(|o| o.into()).unwrap_or_default(), + ); + Ok(ResourceArc::new(LayerResource::new(layer))) + } + Err(_) => Err(Error::RaiseAtom("Failed to get Statsig")), + } +} + #[rustler::nif] pub fn log_event( statsig: ResourceArc, @@ -301,4 +325,18 @@ pub fn layer_get_group_name(layer: ResourceArc) -> Result) { + let unknown = "unknown".to_string(); + let os = system_metadata.get("os").unwrap_or(&unknown); + let arch = system_metadata.get("arch").unwrap_or(&unknown); + let language_version = system_metadata.get("language_version").unwrap_or(&unknown); + StatsigMetadata::update_values( + "statsig-server-core-elixir".to_owned(), + os.to_string(), + arch.to_string(), + language_version.to_string(), + ); +} + rustler::init!("Elixir.Statsig.NativeBindings", load = load); diff --git a/statsig-elixir/test/statsig_test.exs b/statsig-elixir/test/statsig_test.exs index f2280d67a..6ab478a8c 100644 --- a/statsig-elixir/test/statsig_test.exs +++ b/statsig-elixir/test/statsig_test.exs @@ -24,8 +24,8 @@ defmodule StatsigTest do statsig_options = %Options{enable_id_lists: true, output_log_level: "debug"} IO.puts("Initializing with SDK key: #{sdk_key}") - Statsig.start_link(sdk_key, statsig_options) - + initres = Statsig.start_link(sdk_key, statsig_options) + IO.inspect(initres) # Create a test user user = %User{ user_id: "test_user_123", From a02ad24f8042c61d963464868d120e8e6d4a5c1f Mon Sep 17 00:00:00 2001 From: Xin Li <137219293+xinlili-statsig@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:03:56 -0700 Subject: [PATCH 10/23] [cherrypick][releases/0.7.4-rc.2508191829] support gcir option (#1669) [auto][cherrypick] 2205837c0bf8803a95a6da5d9a9dae6052a7cfec support gcir option (#1659) --- statsig-elixir/lib/statsig.ex | 4 ++-- statsig-elixir/lib/statsig/native_bindings.ex | 2 +- .../native/statsig_elixir/src/statsig_nfi.rs | 13 ++++++++--- .../statsig_elixir/src/statsig_types_nfi.rs | 22 +++++++++++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/statsig-elixir/lib/statsig.ex b/statsig-elixir/lib/statsig.ex index 712f41171..aade42942 100644 --- a/statsig-elixir/lib/statsig.ex +++ b/statsig-elixir/lib/statsig.ex @@ -131,11 +131,11 @@ defmodule Statsig do end end - def get_client_init_response_as_string(statsig_user) do + def get_client_init_response_as_string(statsig_user, options \\nil) do try do instance = get_statsig_instance() - case NativeBindings.get_client_init_response_as_string(instance, statsig_user) do + case NativeBindings.get_client_init_response_as_string(instance, statsig_user, options) do {:error, e} -> {:error, e} response -> {:ok, response} end diff --git a/statsig-elixir/lib/statsig/native_bindings.ex b/statsig-elixir/lib/statsig/native_bindings.ex index b0a8d516c..c9ed1a3f2 100644 --- a/statsig-elixir/lib/statsig/native_bindings.ex +++ b/statsig-elixir/lib/statsig/native_bindings.ex @@ -22,7 +22,7 @@ defmodule Statsig.NativeBindings do def get_experiment(_statsig, _experiment_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_layer(_statsig, _layer_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_prompt(_statsig, _prompt_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) - def get_client_init_response_as_string(_statsig, _statsig_user), do: :erlang.nif_error(:nif_not_loaded) + def get_client_init_response_as_string(_statsig, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def log_event(_statsig, _statsig_user, _event_name,_value, _metadata), do: :erlang.nif_error(:nif_not_loaded) def log_event_with_number(_statsig, _statsig_user, _event_name,_value, _metadata), do: :erlang.nif_error(:nif_not_loaded) def flush(_statsig), do: :erlang.nif_error(:nif_not_loaded) diff --git a/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs b/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs index 58cd3e680..edfb3ac6d 100644 --- a/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs +++ b/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs @@ -10,8 +10,8 @@ use std::{ use crate::{ statsig_options_nfi::StatsigOptions, statsig_types_nfi::{ - AllowedPrimitive, DynamicConfig, DynamicConfigEvaluationOptions, Experiment, - ExperimentEvaluationOptions, FeatureGate, FeatureGateEvaluationOptions, + AllowedPrimitive, ClientInitResponseOptions, DynamicConfig, DynamicConfigEvaluationOptions, + Experiment, ExperimentEvaluationOptions, FeatureGate, FeatureGateEvaluationOptions, LayerEvaluationOptions, }, statsig_user_nfi::StatsigUser, @@ -230,10 +230,17 @@ pub fn log_event_with_number( pub fn get_client_init_response_as_string( statsig: ResourceArc, statsig_user: StatsigUser, + options: Option, ) -> Result { match statsig.statsig_core.read() { Ok(read_guard) => { - let response = read_guard.get_client_init_response_as_string(&statsig_user.into()); + let response = match options { + Some(o) => read_guard.get_client_init_response_with_options_as_string( + &statsig_user.into(), + &o.into(), + ), + None => read_guard.get_client_init_response_as_string(&statsig_user.into()), + }; Ok(response) } Err(_) => Err(Error::RaiseAtom("Failed to get Statsig")), diff --git a/statsig-elixir/native/statsig_elixir/src/statsig_types_nfi.rs b/statsig-elixir/native/statsig_elixir/src/statsig_types_nfi.rs index aea339df0..18fc1a330 100644 --- a/statsig-elixir/native/statsig_elixir/src/statsig_types_nfi.rs +++ b/statsig-elixir/native/statsig_elixir/src/statsig_types_nfi.rs @@ -11,6 +11,7 @@ use statsig_rust::statsig_types::{ FeatureGate as FeatureGateActual, }; use statsig_rust::DynamicValue; +use statsig_rust::{ClientInitResponseOptions as ClientInitResponseOptionsActual, HashAlgorithm}; #[derive(NifStruct)] #[module = "Statsig.Experiment"] pub struct Experiment { @@ -184,3 +185,24 @@ impl From for DynamicConfigEvaluationOptionsActu } } } + +#[derive(NifStruct)] +#[module = "Statsig.ClientInitResponseOptions"] +pub struct ClientInitResponseOptions { + pub hash_algorithm: Option, + pub client_sdk_key: Option, + pub include_local_overrides: Option, +} + +impl From for ClientInitResponseOptionsActual { + fn from(option: ClientInitResponseOptions) -> Self { + ClientInitResponseOptionsActual { + hash_algorithm: option + .hash_algorithm + .and_then(|v| HashAlgorithm::from_string(v.as_str())), + client_sdk_key: option.client_sdk_key, + include_local_overrides: option.include_local_overrides, + ..Default::default() + } + } +} From 9e77e7921a00441cb23126f6d4513ae2f47cdc87 Mon Sep 17 00:00:00 2001 From: Xin Li <137219293+xinlili-statsig@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:05:10 -0700 Subject: [PATCH 11/23] [cherrypick][releases/0.7.4-rc.2508191829] elixir: add module definition for clientinitializeresponseoption (#1670) [auto][cherrypick] 5cf4c3213af928764d79467d09a6852c20847254 elixir: add module definition for clientinitializeresponseoption (#1667) --- statsig-elixir/lib/statsig/options.ex | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/statsig-elixir/lib/statsig/options.ex b/statsig-elixir/lib/statsig/options.ex index d7f796dde..fbaa6f0b1 100644 --- a/statsig-elixir/lib/statsig/options.ex +++ b/statsig-elixir/lib/statsig/options.ex @@ -41,4 +41,12 @@ end defmodule Statsig.DynamicConfigEvaluationOptions do defstruct disable_exposure_logging: false +end + +defmodule Statsig.ClientInitResponseOptions do + defstruct [ + hash_algorithm: nil, + client_sdk_key: nil, + include_local_overrides: nil + ] end \ No newline at end of file From 9eb6d57ea157abc8df8ed8a3462af97223369577 Mon Sep 17 00:00:00 2001 From: Xin Li <137219293+xinlili-statsig@users.noreply.github.com> Date: Wed, 20 Aug 2025 12:31:44 -0700 Subject: [PATCH 12/23] [cherrypick][releases/0.7.4-rc.2508191829] tool: new gh workflow to create release (#1673) [auto][cherrypick] 9ecf44b607e035bc39e38f7388fd4a2a29c79fa5 tool: new gh workflow to create release (#1666) --- .github/workflows/create_release.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/create_release.yml diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml new file mode 100644 index 000000000..4d36714fc --- /dev/null +++ b/.github/workflows/create_release.yml @@ -0,0 +1,26 @@ +name: Create Release + +on: + workflow_dispatch: + push: + tags: + - 'v*.*.*' + +jobs: + create-release: + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/heads/releases/') || startsWith(github.ref, 'refs/heads/betas/') + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: pnpm/action-setup@v4 + with: + version: 7.32.4 + + - name: Install CLI(Tore) Dependencies + run: pnpm install --dir cli + + - name: Create GitHub Release + run: ./tore gh-create-release private-statsig-server-core From 94f5a4815fac62aa85571bde5178614a9a87bca8 Mon Sep 17 00:00:00 2001 From: Xin Li <137219293+xinlili-statsig@users.noreply.github.com> Date: Wed, 20 Aug 2025 13:00:46 -0700 Subject: [PATCH 13/23] [cherrypick][releases/0.7.4-rc.2508191829] add getPrompt/bindings (#1677) [auto][cherrypick] 2173797a6beb6e3adb49cf05167289e7738a5e53 add getPrompt/bindings (#1623) --- statsig-dotnet/src/Statsig/Statsig.cs | 24 ++++++++++++++ statsig-dotnet/src/Statsig/StatsigFFI.g.cs | 3 ++ statsig-elixir/lib/statsig.ex | 28 ++-------------- statsig-elixir/lib/statsig/native_bindings.ex | 4 +-- .../native/statsig_elixir/src/statsig_nfi.rs | 33 +++---------------- statsig-ffi/include/statsig_ffi.h | 5 +++ statsig-ffi/src/jni/statsig_jni.rs | 27 +++++++++++++++ statsig-ffi/src/statsig_c.rs | 26 +++++++++++++++ statsig-go/src/statsig.go | 24 ++++++++++++++ .../src/main/java/com/statsig/Statsig.java | 21 ++++++++++++ .../src/main/java/com/statsig/StatsigJNI.java | 3 ++ statsig-node/src/lib/statsig-generated.d.ts | 1 + statsig-node/src/statsig_napi.rs | 16 +++++++++ statsig-php/src/Statsig.php | 13 ++++++++ .../statsig_python_core.pyi | 3 ++ statsig-pyo3/src/statsig_base_py.rs | 31 +++++++++++++++++ statsig-rust/src/statsig.rs | 17 ++++++++-- 17 files changed, 221 insertions(+), 58 deletions(-) diff --git a/statsig-dotnet/src/Statsig/Statsig.cs b/statsig-dotnet/src/Statsig/Statsig.cs index 6477bd22e..f4c59df98 100644 --- a/statsig-dotnet/src/Statsig/Statsig.cs +++ b/statsig-dotnet/src/Statsig/Statsig.cs @@ -284,6 +284,30 @@ unsafe public Layer GetLayer(StatsigUser user, string layerName, EvaluationOptio } } + unsafe public Layer GetPrompt(StatsigUser user, string promptName, EvaluationOptions? options = null) + { + int nameLen = Encoding.UTF8.GetByteCount(promptName); + Span nameBytes = nameLen + 1 <= SpecNameStackThreshold ? stackalloc byte[nameLen + 1] : new byte[nameLen + 1]; + int written = Encoding.UTF8.GetBytes(promptName, nameBytes[..nameLen]); + nameBytes[written] = 0; + + string? optionsJson = options != null ? JsonConvert.SerializeObject(options) : null; + byte[]? optBytes = optionsJson != null ? Encoding.UTF8.GetBytes(optionsJson) : null; + + fixed (byte* optionsPtr = optBytes) + fixed (byte* promptNamePtr = nameBytes) + { + var jsonStringPtr = + StatsigFFI.statsig_get_prompt(_statsigRef, user.Reference, promptNamePtr, optionsPtr); + var jsonString = StatsigUtils.ReadStringFromPointer(jsonStringPtr); + if (jsonString == null) + { + return new Layer(string.Empty, _statsigRef, options); + } + return new Layer(jsonString, _statsigRef, options); + } + } + unsafe public void ManuallyLogLayerParameterExposure(StatsigUser user, string layerName, string parameterName) { int layerNameLen = Encoding.UTF8.GetByteCount(layerName); diff --git a/statsig-dotnet/src/Statsig/StatsigFFI.g.cs b/statsig-dotnet/src/Statsig/StatsigFFI.g.cs index 317cf76c1..f387ed3fd 100644 --- a/statsig-dotnet/src/Statsig/StatsigFFI.g.cs +++ b/statsig-dotnet/src/Statsig/StatsigFFI.g.cs @@ -133,6 +133,9 @@ internal static unsafe partial class StatsigFFI [DllImport(__DllName, EntryPoint = "statsig_get_layer", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern byte* statsig_get_layer(ulong statsig_ref, ulong user_ref, byte* layer_name, byte* options_json); + [DllImport(__DllName, EntryPoint = "statsig_get_prompt", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern byte* statsig_get_prompt(ulong statsig_ref, ulong user_ref, byte* prompt_name, byte* options_json); + [DllImport(__DllName, EntryPoint = "statsig_log_layer_param_exposure", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern void statsig_log_layer_param_exposure(ulong statsig_ref, byte* layer_json, byte* param_name); diff --git a/statsig-elixir/lib/statsig.ex b/statsig-elixir/lib/statsig.ex index aade42942..2b672c619 100644 --- a/statsig-elixir/lib/statsig.ex +++ b/statsig-elixir/lib/statsig.ex @@ -9,7 +9,7 @@ defmodule Statsig do def init({sdk_key, statsig_options}) do try do - instance = NativeBindings.new(sdk_key, statsig_options,get_system_info()) + instance = NativeBindings.new(sdk_key, statsig_options) {:ok, instance} rescue exception -> {:error, Exception.message(exception)} @@ -131,11 +131,11 @@ defmodule Statsig do end end - def get_client_init_response_as_string(statsig_user, options \\nil) do + def get_client_init_response_as_string(statsig_user) do try do instance = get_statsig_instance() - case NativeBindings.get_client_init_response_as_string(instance, statsig_user, options) do + case NativeBindings.get_client_init_response_as_string(instance, statsig_user) do {:error, e} -> {:error, e} response -> {:ok, response} end @@ -200,26 +200,4 @@ defmodule Statsig do exception -> {:error, Exception.message(exception)} end end - - def get_system_info do - try do - %{ - "os"=> :os.type() |> elem(0) |> Atom.to_string(), - "arch"=> :erlang.system_info(:system_architecture) |> List.to_string(), - "language_version"=> System.version() - } - rescue - _ -> %{ - "os"=> "unknown", - "arch"=> "unknown", - "language_version"=> "unknown" - } - catch - _, _ -> %{ - "os"=> "unknown", - "arch"=> "unknown", - "language_version"=> "unknown" - } - end - end end diff --git a/statsig-elixir/lib/statsig/native_bindings.ex b/statsig-elixir/lib/statsig/native_bindings.ex index c9ed1a3f2..44bbc8a95 100644 --- a/statsig-elixir/lib/statsig/native_bindings.ex +++ b/statsig-elixir/lib/statsig/native_bindings.ex @@ -14,7 +14,7 @@ defmodule Statsig.NativeBindings do "x86_64-unknown-linux-musl", "aarch64-unknown-linux-musl", ] - def new(_key, _options, _system_metadata), do: :erlang.nif_error(:nif_not_loaded) + def new(_key, _options), do: :erlang.nif_error(:nif_not_loaded) def initialize(_statsig), do: :erlang.nif_error(:nif_not_loaded) def check_gate(_statsig, _gate_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_feature_gate(_statsig, _gate_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) @@ -22,7 +22,7 @@ defmodule Statsig.NativeBindings do def get_experiment(_statsig, _experiment_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_layer(_statsig, _layer_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_prompt(_statsig, _prompt_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) - def get_client_init_response_as_string(_statsig, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) + def get_client_init_response_as_string(_statsig, _statsig_user), do: :erlang.nif_error(:nif_not_loaded) def log_event(_statsig, _statsig_user, _event_name,_value, _metadata), do: :erlang.nif_error(:nif_not_loaded) def log_event_with_number(_statsig, _statsig_user, _event_name,_value, _metadata), do: :erlang.nif_error(:nif_not_loaded) def flush(_statsig), do: :erlang.nif_error(:nif_not_loaded) diff --git a/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs b/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs index edfb3ac6d..cf1c812fd 100644 --- a/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs +++ b/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs @@ -1,7 +1,5 @@ use rustler::{Env, Error, ResourceArc, Term}; -use statsig_rust::{ - statsig_metadata::StatsigMetadata, statsig_types::Layer as LayerActual, Statsig, -}; +use statsig_rust::{statsig_types::Layer as LayerActual, Statsig}; use std::{ collections::HashMap, sync::{Arc, RwLock}, @@ -10,8 +8,8 @@ use std::{ use crate::{ statsig_options_nfi::StatsigOptions, statsig_types_nfi::{ - AllowedPrimitive, ClientInitResponseOptions, DynamicConfig, DynamicConfigEvaluationOptions, - Experiment, ExperimentEvaluationOptions, FeatureGate, FeatureGateEvaluationOptions, + AllowedPrimitive, DynamicConfig, DynamicConfigEvaluationOptions, Experiment, + ExperimentEvaluationOptions, FeatureGate, FeatureGateEvaluationOptions, LayerEvaluationOptions, }, statsig_user_nfi::StatsigUser, @@ -45,9 +43,7 @@ impl LayerResource { pub fn new( sdk_key: String, options: Option, - system_metadata: HashMap, ) -> Result, Error> { - update_metadata(system_metadata); let statsig = Statsig::new(&sdk_key, options.map(|op| Arc::new(op.into()))); Ok(ResourceArc::new(StatsigResource { statsig_core: RwLock::new(Arc::new(statsig)), @@ -230,17 +226,10 @@ pub fn log_event_with_number( pub fn get_client_init_response_as_string( statsig: ResourceArc, statsig_user: StatsigUser, - options: Option, ) -> Result { match statsig.statsig_core.read() { Ok(read_guard) => { - let response = match options { - Some(o) => read_guard.get_client_init_response_with_options_as_string( - &statsig_user.into(), - &o.into(), - ), - None => read_guard.get_client_init_response_as_string(&statsig_user.into()), - }; + let response = read_guard.get_client_init_response_as_string(&statsig_user.into()); Ok(response) } Err(_) => Err(Error::RaiseAtom("Failed to get Statsig")), @@ -332,18 +321,4 @@ pub fn layer_get_group_name(layer: ResourceArc) -> Result) { - let unknown = "unknown".to_string(); - let os = system_metadata.get("os").unwrap_or(&unknown); - let arch = system_metadata.get("arch").unwrap_or(&unknown); - let language_version = system_metadata.get("language_version").unwrap_or(&unknown); - StatsigMetadata::update_values( - "statsig-server-core-elixir".to_owned(), - os.to_string(), - arch.to_string(), - language_version.to_string(), - ); -} - rustler::init!("Elixir.Statsig.NativeBindings", load = load); diff --git a/statsig-ffi/include/statsig_ffi.h b/statsig-ffi/include/statsig_ffi.h index e9bb2235c..8ef98f0df 100644 --- a/statsig-ffi/include/statsig_ffi.h +++ b/statsig-ffi/include/statsig_ffi.h @@ -190,6 +190,11 @@ char *statsig_get_layer(uint64_t statsig_ref, const char *layer_name, const char *options_json); +char *statsig_get_prompt(uint64_t statsig_ref, + uint64_t user_ref, + const char *prompt_name, + const char *options_json); + void statsig_log_layer_param_exposure(uint64_t statsig_ref, const char *layer_json, const char *param_name); diff --git a/statsig-ffi/src/jni/statsig_jni.rs b/statsig-ffi/src/jni/statsig_jni.rs index ba2549762..857000dc7 100644 --- a/statsig-ffi/src/jni/statsig_jni.rs +++ b/statsig-ffi/src/jni/statsig_jni.rs @@ -447,6 +447,33 @@ pub extern "system" fn Java_com_statsig_StatsigJNI_statsigGetLayer( serialize_json_to_jstring(&mut env, &result) } +#[no_mangle] +pub extern "system" fn Java_com_statsig_StatsigJNI_statsigGetPrompt( + mut env: JNIEnv, + _class: jclass, + statsig_ref: jlong, + user_ref: jlong, + prompt_name: JString, + options: JObject, +) -> jstring { + let statsig = get_instance_or_return_c!(Statsig, &(statsig_ref as u64), std::ptr::null_mut()); + let user = get_instance_or_return_c!(StatsigUser, &(user_ref as u64), std::ptr::null_mut()); + + let prompt_name: String = match env.get_string(&prompt_name) { + Ok(s) => s.into(), + Err(_) => return std::ptr::null_mut(), + }; + + let options = convert_java_get_layer_options_to_rust(&mut env, options); + + let result = match options { + Some(options) => statsig.get_prompt_with_options(user.as_ref(), &prompt_name, options), + None => statsig.get_prompt(user.as_ref(), &prompt_name), + }; + + serialize_json_to_jstring(&mut env, &result) +} + #[no_mangle] pub extern "system" fn Java_com_statsig_StatsigJNI_statsigGetFieldsNeededForLayer( mut env: JNIEnv, diff --git a/statsig-ffi/src/statsig_c.rs b/statsig-ffi/src/statsig_c.rs index c7c2d61a8..61f50ff93 100644 --- a/statsig-ffi/src/statsig_c.rs +++ b/statsig-ffi/src/statsig_c.rs @@ -829,6 +829,32 @@ pub extern "C" fn statsig_get_layer( string_to_c_char(result) } +#[no_mangle] +pub extern "C" fn statsig_get_prompt( + statsig_ref: u64, + user_ref: u64, + prompt_name: *const c_char, + options_json: *const c_char, +) -> *mut c_char { + let statsig = get_instance_or_return_c!(Statsig, &statsig_ref, null_mut()); + let user = get_instance_or_return_c!(StatsigUser, &user_ref, null_mut()); + let prompt_name = unwrap_or_return!(c_char_to_string(prompt_name), null_mut()); + + let layer = match c_char_to_string(options_json) { + Some(opts) => match serde_json::from_str::(&opts) { + Ok(options) => statsig.get_prompt_with_options(&user, &prompt_name, options), + Err(e) => { + log_e!(TAG, "Failed to parse options: {}", e); + return null_mut(); + } + }, + None => statsig.get_prompt(&user, &prompt_name), + }; + + let result = json!(layer).to_string(); + string_to_c_char(result) +} + #[no_mangle] pub extern "C" fn statsig_log_layer_param_exposure( statsig_ref: u64, diff --git a/statsig-go/src/statsig.go b/statsig-go/src/statsig.go index 7de18ffaa..7d0df9dc8 100644 --- a/statsig-go/src/statsig.go +++ b/statsig-go/src/statsig.go @@ -201,6 +201,30 @@ func (s *Statsig) GetLayer(user StatsigUser, layerName string, layerOptions *Get } +func (s *Statsig) GetPrompt(user StatsigUser, promptName string, layerOptions *GetLayerOptions) Layer { + var layer Layer + + if layerOptions == nil { + layerOptions = &GetLayerOptions{} + } + + layerJson := C.statsig_get_prompt(C.uint64_t(s.InnerRef), C.uint64_t(user.innerRef), C.CString(promptName), C.CString(utils.ConvertJSONToString(layerOptions))) + + if layerJson != nil { + err := json.Unmarshal([]byte(C.GoString(layerJson)), &layer) + if err != nil { + return Layer{} + } + + layer.setStatsigInstance(s) + layer.setDisableExposureLogging(layerOptions != nil && layerOptions.DisableExposureLogging) + layer.setRawResult(C.GoString(layerJson)) + } + + return layer + +} + func (s *Statsig) ManuallyLogLayerParameterExposure(user StatsigUser, layerName string, paramName string) { C.statsig_manually_log_layer_parameter_exposure(C.uint64_t(s.InnerRef), C.uint64_t(user.innerRef), C.CString(layerName), C.CString(paramName)) } diff --git a/statsig-java/src/main/java/com/statsig/Statsig.java b/statsig-java/src/main/java/com/statsig/Statsig.java index de9e686b6..c2205c28a 100644 --- a/statsig-java/src/main/java/com/statsig/Statsig.java +++ b/statsig-java/src/main/java/com/statsig/Statsig.java @@ -207,6 +207,27 @@ public Layer getLayer(StatsigUser user, String layerName, GetLayerOptions option return layer; } + public Layer getPrompt(StatsigUser user, String promptName) { + String layerJson = StatsigJNI.statsigGetPrompt(ref, user.getRef(), promptName, null); + Layer layer = JacksonUtil.fromJsonWithRawJson(layerJson, Layer.class); + if (layer != null) { + // Set the Statsig reference in the Layer instance + layer.setStatsigInstance(this); + } + return layer; + } + + public Layer getPrompt(StatsigUser user, String promptName, GetLayerOptions options) { + String layerJson = StatsigJNI.statsigGetPrompt(ref, user.getRef(), promptName, options); + Layer layer = JacksonUtil.fromJsonWithRawJson(layerJson, Layer.class); + if (layer != null) { + // Set the Statsig reference in the Layer instance + layer.setStatsigInstance(this); + layer.setDisableExposureLogging(options != null && options.disableExposureLogging); + } + return layer; + } + public void manuallyLogLayerParamExposure(StatsigUser user, String layerName, String param) { StatsigJNI.statsigManuallyLogLayerParamExposure(ref, user.getRef(), layerName, param); } diff --git a/statsig-java/src/main/java/com/statsig/StatsigJNI.java b/statsig-java/src/main/java/com/statsig/StatsigJNI.java index 356db6634..87e731a68 100644 --- a/statsig-java/src/main/java/com/statsig/StatsigJNI.java +++ b/statsig-java/src/main/java/com/statsig/StatsigJNI.java @@ -80,6 +80,9 @@ public static native String statsigGetFieldsNeededForDynamicConfig( public static native String statsigGetLayer( long statsigRef, long userRef, String layerName, GetLayerOptions options); + public static native String statsigGetPrompt( + long statsigRef, long userRef, String promptName, GetLayerOptions options); + public static native void statsigManuallyLogLayerParamExposure( long statsigRef, long userRef, String layerName, String param); diff --git a/statsig-node/src/lib/statsig-generated.d.ts b/statsig-node/src/lib/statsig-generated.d.ts index c7c3c8ce5..110231e91 100644 --- a/statsig-node/src/lib/statsig-generated.d.ts +++ b/statsig-node/src/lib/statsig-generated.d.ts @@ -64,6 +64,7 @@ export declare class StatsigNapiInternal { getExperimentByGroupName(experimentName: string, groupName: string): Experiment getFieldsNeededForExperiment(experimentName: string): Array getLayer(user: StatsigUser, layerName: string, options?: LayerEvaluationOptions | undefined | null): Layer + getPrompt(user: StatsigUser, promptName: string, options?: LayerEvaluationOptions | undefined | null): Layer getFieldsNeededForLayer(layerName: string): Array identify(user: StatsigUser): void getParameterStore(user: StatsigUser, parameterStoreName: string, options?: ParameterStoreEvaluationOptions | undefined | null): ParameterStore diff --git a/statsig-node/src/statsig_napi.rs b/statsig-node/src/statsig_napi.rs index 959bb1afc..4b75a914f 100644 --- a/statsig-node/src/statsig_napi.rs +++ b/statsig-node/src/statsig_napi.rs @@ -254,6 +254,22 @@ impl StatsigNapiInternal { .into() } + #[napi] + pub fn get_prompt( + &self, + user: &StatsigUser, + prompt_name: String, + options: Option, + ) -> Layer { + self.inner + .get_prompt_with_options( + user.as_inner(), + &prompt_name, + options.map(|opts| opts.into()).unwrap_or_default(), + ) + .into() + } + #[napi] pub fn get_fields_needed_for_layer(&self, layer_name: String) -> Vec { self.inner.get_fields_needed_for_layer(layer_name.as_str()) diff --git a/statsig-php/src/Statsig.php b/statsig-php/src/Statsig.php index 53c4e33eb..83a33d537 100644 --- a/statsig-php/src/Statsig.php +++ b/statsig-php/src/Statsig.php @@ -184,6 +184,19 @@ public function getLayer(StatsigUser $user, string $name, ?array $options = null return new Layer($raw_result, $this->__ref); } + public function getPrompt(StatsigUser $user, string $name, ?array $options = null): Layer + { + $ptr = StatsigFFI::get()->statsig_get_prompt( + $this->__ref, + $user->__ref, + $name, + encode_or_null($options) + ); + + $raw_result = StatsigFFI::takeString($ptr); + return new Layer($raw_result, $this->__ref); + } + public function manuallyLogLayerParameterExposure(StatsigUser $user, string $layer_name, string $param_name): void { StatsigFFI::get()->statsig_manually_log_layer_parameter_exposure( diff --git a/statsig-pyo3/py_src/statsig_python_core/statsig_python_core.pyi b/statsig-pyo3/py_src/statsig_python_core/statsig_python_core.pyi index b43222a69..db41eaba1 100644 --- a/statsig-pyo3/py_src/statsig_python_core/statsig_python_core.pyi +++ b/statsig-pyo3/py_src/statsig_python_core/statsig_python_core.pyi @@ -223,6 +223,9 @@ class StatsigBasePy: def get_layer(self, user:StatsigUser, name:builtins.str, options:typing.Optional[LayerEvaluationOptions]=None) -> Layer: ... + def get_prompt(self, user:StatsigUser, name:builtins.str, options:typing.Optional[LayerEvaluationOptions]=None) -> Layer: + ... + def manually_log_layer_parameter_exposure(self, user:StatsigUser, name:builtins.str, param_name:builtins.str) -> None: ... diff --git a/statsig-pyo3/src/statsig_base_py.rs b/statsig-pyo3/src/statsig_base_py.rs index bb47a4afd..c2c5bfa87 100644 --- a/statsig-pyo3/src/statsig_base_py.rs +++ b/statsig-pyo3/src/statsig_base_py.rs @@ -373,6 +373,37 @@ impl StatsigBasePy { } } + #[pyo3(signature = (user, name, options=None))] + pub fn get_prompt( + &self, + user: &StatsigUserPy, + name: &str, + options: Option, + py: Python, + ) -> LayerPy { + let mut options_actual = options + .as_ref() + .map_or(LayerEvaluationOptions::default(), |o| o.into()); + + options_actual.user_persisted_values = options + .and_then(|o| o.user_persisted_values) + .and_then(|v| extract_user_persisted_values(py, name, v)); + + let layer = self + .inner + .get_prompt_with_options(&user.inner, name, options_actual); + + LayerPy { + name: layer.name.clone(), + rule_id: layer.rule_id.clone(), + group_name: layer.group_name.clone(), + allocated_experiment_name: layer.allocated_experiment_name.clone(), + value: map_to_py_dict(py, &layer.__value), + details: layer.details.clone().into(), + inner: layer, + } + } + #[pyo3(signature = (user, name, param_name))] pub fn manually_log_layer_parameter_exposure( &self, diff --git a/statsig-rust/src/statsig.rs b/statsig-rust/src/statsig.rs index db310798b..c3fe54af8 100644 --- a/statsig-rust/src/statsig.rs +++ b/statsig-rust/src/statsig.rs @@ -923,7 +923,7 @@ impl Statsig { } } - pub fn get_parameter_store(&self, parameter_store_name: &str) -> ParameterStore { + pub fn get_parameter_store(&self, parameter_store_name: &str) -> ParameterStore<'_> { self.get_parameter_store_with_options( parameter_store_name, ParameterStoreEvaluationOptions::default(), @@ -934,7 +934,7 @@ impl Statsig { &self, parameter_store_name: &str, options: ParameterStoreEvaluationOptions, - ) -> ParameterStore { + ) -> ParameterStore<'_> { self.event_logger .increment_non_exposure_checks(parameter_store_name); @@ -1688,6 +1688,19 @@ impl Statsig { self.get_layer_impl(user_internal, layer_name, options) } + pub fn get_prompt(&self, user: &StatsigUser, prompt_name: &str) -> Layer { + self.get_layer(user, prompt_name) + } + + pub fn get_prompt_with_options( + &self, + user: &StatsigUser, + prompt_name: &str, + options: LayerEvaluationOptions, + ) -> Layer { + self.get_layer_with_options(user, prompt_name, options) + } + pub fn manually_log_layer_parameter_exposure( &self, user: &StatsigUser, From 5fb72a9da6a954126537a55564a5093c2fe5221a Mon Sep 17 00:00:00 2001 From: Weihao Ding <158090588+weihao-statsig@users.noreply.github.com> Date: Wed, 20 Aug 2025 13:21:26 -0700 Subject: [PATCH 14/23] [cherrypick][releases/0.7.4-rc.2508191829] fix: add github env in release gh workflow (#1682) [auto][cherrypick] e885640533a63de3b5b22364c2bf349619e1eb7d fix: add github env in release gh workflow (#1681) --- .github/workflows/create_release.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml index 4d36714fc..de7f6c2ce 100644 --- a/.github/workflows/create_release.yml +++ b/.github/workflows/create_release.yml @@ -6,6 +6,12 @@ on: tags: - 'v*.*.*' +env: + # GH Octokit (Kong App) + GH_APP_ID: '229901' + GH_APP_INSTALLATION_ID: '36921303' + GH_APP_PRIVATE_KEY: ${{ secrets.KONG_APP_KEY_V2 }} + jobs: create-release: runs-on: ubuntu-latest From 860acdaa17f7ba3bcd2620319c8cf5e80245d8da Mon Sep 17 00:00:00 2001 From: "statsig-kong[bot]" Date: Wed, 20 Aug 2025 13:34:58 -0700 Subject: [PATCH 15/23] Bot: Updated File Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a4f5c7f41..685f5c406 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ exclude = [ [workspace.package] edition = "2021" license = "ISC" -version = "0.7.4-rc.2508191829" +version = "0.7.4-rc.2508202034" homepage = "https://statsig.com/" authors = ["Statsig", "Daniel Loomb "] readme = "README.md" From 96d285c834441a8421c2290d940f12430306dfee Mon Sep 17 00:00:00 2001 From: "statsig-kong[bot]" Date: Wed, 20 Aug 2025 20:36:47 +0000 Subject: [PATCH 16/23] Bot: Version synchronized in 18 files --- Cargo.lock | 12 ++++++------ examples/rust/mem-bench/Cargo.lock | 2 +- statsig-dotnet/Directory.Build.props | 2 +- statsig-elixir/mix.exs | 2 +- statsig-go/cmd/post-install/main.go | 2 +- statsig-java/gradle.properties | 2 +- statsig-node/npm/aarch64-apple-darwin.package.json | 2 +- .../npm/aarch64-unknown-linux-gnu.package.json | 2 +- .../npm/aarch64-unknown-linux-musl.package.json | 2 +- statsig-node/npm/i686-pc-windows-msvc.package.json | 2 +- statsig-node/npm/x86_64-apple-darwin.package.json | 2 +- statsig-node/npm/x86_64-pc-windows-msvc.package.json | 2 +- .../npm/x86_64-unknown-linux-gnu.package.json | 2 +- .../npm/x86_64-unknown-linux-musl.package.json | 2 +- statsig-node/package.json | 2 +- statsig-php/post-install.php | 2 +- statsig-rust/Cargo.toml | 2 +- statsig-rust/src/statsig_metadata.rs | 2 +- 18 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0505ca4f2..cc52bc629 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2373,7 +2373,7 @@ dependencies = [ [[package]] name = "sigstat-grpc" -version = "0.7.4-rc.2508191829" +version = "0.7.4-rc.2508202034" dependencies = [ "async-trait", "chrono", @@ -2437,7 +2437,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statsig-node" -version = "0.7.4-rc.2508191829" +version = "0.7.4-rc.2508202034" dependencies = [ "async-trait", "napi", @@ -2450,7 +2450,7 @@ dependencies = [ [[package]] name = "statsig-pyo3" -version = "0.7.4-rc.2508191829" +version = "0.7.4-rc.2508202034" dependencies = [ "async-trait", "lazy_static", @@ -2464,7 +2464,7 @@ dependencies = [ [[package]] name = "statsig-rust" -version = "0.7.4-rc.2508191829" +version = "0.7.4-rc.2508202034" dependencies = [ "ahash", "arc-swap", @@ -2504,7 +2504,7 @@ dependencies = [ [[package]] name = "statsig_elixir" -version = "0.7.4-rc.2508191829" +version = "0.7.4-rc.2508202034" dependencies = [ "parking_lot", "rustler", @@ -2516,7 +2516,7 @@ dependencies = [ [[package]] name = "statsig_ffi" -version = "0.7.4-rc.2508191829" +version = "0.7.4-rc.2508202034" dependencies = [ "async-trait", "cbindgen", diff --git a/examples/rust/mem-bench/Cargo.lock b/examples/rust/mem-bench/Cargo.lock index a7498b42a..f0243b644 100644 --- a/examples/rust/mem-bench/Cargo.lock +++ b/examples/rust/mem-bench/Cargo.lock @@ -1815,7 +1815,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statsig-rust" -version = "0.7.4-rc.2508191829" +version = "0.7.4-rc.2508202034" dependencies = [ "ahash", "arc-swap", diff --git a/statsig-dotnet/Directory.Build.props b/statsig-dotnet/Directory.Build.props index 6b496b977..228d65650 100644 --- a/statsig-dotnet/Directory.Build.props +++ b/statsig-dotnet/Directory.Build.props @@ -1,6 +1,6 @@ - 0.7.4-rc.2508191829 + 0.7.4-rc.2508202034 ISC \ No newline at end of file diff --git a/statsig-elixir/mix.exs b/statsig-elixir/mix.exs index da370c170..a11f3e77a 100644 --- a/statsig-elixir/mix.exs +++ b/statsig-elixir/mix.exs @@ -4,7 +4,7 @@ defmodule Statsigelixir.MixProject do def project do [ app: :statsig_elixir, - version: "0.7.4-rc.2508191829", + version: "0.7.4-rc.2508202034", elixir: "~> 1.0", start_permanent: Mix.env() == :prod, description: description(), diff --git a/statsig-go/cmd/post-install/main.go b/statsig-go/cmd/post-install/main.go index fe6ce131d..f478641f4 100644 --- a/statsig-go/cmd/post-install/main.go +++ b/statsig-go/cmd/post-install/main.go @@ -12,7 +12,7 @@ import ( ) const ( - version = "0.7.4-rc.2508191829" + version = "0.7.4-rc.2508202034" ) var output_dir string diff --git a/statsig-java/gradle.properties b/statsig-java/gradle.properties index 5feadf140..a2d5f712f 100644 --- a/statsig-java/gradle.properties +++ b/statsig-java/gradle.properties @@ -1 +1 @@ -version=0.7.4-rc.2508191829 \ No newline at end of file +version=0.7.4-rc.2508202034 \ No newline at end of file diff --git a/statsig-node/npm/aarch64-apple-darwin.package.json b/statsig-node/npm/aarch64-apple-darwin.package.json index 4684be4ac..1f3cdf335 100644 --- a/statsig-node/npm/aarch64-apple-darwin.package.json +++ b/statsig-node/npm/aarch64-apple-darwin.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-darwin-arm64", - "version": "0.7.4-rc.2508191829", + "version": "0.7.4-rc.2508202034", "os": [ "darwin" ], diff --git a/statsig-node/npm/aarch64-unknown-linux-gnu.package.json b/statsig-node/npm/aarch64-unknown-linux-gnu.package.json index 3dd834e41..69e0afd46 100644 --- a/statsig-node/npm/aarch64-unknown-linux-gnu.package.json +++ b/statsig-node/npm/aarch64-unknown-linux-gnu.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-arm64-gnu", - "version": "0.7.4-rc.2508191829", + "version": "0.7.4-rc.2508202034", "os": [ "linux" ], diff --git a/statsig-node/npm/aarch64-unknown-linux-musl.package.json b/statsig-node/npm/aarch64-unknown-linux-musl.package.json index aa5edfea0..ac46f482b 100644 --- a/statsig-node/npm/aarch64-unknown-linux-musl.package.json +++ b/statsig-node/npm/aarch64-unknown-linux-musl.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-arm64-musl", - "version": "0.7.4-rc.2508191829", + "version": "0.7.4-rc.2508202034", "os": [ "linux" ], diff --git a/statsig-node/npm/i686-pc-windows-msvc.package.json b/statsig-node/npm/i686-pc-windows-msvc.package.json index 03f363526..bd6ee1636 100644 --- a/statsig-node/npm/i686-pc-windows-msvc.package.json +++ b/statsig-node/npm/i686-pc-windows-msvc.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-win32-ia32-msvc", - "version": "0.7.4-rc.2508191829", + "version": "0.7.4-rc.2508202034", "os": [ "win32" ], diff --git a/statsig-node/npm/x86_64-apple-darwin.package.json b/statsig-node/npm/x86_64-apple-darwin.package.json index e7ca36096..f6ff18254 100644 --- a/statsig-node/npm/x86_64-apple-darwin.package.json +++ b/statsig-node/npm/x86_64-apple-darwin.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-darwin-x64", - "version": "0.7.4-rc.2508191829", + "version": "0.7.4-rc.2508202034", "os": [ "darwin" ], diff --git a/statsig-node/npm/x86_64-pc-windows-msvc.package.json b/statsig-node/npm/x86_64-pc-windows-msvc.package.json index f1786ba42..a87b0ff90 100644 --- a/statsig-node/npm/x86_64-pc-windows-msvc.package.json +++ b/statsig-node/npm/x86_64-pc-windows-msvc.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-win32-x64-msvc", - "version": "0.7.4-rc.2508191829", + "version": "0.7.4-rc.2508202034", "os": [ "win32" ], diff --git a/statsig-node/npm/x86_64-unknown-linux-gnu.package.json b/statsig-node/npm/x86_64-unknown-linux-gnu.package.json index f59a8e24b..15ecc7fb3 100644 --- a/statsig-node/npm/x86_64-unknown-linux-gnu.package.json +++ b/statsig-node/npm/x86_64-unknown-linux-gnu.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-x64-gnu", - "version": "0.7.4-rc.2508191829", + "version": "0.7.4-rc.2508202034", "os": [ "linux" ], diff --git a/statsig-node/npm/x86_64-unknown-linux-musl.package.json b/statsig-node/npm/x86_64-unknown-linux-musl.package.json index b4deb88a1..461b68596 100644 --- a/statsig-node/npm/x86_64-unknown-linux-musl.package.json +++ b/statsig-node/npm/x86_64-unknown-linux-musl.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-x64-musl", - "version": "0.7.4-rc.2508191829", + "version": "0.7.4-rc.2508202034", "os": [ "linux" ], diff --git a/statsig-node/package.json b/statsig-node/package.json index 5739aff66..e196847ef 100644 --- a/statsig-node/package.json +++ b/statsig-node/package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core", - "version": "0.7.4-rc.2508191829", + "version": "0.7.4-rc.2508202034", "main": "index.js", "scripts": { "test": "jest --colors" diff --git a/statsig-php/post-install.php b/statsig-php/post-install.php index 2a1bb8383..2802cfb69 100644 --- a/statsig-php/post-install.php +++ b/statsig-php/post-install.php @@ -1,7 +1,7 @@ Self { Self { - sdk_version: "0.7.4-rc.2508191829".to_string(), + sdk_version: "0.7.4-rc.2508202034".to_string(), sdk_type: "statsig-server-core".to_string(), session_id: Uuid::new_v4().to_string(), os: None, From 26d41d48e613206117c0e4c9dde2cd75a33d6510 Mon Sep 17 00:00:00 2001 From: Xin Li <137219293+xinlili-statsig@users.noreply.github.com> Date: Wed, 20 Aug 2025 14:50:14 -0700 Subject: [PATCH 17/23] [cherrypick][releases/0.7.4-rc.2508202034] update elixir build command (#1687) [auto][cherrypick] d72d5fbe61b0031cf801f3f63acef8f18b91782e update elixir build command (#1622) --- cli/src/commands/builders/elixir-builder.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cli/src/commands/builders/elixir-builder.ts b/cli/src/commands/builders/elixir-builder.ts index 72ebde17d..47cdcc8cf 100644 --- a/cli/src/commands/builders/elixir-builder.ts +++ b/cli/src/commands/builders/elixir-builder.ts @@ -7,12 +7,13 @@ import { Log } from '@/utils/terminal_utils.js'; const NIF_VERSION = "nif-2.15" export function buildElixir(options: BuilderOptions) { options.subProject = 'statsig_elixir'; + let RUSTFLAGS = "" if (options.os == 'windows') { - // options.envSetupForBuild = 'set RUSTFLAGS="-C target-cpu=native" &&'; + // RUSTFLAGS = 'RUSTFLAGS="-C target-cpu=native"'; } else { - options.envSetupForBuild = 'RUSTFLAGS="-C target-feature=-crt-static"'; + RUSTFLAGS = 'RUSTFLAGS="-C target-feature=-crt-static"'; } - let buildcommand = `cargo build --release -p statsig_elixir --target-dir target/${options.target}` + let buildcommand = `${RUSTFLAGS} cargo build --release -p statsig_elixir --target-dir target/${options.target}` execAndLogSync(buildcommand); let binPath = `target/${options.target}/release`; From af5d1d1dfae8b8e364cf3fc1ab8063bddc8e0c76 Mon Sep 17 00:00:00 2001 From: Xin Li <137219293+xinlili-statsig@users.noreply.github.com> Date: Wed, 20 Aug 2025 15:03:24 -0700 Subject: [PATCH 18/23] [cherrypick][releases/0.7.4-rc.2508202034] chore(elixir): "get_config" to "get_dynamic_config" (#1688) [auto][cherrypick] ba784a2b514df73567fed233c8376731d92ae501 chore(elixir): "get_config" to "get_dynamic_config" (#1679) --- statsig-elixir/lib/statsig.ex | 32 ++++++++++++++--- statsig-elixir/lib/statsig/native_bindings.ex | 6 ++-- .../native/statsig_elixir/src/statsig_nfi.rs | 35 ++++++++++++++++--- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/statsig-elixir/lib/statsig.ex b/statsig-elixir/lib/statsig.ex index 2b672c619..0bce1dd9b 100644 --- a/statsig-elixir/lib/statsig.ex +++ b/statsig-elixir/lib/statsig.ex @@ -9,7 +9,7 @@ defmodule Statsig do def init({sdk_key, statsig_options}) do try do - instance = NativeBindings.new(sdk_key, statsig_options) + instance = NativeBindings.new(sdk_key, statsig_options,get_system_info()) {:ok, instance} rescue exception -> {:error, Exception.message(exception)} @@ -68,11 +68,11 @@ defmodule Statsig do end end - def get_config(config_name, statsig_user, options \\nil) do + def get_dynamic_config(config_name, statsig_user, options \\nil) do try do instance = get_statsig_instance() - case NativeBindings.get_config(instance, config_name, statsig_user, options) do + case NativeBindings.get_dynamic_config(instance, config_name, statsig_user, options) do {:error, e} -> {:error, e} config -> {:ok, config} end @@ -131,11 +131,11 @@ defmodule Statsig do end end - def get_client_init_response_as_string(statsig_user) do + def get_client_init_response_as_string(statsig_user, options \\nil) do try do instance = get_statsig_instance() - case NativeBindings.get_client_init_response_as_string(instance, statsig_user) do + case NativeBindings.get_client_init_response_as_string(instance, statsig_user, options) do {:error, e} -> {:error, e} response -> {:ok, response} end @@ -200,4 +200,26 @@ defmodule Statsig do exception -> {:error, Exception.message(exception)} end end + + def get_system_info do + try do + %{ + "os"=> :os.type() |> elem(0) |> Atom.to_string(), + "arch"=> :erlang.system_info(:system_architecture) |> List.to_string(), + "language_version"=> System.version() + } + rescue + _ -> %{ + "os"=> "unknown", + "arch"=> "unknown", + "language_version"=> "unknown" + } + catch + _, _ -> %{ + "os"=> "unknown", + "arch"=> "unknown", + "language_version"=> "unknown" + } + end + end end diff --git a/statsig-elixir/lib/statsig/native_bindings.ex b/statsig-elixir/lib/statsig/native_bindings.ex index 44bbc8a95..d3b2bae1d 100644 --- a/statsig-elixir/lib/statsig/native_bindings.ex +++ b/statsig-elixir/lib/statsig/native_bindings.ex @@ -14,15 +14,15 @@ defmodule Statsig.NativeBindings do "x86_64-unknown-linux-musl", "aarch64-unknown-linux-musl", ] - def new(_key, _options), do: :erlang.nif_error(:nif_not_loaded) + def new(_key, _options, _system_metadata), do: :erlang.nif_error(:nif_not_loaded) def initialize(_statsig), do: :erlang.nif_error(:nif_not_loaded) def check_gate(_statsig, _gate_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_feature_gate(_statsig, _gate_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) - def get_config(_statsig, _config_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) + def get_dynamic_config(_statsig, _config_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_experiment(_statsig, _experiment_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_layer(_statsig, _layer_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def get_prompt(_statsig, _prompt_name, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) - def get_client_init_response_as_string(_statsig, _statsig_user), do: :erlang.nif_error(:nif_not_loaded) + def get_client_init_response_as_string(_statsig, _statsig_user, _options), do: :erlang.nif_error(:nif_not_loaded) def log_event(_statsig, _statsig_user, _event_name,_value, _metadata), do: :erlang.nif_error(:nif_not_loaded) def log_event_with_number(_statsig, _statsig_user, _event_name,_value, _metadata), do: :erlang.nif_error(:nif_not_loaded) def flush(_statsig), do: :erlang.nif_error(:nif_not_loaded) diff --git a/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs b/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs index cf1c812fd..37822777b 100644 --- a/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs +++ b/statsig-elixir/native/statsig_elixir/src/statsig_nfi.rs @@ -1,5 +1,7 @@ use rustler::{Env, Error, ResourceArc, Term}; -use statsig_rust::{statsig_types::Layer as LayerActual, Statsig}; +use statsig_rust::{ + statsig_metadata::StatsigMetadata, statsig_types::Layer as LayerActual, Statsig, +}; use std::{ collections::HashMap, sync::{Arc, RwLock}, @@ -8,8 +10,8 @@ use std::{ use crate::{ statsig_options_nfi::StatsigOptions, statsig_types_nfi::{ - AllowedPrimitive, DynamicConfig, DynamicConfigEvaluationOptions, Experiment, - ExperimentEvaluationOptions, FeatureGate, FeatureGateEvaluationOptions, + AllowedPrimitive, ClientInitResponseOptions, DynamicConfig, DynamicConfigEvaluationOptions, + Experiment, ExperimentEvaluationOptions, FeatureGate, FeatureGateEvaluationOptions, LayerEvaluationOptions, }, statsig_user_nfi::StatsigUser, @@ -43,7 +45,9 @@ impl LayerResource { pub fn new( sdk_key: String, options: Option, + system_metadata: HashMap, ) -> Result, Error> { + update_metadata(system_metadata); let statsig = Statsig::new(&sdk_key, options.map(|op| Arc::new(op.into()))); Ok(ResourceArc::new(StatsigResource { statsig_core: RwLock::new(Arc::new(statsig)), @@ -106,7 +110,7 @@ pub fn check_gate( } #[rustler::nif] -pub fn get_config( +pub fn get_dynamic_config( statsig: ResourceArc, config_name: &str, statsig_user: StatsigUser, @@ -226,10 +230,17 @@ pub fn log_event_with_number( pub fn get_client_init_response_as_string( statsig: ResourceArc, statsig_user: StatsigUser, + options: Option, ) -> Result { match statsig.statsig_core.read() { Ok(read_guard) => { - let response = read_guard.get_client_init_response_as_string(&statsig_user.into()); + let response = match options { + Some(o) => read_guard.get_client_init_response_with_options_as_string( + &statsig_user.into(), + &o.into(), + ), + None => read_guard.get_client_init_response_as_string(&statsig_user.into()), + }; Ok(response) } Err(_) => Err(Error::RaiseAtom("Failed to get Statsig")), @@ -321,4 +332,18 @@ pub fn layer_get_group_name(layer: ResourceArc) -> Result) { + let unknown = "unknown".to_string(); + let os = system_metadata.get("os").unwrap_or(&unknown); + let arch = system_metadata.get("arch").unwrap_or(&unknown); + let language_version = system_metadata.get("language_version").unwrap_or(&unknown); + StatsigMetadata::update_values( + "statsig-server-core-elixir".to_owned(), + os.to_string(), + arch.to_string(), + language_version.to_string(), + ); +} + rustler::init!("Elixir.Statsig.NativeBindings", load = load); From 6b349b019b404bad37ea7a0d55c9aafc6f132ce6 Mon Sep 17 00:00:00 2001 From: "statsig-kong[bot]" Date: Wed, 20 Aug 2025 15:04:02 -0700 Subject: [PATCH 19/23] Bot: Updated File Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 685f5c406..ad9ae18e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ exclude = [ [workspace.package] edition = "2021" license = "ISC" -version = "0.7.4-rc.2508202034" +version = "0.7.4-rc.2508202203" homepage = "https://statsig.com/" authors = ["Statsig", "Daniel Loomb "] readme = "README.md" From 8becbbbc7cfc7e413f4bc19d95cf390525432c65 Mon Sep 17 00:00:00 2001 From: "statsig-kong[bot]" Date: Wed, 20 Aug 2025 22:05:57 +0000 Subject: [PATCH 20/23] Bot: Version synchronized in 18 files --- Cargo.lock | 12 ++++++------ examples/rust/mem-bench/Cargo.lock | 2 +- statsig-dotnet/Directory.Build.props | 2 +- statsig-elixir/mix.exs | 2 +- statsig-go/cmd/post-install/main.go | 2 +- statsig-java/gradle.properties | 2 +- statsig-node/npm/aarch64-apple-darwin.package.json | 2 +- .../npm/aarch64-unknown-linux-gnu.package.json | 2 +- .../npm/aarch64-unknown-linux-musl.package.json | 2 +- statsig-node/npm/i686-pc-windows-msvc.package.json | 2 +- statsig-node/npm/x86_64-apple-darwin.package.json | 2 +- statsig-node/npm/x86_64-pc-windows-msvc.package.json | 2 +- .../npm/x86_64-unknown-linux-gnu.package.json | 2 +- .../npm/x86_64-unknown-linux-musl.package.json | 2 +- statsig-node/package.json | 2 +- statsig-php/post-install.php | 2 +- statsig-rust/Cargo.toml | 2 +- statsig-rust/src/statsig_metadata.rs | 2 +- 18 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc52bc629..2ba3ca1db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2373,7 +2373,7 @@ dependencies = [ [[package]] name = "sigstat-grpc" -version = "0.7.4-rc.2508202034" +version = "0.7.4-rc.2508202203" dependencies = [ "async-trait", "chrono", @@ -2437,7 +2437,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statsig-node" -version = "0.7.4-rc.2508202034" +version = "0.7.4-rc.2508202203" dependencies = [ "async-trait", "napi", @@ -2450,7 +2450,7 @@ dependencies = [ [[package]] name = "statsig-pyo3" -version = "0.7.4-rc.2508202034" +version = "0.7.4-rc.2508202203" dependencies = [ "async-trait", "lazy_static", @@ -2464,7 +2464,7 @@ dependencies = [ [[package]] name = "statsig-rust" -version = "0.7.4-rc.2508202034" +version = "0.7.4-rc.2508202203" dependencies = [ "ahash", "arc-swap", @@ -2504,7 +2504,7 @@ dependencies = [ [[package]] name = "statsig_elixir" -version = "0.7.4-rc.2508202034" +version = "0.7.4-rc.2508202203" dependencies = [ "parking_lot", "rustler", @@ -2516,7 +2516,7 @@ dependencies = [ [[package]] name = "statsig_ffi" -version = "0.7.4-rc.2508202034" +version = "0.7.4-rc.2508202203" dependencies = [ "async-trait", "cbindgen", diff --git a/examples/rust/mem-bench/Cargo.lock b/examples/rust/mem-bench/Cargo.lock index f0243b644..20b1e96aa 100644 --- a/examples/rust/mem-bench/Cargo.lock +++ b/examples/rust/mem-bench/Cargo.lock @@ -1815,7 +1815,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statsig-rust" -version = "0.7.4-rc.2508202034" +version = "0.7.4-rc.2508202203" dependencies = [ "ahash", "arc-swap", diff --git a/statsig-dotnet/Directory.Build.props b/statsig-dotnet/Directory.Build.props index 228d65650..cccd12471 100644 --- a/statsig-dotnet/Directory.Build.props +++ b/statsig-dotnet/Directory.Build.props @@ -1,6 +1,6 @@ - 0.7.4-rc.2508202034 + 0.7.4-rc.2508202203 ISC \ No newline at end of file diff --git a/statsig-elixir/mix.exs b/statsig-elixir/mix.exs index a11f3e77a..88d1f3463 100644 --- a/statsig-elixir/mix.exs +++ b/statsig-elixir/mix.exs @@ -4,7 +4,7 @@ defmodule Statsigelixir.MixProject do def project do [ app: :statsig_elixir, - version: "0.7.4-rc.2508202034", + version: "0.7.4-rc.2508202203", elixir: "~> 1.0", start_permanent: Mix.env() == :prod, description: description(), diff --git a/statsig-go/cmd/post-install/main.go b/statsig-go/cmd/post-install/main.go index f478641f4..f80233bcb 100644 --- a/statsig-go/cmd/post-install/main.go +++ b/statsig-go/cmd/post-install/main.go @@ -12,7 +12,7 @@ import ( ) const ( - version = "0.7.4-rc.2508202034" + version = "0.7.4-rc.2508202203" ) var output_dir string diff --git a/statsig-java/gradle.properties b/statsig-java/gradle.properties index a2d5f712f..fe5e0b75a 100644 --- a/statsig-java/gradle.properties +++ b/statsig-java/gradle.properties @@ -1 +1 @@ -version=0.7.4-rc.2508202034 \ No newline at end of file +version=0.7.4-rc.2508202203 \ No newline at end of file diff --git a/statsig-node/npm/aarch64-apple-darwin.package.json b/statsig-node/npm/aarch64-apple-darwin.package.json index 1f3cdf335..b100ffd56 100644 --- a/statsig-node/npm/aarch64-apple-darwin.package.json +++ b/statsig-node/npm/aarch64-apple-darwin.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-darwin-arm64", - "version": "0.7.4-rc.2508202034", + "version": "0.7.4-rc.2508202203", "os": [ "darwin" ], diff --git a/statsig-node/npm/aarch64-unknown-linux-gnu.package.json b/statsig-node/npm/aarch64-unknown-linux-gnu.package.json index 69e0afd46..5193c0560 100644 --- a/statsig-node/npm/aarch64-unknown-linux-gnu.package.json +++ b/statsig-node/npm/aarch64-unknown-linux-gnu.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-arm64-gnu", - "version": "0.7.4-rc.2508202034", + "version": "0.7.4-rc.2508202203", "os": [ "linux" ], diff --git a/statsig-node/npm/aarch64-unknown-linux-musl.package.json b/statsig-node/npm/aarch64-unknown-linux-musl.package.json index ac46f482b..358b8876a 100644 --- a/statsig-node/npm/aarch64-unknown-linux-musl.package.json +++ b/statsig-node/npm/aarch64-unknown-linux-musl.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-arm64-musl", - "version": "0.7.4-rc.2508202034", + "version": "0.7.4-rc.2508202203", "os": [ "linux" ], diff --git a/statsig-node/npm/i686-pc-windows-msvc.package.json b/statsig-node/npm/i686-pc-windows-msvc.package.json index bd6ee1636..9cd5ce833 100644 --- a/statsig-node/npm/i686-pc-windows-msvc.package.json +++ b/statsig-node/npm/i686-pc-windows-msvc.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-win32-ia32-msvc", - "version": "0.7.4-rc.2508202034", + "version": "0.7.4-rc.2508202203", "os": [ "win32" ], diff --git a/statsig-node/npm/x86_64-apple-darwin.package.json b/statsig-node/npm/x86_64-apple-darwin.package.json index f6ff18254..1ac619a6b 100644 --- a/statsig-node/npm/x86_64-apple-darwin.package.json +++ b/statsig-node/npm/x86_64-apple-darwin.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-darwin-x64", - "version": "0.7.4-rc.2508202034", + "version": "0.7.4-rc.2508202203", "os": [ "darwin" ], diff --git a/statsig-node/npm/x86_64-pc-windows-msvc.package.json b/statsig-node/npm/x86_64-pc-windows-msvc.package.json index a87b0ff90..ec20b2b72 100644 --- a/statsig-node/npm/x86_64-pc-windows-msvc.package.json +++ b/statsig-node/npm/x86_64-pc-windows-msvc.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-win32-x64-msvc", - "version": "0.7.4-rc.2508202034", + "version": "0.7.4-rc.2508202203", "os": [ "win32" ], diff --git a/statsig-node/npm/x86_64-unknown-linux-gnu.package.json b/statsig-node/npm/x86_64-unknown-linux-gnu.package.json index 15ecc7fb3..375947564 100644 --- a/statsig-node/npm/x86_64-unknown-linux-gnu.package.json +++ b/statsig-node/npm/x86_64-unknown-linux-gnu.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-x64-gnu", - "version": "0.7.4-rc.2508202034", + "version": "0.7.4-rc.2508202203", "os": [ "linux" ], diff --git a/statsig-node/npm/x86_64-unknown-linux-musl.package.json b/statsig-node/npm/x86_64-unknown-linux-musl.package.json index 461b68596..f0546948a 100644 --- a/statsig-node/npm/x86_64-unknown-linux-musl.package.json +++ b/statsig-node/npm/x86_64-unknown-linux-musl.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-x64-musl", - "version": "0.7.4-rc.2508202034", + "version": "0.7.4-rc.2508202203", "os": [ "linux" ], diff --git a/statsig-node/package.json b/statsig-node/package.json index e196847ef..0dd169654 100644 --- a/statsig-node/package.json +++ b/statsig-node/package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core", - "version": "0.7.4-rc.2508202034", + "version": "0.7.4-rc.2508202203", "main": "index.js", "scripts": { "test": "jest --colors" diff --git a/statsig-php/post-install.php b/statsig-php/post-install.php index 2802cfb69..90105ad3c 100644 --- a/statsig-php/post-install.php +++ b/statsig-php/post-install.php @@ -1,7 +1,7 @@ Self { Self { - sdk_version: "0.7.4-rc.2508202034".to_string(), + sdk_version: "0.7.4-rc.2508202203".to_string(), sdk_type: "statsig-server-core".to_string(), session_id: Uuid::new_v4().to_string(), os: None, From 9aa2c6fe3dcd34d6abf66da0f51cd1417535bf96 Mon Sep 17 00:00:00 2001 From: "statsig-kong[bot]" Date: Wed, 20 Aug 2025 15:29:50 -0700 Subject: [PATCH 21/23] Bot: Updated File Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ad9ae18e3..6ed7c31c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ exclude = [ [workspace.package] edition = "2021" license = "ISC" -version = "0.7.4-rc.2508202203" +version = "0.8.0" homepage = "https://statsig.com/" authors = ["Statsig", "Daniel Loomb "] readme = "README.md" From 6083156e1ed9421cd4c06815cd4c494eb1a45dbc Mon Sep 17 00:00:00 2001 From: "statsig-kong[bot]" Date: Wed, 20 Aug 2025 22:31:43 +0000 Subject: [PATCH 22/23] Bot: Version synchronized in 18 files --- Cargo.lock | 12 ++++++------ examples/rust/mem-bench/Cargo.lock | 2 +- statsig-dotnet/Directory.Build.props | 2 +- statsig-elixir/mix.exs | 2 +- statsig-go/cmd/post-install/main.go | 2 +- statsig-java/gradle.properties | 2 +- statsig-node/npm/aarch64-apple-darwin.package.json | 2 +- .../npm/aarch64-unknown-linux-gnu.package.json | 2 +- .../npm/aarch64-unknown-linux-musl.package.json | 2 +- statsig-node/npm/i686-pc-windows-msvc.package.json | 2 +- statsig-node/npm/x86_64-apple-darwin.package.json | 2 +- statsig-node/npm/x86_64-pc-windows-msvc.package.json | 2 +- .../npm/x86_64-unknown-linux-gnu.package.json | 2 +- .../npm/x86_64-unknown-linux-musl.package.json | 2 +- statsig-node/package.json | 2 +- statsig-php/post-install.php | 2 +- statsig-rust/Cargo.toml | 2 +- statsig-rust/src/statsig_metadata.rs | 2 +- 18 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2ba3ca1db..a79853844 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2373,7 +2373,7 @@ dependencies = [ [[package]] name = "sigstat-grpc" -version = "0.7.4-rc.2508202203" +version = "0.8.0" dependencies = [ "async-trait", "chrono", @@ -2437,7 +2437,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statsig-node" -version = "0.7.4-rc.2508202203" +version = "0.8.0" dependencies = [ "async-trait", "napi", @@ -2450,7 +2450,7 @@ dependencies = [ [[package]] name = "statsig-pyo3" -version = "0.7.4-rc.2508202203" +version = "0.8.0" dependencies = [ "async-trait", "lazy_static", @@ -2464,7 +2464,7 @@ dependencies = [ [[package]] name = "statsig-rust" -version = "0.7.4-rc.2508202203" +version = "0.8.0" dependencies = [ "ahash", "arc-swap", @@ -2504,7 +2504,7 @@ dependencies = [ [[package]] name = "statsig_elixir" -version = "0.7.4-rc.2508202203" +version = "0.8.0" dependencies = [ "parking_lot", "rustler", @@ -2516,7 +2516,7 @@ dependencies = [ [[package]] name = "statsig_ffi" -version = "0.7.4-rc.2508202203" +version = "0.8.0" dependencies = [ "async-trait", "cbindgen", diff --git a/examples/rust/mem-bench/Cargo.lock b/examples/rust/mem-bench/Cargo.lock index 20b1e96aa..8ed786266 100644 --- a/examples/rust/mem-bench/Cargo.lock +++ b/examples/rust/mem-bench/Cargo.lock @@ -1815,7 +1815,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statsig-rust" -version = "0.7.4-rc.2508202203" +version = "0.8.0" dependencies = [ "ahash", "arc-swap", diff --git a/statsig-dotnet/Directory.Build.props b/statsig-dotnet/Directory.Build.props index cccd12471..93907726a 100644 --- a/statsig-dotnet/Directory.Build.props +++ b/statsig-dotnet/Directory.Build.props @@ -1,6 +1,6 @@ - 0.7.4-rc.2508202203 + 0.8.0 ISC \ No newline at end of file diff --git a/statsig-elixir/mix.exs b/statsig-elixir/mix.exs index 88d1f3463..581e74c75 100644 --- a/statsig-elixir/mix.exs +++ b/statsig-elixir/mix.exs @@ -4,7 +4,7 @@ defmodule Statsigelixir.MixProject do def project do [ app: :statsig_elixir, - version: "0.7.4-rc.2508202203", + version: "0.8.0", elixir: "~> 1.0", start_permanent: Mix.env() == :prod, description: description(), diff --git a/statsig-go/cmd/post-install/main.go b/statsig-go/cmd/post-install/main.go index f80233bcb..f30e6643b 100644 --- a/statsig-go/cmd/post-install/main.go +++ b/statsig-go/cmd/post-install/main.go @@ -12,7 +12,7 @@ import ( ) const ( - version = "0.7.4-rc.2508202203" + version = "0.8.0" ) var output_dir string diff --git a/statsig-java/gradle.properties b/statsig-java/gradle.properties index fe5e0b75a..dc4548c8a 100644 --- a/statsig-java/gradle.properties +++ b/statsig-java/gradle.properties @@ -1 +1 @@ -version=0.7.4-rc.2508202203 \ No newline at end of file +version=0.8.0 \ No newline at end of file diff --git a/statsig-node/npm/aarch64-apple-darwin.package.json b/statsig-node/npm/aarch64-apple-darwin.package.json index b100ffd56..76010405d 100644 --- a/statsig-node/npm/aarch64-apple-darwin.package.json +++ b/statsig-node/npm/aarch64-apple-darwin.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-darwin-arm64", - "version": "0.7.4-rc.2508202203", + "version": "0.8.0", "os": [ "darwin" ], diff --git a/statsig-node/npm/aarch64-unknown-linux-gnu.package.json b/statsig-node/npm/aarch64-unknown-linux-gnu.package.json index 5193c0560..f2ba61f9f 100644 --- a/statsig-node/npm/aarch64-unknown-linux-gnu.package.json +++ b/statsig-node/npm/aarch64-unknown-linux-gnu.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-arm64-gnu", - "version": "0.7.4-rc.2508202203", + "version": "0.8.0", "os": [ "linux" ], diff --git a/statsig-node/npm/aarch64-unknown-linux-musl.package.json b/statsig-node/npm/aarch64-unknown-linux-musl.package.json index 358b8876a..af0a3ba4d 100644 --- a/statsig-node/npm/aarch64-unknown-linux-musl.package.json +++ b/statsig-node/npm/aarch64-unknown-linux-musl.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-arm64-musl", - "version": "0.7.4-rc.2508202203", + "version": "0.8.0", "os": [ "linux" ], diff --git a/statsig-node/npm/i686-pc-windows-msvc.package.json b/statsig-node/npm/i686-pc-windows-msvc.package.json index 9cd5ce833..2dd597eea 100644 --- a/statsig-node/npm/i686-pc-windows-msvc.package.json +++ b/statsig-node/npm/i686-pc-windows-msvc.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-win32-ia32-msvc", - "version": "0.7.4-rc.2508202203", + "version": "0.8.0", "os": [ "win32" ], diff --git a/statsig-node/npm/x86_64-apple-darwin.package.json b/statsig-node/npm/x86_64-apple-darwin.package.json index 1ac619a6b..a3033c870 100644 --- a/statsig-node/npm/x86_64-apple-darwin.package.json +++ b/statsig-node/npm/x86_64-apple-darwin.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-darwin-x64", - "version": "0.7.4-rc.2508202203", + "version": "0.8.0", "os": [ "darwin" ], diff --git a/statsig-node/npm/x86_64-pc-windows-msvc.package.json b/statsig-node/npm/x86_64-pc-windows-msvc.package.json index ec20b2b72..cad7edf68 100644 --- a/statsig-node/npm/x86_64-pc-windows-msvc.package.json +++ b/statsig-node/npm/x86_64-pc-windows-msvc.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-win32-x64-msvc", - "version": "0.7.4-rc.2508202203", + "version": "0.8.0", "os": [ "win32" ], diff --git a/statsig-node/npm/x86_64-unknown-linux-gnu.package.json b/statsig-node/npm/x86_64-unknown-linux-gnu.package.json index 375947564..4464b906a 100644 --- a/statsig-node/npm/x86_64-unknown-linux-gnu.package.json +++ b/statsig-node/npm/x86_64-unknown-linux-gnu.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-x64-gnu", - "version": "0.7.4-rc.2508202203", + "version": "0.8.0", "os": [ "linux" ], diff --git a/statsig-node/npm/x86_64-unknown-linux-musl.package.json b/statsig-node/npm/x86_64-unknown-linux-musl.package.json index f0546948a..da5afa8fe 100644 --- a/statsig-node/npm/x86_64-unknown-linux-musl.package.json +++ b/statsig-node/npm/x86_64-unknown-linux-musl.package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core-linux-x64-musl", - "version": "0.7.4-rc.2508202203", + "version": "0.8.0", "os": [ "linux" ], diff --git a/statsig-node/package.json b/statsig-node/package.json index 0dd169654..ef63c7ef3 100644 --- a/statsig-node/package.json +++ b/statsig-node/package.json @@ -1,6 +1,6 @@ { "name": "@statsig/statsig-node-core", - "version": "0.7.4-rc.2508202203", + "version": "0.8.0", "main": "index.js", "scripts": { "test": "jest --colors" diff --git a/statsig-php/post-install.php b/statsig-php/post-install.php index 90105ad3c..b773d4f8f 100644 --- a/statsig-php/post-install.php +++ b/statsig-php/post-install.php @@ -1,7 +1,7 @@ Self { Self { - sdk_version: "0.7.4-rc.2508202203".to_string(), + sdk_version: "0.8.0".to_string(), sdk_type: "statsig-server-core".to_string(), session_id: Uuid::new_v4().to_string(), os: None, From a3e25bdfc60c51ef3f666edfcd845e1669310304 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Sep 2025 23:37:17 +0000 Subject: [PATCH 23/23] chore(deps): bump tokio from 1.43.0 to 1.43.1 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.43.0 to 1.43.1. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.43.0...tokio-1.43.1) --- updated-dependencies: - dependency-name: tokio dependency-version: 1.43.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- statsig-elixir/native/statsig_elixir/Cargo.toml | 2 +- statsig-ffi/Cargo.toml | 2 +- statsig-grpc/Cargo.toml | 2 +- statsig-rust/Cargo.toml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a79853844..23fe93b71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2725,9 +2725,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.43.0" +version = "1.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +checksum = "492a604e2fd7f814268a378409e6c92b5525d747d10db9a229723f55a417958c" dependencies = [ "backtrace", "bytes", diff --git a/statsig-elixir/native/statsig_elixir/Cargo.toml b/statsig-elixir/native/statsig_elixir/Cargo.toml index 441e6121b..72a793ce3 100644 --- a/statsig-elixir/native/statsig_elixir/Cargo.toml +++ b/statsig-elixir/native/statsig_elixir/Cargo.toml @@ -14,6 +14,6 @@ rustler = "0.36.1" statsig-rust = { path = "../../../statsig-rust", features = [ "with_zstd", ] } -tokio = { version = "1.39.1", features = ["rt", "rt-multi-thread", "macros"] } +tokio = { version = "1.43.1", features = ["rt", "rt-multi-thread", "macros"] } serde_json = { version = "1.0.125", features = ["float_roundtrip"] } serde = { version = "1.0.204", features = ["derive"] } diff --git a/statsig-ffi/Cargo.toml b/statsig-ffi/Cargo.toml index 825cfab2a..807a4b14a 100644 --- a/statsig-ffi/Cargo.toml +++ b/statsig-ffi/Cargo.toml @@ -12,7 +12,7 @@ repository.workspace = true [dependencies] statsig-rust = { path = "../statsig-rust" } serde_json = "1.0.120" -tokio = "1.39.1" +tokio = "1.43.1" lazy_static = "1.5.0" log = "0.4.22" serde = { version = "1.0.204", features = ["derive"] } diff --git a/statsig-grpc/Cargo.toml b/statsig-grpc/Cargo.toml index 70dca4d08..ef0cae546 100644 --- a/statsig-grpc/Cargo.toml +++ b/statsig-grpc/Cargo.toml @@ -10,7 +10,7 @@ homepage.workspace = true repository.workspace = true [dependencies] -tokio = { version = "1.39.1", features = ["full"] } +tokio = { version = "1.43.1", features = ["full"] } async-trait = "0.1.81" tonic = { version = "0.12.1", features = ["tls"] } parking_lot = "0.12.1" diff --git a/statsig-rust/Cargo.toml b/statsig-rust/Cargo.toml index a2e629b05..402c0c182 100644 --- a/statsig-rust/Cargo.toml +++ b/statsig-rust/Cargo.toml @@ -40,7 +40,7 @@ serde_with = "3.4.0" sha2 = "0.10.8" sigstat-grpc = { path = "../statsig-grpc", version = "0.8.0", optional = true } simple_logger = { version = "5.0.0" } -tokio = { version = "1.39.1", features = ["full"] } +tokio = { version = "1.43.1", features = ["full"] } uaparser = "0.6.4" uuid = { version = "1.10.0", features = ["v4", "fast-rng"] } zstd = { version = "0.13.2", features = ["zdict_builder"] }