farol_grpc 0.1.0
farol_grpc: ^0.1.0 copied to clipboard
gRPC (package:grpc) instrumentation for the Faro RUM client — RPC measurements, errors, and W3C traceparent.
farol_grpc #
package:grpc client instrumentation for
farol: a ClientInterceptor that turns unary and streaming RPCs
into Faro RUM measurements, events, and (optionally) W3C traceparent
propagation.
Implements the Grafana Faro wire protocol. Not affiliated with or endorsed by Grafana Labs.
Install #
dependencies:
farol: ^0.1.0
farol_grpc: ^0.1.0
Or, to track this repo directly instead of pub.flutter-io.cn:
dependencies:
farol:
git:
url: https://github.com/thegorangers/farol.git
path: packages/farol
farol_grpc:
git:
url: https://github.com/thegorangers/farol.git
path: packages/farol_grpc
Usage #
import 'package:farol/farol.dart';
import 'package:farol_grpc/farol_grpc.dart';
import 'package:grpc/grpc.dart';
Faro.initialize(FaroConfig(
collectorUrl: Uri.parse('https://faro-collector.example.com/collect'),
app: const FaroApp(name: 'my-app'),
));
final channel = ClientChannel('api.example.com', port: 443,
options: const ChannelOptions(credentials: ChannelCredentials.secure()));
final stub = MyServiceClient(channel,
interceptors: [FaroGrpcInterceptor(injectTraceparent: false)]);
Every unary or streaming call made through stub now records a
grpc_request event, a grpc duration measurement, and (on failure) a
pushError with the GrpcError code — tagged with the RPC's method path.
The gRPC story #
FaroGrpcInterceptor implements package:grpc's ClientInterceptor, so it
hooks both interceptUnary and interceptStreaming. For streaming calls it
does not subscribe to the response stream itself (that would steal the
caller's single-subscription .listen()); instead it hooks trailers, which
completes on RPC end without a subscription. Caveat: some transport/server
error paths never complete trailers, so the measurement can be late or
absent for those RPCs — this is best-effort, matching the OTel gRPC
instrumentation's own behavior.
Scoping instrumentation by host #
package:grpc's CallOptions — what the interceptor actually receives
per-call — exposes no target authority/host field, so a host-matching gate
inside the interceptor cannot see which host an RPC is going to and would
be a no-op through real RPCs. Because of that, FaroGrpcInterceptor has no
host-allowlist option.
The reliable way to scope instrumentation by host is attachment, not
filtering: only add FaroGrpcInterceptor to the interceptors: list of
the ClientChannel(s) you actually want instrumented, and leave it off
channels to hosts you don't want measured. This is the only mechanism the
package offers for host scoping.
injectTraceparent #
injectTraceparent defaults to true (inject a W3C traceparent header
into outgoing call metadata if one isn't already present). Set it to
false — the recommended mode — when another layer in your stack
already injects W3C traceparent, e.g. an OpenTelemetry gRPC interceptor
ordered before this one in the interceptor chain. In that mode
farol_grpc only reads the traceparent already on the call (via
debugTraceFromMetadata) to correlate its own measurements/events, without
double-injecting.
Endpoint & auth model #
Auth is handled entirely by farol's headersProvider on FaroConfig — this
package adds no auth of its own; it only measures the RPCs your gRPC client
already makes over your own ChannelCredentials.
No-PII rule #
Same as farol: this package only records method paths, status codes, and
timings. Don't put request/response payload contents (which may contain
PII) into the interceptor's context — it never inspects RPC payloads, only
metadata/method/timing.