faro 0.17.0 copy "faro: ^0.17.0" to clipboard
faro: ^0.17.0 copied to clipboard

Grafana Faro SDK for Flutter applications - Monitor your Flutter app with ease.

Changelog #

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased] #

0.17.0 - 2026-09-21 #

Added #

  • Application-specific HTTP query values can be redacted alongside the built-in credential parameters. The same policy applies to spans, HTTP events and fallback network-error logs without changing requests. See the Reference docs for configuration and matching behavior (#346).

  • Known HTTP methods include http.request.method on spans and faro.tracing.fetch events (#109).

Changed #

  • HTTP spans use stable attribute names, including url.full, server.address, server.port, and http.response.status_code. Legacy HTTP fields are removed from automatic spans. The faro.tracing.fetch event retains its existing fields, with URL redaction as described below. Update span consumers before adopting this private-preview schema. See the Reference docs for details (#346).

  • Known HTTP client span names are method-only, such as GET and POST, instead of HTTP GET and HTTP POST. HTTP convenience methods use uppercase verbs. When querying across an SDK upgrade, include both old and new names. For example, a GET TraceQL filter can use { name = "GET" || name = "HTTP GET" || name = "HTTP get" } (#109).

  • Automatic HTTP spans use the faro-mobile-flutter.http scope. Queries that filter by instrumentation scope should include this scope alongside faro-mobile-flutter when searching across SDK versions (#109).

  • Use Dartastic OpenTelemetry stable 0.11.0, which preserves unset span status when a span ends. This also includes upstream sampling fixes: child spans respect an unsampled parent, and only sampled spans are exported.

Fixed #

  • Lowercase and mixed-case known HTTP methods use canonical span names, matching the method sent by Dart's HTTP client. For example, get and GeT produce GET. When the spelling differs from the canonical method, spans and events record it in http.request.method_original (#109).
  • HTTP spans without a response omit the response code and include the exception type in error.type. Faro HTTP events retain the legacy http.status_code value of "0" (#346).
  • HTTP telemetry URLs redact credentials and sensitive query values in spans, events and fallback network-error logs, including common token, password and API-key query parameters. The request URL is unchanged. Exact URL filters and grouping use the redacted values. See the Reference docs for the policy (#346).
  • Successful HTTP spans leave status unset, following OpenTelemetry HTTP conventions. Response completion preserves any previously recorded error (#24).
  • HTTP error responses include a string error.type, such as "404" or "500", and omit the redundant status description. The HTTP event also includes this attribute (#24).

0.17.0-beta.3 - 2026-08-27 #

Added #

  • Add Faro.resetSession() for logout, account changes, and custom session boundaries. It immediately starts and links a new session, restarts timing and sampling, emits session_start, and updates persisted session state (#315).
  • Persist a minimal, versioned session record by default. Every cold start creates a new session and links the prior session ID when known instead of resuming the same live session. Independent native processes use separate records, and secondary Flutter engines or isolates fail closed to in-memory sessions (#283).
  • Rotate the active session when the Grafana Cloud receiver accepts a payload with X-Faro-Session-Status: invalid, following the Faro Web SDK response handling. Duplicate or delayed responses for an older session are ignored. (#286)
  • Automatic log-trace correlation: Logs, events, exceptions, and measurements pushed via pushLog, pushEvent, pushError, and pushMeasurement while a span is active are now automatically stamped with the active span's trace_id/span_id, matching the Faro Web SDK and the OpenTelemetry logs data model. All four push methods accept an optional spanContext parameter (new FaroSpanContext(traceId:, spanId:) value type; use span.spanContext when you hold a Span) that always takes precedence over the active span. Span context is captured at push time, so buffered signals keep the span that was active when they were recorded.
  • App-owned spans in FaroWebViewBridge. instrumentedUrl accepts an optional span and propagates that span's traceparent instead of creating a span of its own, so repeated calls during one WebView session keep injecting the same traceparent. The bridge leaves a span you pass in untouched — no attributes, no status, and end() will not end it. See the Reference docs for details.
  • FaroStartupProvider, a content provider merged into your Android manifest automatically. It samples process importance at startup so the SDK can tell a user-initiated launch from a background one; it stores no data and answers no queries. It can be removed with tools:node="remove", at the cost of cold start reporting on Android entirely. See the Reference docs for details.

Changed #

  • BREAKING (behavioral): iOS recovered crashes now use type: crash. The native signal and code remain available in context.nativeType. Dashboards and alerts matching signal names in exception.type should match crash and read context.nativeType instead (#269).
  • Automatic session rotations now re-evaluate sampling. Sessions created after inactivity, maximum lifetime, or receiver invalidation make an independent sampling decision, matching explicit resets and Faro Web. Telemetry collection can now start or stop when a session rotates instead of retaining the previous session's decision. (#284)
  • BREAKING (behavioral): Session inactivity now refreshes only for user interactions, view or navigation changes, foreground returns, explicit user actions, and spans linked to those actions. Generic telemetry, unmarked spans and HTTP requests, lifecycle events, asset loads, and automatic measurements still check expiry but no longer keep an idle session alive. Applications that relied on pushEvent, pushLog, pushError, pushMeasurement, or unmarked spans to extend a session should wrap that work in startUserAction. (#314)
  • BREAKING: The trace: Map<String, String>? parameter on pushLog and pushEvent is replaced by spanContext: FaroSpanContext?. pushError and pushMeasurement also gain the optional spanContext parameter (additive — they had no trace parameter before). Migrate by wrapping ids in FaroSpanContext(traceId:, spanId:), or use span.spanContext when you hold a Span.
  • BREAKING: The HTTP tracking integration now only exports FaroHttpOverrides from package:faro/faro.dart. The internal wrapper classes (FaroHttpTrackingClient, FaroTrackingHttpClientRequest, FaroTrackingHttpResponse) were previously exported unintentionally and are no longer part of the public API. Only FaroHttpOverrides is needed to enable HTTP tracking. This is a source-breaking change only for code that imported those implementation-detail classes directly.
  • The cold start interval now ends at the first frame the engine rasterized rather than the first frame after Faro.init. An app that initialises Faro after that frame is measured up to init instead, which is still shorter than before.
  • app_startup measurements carry an additional prewarmed value (1 when iOS prewarmed the process, 0 otherwise). appStartDuration and coldStart are unchanged, so existing dashboards keep working.

Deprecated #

  • Direct crash-reporter setup is deprecated. Enable crash reporting and configure its transports through FaroConfig instead of calling Faro.enableCrashReporter.

Fixed #

  • Recovered Android crashes now respect process-scoped session ownership. Only the root Flutter engine that owns the durable session chain reads historical application exits. Other engines, including those whose native process identity cannot be resolved, skip recovery instead of emitting an old crash with an unrelated live session. If ownership cannot be established during startup, recovery is deferred to a later launch. Enable crash reporting on every root-engine entrypoint that may initialize Faro first (#340).
  • iOS crash reports now use the configured SDK transports. Pending PLCrashReporter data returns to Dart on the next launch and follows the configured collector and custom transport paths, sampling, data collection policy, and collector headers. Accepted reports are purged; collector rejections and transport errors remain pending. Custom transports must complete with an error when handoff fails because returning normally counts as acceptance. Reports are discarded when data collection is disabled. Pending native reports skip OfflineTransport because the native report is already the durable retry copy (#269).
  • Recovered native crashes retain their original session. Android and iOS crash metadata includes crashedSessionId and preserves the persisted sampling decision without changing the new live session. Historical Android exits are matched to their retained per-process sessions. When persistence is active, crashes without a matching session are discarded instead of being attributed to the new session (#151).
  • Session lifecycle events now use session_start for every new session. Flutter no longer emits the Web-only session_extend event when rotation creates a new session. Expect session_extend volume to drop to zero on Flutter and session_start volume to increase by the same number of rotation events. Dashboards and alerts matching session_extend should match session_start and read meta.session.attributes.previousSession to identify linked sessions (#316).
  • Accurate Android runtime metadata. Root Flutter engines that never attach to an Activity now report dart_isolate_name=headless instead of main. Activity-backed engines remain main; dashboards filtering only for dart_isolate_name=main no longer include Android background engines. Pre-warmed UI engines can opt into FaroEngineRole.foreground, and session-persistence ownership is unchanged (#333).
  • Filter Android LOW_MEMORY exits for service and less important process states regardless of whether Android records status 0 or SIGKILL. Foreground, foreground-service, visible, and perceptible exits remain reportable (#307).
  • Preserve the last known view metadata when navigating through unnamed Flutter routes, and suppress empty view_changed events. (#305)
  • Report Flutter framework errors even when no stack trace is available (#271).
  • HTTP network-error fallback logs are now correlated with their request span. When a response stream error handler has an unsupported signature, the SDK's fallback network_error log now carries the HTTP span's trace_id/span_id instead of no trace context.
  • Forward Android native crash and ANR traces from ApplicationExitInfo into the Faro exception context instead of always reporting No stacktrace.
  • Cold start duration measured process age, not user-visible startup (#302): Processes the system started in the background — push messages, jobs and broadcasts on Android, prewarming on iOS — reported the age of the process as the cold start, which in production data reached hours. Android now reports a cold start only for launches it can show were user-visible; iOS cannot tell a background launch apart, so it instead measures a prewarmed launch from when the SDK loaded. Both platforms discard anything over 60 seconds. Expect cold start volume to drop on Android, where launches that cannot be shown to be user-visible now emit nothing rather than a misleading duration. See the Reference docs for per-platform detection and known limitations.
  • Every launch also reported a phantom warm start of a few milliseconds alongside its cold start. Warm starts are now reported only when the app returns from the background. Expect warm start volume to drop and durations to rise, as those near-zero measurements are gone.
  • Android cold starts no longer count time the device spent in deep sleep.
  • iOS no longer reports a garbage duration when the process start-time lookup fails.

0.17.0-beta.2 - 2026-07-16 #

Added #

  • Session rotation (#52): Sessions now rotate automatically after 15 minutes of inactivity or 4 hours of total lifetime (fixed to match the Faro session definition and the collector's server-side validation). On rotation a new session id is generated, a session_extend event is emitted (the initial session emits session_start), and the previous id is recorded in the previousSession attribute so backends can link sessions. Automatic vitals (CPU, memory, etc.) count as activity only while the app is in the foreground: a foregrounded but idle app (e.g. a user reading a screen) stays in one session, while a backgrounded app's vitals cannot keep its session alive. Sampling is not re-evaluated on rotation. See the Reference docs for full details.

Fixed #

  • Offline transport is now resilient to malformed cache data (#22). A corrupt cached entry (e.g. from a partial write or schema drift) is now skipped and purged instead of aborting the read and permanently blocking all remaining cached telemetry. Additionally, payloads whose user-supplied log context or event attributes cannot be JSON-encoded (a DateTime, custom object, or non-finite double) are dropped with a type-only diagnostic rather than failing the cache write.
  • Offline transport connectivity probe reliability (#11): The DNS lookup used by OfflineTransport to confirm internet access now has a 5-second timeout (previously it could hang indefinitely on some platforms, stalling online/offline decisions) and catches all probe errors instead of only SocketException. Any probe failure is still treated as offline: while offline, payloads are cached on disk and flushed once connectivity returns, whereas a send attempted while actually offline is dropped without retry — so a false "offline" only costs disk usage, while a false "online" would risk permanent data loss. Overlapping probes from rapid connectivity changes are now also ordered: a stale probe result that completes after a newer probe can no longer overwrite the newer online/offline state. The lookup function is also injectable for testing via the new required addressLookup parameter and optional lookupTimeout parameter on InternetConnectivityService.

0.17.0-beta.1 - 2026-07-01 #

Changed #

  • Renamed the SDK-generated install identifier model and provider to InstallationId / InstallationIdProvider. The persisted device_id storage key and legacy flat session.attributes['device_id'] payload key are unchanged for migration compatibility.
  • Swapped the underlying OpenTelemetry implementation from the Workiva opentelemetry Dart package to dartastic_opentelemetry for tracing. (#242)

Deprecated #

  • DeviceId is deprecated; use InstallationId instead. The deprecated alias is kept for backward compatibility.

Added #

  • Emit structured mobile metadata in Flutter SDK payloads: meta.device, meta.os, meta.app.installationId, and exception.fatal, while keeping legacy flat session attributes during migration. The duplicated flat device_* session attributes are kept for compatibility and can be removed after collector and plugin query parity is confirmed.

Changed #

  • CI: Attest SLSA build provenance for the published pub.dev archive. Inlined the dart-lang/setup-dart reusable publish workflow so we can download the canonical archive pub.dev serves and attest those bytes via actions/attest-build-provenance. Consumers can verify with gh attestation verify <tarball> --repo grafana/faro-flutter-sdk.

Fixed #

  • Preserve stack trace lines that do not match the expected Dart VM format instead of silently dropping the whole stack trace. Lines that cannot be parsed into structured frames (e.g. sanitized, obfuscated, or free-form lines) are now kept as raw text in the frame's function field. (#102)
  • iOS native crash reports no longer lose all stack frames: a broken work-in-progress sanitization step in CrashReportingIntegration unconditionally replaced non-empty stack traces with an empty array before export. The dead sanitization has been removed so frames flow through to the exported crash payload. Load/parse failures of pending crash reports are now logged with a clearer message before the report is purged. (#220)

0.16.0 - 2026-05-11 #

Added #

  • Span exception handling control: Added SpanExceptionOptions for controlling how exceptions are recorded on spans. Configurable globally via FaroConfig.spanExceptionOptions or per-span via the exceptionOptions parameter of startSpan(). Includes ExceptionSanitizer callback for PII-safe error recording and boolean flags (recordException, setStatusOnException) for selective control. Per-span options are merged field-by-field over the global config — omitted fields inherit from global configuration. If the sanitizer callback throws, the span is marked as failed with a generic status description to avoid leaking PII.

0.15.0 - 2026-05-07 #

Changed #

  • Breaking for consumers on Flutter < 3.29 / Dart < 3.7: Raised the declared Dart SDK lower bound to >=3.7.0 and Flutter lower bound to >=3.29.0 to match the effective device_info_plus dependency floor.
  • Widened device_info_plus dependency to >=12.3.0 <14.0.0 (adds v13.x support).
  • Widened package_info_plus dependency to >=8.0.1 <11.0.0 (adds v10.x support).

0.14.0 - 2026-04-14 #

Fixed #

  • Fix OOM crash in ANRTracker when capturing stack traces on low-memory Android devices (#174).

Changed #

  • SDK metadata improvements: Updated SDK identification to align with Faro Web SDK patterns and improve backend analytics
    • Changed SDK name from 'faro-flutter-sdk' to 'faro-mobile-flutter' to match naming convention discussed with Faro team
    • Removed hardcoded version '1.3.5' workaround and now sends actual SDK version in meta.sdk.version
    • Removed integrations field from SDK metadata (following Faro Web SDK pattern - this field provided no actionable insights)
    • Removed unused Integration model class and its export from models barrel file
    • Backend endpoint service now properly handles Flutter SDK payloads with correct version checking
    • Enables better SDK version analytics and distribution tracking across different Faro implementations
  • Bump Android compileSdkVersion from 35 to 36 (aligned with Flutter default since May 2025).
  • Reorganized iOS source files from ios/Classes/ to ios/faro/Sources/faro/ to support the SPM directory convention.
  • Bumped iOS deployment target from 11.0 to 13.0.
  • Updated faro.podspec metadata (homepage, author, license type, summary/description).
  • Fixed pre-existing Swift compiler warnings in iOS native code.

Added #

  • Swift Package Manager (SPM) support for the iOS plugin, enabling dependency resolution via SPM alongside existing CocoaPods support (#189, #35).
  • Android native unit test infrastructure (JUnit) with CI and pre-release script integration.

0.13.0 - 2026-04-09 #

Added #

  • FaroWebViewBridge — a public API for cross-boundary session and trace correlation between Flutter apps and web apps running in a WebView. Provides instrumentedUrl() to decorate URLs with traceparent and session.parent_* query parameters, linkChildSession() to push a session.linked event correlating the web session, and end() to close the WebView span.

  • Span.traceparent getter — exposes the W3C Trace Context traceparent header value (00-{traceId}-{spanId}-01) directly on the Span interface, removing the need to cast to InternalSpan.

Changed #

  • Widened connectivity_plus dependency to >=6.1.2 <8.0.0 (adds v7.x support).
  • Widened package_info_plus dependency to >=8.0.1 <10.0.0 (adds v9.x support).

Fixed #

  • Faro.init() now ignores repeated calls after the first successful initialization, preventing duplicate startup side effects such as extra transports, repeated session_start events, and duplicate widget observers.
  • Asset loads and tracked HTTP requests now keep user actions pending until the underlying operation completes, avoiding prematurely ended or stalled actions when using long-running asset loads, HttpClientRequest.done, or abort().

0.12.0 - 2026-03-05 #

Deprecated #

  • markEventStart() and markEventEnd() are now deprecated. Use startSpan() for duration tracking. Use startUserAction() when you need interaction-level correlation across logs, events, exceptions, and spans. Use startSpanManual() for manual span lifecycle control.

Added #

  • UI activity monitoring for user actions: The SDK now automatically monitors Flutter widget rebuilds to detect UI responses to user actions. This emits bounded activity signals that keep user actions alive while the UI is updating, similar to DOM mutation observation in the Web SDK. Disable via enableUiActivityMonitoring: false in FaroConfig.
  • Asset load lifecycle signals: Asset loads via FaroAssetTracking now emit activity signals to keep user actions alive during resource loading.
  • Expanded asset tracking: FaroAssetBundle now also tracks loadBuffer and loadStructuredBinaryData in addition to load and loadString.

Changed #

  • BREAKING: FaroAssetTracking replaces FaroAssetBundle in public API: FaroAssetBundle is no longer exported from package:faro/faro.dart. Use FaroAssetTracking(child: ...) instead of DefaultAssetBundle(bundle: FaroAssetBundle(), child: ...).

    // Before
    DefaultAssetBundle(
      bundle: FaroAssetBundle(),
      child: const FaroUserInteractionWidget(child: MyApp()),
    )
    
    // After
    FaroAssetTracking(
      child: const FaroUserInteractionWidget(child: MyApp()),
    )
    
  • HTTP tracking no longer emits the legacy http_request custom event from HttpTrackingClient.

  • HTTP request telemetry continues to be available through span-derived faro.tracing.fetch events and OTLP spans.

  • Pending operation lifecycle signals are now span-driven via UserActionConstants.pendingOperationKey:

    • HTTP spans set this marker automatically.
    • Custom spans can opt in by setting this attribute to true.
    • Marker-based pending operations use span ID as operation ID.
    • The marker attribute is exported with the span/event attributes.

0.11.0 - 2026-03-03 #

Added #

  • User Actions: Group related telemetry (logs, events, exceptions, traces) under a single action context to track end-to-end user interactions. (Resolves #131)

    • Faro().startUserAction('name') starts a new action that buffers and enriches telemetry with action context
    • Faro().getActiveUserAction() returns the currently active action handle
    • Automatic lifecycle management with follow-up timeout (100ms) and halt timeout (10s)
    • HTTP requests and navigation events automatically extend action lifetime via signal channels
    • Telemetry items captured during an action include action.name and action.id for correlation in Grafana
    • Only one action can be active at a time; overlapping calls return null
    • Spans created during an action automatically receive faro.action.user.name and faro.action.user.parentId attributes via FaroUserActionSpanProcessor
  • HTTP Tracking Filter: New HttpTrackingFilter for controlling which URLs are instrumented

    • Automatically excludes Faro collector URL from tracking
    • Supports ignoreUrls patterns from FaroConfig to skip custom URL patterns
  • New dependency: Added dartypod (^0.2.0) for lightweight dependency injection

Changed #

  • Documentation consolidation: Replaced separate Getting Started.md, Features.md, and Configurations.md with a single comprehensive Reference.md

0.10.0 - 2026-02-09 #

Added #

  • Session sampling support: New sampling configuration option allows controlling what percentage of sessions send telemetry data. This enables cost management and traffic reduction for high-volume applications. (Resolves #89)

    • Use SamplingRate(0.5) for fixed 50% sampling
    • Use SamplingFunction((context) => ...) for dynamic sampling based on session context (user attributes, app environment, etc.)
    • If not provided, all sessions are sampled (100%)
    • Sampling decision is made once per session at initialization and applies to all telemetry types (events, logs, exceptions, measurements, traces)
    • Example: sampling: SamplingFunction((context) => context.meta.user?.attributes?['role'] == 'beta' ? 1.0 : 0.1)
    • Aligns with Faro Web SDK sampling behavior
  • ContextScope for span context lifetime control: New contextScope parameter on startSpan() controls how long a span remains active in zone context for auto-assignment. ContextScope.callback (default) deactivates the span when the callback completes, preventing timer/stream callbacks from inheriting it. ContextScope.zone keeps the span active for the entire zone lifetime, useful when you want timer callbacks to be children of the parent span. (Resolves #105)

  • Span.noParent sentinel: New Span.noParent static constant allows explicitly starting a span with no parent, ignoring the active span in zone context. Useful for timer callbacks or event-driven scenarios where you want to start a fresh, independent trace. (Resolves #105)

Fixed #

  • SDK-internal span attributes now use typed values: HTTP span attributes (http.status_code, http.request_size, http.response_size) are now sent as integers instead of strings, enabling proper numeric queries in Tempo (e.g., status_code > 400)
  • Session attributes support typed values: sessionAttributes config now accepts Map<String, Object> allowing typed custom attributes. The device_is_physical attribute is now sent as a boolean instead of a string. (Resolves #133)

0.9.0 - 2026-01-28 #

Fixed #

  • OTLP trace attributes now preserve types: Span attributes and event attributes now correctly preserve their original types (int, double, bool, String) when sent via OTLP
    • Previously, all attribute values were converted to strings, making numeric querying and bucketing difficult in Grafana/Tempo
    • Now attributes like user.account_count: 42 are sent as integers, enabling queries like account_count > 10 and proper histogram bucketing
    • Updated TraceAttributeValue to support stringValue, intValue, doubleValue, and boolValue fields per OTLP specification
    • Updated Span.setAttributes() and Span.addEvent() to accept Map<String, Object> for typed values
    • Updated Span.setAttribute(String key, Object value) to accept any supported type (previously only String)
    • Backward compatible: Span.setAttribute(String key, String value) still works for string-only use cases
    • Resolves issue #126: OTLP trace attributes forced to string type

0.8.0 - 2026-01-13 #

Added #

  • User management with FaroUser model: New FaroUser class for comprehensive user identification

    • Replaces the legacy User model with a more feature-rich implementation
    • Supports id, username, email, and custom attributes fields
    • Custom attributes align with Faro Web SDK MetaUser for cross-platform consistency
    • Includes FaroUser.cleared() constructor to explicitly clear user data
  • User persistence: New persistUser option in FaroConfig (default: true)

    • Automatically saves user identity to device storage
    • Restores user on subsequent app launches for consistent session tracking
    • Early events like appStart include user data when persistence is enabled
    • Fires user_set event on restore and user_updated event on changes
  • Initial user configuration: New initialUser option in FaroConfig

    • Set a user immediately on SDK initialization
    • Use FaroUser.cleared() to explicitly clear any persisted user on start
    • Useful for apps that know the user at startup or need to force logout state
  • New setUser() API: Streamlined method for setting user identity

    • Faro().setUser(FaroUser(...)) to set user
    • Faro().setUser(FaroUser.cleared()) to clear user
    • Returns Future<void> for awaiting persistence completion

Changed #

  • Deprecated setUserMeta(): Use setUser(FaroUser(...)) instead
    • Legacy method still works but will be removed in a future version
    • Migration: Replace setUserMeta(userId: 'x', userName: 'y', userEmail: 'z') with setUser(FaroUser(id: 'x', username: 'y', email: 'z'))
    • Breaking: Now requires SDK initialization (init() or runApp()) before calling. Previously, setUserMeta() could be called before initialization. Calls made before initialization will now be silently ignored.

0.7.0 - 2025-12-02 #

⚠️ Note: This release updates Android build requirements.

Due to the device_info_plus v12 upgrade, your Android project now requires:

  • Android Gradle Plugin ≥8.7.0
  • Gradle wrapper ≥8.10
  • Kotlin ≥2.2.0
  • Java 17

Added #

  • Human-readable device model name: Added new deviceModelName field to DeviceInfo and device_model_name session attribute
    • iOS: Returns marketing name (e.g., "iPhone 15 Pro") instead of internal identifier ("iPhone16,1")
    • Android: Same as deviceModel - Android does not provide a mapping from model codes to marketing names

Changed #

  • Upgraded device_info_plus from v11.4.0 to v12.3.0
    • Enables access to new modelName property on iOS for human-readable device names
    • Includes latest device identifier mappings (iPhone 16/17 series, iPad Pro M5, etc.)

0.6.0 - 2025-11-25 #

Added #

  • control Flutter error reporting: new enableFlutterErrorReporting in FaroConfig to control Flutter error reporting (default = true)

0.5.0 - 2025-10-31 #

Added #

  • Custom session attributes: New optional sessionAttributes parameter in FaroConfig for adding custom labels to all telemetry
    • Allows setting custom key-value pairs that are included in all telemetry data (logs, events, exceptions, traces, measurements)
    • Useful for access control labels, team/department segmentation, and environment-specific metadata
    • Custom attributes are merged with default attributes (SDK version, device info, etc.)
    • Default attributes take precedence if naming conflicts occur
    • Equivalent to sessionTracking.session.attributes in Faro Web SDK

0.4.2 - 2025-08-28 #

Changed #

  • Removed intl dependency: Replaced custom date formatting with built-in DateTime.toIso8601String() method
    • Removed intl package dependency to reduce package footprint
    • Updated timestamp generation in Event, FaroLog, FaroException, and Measurement models
    • Uses standard ISO 8601 format via Dart's native DateTime.toIso8601String() method
    • Maintains compatibility while eliminating external dependency

0.4.1 - 2025-07-16 #

Fixed #

  • SDK name consistency across telemetry types: Updated SDK identification to use consistent naming

    • Changed hardcoded 'rum-flutter' SDK name to use FaroConstants.sdkName for consistency with OpenTelemetry traces
    • Maintains backend-compatible version '1.3.5' for proper web SDK version validation
    • Added actual Faro Flutter SDK version to session attributes as 'faro_sdk_version' for tracking real SDK version
  • FaroZoneSpanManager span status preservation: Fixed issue where manually set span statuses were overridden by automatic status setting

    • Added statusHasBeenSet property to Span interface to track when status has been manually set
    • Updated FaroZoneSpanManager.executeWithSpan() to respect manually set span statuses for both success and error cases
    • Prevents overriding of custom span statuses (e.g., business logic errors) when code executes without throwing exceptions
    • Maintains existing behavior for spans that haven't had their status manually set
    • Resolves issue #86: FaroZoneSpanManager overrides manually set span statuses on success

0.4.0 - 2025-07-02 ⚠️ BREAKING CHANGES #

Changed #

  • BREAKING: Package structure refactoring to follow Flutter plugin conventions: Reorganized the package to align with Flutter/Dart ecosystem standards and best practices
    • Breaking Change: Main entry point changed from faro_sdk.dart to faro.dart

      • The package now follows the standard lib/<package_name>.dart convention
      • Removed lib/faro_sdk.dart file entirely
      • lib/faro.dart is now the single main entry point with selective barrel exports
    • Migration: Update your imports to use the new main entry point

      // Before
      import 'package:faro/faro_sdk.dart';
      
      // After
      import 'package:faro/faro.dart';
      
    • Architecture Improvements:

      • Moved core Faro class implementation from lib/faro.dart to lib/src/faro.dart
      • lib/faro.dart now serves as a clean barrel export file exposing only public APIs
      • All implementation details properly organized under lib/src/ directory
      • Clear separation between public API surface and private implementation
      • Follows established Flutter ecosystem conventions used by popular packages like Provider, BLoC, and Dio
    • Benefits:

      • Cleaner API boundaries: Clear distinction between public and private APIs
      • Better maintainability: Implementation details can evolve without affecting public interface
      • Consistent developer experience: Matches patterns developers expect from other Flutter packages
      • Future-proof: Enables easier API evolution and versioning
      • Community alignment: Follows official Flutter/Dart documentation recommendations
    • No functionality changes: All existing public APIs remain the same, only import paths have changed

Added #

  • Type-Safe Log Level API: New LogLevel enum for improved logging reliability and developer experience

    • Introduced LogLevel enum with values: trace, debug, info, log, warn, error
    • Aligns with Grafana Faro Web SDK for cross-platform consistency
    • Includes fromString() method for backward compatibility, supporting both 'warn' and 'warning' variants
  • Enhanced Tracing and Span API: Major improvements to distributed tracing capabilities

    • New startSpan<T>() method for automatic span lifecycle management with callback-based execution
    • New startSpanManual() method for manual span lifecycle management when precise control is needed
    • New getActiveSpan() method to access the currently active span from anywhere in the execution context
    • Zone-based span context management ensures proper parent-child relationships across async boundaries
    • Automatic session ID injection - all spans now include both session_id and session.id attributes
    • Improved error handling with automatic span status updates when exceptions occur
    • Enhanced span status tracking with proper OpenTelemetry status code mapping
    • Support for custom parent span specification to create explicit span hierarchies
    • Comprehensive documentation with detailed examples for common tracing patterns
  • Centralized Session Management: New SessionIdProvider for consistent session handling across the SDK

    • Dedicated session ID generation and management
    • Better integration with tracing system for session context propagation
    • Factory pattern for testable session management
  • SDK Constants Management: New centralized constants system

    • Added FaroConstants class for SDK version and name management
    • Better version tracking and consistency across the codebase
  • BREAKING: Synchronous API for telemetry methods: Refactored telemetry methods to remove unnecessary async patterns for improved performance and developer experience

    • Breaking Change: The following methods changed from Future<void>? to void:

      • pushEvent() - Send custom events
      • pushLog() - Send custom logs
      • pushError() - Send custom errors
      • pushMeasurement() - Send custom measurements
      • markEventEnd() - Mark event completion
    • Migration: Remove await keywords from calls to these methods as they are now synchronous

      // Before
      await Faro().pushEvent('event_name');
      await Faro().pushLog('message', level: LogLevel.info);
      
      // After
      Faro().pushEvent('event_name');
      Faro().pushLog('message', level: LogLevel.info);
      
    • Benefits:

      • Improved performance by eliminating unnecessary async overhead
      • Cleaner API that better reflects the synchronous nature of these operations
      • Reduced complexity in application code
    • Internal Architecture: Introduced BatchTransportFactory singleton pattern for better dependency management and testing

  • BREAKING: pushLog API requires LogLevel enum: Enhanced logging API for better type safety and consistency

    • Breaking Change: pushLog() now requires a LogLevel parameter instead of optional String?
    • Migration: Replace level: "warn" with level: LogLevel.warn in your pushLog calls
    • Benefit: Eliminates typos in log levels and provides better IDE support
    • Compatibility: Existing string-based log levels in internal code updated to use LogLevel enum
    • Documentation: All examples and documentation updated to reflect the new API
  • Tracing Architecture Refactoring: Complete redesign of the internal tracing system

    • Replaced legacy tracer.dart and tracer_provider.dart with new FaroTracer implementation
    • New FaroZoneSpanManager for robust zone-based span context management
    • Improved Span class with cleaner API and better OpenTelemetry integration
    • Enhanced span creation and management with proper resource attribution
    • Better separation of concerns between tracing components
    • Zone-based implementation ensures proper parent-child relationships across async boundaries
    • Enhanced developer experience with multiple tracing approaches for different use cases
    • Better integration between tracing and other SDK components
  • Session Management: Extracted session logic from distributed components

    • Removed deprecated generate_session.dart utility
    • Centralized session management in dedicated provider
    • Improved testability and maintainability of session-related functionality

0.3.7 - 2025-06-10 #

Added #

  • Enhanced HTTP tracing attributes: HTTP spans now include additional attributes for better observability
    • Added http.request_size attribute with request content length
    • Added http.response_size attribute with response content length
    • Added http.content_type attribute with response content type
    • Provides more comprehensive HTTP request/response metadata for monitoring
  • Session attributes in OpenTelemetry traces: Tracer resources now automatically include session attributes
    • Session metadata is propagated to all OpenTelemetry spans
    • Enables correlation of traces with user sessions and custom session data
    • Supports dynamic session attribute values (strings, numbers, booleans, objects)
    • Added comprehensive test coverage for DartOtelTracerResourcesFactory
  • Human-readable timestamps for Android crashes: Added readable timestamp formatting for crash reports
    • Crash context now includes both original Unix epoch timestamp and human-readable ISO 8601 format
    • Added timestamp_readable_utc field alongside existing timestamp field
    • Timestamps converted to UTC ISO 8601 format (e.g., "2025-06-04T23:49:20.296Z")
    • Includes new TimestampExtension utility for reusable timestamp conversion
    • Improves debugging experience with easily interpretable crash timestamps
    • Resolves issue #53: Add human readable timestamp for Android crashes
  • Trace event duration: Added duration information to trace events
    • Events now include duration_ns attribute with span duration in nanoseconds
    • Duration calculated as endTime - startTime when both timestamps are valid
    • Improves observability by providing timing information for traced operations
    • Resolves issue #23: Add duration to Faro events

Fixed #

  • Span event naming: Fixed incorrect event names for tracing spans
    • HTTP spans now correctly use faro.tracing.fetch event name
    • Non-HTTP spans use span.{name} format for better event categorization
    • Added logic to detect HTTP spans based on http.scheme or http.method attributes
    • Resolves issue #41: Incorrect span event names being sent to collector
  • Event data URL formatting: Fixed inconsistent formatting of event_data_url parameter
    • Attribute values are now properly sanitized to remove surrounding quotes
    • Ensures consistent formatting across all event attributes
    • Resolves issue #25: Inconsistent event_data_url formatting

0.3.6 - 2025-06-05 #

Added #

  • Data Collection Persistence: The enableDataCollection setting now persists across app restarts
    • Automatically saves the data collection preference to device storage using SharedPreferences
    • Defaults to enabled on first app launch
    • Fire-and-forget persistence - no need to await setting changes
    • Maintains full backward compatibility with existing API
    • Resolves issue #62: "Persist faro.enableDataCollection"
  • GitHub issue templates for bug reports and feature requests
  • Pull request template for standardized contributions
  • Code of Conduct (Contributor Covenant v1.4)
  • Comprehensive Contributing Guidelines with setup instructions and development workflow
  • Maintainers documentation listing current project maintainers

Changed #

  • Major documentation overhaul:
    • Enhanced README with improved badges, clearer setup instructions, and better project description
    • Completely rewritten Features documentation with detailed explanations and code examples
    • Improved Getting Started guide with step-by-step setup for both Grafana Cloud and self-hosted options
  • Updated example app to demonstrate latest SDK features and best practices

Improved #

  • Project governance and community guidelines establishment
  • Developer experience with better onboarding documentation
  • Code contribution workflow with standardized templates and processes

Fixed #

  • Critical NullPointerException in Android frame monitoring: Fixed crash when frame monitoring callbacks execute after Flutter engine detachment
    • Added proper cleanup in stopFrameMonitoring() to remove Choreographer callbacks
    • Added null checks in handleFrameDrop(), handleSlowFrameDrop(), and handleRefreshRate() methods
    • Added safety guards to prevent frame processing when monitoring is stopped
    • Prevents crashes when app goes to background or during configuration changes

0.3.5 - 2025-05-28 #

Added #

  • Support for custom HTTP headers in FaroConfig via the collectorHeaders field
    • Allows users to specify headers that will be included in all requests to the collector endpoint
    • Useful for deployments that require specific headers for routing or authentication

0.3.4 - 2025-05-22 #

Added #

  • Automated pub.dev deployment with GitHub Actions
  • Pre-release validation tools

Changed #

  • Improved release workflow with safety checks

0.3.3 #

Changed #

  • Updated intl dependency to newer version to be compatible with latest flutter version

0.3.2 #

Changed #

  • Maintenance release

0.3.1 #

Changed #

  • Updates README

0.3.0 #

Changed #

  • Restructure where faro code is located. Moved from packages/faro to root. Since we only have one package in this repo for now

0.2.2 #

Added #

  • Comprehensive test coverage for model serialization

Changed #

  • Enhanced Android Exit Info filtering to reduce noise in crash reports
  • Improved JSON parsing and error handling in model classes

Fixed #

  • Fixed handling of non-string values in exception context and stacktrace

0.2.0 #

Changed #

  • Renamed package from rum_sdk to faro
  • Renamed main API class from RumFlutter to Faro
  • Renamed all related classes with "Rum" prefix to "Faro" prefix
  • Updated all import statements to use the new package name
  • Updated documentation with new package name and examples

0.1.2 #

Fixed #

  • Bug fixes and improvements

0.0.1 #

Added #

The following Key Metrics of Flutter Applications are Added in the Alpha Release.

  • Mobile App Performance
    • cpu usage
    • memory usage
    • cold/warm start
    • ANR ( android)
    • Native slow/frozen frames
  • Flutter Errors & Exceptions
  • Events
    • session start
    • route changes
    • user interaction
  • Http network info
    • Load Duration , method , resource/type , request/response size
  • Rum Asset Bundle
    • Asset Size, Load time
  • Custom events, logs, measurement, error
  • Offline Caching of Events