GithubHelp home page GithubHelp logo

grafana / faro-web-sdk Goto Github PK

View Code? Open in Web Editor NEW
735.0 136.0 64.0 13.29 MB

The Grafana Faro Web SDK, part of the Grafana Faro project, is a highly configurable web SDK for real user monitoring (RUM) that instruments browser frontend applications to capture observability signals. Frontend telemetry can then be correlated with backend and infrastructure data for full-stack observability.

Home Page: https://grafana.com/oss/faro/

License: Apache License 2.0

JavaScript 1.67% Shell 0.01% TypeScript 97.29% Dockerfile 1.03%

faro-web-sdk's Introduction

Grafana Faro Web SDK

Build Status

Grafana Faro logo

The Grafana Faro Web SDK can instrument frontend JavaScript applications to collect telemetry and forward it to the Grafana Alloy (with faro receiver integration enabled), to a Grafana Cloud instance or to a custom receiver. Grafana Alloy can then send this data to Loki or Tempo.

The repository consists of multiple packages that can be combined depending on your requirements, as well as a demo, which can be run by following the README.md file.

Get started

Note

For more information, you can find the Faro documentation in the Grafana Cloud docs for Faro.

See quick start for web applications.

Packages

Core

@grafana/faro-core is the main package that provides the core functionality of the SDK. The README.md file provides an overview of the architecture and the API of library.

Web SDK

@grafana/faro-web-sdk provides instrumentations, metas and transports for use in web applications. See the README.md for more information.

Web Tracing

@grafana/faro-web-tracing provides implementation for tracing web applications. See the README.md for more information.

React Support

@grafana/faro-react is a package that enables easier integration in projects built with React. See the README.md for more information.

Releases

Faro releases follow the Semantic Versioning naming scheme: MAJOR.MINOR.PATCH.

  • MAJOR: Major releases include large new features which will significantly change how Faro operates and possible backwards-compatibility breaking changes.

  • MINOR: these releases include new features which generally do not break backwards-compatibility.

  • PATCH: patch releases include bug and security fixes which do not break backwards-compatibility.

    NOTE: Our goal is to provide regular releases that are as stable as possible, and we take backwards-compatibility seriously. As with any software, always read the release notes and the upgrade guide whenever choosing a new version of Faro to install.

faro-web-sdk's People

Contributors

addshore avatar amontagu avatar bfmatei avatar bubu11e avatar cedricziel avatar charsleysa avatar codecapitano avatar condla avatar connorlindsey avatar dependabot[bot] avatar domasx2 avatar eskirk avatar foch01 avatar globin avatar hasparus avatar hoop71 avatar kpelelis avatar leoneck avatar linusbf avatar mengyubit avatar mxab avatar myrle-krantz avatar nickakhmetov avatar pajn avatar richih avatar simenb avatar steven-pribilinskiy avatar svennergr avatar victor-lindh avatar wilfriedroset avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

faro-web-sdk's Issues

Add debug/diagnostic mode

Should be possible to confiugre agent for debugging/diagnostics, where it would output debug logs and internal errors to console.

Curretly we have a lot of catch {}, thse should at the very least log the error in debug mode

Circular dependency detected in core package

Description

When building the IIFE bundle in core package, rollup complains about a circular dependency. Given that the IIFE bundle is loaded in the browser, it's best to fix this as other issues may result from this.

Steps to reproduce

  1. Run yarn build

Expected behavior

No circular dependency errors should occur.

Actual behavior

Circular dependency error occurs.

Environment

  • SDK version: -
  • SDK instrumentations: -
  • Device type: -
  • Device name: -
  • OS: -
  • Browser: -

Demo

Context

Fetch transport: limit number of concurrent requests

I believe currently we don't limit number of concurrent requests, so run some risk of exhausting a page's connection pool in case of an error. Should look into something similar to what sentry does to make sure we only have several requests in flight

Event deduplication

Add (optional) event deduplication. Deduplicate identical errors / log messages. Optional, opt out maybe?. Would be good to indicate number of events skipped. Research of prior art in other libs would be good

Grafana say ok but does not forward to tempo

I tried to send trace with faro to a Grafana Agent to be forwarded to Grafana Tempo:

  • the Grafana Agent responds 'ok' to Faro trace request ;
  • the trace is not logged by Grafana Agent but no error ;
  • the trace is not logged by Grafana Tempo but no error.

