Shipeasy
SDKsReferenceJava

Snippets

Minimal copy-paste blocks for flags, configs, kill switches and metric tracking.

Minimal copy-paste blocks, grouped by the registry taxonomy. These are the same leaves the docs get op returns.

release

release / flags

Read new_checkout off a user-bound Client. Assumes configure() ran at startup — see Installation.

import ai.shipeasy.Client;
import java.util.Map;

// construct once per callsite (cheap; binds the user)
Client client = new Client(Map.of("user_id", "u_123"));

boolean enabled = client.getFlag("new_checkout"); // gate name
// optional default overload — returned ONLY when unresolvable (engine not
// ready / flag absent), never when the flag legitimately evaluates to false:
// boolean enabled = client.getFlag("new_checkout", true /* default */);

release / configs

Read the dynamic config billing_copy (with a fallback when absent). Assumes configure() ran at startup — see Installation.

import ai.shipeasy.Client;
import java.util.Map;

// construct once per callsite (cheap; binds the user)
Client client = new Client(Map.of("user_id", "u_123"));

Object cfg = client.getConfig(
    "billing_copy",          // config name
    Map.of("title", "Default")); // fallback returned when the config is absent
// one-arg overload returns null when absent: client.getConfig("billing_copy")

release / killswitches

Check whether the kill switch payments is killed. Assumes configure() ran at startup — see Installation.

import ai.shipeasy.Client;
import java.util.Map;

// construct once per callsite (cheap; binds the user)
Client client = new Client(Map.of("user_id", "u_123"));

boolean killed = client.getKillswitch("payments"); // killswitch name
// optional second arg reads one named per-key switch (null = whole killswitch):
// boolean off = client.getKillswitch("payments", "eu_region" /* switchKey */);

if (killed) {
    // disable the protected path
}

metrics

metrics / track

Track a metric/conversion event from the bound Client. Metrics in the dashboard are computed from these events. Assumes Shipeasy.configure(...) ran at startup — see Installation.

Track an event

import ai.shipeasy.Client;
import java.util.Map;

Client client = new Client(Map.of("user_id", "u_123")); // construct once per callsite

// track(eventName, props)
//   eventName — the event your metric is built on (required)
//   props     — optional payload; numeric/string fields you can sum/filter on in
//               a metric (private attributes are stripped before egress)
client.track("checkout_started", Map.of("amount", 49, "currency", "usd"));

Fire-and-forget (never blocks your response) and a no-op under Shipeasy.configureForTesting / configureForOffline. The unit is the bound user (user_id, else anonymous_id); with no unit the call is a no-op.

Track without properties

Client client = new Client(Map.of("user_id", "u_123")); // construct once per callsite

client.track("checkout_started", Map.of()); // props are optional (pass an empty map)

ops

ops / see

Report a caught, handled error (or a non-exception "violation") to Shipeasy with see() — fire-and-forget, never re-throws. The static form reports against the engine from Shipeasy.configure(...). Assumes Shipeasy.configure(...) ran at startup — see Installation.

Report a handled exception

import static ai.shipeasy.See.see;
import java.util.Map;

try {
    charge(order);
} catch (Exception e) {
    // .causesThe(subject)  what the error affects (e.g. "checkout")
    // .to(outcome)         the terminal — what you do about it; builds + fires once
    see(e).causesThe("checkout").to("use the backup processor");
    fallbackCharge(order);
}

Attach context with .extras(...)

import static ai.shipeasy.See.see;

try {
    charge(order);
} catch (Exception e) {
    // .to(outcome, map)    PREFERRED: fold the extras into the terminal. The
    //                      consequence sentence stays whole and there is no
    //                      ordering to remember.
    see(e).causesThe("checkout").to("use cached prices", Map.of("order_id", oid));

    // .to returns void, so extras CANNOT trail it — this does not compile:
    // see(e).causesThe("checkout").to("use cached prices").extras(Map.of("order_id", oid));

    // NEVER: extras wedged between the subject and the outcome — it splits the
    // consequence sentence in half and is hard to read.
    // see(e).causesThe("checkout").extras(Map.of("order_id", oid)).to("use cached prices");
}

Attach context from anywhere with See.addExtras(...)

Prefer this over the inline form whenever the context already exists above the catch — it keeps the catch site a clean one-liner.

import static ai.shipeasy.See.see;
import ai.shipeasy.See;

// Buffer extras earlier in the request — from any layer, not just the catch.
// Every see() report that fires LATER on the same thread carries them, so you
// don't have to thread context down into the catch site. Thread-local, so
// concurrent requests never mix; AnonIdFilter clears it per request (register it
// like any servlet filter — outside a servlet request call See.clearExtras()).
See.addExtras(Map.of("order_id", order.id(), "tenant", tenant.slug()));

// ...deep in a service, later in the same request...
try {
    charge(order);
} catch (Exception e) {
    // report carries order_id + tenant automatically; a chained .extras / inline
    // .to extra of the same key wins over the ambient one.
    see(e).causesThe("checkout").to("use cached prices");
}

Report a non-exception violation

import static ai.shipeasy.See.violation;

// a bad state that isn't an exception — the name is a STABLE fingerprint; put
// variable data in .extras, never the name. .to() is the terminal.
violation("missing_invoice").causesThe("billing").to("skip the dunning email");

Mark an expected exception — report NOTHING

import static ai.shipeasy.See.controlFlowException;

try {
    parse(token);
} catch (NoSuchElementException e) {
    // transmits nothing; .because(...) is local-debug only
    controlFlowException(e).because("end of stream is expected");
}
Was this page helpful?
Updated July 25, 2026

On this page