Skip to main content

smart_grow_logs_plugin 3.1.0 copy "smart_grow_logs_plugin: ^3.1.0" to clipboard
smart_grow_logs_plugin: ^3.1.0 copied to clipboard

retracted

Flutter plugin for Smart Grow Logs SDK. Secure logging with end-to-end encryption. Supports Android and iOS.

Smart Grow Logs Plugin for Flutter #

Smart Grow Logs for Flutter sends encrypted logs from your app to Smart Grow Logs, with optional automatic capture of uncaught errors.

What This Plugin Is For #

Use this plugin if you want to:

  • send debug, info, warn, error and fatal logs from Flutter
  • attach metadata such as user, session or business context
  • capture uncaught Flutter errors automatically
  • capture async errors launched in a guarded zone
  • capture failures from secondary isolates when you wire them explicitly

Before You Start #

You need:

  1. A Smart Grow Logs project.
  2. An API key.
  3. Your ingestion URL, for example https://logs-api.smart-grow.app/.

Installation #

Add the dependency:

dependencies:
  smart_grow_logs_plugin: ^3.1.0

Requires a Smart Grow Logs server >= 5.2.0.

Then run:

flutter pub get

Quick Start #

This is the recommended startup pattern for most Flutter apps:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await SmartGrowLogs.initialize(
    apiKey: 'sgl_your_api_key',
    baseUrl: 'https://logs-api.smart-grow.app/',
  );
  runApp(const MyApp());
}

Desde Flutter 3.3 (el mínimo de este plugin) PlatformDispatcher.instance.onError captura los errores asíncronos no controlados de la zona raíz, así que no hace falta envolver main en una zona. runWithAutoCapture() sigue disponible para quien necesite una zona propia.

Common Use Cases #

1. Send a Simple Log #

await SmartGrowLogs.instance.info('User opened settings');

2. Send a Log With Metadata #

metadata acepta un String (JSON o texto plano, tal cual) o cualquier otro objeto, que se serializa con jsonEncode (por ejemplo un Map):

await SmartGrowLogs.instance.warn(
  'Payment retry scheduled',
  metadata: {'orderId': 'ORD-123', 'retry': 2},
  userIdentifier: 'user@example.com',
  sessionId: 'session-abc-123',
);

3. Default User and Session #

setUser/setSession fijan un userIdentifier/sessionId por defecto para todos los logs (manuales y auto-capturados, incluidos los errores auto-capturados) que no pasen uno explícito en la llamada. Un valor explícito en la llamada siempre gana; null borra el defecto. Se resuelven antes de beforeSend, que puede verlos y modificarlos o quitarlos.

SmartGrowLogs.instance.setUser('user@example.com');
SmartGrowLogs.instance.setSession('session-456');

await SmartGrowLogs.instance.info('User opened profile'); // lleva userIdentifier y sessionId por defecto
await SmartGrowLogs.instance.warn(
  'Impersonating support view',
  userIdentifier: 'support-agent-1', // gana el explícito
);

// En logout:
SmartGrowLogs.instance.setUser(null);
SmartGrowLogs.instance.setSession(null);

4. Capture a Caught Exception #

try {
  await repository.sync();
} catch (error, stackTrace) {
  await SmartGrowLogs.instance.errorWithException(
    'Sync failed',
    error,
    stackTrace: stackTrace,
    metadata: '{"feature":"sync"}',
  );
}

5. Send a Full Custom Log #

final response = await SmartGrowLogs.instance.sendLog(
  LogOptions(
    level: LogLevel.error,
    message: 'Checkout failed',
    stackTrace: StackTrace.current.toString(),
    metadata: '{"cartId":"CART-42","step":"payment"}',
    userIdentifier: 'user@example.com',
    sessionId: 'session-abc-123',
  ),
);

if (!response.success) {
  debugPrint('Log failed: ${response.error}');
}

Cola offline y flush #

Desde 3.0.0 todo log (manual o auto-capturado) se encola en la cola cifrada del SDK nativo y el core la entrega de forma asíncrona. Esto implica:

  • LogResponse.logId es siempre null: el id del servidor ya no se conoce de forma síncrona en la llamada.
  • Que sendLog/info/error/... devuelvan success: true significa "aceptado en la cola local cifrada", no "entregado".
  • Llama a flush() para drenar la cola de inmediato y esperar (del lado nativo) hasta un timeout, por ejemplo antes de que la app pase a segundo plano:
final drained = await SmartGrowLogs.instance.flush(timeoutMs: 5000);

Devuelve si no quedó nada pendiente.

Sobre v2: contra un servidor ≥ 5.3.0 el core negocia automáticamente el sobre v2 (deflate + AES-GCM + base64) para la cola; contra 5.2.x sigue usando el sobre v1. No requiere ningún cambio en el código del SDK: la negociación es transparente.

minLevel #

Pasa minLevel a initialize para descartar en el core nativo, antes de tocar disco, los eventos por debajo de un umbral:

await SmartGrowLogs.initialize(
  apiKey: 'sgl_your_api_key',
  baseUrl: 'https://logs-api.smart-grow.app/',
  minLevel: LogLevel.info,
);

Default: LogLevel.debug (no filtra nada).

beforeSend #

beforeSend corre en Dart, una vez por evento, en todos los caminos de envío: llamadas manuales (info, error, sendLog, ...) y los cuatro mecanismos de auto-captura (FlutterError.onError, PlatformDispatcher.onError, runWithAutoCapture, errores de isolate). Devuelve el evento modificado o sin modificar, o null para descartarlo antes de que llegue a la cola nativa:

await SmartGrowLogs.initialize(
  apiKey: 'sgl_your_api_key',
  baseUrl: 'https://logs-api.smart-grow.app/',
  beforeSend: (options) {
    if (options.message.contains('password')) return null;
    return options.copyWith(message: options.message);
  },
);

Si beforeSend lanza una excepción, se atrapa y el evento se envía sin modificar. Nunca debe hacer trabajo de red ni bloquear.

Nota: los crashes nativos capturados directamente por los SDKs nativos de Android/iOS (excepción JVM no controlada, NSException, ANR, MetricKit) no pasan por este beforeSend de Dart; solo lo hacen los eventos generados desde Dart.

Nota: si llamas a initialize más de una vez, las opciones nativas (minLevel, androidAnrWatchdogEnabled/androidAnrTimeoutMs, extraCaPem) se fijan en la primera llamada y no se reenvían al canal en llamadas posteriores; beforeSend y autoCaptureEnabled sí se actualizan en cada llamada.

Auto-Capture #

When autoCaptureEnabled is true, the plugin installs these mechanisms automatically:

  • FlutterError.onError for framework and rendering errors
  • PlatformDispatcher.instance.onError for uncaught main-isolate runtime errors
  • runWithAutoCapture() for async errors inside the guarded zone

Cobertura de auto-captura #

All auto-captured errors from Dart mechanisms are sent at fatal level, and every one of them (Dart and native) carries autoCaptured: true.

Fallo Dart Android 8-10 Android 11 Android 12+ iOS 14+
Error de framework / async no controlado Sí — — — —
Error en aislado secundario Con createIsolateErrorListener — — — —
Excepción JVM / NSException no controlada — Sí Sí Sí Sí
ANR / hang del hilo principal — Watchdog opt-in Sí (sistema) + watchdog Sí (sistema) + watchdog Sí (MetricKit)
Crash nativo (engine, plugins, Rust) — No Razón y señal Razón y señal Sí (MetricKit, sin simbolicar)
Muerte por memoria — No Sí Sí Sí (MetricKit)
Crash antes de runApp — Sí (instalación temprana del plugin) Sí Sí Sí

Instalación temprana #

El plugin instala los handlers nativos de auto-captura al registrarse en el engine de Flutter, antes de que se ejecute main(). Esto es lo que permite cubrir crashes previos a runApp en la tabla de arriba.

Se puede desactivar:

  • Android: <meta-data android:name="app.smart_grow.logs.AUTO_CAPTURE_EARLY" android:value="false"/> en el manifest.
  • iOS: clave SmartGrowLogsAutoCaptureEarly con valor NO en Info.plist.

Lo que sigue sin cubrirse son los crashes que ocurren en Application.onCreate (Android) o AppDelegate (iOS) antes de que el engine registre este plugin. Para ese caso extremo, el integrador puede llamar directamente a installCrashMarkersEarly (Android) o installAutoCaptureEarly (iOS) desde su propio código nativo, lo antes posible en el arranque.

Throttle #

Los eventos automáticos pasan por el mismo throttle del core nativo que los logs manuales: si un mismo tipo de fallo se repite en un bucle, el SDK limita cuántos envía en lugar de saturar la red o el backend.

Disable Auto-Capture #

Disable it if your app already owns global error handling and you want to forward failures manually:

await SmartGrowLogs.initialize(
  apiKey: 'sgl_your_api_key',
  baseUrl: 'https://logs-api.smart-grow.app/',
  autoCaptureEnabled: false,
);

Secondary Isolates #

If your app uses Isolate.spawn, create one listener on the main isolate and pass its sendPort to child isolates.

final isolateErrorPort = SmartGrowLogs.createIsolateErrorListener(
  mechanism: 'MyBackgroundIsolate',
);

await Isolate.spawn<SendPort>(
  backgroundEntryPoint,
  isolateErrorPort.sendPort,
  onError: isolateErrorPort.sendPort,
  errorsAreFatal: true,
);

void backgroundEntryPoint(SendPort errorPort) {
  SmartGrowLogs.attachCurrentIsolateToAutoCapture(errorPort);
  throw StateError('Background isolate failure');
}

When that listener is no longer needed:

isolateErrorPort.close();

API Essentials #

Main entry points:

  • SmartGrowLogs.initialize(...)
  • SmartGrowLogs.instance
  • SmartGrowLogs.instance.setUser(identifier) / SmartGrowLogs.instance.setSession(id): defectos de userIdentifier/sessionId para todos los logs
  • SmartGrowLogs.instance.flush({timeoutMs})
  • SmartGrowLogs.runWithAutoCapture(...)
  • SmartGrowLogs.createIsolateErrorListener(...)
  • SmartGrowLogs.attachCurrentIsolateToAutoCapture(...)

Main send methods (todos aceptan metadata como String o cualquier objeto serializable con jsonEncode, más userIdentifier y sessionId):

  • debug(...) (logDebug(...) queda como alias @Deprecated)
  • info(...)
  • warn(...)
  • error(...)
  • errorWithException(...)
  • fatal(...)
  • sendLog(LogOptions(...))

Response object:

  • success: whether the log was accepted into the local encrypted queue
  • logId: always null since 3.0.0 (delivery is asynchronous, handled by the native core's queue)
  • error: failure message when not successful

Cada log lleva clientTimestamp (UTC, RFC 3339) marcado por Dart en el momento del evento.

Performance Recommendation #

Logging does network work. If you do not need to wait for the result, prefer non-blocking usage:

unawaited(SmartGrowLogs.instance.info('Screen opened'));

Use await only when you need to inspect success, logId or error.

Troubleshooting #

I get a zone error when starting the app #

Make sure WidgetsFlutterBinding.ensureInitialized() and runApp() are both inside SmartGrowLogs.runWithAutoCapture(...).

My child isolate errors are not showing up #

Make sure you:

  1. create the listener on the main isolate
  2. pass its sendPort to Isolate.spawn
  3. call attachCurrentIsolateToAutoCapture(sendPort) inside the child isolate

iOS crashes appear on the next launch #

That is expected for uncaught NSException. The plugin persists a crash marker and retries delivery on the next successful startup.

La UI se congelaba al enviar logs en iOS (2.0.x) #

Resuelto en 2.1.0: el plugin envía desde una cola en segundo plano en lugar de bloquear el hilo principal.

Requirements #

  • Flutter 3.3.0+
  • Dart 3.0.0+
  • iOS 15.0+
  • Android API 26+

Este plugin cubre Android e iOS. Flutter Web: usa @smart-dev-agency/smart-grow-logs (el paquete npm) directamente.

License #

Proprietary - Smart Dev Agency

1
likes
0
points
44
downloads

Publisher

verified publishersmart-dev.com.co

Weekly Downloads

Flutter plugin for Smart Grow Logs SDK. Secure logging with end-to-end encryption. Supports Android and iOS.

Repository
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on smart_grow_logs_plugin

Packages that implement smart_grow_logs_plugin