The Faro to Grafana Agent communication seems fine: logs from Faro are correctly forwared by this Grafana Agent instance to a Grafana Loki.

The Grafana Agent to Grafana Tempo seems fine: traces from a java backend sources work with this Grafana Tempo instance.

Javascript code using faro web sdk:

import { TracingInstrumentation } from "./_snowpack/pkg/@grafana/faro-web-tracing.js";
import { initializeFaro, getWebInstrumentations } from "./_snowpack/pkg/@grafana/faro-web-sdk.js";

initializeFaro({
  url: "http://localhost:12347/collect";,
  instrumentations: [...getWebInstrumentations(), new TracingInstrumentation()],
  app: {
    name: "myapp",
    version: "1.0.0",
  },
});

const { trace, context } = faro.api.getOTEL();

const tracer = trace.getTracer('default');
const span = tracer.startSpan('prout');
context.with(trace.setSpan(context.active(), span), () => {
  span.end();
});

Grafana Agent says ok:

image

Grafana Agent configuration:

logs:
  positions_directory: /tmp/loki-pos
  configs:
    - name: default
      scrape_configs: []
      clients:
        - url: http://grafana-loki:3100/loki/api/v1/push
traces:
  configs:
    - name: default
      automatic_logging:
        backend: stdout
        roots: true
      remote_write:
        - endpoint: http://grafana-tempo:4317
          insecure: true
      receivers:
        otlp:
          protocols:
            http:
            grpc:
integrations:
  app_agent_receiver_configs:
    - autoscrape:
        enable: false
      logs_instance: 'default'
      traces_instance: 'default'
      server:
        host: 0.0.0.0
        port: 12347
        cors_allowed_origins:
          - 'http://localhost:8081'
          - 'http://localhost:8082'
      logs_labels: # labels to add to loki log record
        app: frontend # static valuefrontend
        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

Grafana Tempo config:

search_enabled: true
metrics_generator_enabled: false

server:
  http_listen_port: 3200

distributor:
  log_received_traces: true
  log_received_spans:
    enabled: true
  receivers:
    otlp:
      protocols:
        http:
        grpc:

ingester:
  trace_idle_period: 10s               # the length of time after a trace has not received spans to consider it complete and flush it
  max_block_bytes: 1_000_000           # cut the head block when it hits this size or ...
  max_block_duration: 5m               #   this much time passes

compactor:
  compaction:
    compaction_window: 1h              # blocks in this time window will be compacted together
    max_block_bytes: 100_000_000       # maximum size of compacted blocks
    block_retention: 1h
    compacted_block_retention: 10m

metrics_generator:
  registry:
    external_labels:
      source: tempo
      cluster: docker-compose
  storage:
    path: /tmp/tempo/generator/wal
    remote_write:
      - url: http://prometheus:9090/api/v1/write
        send_exemplars: true

storage:
  trace:
    backend: local                     # backend configuration to use
    block:
      bloom_filter_false_positive: .05 # bloom filter false positive rate.  lower values create larger filters but fewer false positives
      index_downsample_bytes: 1000     # number of bytes per index record
      encoding: zstd                   # block encoding/compression.  options: none, gzip, lz4-64k, lz4-256k, lz4-1M, lz4, snappy, zstd, s2
    wal:
      path: /tmp/tempo/wal             # where to store the the wal locally
      encoding: snappy                 # wal encoding/compression.  options: none, gzip, lz4-64k, lz4-256k, lz4-1M, lz4, snappy, zstd, s2
    local:
      path: /tmp/tempo/blocks
    pool:
      max_workers: 100                 # worker pool determines the number of parallel requests to the object store backend
      queue_depth: 10000

overrides:
  metrics_generator_processors: [service-graphs, span-metrics]

Upgrade demo app

It would be very helpful to have a more fleshed out demo app, both to serve as an example and as a testing ground:

  • make it a more "realistic" react app
  • add backend & db
  • add grafana agent + tempo/loki maybe
  • full stack traces

Expose unpatched console

when using ConsoleInstrumentation, some methods on global console object will trigger sending to bakcend. It would be useful to expose an "unpatched" version with te same api, eg agent.unpatchedConsole.
Currently we have agent.api.callOriginalConsoleMethod, but it's not ideal that it's not the same api - can't pass it to other libs, have to look up usage etc.

