npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@e-volv/logs-react-native

v0.1.0

Published

e-volv Observer SDK for React Native — logs, traces, JS crash capture and traceparent propagation. A wrapper with no transport of its own: finished events cross the native module into the Android (io.e-volv:logs-android) and iOS (e-volv-logs-swift) client

Readme

@e-volv/logs-react-native

e-volv Observer SDK for React Native — logs, traces, JS crash capture and traceparent propagation against the e-volv ingest endpoint (POST /api/public/v1/logs). A wrapper with no transport of its own: the JS layer builds events with the browser core's model and redaction (packages/logs-js/src/types.ts, vendored into src/types.ts) and hands finished events over a TurboModule to the Android client (io.e-volv:logs-android) or the iOS client (e-volv-logs-swift), which own the disk queue, the retry schedule, the lifecycle flush and crash capture. Companions: @e-volv/logs (Node/browser), e-volv-logs (Python), e-volv-logs-go (Go). All speak one wire contract (docs/OBSERVER-SDK.md).

React Native 0.74+, New or Old Architecture. react and react-native are peer dependencies.

Quick start

npm install @e-volv/logs-react-native
# iOS:
cd ios && pod install   # New Architecture: codegen runs from package.json's codegenConfig
import EvolveLogs from '@e-volv/logs-react-native';

EvolveLogs.init({
  key: 'evk_pub_…', // public project key — the ONLY kind allowed in an app
  appId: 'com.acme.shop', // Android application id / iOS bundle id
  service: 'shop-app',
  environment: 'production',
  release: '1.4.2', // match the --release you upload source maps for
});

EvolveLogs.info('order created', { orderId: 'o_1', total: 42.5 });

try {
  await charge();
} catch (err) {
  EvolveLogs.exception(err, { orderId: 'o_1' }); // exception.type/message/stack
}

await EvolveLogs.span('db.query', () => db.query('…'), { table: 'orders' });
// an exception inside the callback ends the span as failed and rethrows

// Queue consumers / deep links: continue an inbound traceparent.
EvolveLogs.runWithTraceparent(job.traceparent, () => {
  EvolveLogs.info('job received', { jobId: job.id });
  EvolveLogs.span('queue.consume', () => handle(job));
});

If key or appId is missing the client is a no-op and warns once. A server key (evk_…) is refused — it has no app-id allowlist and no per-install quota, so it must never ship in a binary; mobile SDKs only accept evk_pub_… public keys. The JS layer holds no key material beyond the configure() call into native.

Launch flags

EvolveLogs.init({ key: 'evk_pub_…', appId: 'com.acme.shop' });

// Reads are synchronous — a snapshot the native client holds, never a bridge
// round trip. Before the first snapshot they return your default.
const checkout = EvolveLogs.flags.bool('checkout.new', false);

// Login/logout: re-fetch values for the new context.
await EvolveLogs.flags.identify({ targetingKey: user.id, plan: user.plan });

await EvolveLogs.flags.ready(); // first network confirmation
EvolveLogs.flags.onChange((keys) => {
  // native pushed a new snapshot
  if (keys.includes('checkout.new')) render();
});
await EvolveLogs.flags.verify(); // the install check (GET /ping)

With the native module linked, the native flags client is the single fetcher — it owns fetching, the on-device cache (§6), polling and lifecycle refresh, and pushes a JSON snapshot over the bridge on every change. Without one (Expo Go, nativeTransport: false) the shared @e-volv/flags-client core fetches with fetch, caches in AsyncStorage when the optional @react-native-async-storage/async-storage peer is installed, and refreshes on AppState active. The two are never active at once.

Options: flags: false disables flags; otherwise flags takes the client flags options of contract §4 (context, pollIntervalSeconds, cache, privateAttributes, exposures.*). Exposures are recorded on the JS side, where reads happen, and drained to native in batches — a read is recorded exactly once.

What runs where

| Concern | Owner | | ----------------------------------------------------------------------------------------------------- | ----------------- | | Event model, redaction, span/trace ids, JS crash capture, fetch/XHR traceparent | JS layer (src/) | | Disk queue, batching, gzip, retry, lifecycle flush, x-evolve-app-id / x-evolve-install-id headers | Native clients | | Native crashes (Kotlin exceptions, ANRs, Obj-C/Swift exceptions, signals) | Native clients |

JS crashes are captured by wrapping ErrorUtils.getGlobalHandler / setGlobalHandler, chaining the previous handler so the red box and the fatal-crash behaviour are unchanged. Because JS and native events carry the same key, app id and release, both crash streams land in one project.

Options (init)

