shipeasy-sdk 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/shipeasy/config.rb +27 -5
- data/lib/shipeasy/engine.rb +27 -10
- data/lib/shipeasy/sdk/env.rb +55 -0
- data/lib/shipeasy/sdk/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 49743db7faf0600dcc8a7cacb3f7a6fc7418c4d3d125efa6fdd1067b24fe4d16
|
|
4
|
+
data.tar.gz: 031b3acc69308ce512fb67c073b1f7f1894e276e17ab23f5ff3495678c2dab99
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 479ca3e747f954922315f6bb062b385ba8e7710ac37799d7a732f8da63de87321d5c497b8ee3cc605cb80c66bd9f4ebbceea6acc9486ff7d37d8f0b9c153f628
|
|
7
|
+
data.tar.gz: 1f9a70f2ccff8c6fcaeb5a9e913657fb88ceac7c37505f21d409880740d1d7af4b952732a3607ee94908a1e8c1921d23e9997852c3622e8a315ab1168a2c2def
|
data/lib/shipeasy/config.rb
CHANGED
|
@@ -25,7 +25,18 @@ module Shipeasy
|
|
|
25
25
|
# Advanced `configure` options — threaded into the global Engine `configure`
|
|
26
26
|
# builds, so callers never construct an Engine themselves:
|
|
27
27
|
# - env (default "prod"): deployment tag on see() events + usage telemetry.
|
|
28
|
-
# -
|
|
28
|
+
# - is_network_enabled (default: environment-derived): master switch for ALL
|
|
29
|
+
# outbound requests (flag/experiment/config fetch, track, exposure logging,
|
|
30
|
+
# see() reports, AND telemetry). Defaults ON in production and OFF in every
|
|
31
|
+
# other environment, so a dev machine / CI run stays fully offline unless
|
|
32
|
+
# you opt in. Explicit true/false always overrides. "Production" is decided
|
|
33
|
+
# from SHIPEASY_ENV / RAILS_ENV / RACK_ENV / APP_ENV, then the `env` tag
|
|
34
|
+
# (see sdk/env.rb). When off, reads answer from overrides / in-code
|
|
35
|
+
# defaults and nothing is sent.
|
|
36
|
+
# - disable_telemetry (default: environment-derived — off in prod, i.e.
|
|
37
|
+
# telemetry ON in prod / OFF outside prod): opt out of per-eval usage
|
|
38
|
+
# telemetry. Explicit true/false overrides; forced off when the network is
|
|
39
|
+
# disabled.
|
|
29
40
|
# - telemetry_url: override the telemetry endpoint (rarely needed).
|
|
30
41
|
# - private_attributes: attribute keys stripped from every outbound event
|
|
31
42
|
# before it leaves the process (they still drive targeting locally).
|
|
@@ -35,7 +46,7 @@ module Shipeasy
|
|
|
35
46
|
# swallows one of its OWN internal errors it normally ships a structured
|
|
36
47
|
# see event to Shipeasy's own project (NOT yours) so the SDK team can
|
|
37
48
|
# track SDK bugs; set true to disable that entirely.
|
|
38
|
-
attr_accessor :env, :disable_telemetry, :telemetry_url,
|
|
49
|
+
attr_accessor :env, :is_network_enabled, :disable_telemetry, :telemetry_url,
|
|
39
50
|
:private_attributes, :sticky_store,
|
|
40
51
|
:disable_internal_error_reporting
|
|
41
52
|
|
|
@@ -80,7 +91,10 @@ module Shipeasy
|
|
|
80
91
|
@init = true
|
|
81
92
|
@poll = false
|
|
82
93
|
@env = "prod"
|
|
83
|
-
|
|
94
|
+
# nil ⇒ environment-derived default (see Engine / sdk/env.rb). An explicit
|
|
95
|
+
# true/false set in the configure block always overrides.
|
|
96
|
+
@is_network_enabled = nil
|
|
97
|
+
@disable_telemetry = nil
|
|
84
98
|
@disable_internal_error_reporting = false
|
|
85
99
|
@telemetry_url = nil
|
|
86
100
|
@private_attributes = nil
|
|
@@ -159,6 +173,7 @@ module Shipeasy
|
|
|
159
173
|
api_key: cfg.api_key,
|
|
160
174
|
base_url: cfg.base_url,
|
|
161
175
|
env: cfg.env,
|
|
176
|
+
is_network_enabled: cfg.is_network_enabled,
|
|
162
177
|
disable_telemetry: cfg.disable_telemetry,
|
|
163
178
|
telemetry_url: cfg.telemetry_url,
|
|
164
179
|
private_attributes: cfg.private_attributes,
|
|
@@ -170,13 +185,13 @@ module Shipeasy
|
|
|
170
185
|
# Capture +engine+ in the closure (not the @engine ivar, which a concurrent
|
|
171
186
|
# reset/reconfigure could nil out before the thread runs).
|
|
172
187
|
if cfg.poll
|
|
173
|
-
Thread.new do
|
|
188
|
+
@boot_thread = Thread.new do
|
|
174
189
|
engine.init # initial fetch + background poll thread
|
|
175
190
|
rescue => e
|
|
176
191
|
Shipeasy::Logging.error "[shipeasy] configure(poll) background poll failed: #{e.message}"
|
|
177
192
|
end
|
|
178
193
|
elsif cfg.init
|
|
179
|
-
Thread.new do
|
|
194
|
+
@boot_thread = Thread.new do
|
|
180
195
|
engine.init_once
|
|
181
196
|
rescue => e
|
|
182
197
|
Shipeasy::Logging.error "[shipeasy] configure() one-shot fetch failed: #{e.message}"
|
|
@@ -327,6 +342,13 @@ module Shipeasy
|
|
|
327
342
|
|
|
328
343
|
# Reset the config back to defaults — primarily for tests.
|
|
329
344
|
def reset_config!
|
|
345
|
+
# Reap the fire-and-forget boot thread first: it holds its own engine
|
|
346
|
+
# reference, so left alive it can call init/init_once during the NEXT
|
|
347
|
+
# test example and trip any_instance expectations armed there.
|
|
348
|
+
if (t = @boot_thread)
|
|
349
|
+
t.join(1) || t.kill
|
|
350
|
+
@boot_thread = nil
|
|
351
|
+
end
|
|
330
352
|
@config = nil
|
|
331
353
|
@flags_pid = nil
|
|
332
354
|
@flags&.destroy
|
data/lib/shipeasy/engine.rb
CHANGED
|
@@ -4,6 +4,7 @@ require "json"
|
|
|
4
4
|
require "thread"
|
|
5
5
|
require "cgi"
|
|
6
6
|
require_relative "logging"
|
|
7
|
+
require_relative "sdk/env"
|
|
7
8
|
require_relative "sdk/eval"
|
|
8
9
|
require_relative "sdk/telemetry"
|
|
9
10
|
require_relative "sdk/anon_id"
|
|
@@ -35,7 +36,7 @@ module Shipeasy
|
|
|
35
36
|
# /sdk/i18n/loader.js) — distinct from the edge API the blobs are fetched from.
|
|
36
37
|
DEFAULT_CDN_BASE = "https://cdn.shipeasy.ai"
|
|
37
38
|
|
|
38
|
-
def initialize(api_key:, base_url: nil, env: "prod", disable_telemetry:
|
|
39
|
+
def initialize(api_key:, base_url: nil, env: "prod", is_network_enabled: nil, disable_telemetry: nil, telemetry_url: nil, test_mode: false, private_attributes: nil, sticky_store: nil, log_level: nil, disable_internal_error_reporting: false)
|
|
39
40
|
# SDK-wide diagnostic verbosity. Set the leveled logger from the passed
|
|
40
41
|
# level (default :warn; unknown falls back to :warn). The logger is
|
|
41
42
|
# module-scoped, so the last-built engine wins — mirrors the TS SDK,
|
|
@@ -59,14 +60,30 @@ module Shipeasy
|
|
|
59
60
|
# evaluation answers come purely from local overrides. Built via the
|
|
60
61
|
# Engine.for_testing factory; see clear_overrides / override_*.
|
|
61
62
|
@test_mode = test_mode
|
|
62
|
-
#
|
|
63
|
-
#
|
|
63
|
+
# Environment-derived egress default. Both the master network switch and
|
|
64
|
+
# usage telemetry default ON in production and OFF everywhere else, so an
|
|
65
|
+
# app that embeds the SDK is quiet by default on a dev machine or in CI.
|
|
66
|
+
# The production decision consults native env vars first (SHIPEASY_ENV /
|
|
67
|
+
# RAILS_ENV / RACK_ENV / APP_ENV), then falls back to the configured `env`
|
|
68
|
+
# tag. See sdk/env.rb.
|
|
69
|
+
prod = Shipeasy::SDK::Env.is_production_env(env)
|
|
70
|
+
# Master network gate. test_mode always forces the SDK fully offline;
|
|
71
|
+
# otherwise honour an explicit is_network_enabled, else default to
|
|
72
|
+
# prod-on. When @offline, every fetch / track / exposure / see() / poll /
|
|
73
|
+
# telemetry send is a no-op — reads answer from overrides / in-code
|
|
74
|
+
# defaults only.
|
|
75
|
+
network_enabled = @test_mode ? false : (is_network_enabled.nil? ? prod : (is_network_enabled ? true : false))
|
|
76
|
+
@offline = !network_enabled
|
|
77
|
+
# Per-evaluation usage telemetry. Honour an explicit disable_telemetry,
|
|
78
|
+
# else default to prod-on (off outside production). Forced off whenever
|
|
79
|
+
# the master network switch is off. See telemetry.rb.
|
|
80
|
+
telemetry_disabled = @offline || (disable_telemetry.nil? ? !prod : (disable_telemetry ? true : false))
|
|
64
81
|
@telemetry = Telemetry.new(
|
|
65
82
|
endpoint: telemetry_url || Telemetry::DEFAULT_TELEMETRY_URL,
|
|
66
83
|
sdk_key: api_key,
|
|
67
84
|
side: "server",
|
|
68
85
|
env: env,
|
|
69
|
-
disabled:
|
|
86
|
+
disabled: telemetry_disabled,
|
|
70
87
|
)
|
|
71
88
|
@flags_blob = nil
|
|
72
89
|
@exps_blob = nil
|
|
@@ -103,7 +120,7 @@ module Shipeasy
|
|
|
103
120
|
Shipeasy::SDK::InternalReport.set_context(
|
|
104
121
|
side: "server",
|
|
105
122
|
sdk_version: Shipeasy::SDK::VERSION,
|
|
106
|
-
enabled:
|
|
123
|
+
enabled: !@offline && !disable_internal_error_reporting,
|
|
107
124
|
)
|
|
108
125
|
# Register as the default client backing the module-level Shipeasy::SDK
|
|
109
126
|
# .see/.see_violation funcs (last constructed wins — the server-SDK
|
|
@@ -153,14 +170,14 @@ module Shipeasy
|
|
|
153
170
|
end
|
|
154
171
|
|
|
155
172
|
def init
|
|
156
|
-
return if @
|
|
173
|
+
return if @offline
|
|
157
174
|
fetch_all
|
|
158
175
|
@initialized = true
|
|
159
176
|
start_poll
|
|
160
177
|
end
|
|
161
178
|
|
|
162
179
|
def init_once
|
|
163
|
-
return if @
|
|
180
|
+
return if @offline
|
|
164
181
|
return if @initialized
|
|
165
182
|
fetch_all
|
|
166
183
|
@initialized = true
|
|
@@ -470,7 +487,7 @@ module Shipeasy
|
|
|
470
487
|
|
|
471
488
|
def track(user_id, event_name, props = {})
|
|
472
489
|
safe_run("track('#{event_name}')", nil) do
|
|
473
|
-
next if @
|
|
490
|
+
next if @offline
|
|
474
491
|
|
|
475
492
|
safe_props = strip_private(props)
|
|
476
493
|
|
|
@@ -583,7 +600,7 @@ module Shipeasy
|
|
|
583
600
|
# spam /collect. Fire-and-forget; no-op in test mode. This is how
|
|
584
601
|
# assign_universe auto-logs — the browser's auto-exposure parity for SSR.
|
|
585
602
|
def post_exposure(user, experiment, group)
|
|
586
|
-
return if @
|
|
603
|
+
return if @offline
|
|
587
604
|
u = user.transform_keys(&:to_s)
|
|
588
605
|
uid = u["user_id"] || u["anonymous_id"]
|
|
589
606
|
dedup_key = "#{uid}:#{experiment}:#{group}"
|
|
@@ -614,7 +631,7 @@ module Shipeasy
|
|
|
614
631
|
# Build the wire event and fire-and-forget POST it to /collect. No-op in
|
|
615
632
|
# test mode (mirrors track). Spam-guarded. Never raises into caller code.
|
|
616
633
|
def dispatch_see(built)
|
|
617
|
-
return if @
|
|
634
|
+
return if @offline
|
|
618
635
|
|
|
619
636
|
ev = See.build_event(
|
|
620
637
|
built.problem,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Shipeasy
|
|
2
|
+
module SDK
|
|
3
|
+
# Native runtime-environment detection.
|
|
4
|
+
#
|
|
5
|
+
# Used ONLY to pick the DEFAULT for outbound egress when the caller does not
|
|
6
|
+
# set it explicitly:
|
|
7
|
+
# - is the SDK allowed to make network requests at all (is_network_enabled)?
|
|
8
|
+
# - is per-evaluation usage telemetry allowed (disable_telemetry)?
|
|
9
|
+
#
|
|
10
|
+
# Both default to ON in production and OFF everywhere else, so a local/dev/CI
|
|
11
|
+
# run of an app that embeds the SDK never phones home unless it explicitly
|
|
12
|
+
# opts in.
|
|
13
|
+
#
|
|
14
|
+
# Precedence for the production decision (mirrors the TS SDK's src/env.ts):
|
|
15
|
+
# 1. A native runtime env var — SHIPEASY_ENV, then RAILS_ENV, then RACK_ENV,
|
|
16
|
+
# then APP_ENV. A value of "production"/"prod" (case-insensitive) ⇒ prod;
|
|
17
|
+
# anything else present ("development"/"staging"/"test"/…) ⇒ not prod.
|
|
18
|
+
# 2. When no native env var is set (e.g. serverless / some containers), fall
|
|
19
|
+
# back to the SDK's OWN configured `env` option, which the caller sets and
|
|
20
|
+
# which itself defaults to "prod". This keeps a real production deploy
|
|
21
|
+
# "on" by default while an `env: "dev"` config stays quiet.
|
|
22
|
+
#
|
|
23
|
+
# The env option is always present (it defaults to "prod"), so the production
|
|
24
|
+
# decision is always inferrable — the SDK never has to make the field required.
|
|
25
|
+
module Env
|
|
26
|
+
# Native env vars consulted, in precedence order.
|
|
27
|
+
NATIVE_ENV_VARS = %w[SHIPEASY_ENV RAILS_ENV RACK_ENV APP_ENV].freeze
|
|
28
|
+
|
|
29
|
+
module_function
|
|
30
|
+
|
|
31
|
+
# True when the host runtime looks like a production deployment.
|
|
32
|
+
# +configured_env+ is the SDK's own `env` option (dev/staging/prod); it is
|
|
33
|
+
# consulted ONLY when no native runtime env var is set.
|
|
34
|
+
def is_production_env(configured_env = nil)
|
|
35
|
+
native = read_native_env
|
|
36
|
+
return native == "production" || native == "prod" unless native.nil?
|
|
37
|
+
|
|
38
|
+
(configured_env || "prod").to_s.strip.downcase == "prod"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Read the first present native env var (lowercased, trimmed), or nil when
|
|
42
|
+
# none of them is set to a non-empty value.
|
|
43
|
+
def read_native_env
|
|
44
|
+
NATIVE_ENV_VARS.each do |name|
|
|
45
|
+
raw = ENV[name]
|
|
46
|
+
next if raw.nil?
|
|
47
|
+
|
|
48
|
+
v = raw.strip.downcase
|
|
49
|
+
return v unless v.empty?
|
|
50
|
+
end
|
|
51
|
+
nil
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
data/lib/shipeasy/sdk/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: shipeasy-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shipeasy, Inc.
|
|
@@ -142,6 +142,7 @@ files:
|
|
|
142
142
|
- lib/shipeasy/i18n/view_helpers.rb
|
|
143
143
|
- lib/shipeasy/logging.rb
|
|
144
144
|
- lib/shipeasy/sdk/anon_id.rb
|
|
145
|
+
- lib/shipeasy/sdk/env.rb
|
|
145
146
|
- lib/shipeasy/sdk/eval.rb
|
|
146
147
|
- lib/shipeasy/sdk/internal_report.rb
|
|
147
148
|
- lib/shipeasy/sdk/murmur3.rb
|