Traces does not show response content length in safari

Description

Trace attributes for documentFetch and resourceFetch trace do not show response content length for traces sent through safari browser.

Steps to reproduce

  1. Add Faro to the project
  2. Include Tracing Instrumentation
  3. Check trace attribute

Expected behavior

Traces sent through chrome display response content length
chrome-trace

Actual behavior

Trace attribute from safari do not contain response content length
safari-trace

Environment

  • SDK version:
    "@grafana/faro-react": "^1.0.0-beta5",
    "@grafana/faro-web-sdk": "^1.0.0-beta4",
    "@grafana/faro-web-tracing": "^1.0.0-beta5",
  • SDK instrumentations: Web SDK,Web Tracing, React
  • Device type: Desktop
  • Device name: MacBook Pro 16"
  • OS: macOS Monterey
  • Browser: Safari 15.6.1

Demo

Context

React Router integration. Add log of previous route.

Description

Current version of React Router logs only destination of route. It would be useful if previous route also was logged.
Example of an event:

{
  "events": [
    {
      "name": "routeChange",
      "domain": "browser",
      "attributes": {
        "url": "http://localhost:3000/lk/personal",
        "route": "/lk/personal",
        "from": "/index"
      },
      "timestamp": "2023-01-16T09:02:53.416Z"
    }
  ]
}

Capturing performance.marks / performance.measure

Description

Having faro capture the performance.marks and performance.measure and sending it as a trace for certain custom events/ actions would make it easier to measure and track the user activity .

Proposed solution

Add an instrumentation for capturing performance.mark/measure info

Context

performance.measure

Demo does not run on Windows

Hello,

I´ve tried to run the demo application with Docker on Windows 10.

I cloned the whole repository and after I´ve run 'docker compose --profile demo up' all Docker containers have been created. However, there not able to start.

I get the following error message:
Error response from daemon: failed to mount local volume: mount /demo/logs:/var/lib/docker/volumes/faro-web-sdk_demo_demo_logs/_data, flags: 0x1000: no such file or directory

Even though the directory '/demo/logs' exists inside the repository.

I´ve also tried to run the demo on MacOS and everything was fine, so I guess the reason for the problem is Windows.
I believe something is wrong with the paths, but I couldn´t figure out where exactly the problem is.

Would be great if someone could solve this problem.

Cheers

Sampling

Add sampling control. A probabilistic sampling (eg, X% of events) would be a good start. Consider if to apply per-event, or per-session.

Tasks

ReferenceError: exports is not defined in ES module scope

Description

Hi folks! We got

event - compiled client and server successfully in 261 ms (3557 modules)
ReferenceError: exports is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '....../node_modules/@grafana/faro-web-tracing/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

at file:///...../node_modules/@grafana/faro-web-tracing/dist/cjs/index.js:2:23

when trying to integrate faro with our nextjs + TS application. The setup is rather simple, as we just imported several stuff following the readme:

import { initializeFaro } from '@grafana/faro-web-sdk';
import {
  FaroSessionSpanProcessor,
  FaroTraceExporter,
} from '@grafana/faro-web-tracing';

Steps to reproduce

Expected behavior

It should not cry like this?

Actual behavior

Environment

  • SDK version:
"@grafana/faro-core": "^1.0.0-beta4",
"@grafana/faro-web-sdk": "^1.0.0-beta4",
"@grafana/faro-web-tracing": "^1.0.0-beta4",
  • SDK instrumentations:
  • Device type:
  • Device name:
  • OS: Ubuntu 2204
  • Browser: Chrome stable

Demo

Context

I tracked it all the way back to #27, but found nothing really helpful to this issue.

Thanks!

Couldn't find any versions for "@grafana/faro-web-sdk" that matches "^1.0.0-beta6"

Description
"@grafana/faro-web-sdk" "^1.0.0-beta6" is not available on npm to use faro.api.setView()

Steps to reproduce
Update "@grafana/faro-web-sdk" version to ^1.0.0-beta6 and run npm

Expected behavior
"@grafana/faro-web-sdk" version to ^1.0.0-beta6 should be updated

Actual behavior

Couldn't find any versions for "@grafana/faro-web-sdk" that matches "^1.0.0-beta6"
? Please choose a version of "@grafana/faro-web-sdk" from this list: 
❯ 1.0.0-beta4 
  1.0.0-beta3 
  1.0.0-beta2 
  1.0.0-beta1 