key (public evk_pub_…), appId, service, environment, release, redactKeys (extra keys merged into the standard password|secret|token|authorization|cookie|set-cookie|api[-_]?key backstop), sampleRate (0–1), nativeTransport (default true), networkInstrumentation (default true), captureJsErrors (default true), url + fetchImpl (only used when nativeTransport: false), flags (Launch flags options or false, see above).

nativeTransport: false makes the JS layer ship events itself with fetch (identity encoding, the mobile headers sent from JS). It exists for development, tests and the conformance runner — it has no disk queue, so it is not a production configuration.

Network instrumentation

With networkInstrumentation: true (default), fetch and XMLHttpRequest made inside a span/trace get a W3C traceparent header — an existing header is never overwritten — and traceparent is read off responses (EvolveLogs.getLastResponseTraceparent()), so a later JS crash can be attached to the server trace that caused it.

Architecture

New Architecture: src/spec/NativeEvolveLogs.ts is the codegen spec (codegenConfig in package.json); the JSI TurboModule (NativeEvolveLogs) serves all four methods with no bridge serialization. Old Architecture: the same Kotlin class / ObjC++ module is served through the bridge (hand-written spec on Android, NativeModules fallback on the JS side). Autolinking picks the package up on both platforms; no manual linking step.

TurboModule method map

| Method | Direction | Purpose | | ---------------------- | ---------------------- | ------------------------------------------------------------------------------------------ | | configure(config) | JS → native, once | Init the native client (key, appId, service, environment, release, redactKeys, sampleRate) | | emitEvent(eventJson) | JS → native, per event | Hand a finished, redacted event (JSON) to the native queue | | flush() | JS → native, promise | Resolve when the native queue is empty | | getInstallId() | native → JS, promise | The SDK install id (also sent as x-evolve-install-id) |

Native interfaces (S5 clients, wired in S6)

The bridges call the real native clients — no assumed facades:

  • Android (packages/logs-jvm/android, io.e-volv:logs-android): EvolveLogsAndroid.init(context, EvolveAndroidOptions) (built with EvolveAndroidOptions.builder(); a server key is refused with IllegalArgumentException and surfaced once), EvolveLogsAndroid.clientOrNull()?.emitJson(eventJson), client.flush() (the bridge moves it off the JS thread), client.installId().
  • iOS (packages/logs-swift, pod EvolveLogs): EvolveLogs.initialize(EvolveLogsOptions(key:url:service:environment:release:redactKeys:sampleRate:appID:)), client.emit(json:), client.flush() (on a utility queue), client.installID.

The compile gate for both is ci.yml's react-native-build job, which builds the generated example/ app (both architectures on Android) against the published native artifacts.

Source maps (Hermes)

Release builds ship minified Hermes bytecode, so JS stacks arrive as bytecode frames. Upload the source map per release — make it a release-pipeline step, one per platform:

# Android (index.android.bundle.map) and iOS (main.jsbundle.map):
evolve-logs upload-artifacts --key evk_… --url https://api.e-volv.io \
  --release 1.4.2 --platform react-native --type sourcemap \
  index.android.bundle.map

(evolve-logs is the CLI in tools/logs-cli, or npx @e-volv/logs.) Without the map the error group still forms and counts, but frames show minified names and no file:line.

Conformance

The JS layer conforms in Node through the pure-JS transport:

npx tsx packages/logs-conformance/run.ts packages/logs-conformance/fixture.json -- \
  npx tsx packages/logs-react-native/runner/conformance-runner.ts

Launch flags conform through the same pure-JS path (the Expo Go fallback — the native path is S5's own conformance rows):

npx tsx packages/flags-conformance/run.ts client -- \
  npx tsx packages/logs-react-native/runner/flags-conformance-runner.ts

Under npx react-native run-android / run-ios, the same runner conforms through the native path with nativeTransport: true (the stub URL is reachable from the device/emulator via adb reverse / the dev-server host).

Limitations

  • The Kotlin/Swift in android/ and ios/ is compile-gated by ci.yml's react-native-build job (the generated example/ app on both Android architectures and the iOS simulator). The underlying native clients are unit-tested in their own packages (Robolectric / XCTest).
  • In the default native mode the JS buffer is a hand-off, not a queue: if the native module is missing, events are dropped with a startup warning.
  • XHR interception wraps send/setRequestHeader on the prototype; a request that sets traceparent itself is left untouched by contract, but exotic XHR subclasses that bypass the prototype are not covered.
  • nativeTransport: false keeps the buffer in memory and sends identity (ungzipped) bodies — development and conformance only.