Monitoring Implementations
grafana_monitoring_impl Free
- Tier
- Freeversion 1.2.8
- Command
archipelago generate grafana_monitoring_impl- Generates
infrastructure/grafana_monitoring_impl
- Depends on
- network_sdk, monitoring_sdkgenerate these first
Grafana stack vendor implementation for
monitoring_apiusing OpenTelemetry traces (Tempo) and HTTP log push (Loki).
Variables
| Variable | Type | Default | Description |
|---|---|---|---|
| appName | string | — | The name of your application |
| isForMonorepo | boolean | true | Whether this is being generated as part of a monorepo |
Install
Interactive
archipelago generate grafana_monitoring_implNon-interactive (CI)
archipelago generate grafana_monitoring_impl --config my_config.jsonGenerate monitoring_sdk first — this brick depends on its monitoring_api and network_sdk_api packages.
Public API
GrafanaMonitoringImpl implements monitoring_api's AppMonitoringVendor contract — see monitoring_sdk's own page for how the SDK orchestrates multiple registered vendors. Called directly, the vendor exposes:
final vendor = getIt<AppMonitoringVendor>(instanceName: MonitoringInjectorKey.grafana);
await vendor.initialize();
vendor.log('user opened checkout', level: MonitoringLevel.info);
await vendor.recordError(exception, stackTrace);
await vendor.recordTransaction('checkout', () => api.submitOrder());
await vendor.setUserContext(userId);
vendor.flushLogs(); // force an immediate Loki push
vendor.flushTraces(); // force an immediate Tempo pushArchitecture
grafana_monitoring_impl is a vendor brick that implements the AppMonitoringVendor contract from monitoring_api by shipping telemetry directly to a Grafana stack — no OpenTelemetry SDK dependency, despite the brick description's "using OpenTelemetry": it hand-builds OTLP-JSON-over-HTTP payloads and Loki push payloads using plain package:http, not an opentelemetry pub package.
It is selected during flutter_modular_monorepo generation when the user picks grafana from the monitoringVendors multi-select.
GrafanaMonitoringImpl is registered as a @LazySingleton named MonitoringInjectorKey.grafana (not grafanaImpl) and bound to the AppMonitoringVendor interface. It receives a GrafanaConfig instance via constructor injection. The config is provided by GrafanaRegisterModule, which the host app must override with real endpoint URLs and credentials. GrafanaRegisterModule also provides the http.Client used for pushes, registered as @Named('grafanaHttpClient') so it cannot collide with the unnamed http.Client from network_sdk_http.
DI Registration
The package uses @InjectableInit.microPackage() for modular registration. post_gen.dart adds the package to the host app's pubspec.yaml and registers GrafanaMonitoringImplPackageModule in the app's injector.dart. The monitoring_impl fanout builds its vendor list from the @Named registrations when AppMonitoring is first resolved, so every vendor module must run before that. Install order does not decide this. The hook rebuilds the injector entries from each package's archipelago: di_modules manifest in dependency order. Generate monitoring_sdk first when you install standalone. You then override GrafanaRegisterModule to provide endpoints.
Buffering Model
Both logs and traces are buffered in memory and flushed on a timer to avoid per-call HTTP overhead:
| Buffer | Flush interval | Max size | Destination |
|---|---|---|---|
| Logs | 5 seconds | 100 entries | Loki /loki/api/v1/push |
| Traces | 10 seconds | 50 spans | Tempo /api/traces (OTLP JSON) |
Both buffers are also flushed immediately when they reach capacity, and are drained on dispose(). When diagnostics consent is withdrawn the timers stop and both buffers are cleared unsent.
Generated Structure
infrastructure/
└── grafana_monitoring_impl/
├── pubspec.yaml
└── lib/
├── grafana_monitoring_impl.dart # Barrel export
└── src/
├── grafana_monitoring_impl.dart # AppMonitoring impl + buffer types
├── config/
│ └── grafana_config.dart # GrafanaConfig + grafanaCloud factory
└── di/
├── injector.dart # microPackage init
├── injector.module.dart # Generated DI module
└── register_module.dart # GrafanaConfig provider (override required)Key Features
- No proprietary SDK — Uses
package:httpto talk directly to Loki and Tempo; works with both Grafana Cloud and self-hosted Grafana stacks - OTLP-compliant traces — Emits OpenTelemetry Protocol JSON with
resourceSpans,scopeSpans, and typedattributes; spans carry service name, version, environment, and user ID - Loki log streaming — Groups buffered log entries by
MonitoringLevelinto Loki streams withservice,environment, andlevellabels - Grafana Cloud factory —
GrafanaConfig.grafanaCloud(instanceId:, apiKey:)pre-fills standard Grafana Cloud endpoint URLs and encodes Basic Auth from the instance ID and API key - Buffered flush — Periodic timers minimize HTTP calls; failed flushes re-queue entries up to the buffer limit to avoid silent data loss
- User context propagation —
setUserIdstores the ID in memory; it is embedded in every subsequent log line (user_id=…) and in every trace span attribute (user.id) - Error spans —
recordErrorlogs to Loki and, when tracing is enabled, records an error span in Tempo witherror.type,error.message,error.fatal, anderror.stacktraceattributes - Manual flush —
flushLogs()andflushTraces()allow explicit drain before app suspend or logout
Dependencies
| Package | Version | Purpose |
|---|---|---|
http | ^1.6.0 | HTTP transport for Loki and Tempo |
monitoring_api | path | AppMonitoringVendor contract |
network_sdk_api | path | Present as a dependency but not referenced by this vendor's own code |
dependencies | path | injectable / get_it re-export |
Platform Setup
None required — pushes go over plain HTTPS via package:http.
Limitations
setUserContext'sextrasparameter is accepted but not yet applied to subsequent log lines/trace spans — the vendor threads through_userIdonly (marked with aTODO(archipelago)in source).- No OpenTelemetry SDK, retry/backoff policy beyond "re-queue on failure up to buffer size", or gzip compression on the HTTP payloads.
Changelog
Run archipelago brick info grafana_monitoring_impl to see the latest published version. Enterprise customers can read the full CHANGELOG.md in the brick source repository.
Configuration
Override GrafanaRegisterModule in your app DI module to provide endpoints and credentials.
Grafana Cloud
@module
abstract class AppGrafanaModule extends GrafanaRegisterModule {
@override
@lazySingleton
GrafanaConfig get grafanaConfig => GrafanaConfig.grafanaCloud(
instanceId: Env.grafanaInstanceId, // Grafana Cloud instance / stack ID
apiKey: Env.grafanaApiKey, // Grafana Cloud API key with MetricsPublisher role
serviceName: Env.appName,
serviceVersion: Env.version,
environment: Flavor.status.name,
);
}Self-Hosted Grafana
@module
abstract class AppGrafanaModule extends GrafanaRegisterModule {
@override
@lazySingleton
GrafanaConfig get grafanaConfig => GrafanaConfig(
lokiEndpoint: Uri.parse(Env.lokiEndpoint), // e.g. https://loki.internal/loki/api/v1/push
tempoEndpoint: Uri.parse(Env.tempoEndpoint), // e.g. https://tempo.internal/api/traces
basicAuthUser: Env.grafanaUser, // optional Basic Auth
basicAuthPassword: Env.grafanaPassword,
serviceName: Env.appName,
serviceVersion: Env.version,
environment: Flavor.status.name,
enableLogging: true,
enableTracing: true,
);
}GrafanaConfig Fields
| Field | Type | Default | Description |
|---|---|---|---|
lokiEndpoint | Uri | required | Loki log push endpoint |
tempoEndpoint | Uri | required | Tempo/OTLP trace endpoint |
basicAuthUser | String? | null | Basic Auth username (instance ID for Grafana Cloud) |
basicAuthPassword | String? | null | Basic Auth password (API key for Grafana Cloud) |
serviceName | String | 'flutter-app' | Service name for telemetry attribution |
serviceVersion | String | '1.0.0' | Service version embedded in resource spans |
environment | String | 'production' | Environment label on logs and traces |
enableLogging | bool | true | Enable log buffering and Loki push |
enableTracing | bool | true | Enable trace buffering and Tempo push |
Grafana Cloud credentials are found in Grafana Cloud Portal → Stack → Details. Create an API key under Access Policies with at least logs:write and traces:write scopes.