⛯ Grafana Faro + qryn

⛯ Grafana Faro + qryn

frontend application observability

Faro

Grafana just released Faro, an open source project for application frontend observability that enables an easy way to track the health of your web applications.

image.png

Faro provides a JavaScript library you can add to your frontend application to collect logs, errors, and performance metrics, add metadata and forward it to the Grafana Agent which writes data to Prometheus, Loki, or Tempo.

This sounds very exciting!

Will Faro work with qryn out of the box? Let's look at the app diagram:

image.png

Loki, Prometheus and Tempo - this sounds like a perfect polyglot match!

Let's go instrument webapps using Faro and our ClickHouse powered stack!

Grafana Agent

The recipe uses a Grafana Agent powered public collector endpoint to receive and forward webapplication telemetry to Loki, Tempo, and Prometheus... or just qryn. Since we are drop-in compatible, all we have to change are the API URL endpoints.

metrics:
  wal_directory: /tmp/wal
  global: {}
  configs:
    - name: default
      remote_write:
        - url: https://qryn:3100/api/prom/push
          basic_auth:
            username: xxx
            password: xxx
logs:
  positions_directory: /tmp/loki-pos
  configs:
    - name: default
      scrape_configs: []
      clients:
        - url: https://xxx:xxx@qryn:3100/loki/api/v1/push
traces:
  configs:
    - name: default
      remote_write:
        - endpoint: qryn:3100
          basic_auth:
            username: xxx
            password: xxx
      receivers:
        otlp:
          protocols:
            grpc:
            http:
              cors:
                allowed_origins:
                  - http://localhost:1234
                max_age: 7200
integrations:
  app_agent_receiver_configs:
    - autoscrape:
        enable: true
        metrics_instance: 'default'
      api_key: 'secret' # optional, if set, client will be required to provide it via x-api-key header
      instance: 'frontend'
      logs_instance: 'default'
      traces_instance: 'default'
      server:
        host: 0.0.0.0
        port: 12345
        cors_allowed_origins:
          - 'https://my-app.example.com'
      logs_labels: # labels to add to loki log record
        app: frontend # static value
        kind: # value will be taken from log items. exception, log, measurement, etc
      logs_send_timeout: 5000
      sourcemaps:
        download: true # will download source file, extract source map location,
        # download source map and use it to transform stack trace locations

Faro SDK

The Grafana Faro Web SDK comes baked with a lot of useful features:

  • Set up in seconds with just two lines of code
  • Lightweight
  • Automatic instrumentation that captures errors, logs, and performance metrics
  • Pre-configured tracing system based on OpenTelemetry with automatic instrumentations
  • Easy-to-use API for manual instrumentation
  • Fully customizable and extensible

Follow the integration document to instrument your webapplication.

Take your sweet time to follow the tutorial

SDK Example

We can refer to the Grafana example for manually sending some test data.

import { LogLevel } from '@grafana/faro-web-sdk';

// there's a global property
const faro = window.faro;

// send a log message
// by default info, warn and error levels are captured.
// trace, debug and log are not
console.info('Hello world', 123);
// or
faro.api.pushLog(['Hello world', 123], { level: LogLevel.Debug });

// log with context
faro.api.pushLog(['Sending update'], {
  context: {
    payload: thePayload,
  },
  level: LogLevel.TRACE,
});

// set user metadata, to be included with every event. All properties optional
faro.api.setUser({
  email: 'bob@example.com',
  id: '123abc',
  username: 'bob',
  attributes: {
    role: 'manager',
  },
});

// unset user
faro.api.resetUser();
// set session metadata, to be included with every event
faro.api.setSession(createSession({ plan: 'paid' }));
// unset session
faro.api.resetSession();
// push measurement
faro.api.pushMeasurement({
  type: 'cart-transaction',
  values: {
    delay: 122,
    duration: 4000,
  },
});

// push an error
faro.api.pushError(new Error('everything went horribly wrong'));
// push an event
faro.api.pushEvent('navigation', { url: window.location.href });
// pause faro, preventing events from being sent
faro.pause();
// resume sending events
faro.unpause();

Sample Dashboards

Last but not least, include the sample dashboards to complete your setup.


Update

Jachen tried using Faro and came up with his tiny alternative: boscaiolog

Conclusion

Faro is compatible with qryn out of the box. And qryn is amazing. 💛

image.png

Did you find this article valuable?

Support qryn by becoming a sponsor. Any amount is appreciated!