Cannot search `session_id` using `traceQL` in demo

Description

When running the demo app in this repo (docker-compose.yml) I note that it logs the session_id as a span attribute.

If i view traces for the @grafana/faro-demo-client service I can see the session_id as a span attribute.

However, when using the TraceQL tab, I cannot get any results.

This seems to actually be a problem across numerous fields for me, not just sesssion_id.

Steps to reproduce

Run docker-compose up in this repo.

Find a session_id from any recent traces you create (or use the session-id reported on the UI of the app)

Run TraceQL queries:

{span.session_id="$some-session-id"}

I also tried

{.session_id="$some-session-id"}

I don't see any errors in the inspector - just zero results.


Not too sure what I'm doing wrong...any help appreciated. Thanks

app_agent_receiver_configs in config file causing start Grafana Agent failed

Description

Hello, I'm new to grafana and faro-web-sdk, and I'm following your quick-start document.
However, I'm facing some problems when I try to set up my grafana agent, and i'm following
the config file from quick-start-browser.md to start it.

When I start it, it says:

/usr/bin/grafana-agent --config.file /etc/grafana-agent.yaml 
2023/01/28 15:19:32 error loading config file /etc/grafana-agent.yaml: yaml: unmarshal errors:
  line 1: field app_agent_receiver_configs not found in type integrations.ManagerConfig

According to my knowledge, the app_agent_receiver_configs is a config for faro,
and I don't know why it caused the grafana agent can't start.

Steps to reproduce

I’m using the prometheus, loki and tempo address provided by Grafana Cloud,
and my config is:

metrics:
  wal_directory: /tmp/wal
  global: {}
  configs:
    - name: default
      remote_write:
        - url: https://prometheus-prod-xx-prod-ap-southeast-0.grafana.net/api/prom/push
          basic_auth:
            username: <myUserName>
            password: <myAPIKEY>
logs:
  positions_directory: /tmp/loki-pos
  configs:
    - name: default
      scrape_configs: []
      clients:
        - url: https://<myUserName>:<myAPIKEY>@logs-prod-xxx.grafana.net/loki/api/v1/push
traces:
  configs:
    - name: default
      remote_write:
        - endpoint: tempo-prod-xx-prod-ap-southeast-x.grafana.net:xxx
          basic_auth:
            username: <myUserName>
            password: <myAPIKEY>
      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: 9090
        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

Expected behavior

start grafana agent success

Actual behavior

start grafana agent failed

Environment

OS: CentOS 7

Grafana Agent:

/usr/bin/grafana-agent -version 
agent, version v0.30.2 (branch: HEAD, revision: 59144c61)
  build user:       root@c01bcc4cd472
  build date:       2023-01-11T17:46:30Z
  go version:       go1.19.3
  platform:         linux/amd64

Demo

Context

Dart / Flutter SDK

Description

We need to know if there is any plan to come up with a Mobile SDK for RUM and if there is what is the road-map and estimated time-line when we can expect an important feature release like this.

TracingInstrumentation breaks fetch requests

Description

When using TracingInstrumentation, fetch requests with relative URLs are broken in sub-pages.

Steps to reproduce

  1. Add Faro Web SDK and TracingIntrumentation to the project
  2. Add a fetch request with a relative URL
  3. Navigate to a sub-page
  4. Observe the fetch request

Expected behavior

The request will be executed without any issue.

Actual behavior

The request has a tampered URL relative to the sub-page.

Environment

  • SDK version: 1.0.0-beta3
  • SDK instrumentations: Web SDK, Web Tracing
  • Device type: all
  • Device name: all
  • OS: all
  • Browser: all

Strict typing for meta

Meta should be strictly typed, according to backend payload schema.
Also would be great to add some helpers like setUser etc

Remove started property from session meta

Description

The session meta interface specifies started property but we don't accept it in the collector.

Steps to reproduce

Expected behavior

Actual behavior

The started property should be removed.

Environment

  • SDK version: -
  • SDK instrumentations: -
  • Device type: -
  • Device name: -
  • OS: -
  • Browser: -

Demo

Context

Auto capture Performance, Navigation and Resource timings

Description

For APM it is important to able track Performance, Navigation and Resource Timings to drill down into that data to for example find slow page loads, request times we can improved have an idea about the size of assets and many many more.

Having that data also enables functionality like adding alerts base on that data, define and observe performance and many more.

Proposed solution

Add and instrumentation which automatically collects and sends that data.

Context

See: Navigation and resource timings

TL;DR Some Perf. Timings we can collect or calculate based on browser metrics

image

TL;DR Some Resource Timings we can collect or calculate based on browser metrics

image

docker-compose.yml cant start Tempo

Description

When trying to start docker from docker-compose.yml there is a problem starting Tempo service.

failed parsing config: failed to parse configFile /etc/tempo-config/tempo.yaml: yaml: unmarshal errors:
  line 1: field metrics_generator_enabled not found in type app.Config
  line 2: field search_enabled not found in type app.Config
  line 52: field index_downsample_bytes not found in type common.BlockConfig
  line 53: field encoding not found in type common.BlockConfig
  line 56: field encoding not found in type wal.Config

Steps to reproduce

  1. Copy repo
  2. Run docker compose up -d

Expected behavior

All services run

Actual behavior

Tempo is not working

Environment

Latest main branch

Wrong version for Session and View instrumentations

Description

SessionInstrumentation and ViewInstrumentation are reporting the wrong instrumentation version.

Steps to reproduce

  1. Add Faro Web SDK to your project
  2. Look over the payload and identify @grafana/faro-web-sdk:instrumentation-view
  3. Look at the version

Expected behavior

The version should match the Faro Web SDK version.

Actual behavior

The version is different from the Faro Web SDK version.

Environment

  • SDK version: 1.0.0-beta5
  • SDK instrumentations: default
  • Device type: all
  • Device name: all
  • OS: all
  • Browser: all

Demo

Context

Question regarding meta's and passing fields to traces

Hi, I've been playing around with the demo locally. I wanted to get some more fields passed through to trace so I tried changing the agent.yml for the trace config to add attributes like this:

  attributes:
    actions:
      - action: upsert
        key: testNewValue
        from_context: meta.user.email

But it doesn't appear to work. What am I doing wrong or is this even possible / am I approaching this the wrong way? I'm totally new to this so feel free to set me straight.

Basically my logic was rather than only being able to search on the session_id it would be great to have something like the user_email passed through to tempo and then I could search all traces which include that.

Any thoughts appreciated.

docs: Include browser support

Description

As this will be a library that will run in multiple systems, the documentation should include the list of browsers that the SDK will work on.

Proposed solution

Run the SDK in an extensive test in different versions of the browsers to verify

Build & publish esm modules

I believe right now we only build cjs modules. Publish esm too, adding module property to respective package jsons

Align measurement payload to only be able to contain exactly one measurement.

The Otel spec says that we don't have multiple metrics in the same scoped resource.

In Faro it is possible to add more then one metric type to the measurements array.
The original intention was to be able to log different metrics which belong to the same type in one line.
But, we never used this variant an in the current Faro implementation we create a single log line for each metric because we call pushMeasuerent for each.

For example the WebVitals transport. Here we call pushMeasurement for each WV which will translate into one measurement for each Web Vital.

Example payload WebVitals:

"measurements": [
    { "type": "web-vitals", "values": { "fcp": 213.7000000011176 } }
  ],

We need to change this in way so that a paylaod only contains one metric.
Fro example:

measurementPayload: {
    type: 'web-vitals',
    name: 'fcp'
    value: '1.234'
}

agent config

Hello sir, I'm failing to connect to the domain the agent is exposing to start collecting data. May I be missing something?. This is my config:

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: localhost
port: 12345
cors_allowed_origins:
- https://localhost:3000
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

with this config page http://localhost:12345/collect is not found. tried with another host name but got the same result

Using Faro with applications that are not based on nodejs?

Hey all,

Absolutely fantastic to see this project released!

I can see a huge amount of use for a lot of our customers, however most of them are not running SPAs or nodejs-based apps for their websites.

Is there any documentation on using these libraries with a "legacy" website? I'm thinking about apps that use Django to render the page and call javascript from CDN's to enable bootstrap4 or similar?

OTLP compliant transport

Description

The current FetchTransport uses a proprietary schema for the payload which is not compliant with the OTLP schema.

Proposed solution

The best approach to this issue is to create another HTTP transport, which we will refer to as OtlpTransport.

