Skip to content
This repository was archived by the owner on Mar 13, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6d13eed
chore: bump version to 0.7.4-rc.2508181316
statsig-kong[bot] Aug 18, 2025
3281d76
[Cherrypick][releases/0.7.4-rc.2508181316] chore: reuse tokio rt acro…
weihao-statsig Aug 18, 2025
ebcd5a8
Bot: Updated File Cargo.toml
weihao-statsig Aug 18, 2025
be3445b
Bot: Version synchronized in 18 files
statsig-kong[bot] Aug 18, 2025
c7c5d98
[Cherrypick][releases/0.7.4-rc.2508182310] Fix elixir publish action …
xinlili-statsig Aug 19, 2025
eeb6da2
[Cherrypick][releases/0.7.4-rc.2508182310] elixir: add gcir, make use…
xinlili-statsig Aug 19, 2025
6646ee7
Bot: Updated File Cargo.toml
xinlili-statsig Aug 19, 2025
5a37359
Bot: Version synchronized in 18 files
statsig-kong[bot] Aug 19, 2025
62b863a
[cherrypick][releases/0.7.4-rc.2508191829] elixir: statsigmetadata up…
xinlili-statsig Aug 20, 2025
a02ad24
[cherrypick][releases/0.7.4-rc.2508191829] support gcir option (#1669)
xinlili-statsig Aug 20, 2025
9e77e79
[cherrypick][releases/0.7.4-rc.2508191829] elixir: add module definit…
xinlili-statsig Aug 20, 2025
9eb6d57
[cherrypick][releases/0.7.4-rc.2508191829] tool: new gh workflow to c…
xinlili-statsig Aug 20, 2025
94f5a48
[cherrypick][releases/0.7.4-rc.2508191829] add getPrompt/bindings (#1…
xinlili-statsig Aug 20, 2025
5fb72a9
[cherrypick][releases/0.7.4-rc.2508191829] fix: add github env in rel…
weihao-statsig Aug 20, 2025
860acda
Bot: Updated File Cargo.toml
xinlili-statsig Aug 20, 2025
96d285c
Bot: Version synchronized in 18 files
statsig-kong[bot] Aug 20, 2025
26d41d4
[cherrypick][releases/0.7.4-rc.2508202034] update elixir build comman…
xinlili-statsig Aug 20, 2025
af5d1d1
[cherrypick][releases/0.7.4-rc.2508202034] chore(elixir): "get_config…
xinlili-statsig Aug 20, 2025
6b349b0
Bot: Updated File Cargo.toml
xinlili-statsig Aug 20, 2025
8becbbb
Bot: Version synchronized in 18 files
statsig-kong[bot] Aug 20, 2025
9aa2c6f
Bot: Updated File Cargo.toml
xinlili-statsig Aug 20, 2025
6083156
Bot: Version synchronized in 18 files
statsig-kong[bot] Aug 20, 2025
a3e25bd
chore(deps): bump tokio from 1.43.0 to 1.43.1
dependabot[bot] Sep 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/create_release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Create Release

on:
workflow_dispatch:
push:
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
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
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ exclude = [
[workspace.package]
edition = "2021"
license = "ISC"
version = "0.7.4-beta.2508160236"
version = "0.8.0"
homepage = "https://statsig.com/"
authors = ["Statsig", "Daniel Loomb <daniel@statsig.com>"]
readme = "README.md"
Expand Down
7 changes: 4 additions & 3 deletions cli/src/commands/builders/elixir-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`;
Expand Down
38 changes: 20 additions & 18 deletions cli/src/commands/publishers/elixir-publisher.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getRootedPath } from '@/utils/file_utils.js';
import { BASE_DIR, getRootedPath } from '@/utils/file_utils.js';
import {
GhRelease,
createReleaseForVersion,
Expand All @@ -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();
Expand All @@ -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
Expand All @@ -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');
}

Expand All @@ -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,
);
}

Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion examples/rust/mem-bench/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion statsig-dotnet/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<StatsigVersion>0.7.4-beta.2508160236</StatsigVersion>
<StatsigVersion>0.8.0</StatsigVersion>
<PackageLicenseExpression>ISC</PackageLicenseExpression>
</PropertyGroup>
</Project>
24 changes: 24 additions & 0 deletions statsig-dotnet/src/Statsig/Statsig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<byte> 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);
Expand Down
3 changes: 3 additions & 0 deletions statsig-dotnet/src/Statsig/StatsigFFI.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
61 changes: 57 additions & 4 deletions statsig-elixir/lib/statsig.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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)}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -116,14 +116,45 @@ 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, options \\nil) do
try do
instance = get_statsig_instance()

case NativeBindings.get_client_init_response_as_string(instance, statsig_user, options) 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
try 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) ->
Expand Down Expand Up @@ -169,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
4 changes: 2 additions & 2 deletions statsig-elixir/lib/statsig/dynamic_config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading