cyclopes_
sign in sign up

Docs / Web

JavaScript

Browser and Node from one package, zero dependencies. Global handlers for whichever runtime you are in are installed for you.

What you need first

A project's DSN. Create a project, then copy it from that project's settings page: it carries the host and the project id, so it is the only thing this SDK needs to be pointed at.

https://<key>@cyclopes.localhost.co.zw/ingest/<project-id>

The key is write-only: it can send events and nothing else, so shipping it inside a mobile app is fine. Read it from your environment rather than committing it.

Install

The package is served by this install rather than by npm, so install it from the tarball this server publishes.

$ npm install https://cyclopes.localhost.co.zw/packages/cyclopes-sdk-0.4.0.tgz

Wire it up

import * as cyclopes from "@cyclopes/sdk";

cyclopes.init({
  dsn: "https://<key>@cyclopes.localhost.co.zw/ingest/<project-id>",
  environment: "production",
  release: "webapp@2.0.0",
});

That is enough for errors. Uncaught errors and unhandled promise rejections are reported automatically: window.onerror and onunhandledrejection in the browser, uncaughtException and unhandledRejection in Node.

Errors

try {
  risky();
} catch (err) {
  cyclopes.captureException(err);
}

cyclopes.setTag("tier", "pro");
cyclopes.setUser({ id: "u_123" });
cyclopes.captureMessage("checkout completed", { level: "info" });

Events go out with fetch, using keepalive so they survive a page navigation, from a queue that drops silently on failure. A Cyclopes outage never breaks or blocks your application.

Logs and journeys

Logs and activity are buffered together and streamed in batches: 30 items, or five seconds after the first, whichever comes first, plus a best-effort flush on page hide and process exit.

cyclopes.logger.debug("cache miss", { key: "user:42" });
cyclopes.logger.info("checkout started");
cyclopes.logger.warn("retrying payment", { attempt: 2 }); // sent as "warning"
cyclopes.logger.error("payment failed", { gateway: "stripe" });

cyclopes.track("checkout_started", { cart_total: 42 });
cyclopes.screen("Cart", { items: 3 });
cyclopes.identify({ id: "u_123", email: "u@example.com" });

identify() also stores the user as the client's identity: later error events use it as event.user unless setUser() set one explicitly. Every batch and every error carries the same session id, so the server can line an error up with the journey that led to it.

screen() records where the user is, and every track() after it says so. For an arrival no navigation announces, a modal, a tab, a step in a wizard, say so yourself:

cyclopes.setCurrentScreen("PromoSheet");

cyclopes.flush() flushes pending events and the batch together. Call it before a short-lived Node process exits.

Sessions

A session is one continuous sitting. The SDK makes an id at init() and rotates it after 30 idle minutes (sessionTimeout: 1800; 0 disables). In the browser it lives in sessionStorage, so it survives navigation but dies with the tab: two tabs are two sessions, on purpose.

cyclopes.newSession();          // rotate explicitly, e.g. on logout
cyclopes.setSession("abc");     // pin a known id

On Node, scope one per request. Otherwise every user you serve shares one session id and their journeys merge together:

await cyclopes.withSession(req.id, async () => {
  cyclopes.track("checkout_started", { cartTotal });
});

Nothing leaks across a withSession scope: one request's page is never stamped onto another request's actions.

Breadcrumbs and context

cyclopes.addBreadcrumb({ category: "navigation", message: "/checkout", level: "info" });
cyclopes.addBreadcrumb({ category: "http", message: "POST /api/pay → 500", level: "error" });
// browser (userAgent) and runtime (node/browser) contexts attach automatically

Every field, breadcrumbs and contexts included, passes through beforeSend(event) => event | null before it leaves the client, so you can redact or drop anything.

Options

optiondefaultmeaning
dsnnoneRequired. Your project DSN.
environment""e.g. production, staging.
release""e.g. webapp@2.0.0.
beforeSendnull(event) => event | null: scrub PII, or drop the event.
autoSessionHandlerstrueInstall the global error handlers.
debugfalseLog transport problems to console.warn.