The OtlpTransport should be pretty similar to the current FetchTransport, but with an important difference: it should batch multiple events into a single HTTP request rather than sending an HTTP request for each signal. The batching should be configurable by number of signals send in a single request but also by the delay of waiting for a new signal before sending the current one.

For example, let's assume that whenever a signal is sent to a transport, it will wait for another 250ms (this should be configurable) in order to wait for another signal. If no other signal came, the signal is sent. But if 30 (this should also be configurable) other signals are sent, then we should batch those 30 in a single request and any other subsequent signal will be part of the next batch.

The OtlpTransport should also implement the retrying mechanism and concurrency handling mechanism that are currently present in the FetchTransport.

As a stretch goal for the OtlpTransport, simple sampling should also be implemented. Simple sampling refers to dropping a percentage of the signals unless they are are from certain categories (i.e. errors, error logs or events). This should be disabled by default and it would offer a way for implementing proper sampling in the future.

The OtlpTransport will replace the FetchTransport as the default transport in @grafana/faro-web-sdk but FetchTransport should continue to exist for backwards compatibility and Grafana Agent compatibility purposes.

Context

Otel compatible Logs and Traces transport

Otel compatible Logs and Traces transport

  • should be pretty similar to the current FetchTransport
  • should batch multiple events into a single HTTP request rather than sending an HTTP request for each signal.
    • The batching should be configurable by number of signals send in a single request
    • But also by the delay of waiting for a new signal before sending the current one.
  • Should also implement the retrying mechanism and concurrency handling mechanism that are currently present in the FetchTransport.

Example:
Let's assume that whenever a signal is sent to a transport, it will wait for another 250ms (this should be configurable) in order to wait for another signal. If no other signal came, the signal is sent. But if 30 (this should also be configurable) other signals are sent, then we should batch those 30 in a single request and any other subsequent signal will be part of the next batch.

Part of: #90
Also see: #101

Events API

Add Events API. Items sent to receiver as Event kind: grafana/agent#2062

agent.api.pushEvent(semantic.events.click, { [semantic.attributes.interaction.target]: 'button-id' });
agent.api.pushEvent(semantic.events.navigate, { [semantic.attributes.navigation.pageId]: 'details' }, 'mydomain');
agent.api.pushEvent(semantic.events.login);

yarn clean breaks the demo in Docker

Description

When running yarn clean, the demo/logs folder gets deleted and docker compose up won't run anymore.

Steps to reproduce

  1. Run yarn clean
  2. Run docker compose up

Expected behavior

The demo runs without any issues.

Actual behavior

Docker complains about missing folder.

Environment

  • SDK version: -
  • SDK instrumentations: -
  • Device type: -
  • Device name: -
  • OS: -
  • Browser: -

Demo

Context

Improvements to the global object

Currently if a library is instantiating the agent and the user is doing it again, there will be two instances available and the latter will be declared on the global object.

We need to do some improvements here:

  • ensure that the global object is not redeclared
  • provide an API for registering new metas, transports etc. on the fly
  • when instantiating a new global agent, it should first look to see if there's one available. If it is, then just add the new instrumentations, transports etc. using the above-mentioned API
  • allow isolated agents to exist through the preventGlobalExposure flag

TracingInstrumentation breaks Faro initialization.

Description

Hi Folks! I'm trying to initialize Faro within our NextJs based application and run into:

TypeError: Method Promise.prototype.then called on incompatible receiver [object Object]
    at ZoneAwarePromise.then (<anonymous>)
    at node:internal/per_context/primordials:440:35
    at new Promise (<anonymous>)
    at new SafePromise (node:internal/per_context/primordials:408:29)
    at node:internal/per_context/primordials:440:9
    at Array.map (<anonymous>)
    at arrayToSafePromiseIterable (node:internal/per_context/primordials:437:5)
    at node:internal/per_context/primordials:453:21
    at new Promise (<anonymous>)
    at primordials.SafePromiseAll (node:internal/per_context/primordials:452:3)
    at ESMLoader.import (node:internal/modules/esm/loader:530:30)
    at importModuleDynamically (node:internal/modules/cjs/loader:1098:29)
    at importModuleDynamicallyWrapper (node:internal/vm/module:438:21)
    at importModuleDynamically (node:vm:389:46)
    at importModuleDynamicallyCallback (node:internal/process/esm_loader:35:14)
    .....
    at Object.<anonymous> (...../.next/server/pages/_app.js:2584:3)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Module._load (node:internal/modules/cjs/loader:878:12)
    at Module.require (node:internal/modules/cjs/loader:1061:19)
