@capawesome/capacitor-grafana-faro
v0.1.0
Published
Unofficial Capacitor plugin for Grafana Faro.
Maintainers
Readme
@capawesome/capacitor-grafana-faro
Unofficial Capacitor plugin for Grafana Faro.[^1]
⚠️ Experimental: This plugin is in early development. APIs may change between minor versions. Feedback and bug reports are very welcome — please open an issue.
Newsletter
Stay up to date with the latest news and updates about the Capawesome, Capacitor, and Ionic ecosystem by subscribing to our Capawesome Newsletter.
Features
We are proud to offer one of the most complete and feature-rich Capacitor plugins for Grafana Faro. Here are some of the key features:
- 🖥️ Cross-platform: Supports Android, iOS and Web.
- 📝 Logs: Capture log messages with severity levels and structured context.
- 📡 Events: Track custom events with attributes and a platform domain.
- 💥 Errors: Capture errors with optional stack frames (compatible with
stacktrace.js). - 📊 Measurements: Record numeric metrics for performance and business KPIs.
- 👤 User, Session and View Metadata: Attach user, session and view information to every signal.
- 🛡️ Native Crash Reporting: Capture native crashes via PLCrashReporter on iOS and
ApplicationExitInfoon Android. - 🐌 ANR Detection: Detect Application Not Responding events on the Android main thread.
- 🌐 Web Auto-Instrumentation: Automatically capture uncaught errors, console output, Core Web Vitals, route changes and network performance on Web.
- ⏯️ Pause and Resume: Pause and resume telemetry on demand.
- 🎯 Session Sampling: Sample sessions with a configurable rate to control data volume.
Compatibility
| Plugin Version | Capacitor Version | Status | | -------------- | ----------------- | -------------- | | 0.1.x | >=8.x.x | Active support |
Installation
You can use our AI-Assisted Setup to install the plugin. Add the Capawesome Skills to your AI tool using the following command:
npx skills add capawesome-team/skills --skill capacitor-pluginsThen use the following prompt:
Use the `capacitor-plugins` skill from `capawesome-team/skills` to install the `@capawesome/capacitor-grafana-faro` plugin in my project.If you prefer Manual Setup, install the plugin by running the following commands and follow the platform-specific instructions below:
npm install @capawesome/capacitor-grafana-faro @grafana/faro-web-sdk
npx cap synciOS
Minimum Deployment Target
This plugin depends on PLCrashReporter for native crash reporting. Make sure that your iOS deployment target is set to at least 15.0 in your Xcode project settings (usually in ios/App/App.xcodeproj):
-IPHONEOS_DEPLOYMENT_TARGET = 14.0
+IPHONEOS_DEPLOYMENT_TARGET = 15.0If you are using CocoaPods, make sure that your iOS deployment target is set to at least 15.0 in your Podfile:
platform :ios, '15.0'Conflicts with other crash reporters
PLCrashReporter installs global crash handlers. Running this plugin alongside another crash reporter that also installs handlers (e.g. Firebase Crashlytics, Sentry) can lead to one or both reporters losing crash reports. Enable instrumentations.nativeCrashReporting only when no other crash reporter is active.
Configuration
Build-time configuration for the Grafana Faro plugin.
When url and appName are both provided, the native plugin
auto-initializes during app startup. This allows native crash and ANR
handlers to be installed before any JavaScript code runs. Calling
GrafanaFaro.initialize(...) from JavaScript afterwards is not required
and will fail with an already initialized error.
Only applies to Android and iOS.
| Prop | Type | Description | Since |
| ---------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ----- |
| apiKey | string | The API key sent as the x-api-key header. | 0.1.0 |
| appEnvironment | string | The environment of the application (e.g. production, staging). | 0.1.0 |
| appName | string | The name of the application. | 0.1.0 |
| appNamespace | string | The namespace of the application. | 0.1.0 |
| appVersion | string | The version of the application. | 0.1.0 |
| instrumentations | { anrTracking?: boolean; nativeCrashReporting?: boolean; } | Toggles for built-in automatic instrumentations. Only the toggles that apply at build time on Android and iOS are honored. | 0.1.0 |
| url | string | The Faro collector endpoint URL. | 0.1.0 |
Examples
In capacitor.config.json:
{
"plugins": {
"GrafanaFaro": {
"apiKey": undefined,
"appEnvironment": undefined,
"appName": undefined,
"appNamespace": undefined,
"appVersion": undefined,
"instrumentations": undefined,
"url": 'https://faro-collector-prod.grafana.net/collect/<token>'
}
}
}In capacitor.config.ts:
/// <reference types="@capawesome/capacitor-grafana-faro" />
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
plugins: {
GrafanaFaro: {
apiKey: undefined,
appEnvironment: undefined,
appName: undefined,
appNamespace: undefined,
appVersion: undefined,
instrumentations: undefined,
url: 'https://faro-collector-prod.grafana.net/collect/<token>',
},
},
};
export default config;Usage
import { GrafanaFaro } from '@capawesome/capacitor-grafana-faro';
const initialize = async () => {
await GrafanaFaro.initialize({
app: {
environment: 'production',
name: 'my-app',
version: '1.0.0',
},
instrumentations: {
anrTracking: true,
console: true,
errors: true,
nativeCrashReporting: true,
performance: true,
view: true,
webVitals: true,
},
url: 'https://faro-collector-prod-us-central-0.grafana.net/collect/REPLACE_ME',
});
};
const pushLog = async () => {
await GrafanaFaro.pushLog({
level: 'info',
message: 'User pressed sign-in button',
});
};
const pushEvent = async () => {
await GrafanaFaro.pushEvent({
attributes: { provider: 'google' },
name: 'sign_in_started',
});
};
const pushError = async (error: Error) => {
await GrafanaFaro.pushError({
type: error.name,
value: error.message,
});
};
const pushErrorWithStacktrace = async (error: Error) => {
// Use `stacktrace-js` (or any equivalent) to parse the stack into
// structured frames.
const StackTrace = await import('stacktrace-js');
const stackFrames = await StackTrace.fromError(error);
await GrafanaFaro.pushError({
type: error.name,
value: error.message,
stackFrames: stackFrames.map(frame => ({
columnNumber: frame.columnNumber,
fileName: frame.fileName,
functionName: frame.functionName,
lineNumber: frame.lineNumber,
})),
});
};
const pushMeasurement = async () => {
await GrafanaFaro.pushMeasurement({
type: 'sign_in_duration',
values: { duration_ms: 320 },
});
};
const setUser = async () => {
await GrafanaFaro.setUser({
email: '[email protected]',
id: 'user-123',
username: 'jane',
});
};
const setView = async () => {
await GrafanaFaro.setView({ name: 'SignInView' });
};API
getSession()getView()initialize(...)pause()pushError(...)pushEvent(...)pushLog(...)pushMeasurement(...)resetSession()resetUser()setSession(...)setUser(...)setView(...)unpause()- Interfaces
- Type Aliases
getSession()
getSession() => Promise<GetSessionResult>Get the current session.
Returns: Promise<GetSessionResult>
Since: 0.1.0
getView()
getView() => Promise<GetViewResult>Get the current view.
Returns: Promise<GetViewResult>
Since: 0.1.0
initialize(...)
initialize(options: InitializeOptions) => Promise<void>Initialize the Faro SDK.
Attention: This method must be called before any other method.
| Param | Type |
| ------------- | --------------------------------------------------------------- |
| options | InitializeOptions |
Since: 0.1.0
pause()
pause() => Promise<void>Pause sending telemetry. New signals are still buffered locally.
Since: 0.1.0
pushError(...)
pushError(options: PushErrorOptions) => Promise<void>Push an error/exception.
| Param | Type |
| ------------- | ------------------------------------------------------------- |
| options | PushErrorOptions |
Since: 0.1.0
pushEvent(...)
pushEvent(options: PushEventOptions) => Promise<void>Push a custom event.
| Param | Type |
| ------------- | ------------------------------------------------------------- |
| options | PushEventOptions |
Since: 0.1.0
pushLog(...)
pushLog(options: PushLogOptions) => Promise<void>Push a log message.
| Param | Type |
| ------------- | --------------------------------------------------------- |
| options | PushLogOptions |
Since: 0.1.0
pushMeasurement(...)
pushMeasurement(options: PushMeasurementOptions) => Promise<void>Push a measurement (numeric metric).
| Param | Type |
| ------------- | ------------------------------------------------------------------------- |
| options | PushMeasurementOptions |
Since: 0.1.0
resetSession()
resetSession() => Promise<void>Clear the current session and start a new one.
Since: 0.1.0
resetUser()
resetUser() => Promise<void>Clear the current user.
Since: 0.1.0
setSession(...)
setSession(options: SetSessionOptions) => Promise<void>Set the current session.
| Param | Type |
| ------------- | --------------------------------------------------------------- |
| options | SetSessionOptions |
Since: 0.1.0
setUser(...)
setUser(options: SetUserOptions) => Promise<void>Set the current user.
| Param | Type |
| ------------- | ----------------------------------------------------- |
| options | UserMetadata |
Since: 0.1.0
setView(...)
setView(options: SetViewOptions) => Promise<void>Set the current view (e.g. screen / route name).
| Param | Type |
| ------------- | ----------------------------------------------------- |
| options | ViewMetadata |
Since: 0.1.0
unpause()
unpause() => Promise<void>Resume sending telemetry.
Since: 0.1.0
Interfaces
GetSessionResult
| Prop | Type | Description | Since |
| ---------------- | --------------------------------------- | ------------------------------- | ----- |
| attributes | { [key: string]: string; } | The current session attributes. | 0.1.0 |
| id | string | The current session ID. | 0.1.0 |
GetViewResult
| Prop | Type | Description | Since |
| ---------- | ------------------- | ---------------------- | ----- |
| name | string | The current view name. | 0.1.0 |
InitializeOptions
| Prop | Type | Description | Default | Since |
| ------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------ | ----- |
| apiKey | string | API key sent as the x-api-key header to the collector. | | 0.1.0 |
| app | AppMetadata | Application metadata attached to every signal. | | 0.1.0 |
| ignoreErrors | string[] | Error message patterns to ignore. | | 0.1.0 |
| ignoreUrls | string[] | URL patterns to ignore when instrumenting network calls. | | 0.1.0 |
| instrumentations | InstrumentationsOptions | Toggles for built-in automatic instrumentations. | | 0.1.0 |
| paused | boolean | Start in a paused state. Telemetry must be resumed via unpause(). | false | 0.1.0 |
| sessionAttributes | { [key: string]: string; } | Initial session attributes. | | 0.1.0 |
| sessionSamplingRate | number | Session sampling rate in [0, 1]. 1 = all sessions, 0 = none. | 1 | 0.1.0 |
| url | string | The Faro collector endpoint URL. | | 0.1.0 |
| user | UserMetadata | Initial user metadata. | | 0.1.0 |
| view | ViewMetadata | Initial view metadata. | | 0.1.0 |
AppMetadata
| Prop | Type | Description | Since |
| ----------------- | ------------------- | ------------------------------------------------------------------ | ----- |
| environment | string | The environment of the application (e.g. production, staging). | 0.1.0 |
| name | string | The name of the application. | 0.1.0 |
| namespace | string | The namespace of the application. | 0.1.0 |
| version | string | The version of the application. | 0.1.0 |
InstrumentationsOptions
Toggles for built-in automatic instrumentations.
Note: some toggles only apply on specific platforms. The plugin silently ignores toggles that do not apply on the current platform.
| Prop | Type | Description | Default | Since |
| -------------------------- | -------------------- | ------------------------------------------------------------------------------------------ | ------------------ | ----- |
| anrTracking | boolean | Detect Application Not Responding events on the main thread. Only available for Android. | false | 0.1.0 |
| console | boolean | Capture console.warn and console.error calls. Only available for Web. | true | 0.1.0 |
| errors | boolean | Capture uncaught errors and unhandled promise rejections. Only available for Web. | true | 0.1.0 |
| nativeCrashReporting | boolean | Capture native crashes (reported on the next session). Only available for Android and iOS. | false | 0.1.0 |
| performance | boolean | Capture fetch and XHR performance entries. Only available for Web. | true | 0.1.0 |
| view | boolean | Capture History API navigation as view changes. Only available for Web. | true | 0.1.0 |
| webVitals | boolean | Capture Core Web Vitals (LCP, FID, CLS, INP, TTFB). Only available for Web. | true | 0.1.0 |
UserMetadata
| Prop | Type | Description | Since |
| ---------------- | --------------------------------------- | --------------------------------------------- | ----- |
| attributes | { [key: string]: string; } | Additional key-value attributes for the user. | 0.1.0 |
| email | string | The user's email address. | 0.1.0 |
| fullName | string | The user's full name. | 0.1.0 |
| id | string | The user's ID. | 0.1.0 |
| username | string | The user's username. | 0.1.0 |
ViewMetadata
| Prop | Type | Description | Since |
| ---------- | ------------------- | --------------------- | ----- |
| name | string | The name of the view. | 0.1.0 |
PushErrorOptions
| Prop | Type | Description | Default | Since |
| ----------------- | --------------------------------------- | ----------------------------------------------------- | ------------------ | ----- |
| context | { [key: string]: string; } | Additional context attached to the error. | | 0.1.0 |
| fatal | boolean | Mark the error as fatal (e.g. caused a crash). | false | 0.1.0 |
| stackFrames | StackFrame[] | Pre-parsed stack frames generated by stacktrace.js. | | 0.1.0 |
| type | string | The error type (e.g. 'TypeError'). | | 0.1.0 |
| value | string | The error message. | | 0.1.0 |
StackFrame
Subset of the stacktrace generated by stacktrace.js.
| Prop | Type | Since |
| ------------------ | ------------------- | ----- |
| columnNumber | number | 0.1.0 |
| fileName | string | 0.1.0 |
| functionName | string | 0.1.0 |
| lineNumber | number | 0.1.0 |
PushEventOptions
| Prop | Type | Description | Since |
| ---------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------ | ----- |
| attributes | { [key: string]: string; } | Key-value attributes attached to the event. | 0.1.0 |
| domain | string | Logical grouping for the event. Defaults to the platform domain ('web', 'android', 'ios'). | 0.1.0 |
| name | string | The name of the event. | 0.1.0 |
PushLogOptions
| Prop | Type | Description | Default | Since |
| ------------- | --------------------------------------------- | --------------------------------------- | ------------------- | ----- |
| context | { [key: string]: string; } | Additional context attached to the log. | | 0.1.0 |
| level | LogLevel | The log level. | 'info' | 0.1.0 |
| message | string | The log message. | | 0.1.0 |
PushMeasurementOptions
| Prop | Type | Description | Since |
| ------------- | --------------------------------------- | ----------------------------------------------- | ----- |
| context | { [key: string]: string; } | Additional context attached to the measurement. | 0.1.0 |
| type | string | The measurement type (e.g. 'custom_latency'). | 0.1.0 |
| values | { [key: string]: number; } | Key-value numeric measurements. | 0.1.0 |
SetSessionOptions
| Prop | Type | Description | Since |
| ---------------- | --------------------------------------- | --------------------------------------------------------- | ----- |
| attributes | { [key: string]: string; } | The session attributes. | 0.1.0 |
| id | string | Optional session ID. A UUID v4 is generated when omitted. | 0.1.0 |
Type Aliases
LogLevel
'debug' | 'error' | 'info' | 'log' | 'trace' | 'warn'
SetUserOptions
UserMetadata
SetViewOptions
ViewMetadata
Changelog
See CHANGELOG.md.
License
See LICENSE.
[^1]: This project is not affiliated with, endorsed by, sponsored by, or approved by Grafana Labs or any of their affiliates or subsidiaries.