import {
  ErrorsInstrumentation,
  WebVitalsInstrumentation,
  initializeFaro as coreInit,
} from '@grafana/faro-web-sdk';
import { TracingInstrumentation } from '@grafana/faro-web-tracing';

const initializeFaro = () => {
  const faro = coreInit({
    url: composeOTELCollectorString(),
    // apiKey: 'secret',
    app: {
      name:
        `some-trivial-app,
      version: '0.0.0',
      environment: process.env.NEXT_PUBLIC_ENV,
    },
    instrumentations: [
      new ErrorsInstrumentation(),
      new WebVitalsInstrumentation(),
      new TracingInstrumentation(),
    ],
    // transports: [new ConsoleTransport()],
    session: undefined,
  });

  return faro;
};

It works fine as long as we don't try to register TracingInstrumentation, which is a must have in our use case. Any ideas?

Steps to reproduce

Expected behavior

Actual behavior

Environment

  • SDK version:
"@opentelemetry/api": "^1.3.0",
"@opentelemetry/auto-instrumentations-node": "^0.35.0",
"@opentelemetry/auto-instrumentations-web": "^0.31.0",
"@opentelemetry/context-zone": "^1.8.0",
"@opentelemetry/sdk-node": "^0.34.0",
"@grafana/faro-core": "^1.0.0-beta4",
"@grafana/faro-web-sdk": "^1.0.0-beta4",
"@grafana/faro-web-tracing": "^1.0.0-beta5",
"next": "12.3.1"
...

with node version v18.12.1

  • SDK instrumentations:
  • Device type: PC
  • Device name:
  • OS: Ubuntu 2204
  • Browser: Chrome Stable channel

Demo

Context

Session tracking

Track user session. Assign session id to events / spans

Needs to be elaborated:
Does session persist between page reloads? How?
Should we send a separate event for initializing session?
Anything else?

Traces have wrong Trace Start time

Description

After the setup of the LGTM stack with Faro and Grafana Agent receiver, and configuring React app the same way as it is a demo application, tracers are received and able to browse them in Tempo but they all have the wrong Trace Start time.
Logs on the other hand in Loki have the correct time.

trace

Agent configuration:

metrics:
  wal_directory: /tmp/wal
  global: {}
  configs:
    - name: default
      remote_write:
        - url: http://prometheus.app:9090/api/v1/write
logs:
  positions_directory: /tmp/loki-pos
  configs:
    - name: default
      clients:
        - url: http://loki..app:3100/loki/api/v1/push
      scrape_configs:
      - job_name: frontend-core-ui
        pipeline_stages:
          - logfmt:
              mapping:
                timestamp: timestamp
          - timestamp:
              format: "2006-01-02 15:04:05.000 -0700 MST"
              source: timestamp
          - output:
              source: output
        static_configs:
          - labels:
              job: frontend-core-ui

traces:
  configs:
    - name: default
      remote_write:
        - endpoint: tempo.app:4317
          insecure: true
          tls_config:
            insecure_skip_verify: true
      receivers:
        otlp:
          protocols:
            grpc:
            http:
              cors:
                allowed_origins:
                  - http://localhost:8080
                max_age: 7200

integrations:
  app_agent_receiver_configs:
    - autoscrape:
        enable: true
        metrics_instance: 'default'
      instance: 'frontend-core-ui'
      logs_instance: 'default'
      traces_instance: 'default'
      server:
        host: 0.0.0.0
        port: 8081
        cors_allowed_origins:
          - 'http://localhost:3000'
      logs_labels: # labels to add to loki log record
        job: frontend-core-ui
        kind: # value will be taken from log items. exception, log, measurement, etc
        Time:
        timestamp:
      logs_send_timeout: 5000
      sourcemaps:
        download: true

Don't know where to look anymore for potential fix...

Environment

  • SDK version: 1.0.0-beta3
  • SDK instrumentations: Core, Web SDK, Web Tracing, React
  • Device type: desktop
  • Device name: MacBook Pro 16"
  • OS: macOS Ventura 13.1
  • Browser: Chrome 108.0.5359.98

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.