npm package: @qwant/telemetry-react
Description: Qwant library for collecting telemetry information through react components
Author: Qwant
Latest version: 0.0.2

# Logger Documentation

The goal of the logger is to be able to log events happening on the app (click, display, loading...) trough a react app.
This library try to solve the headache of building an event with data available at different levels of the application 🧠.

## Definitions

- **Event** - The data representing the user's interaction that will be sent. An event has two parts, a string representing the **type** of the event (ui, url, display....), and an object transporting additional data (component, context, url, zone...)..
- **Client** - The browser
- **DataHub** - External service that will receive the event.

## API

The telemetry is exposed with multiple systems.

### Components

#### TelemetryConfiguration

To bootstrap `useTelemetry` you need to set the configuration with `TelemetryConfiguration`.

```jsx
const telemetryLogger = (endpoint, data) => {
  /* You can use whatever you want here */
  navigator.sendBeacon(endpoint, JSON.stringify(data))
}

return (
  <TelemetryConfiguration
    fetcher={telemetryLogger}
    endpoint="https://www.qwant.com/action"
    product={{
      name: 'front',
      module: 'my-product',
      version: '0.0.1',
    }}
  >
    {/* Your application */}
  </TelemetryConfiguration>
)
```

#### TelemetryProvider

The telemetry provider is used to "tag" specific area of the application and allows children to retrieve the context of an event more easily.

```jsx
// app.jsx
return (
  <TelemetryProvider context={TelemetryEnumContexts.HOMEPAGE}>
    <Box>
      <TelemetryProvider component={TelemetryEnumComponents.SIDEBAR}>
        <Sidebar /> {/* // here we will have "context" and "component" set */}
      </TelemetryProvider>
    </Box>
  </TelemetryProvider>
)

// Sidebar
function Sidebar() {
  const logClick = useLogCallback('ui', {
    component: TelemetryEnumZones.BUTTON,
  })

  return <button onClick={logClick}>I'm a button</button>
}
```

The button will automatically send the **context** and **component** retrieved from the provider and will call `sendEvent('ui', {context: 'homepage', component: 'sidebar', zone: 'button'})`. Multiple providers can be nested to provide information for emitted events.

### Hooks

#### useLogCallback(type: string, data: object): function

Return a memoized function that sends an event.

```js
function MyComponent({ onClick }) {
  const loggableClick = useLogCallback(TelemetryEvents.UI, {
    zone: TelemetryEnumZones.BLOG,
  })

  return <button onClick={loggableClick}>Hello</button>
}
```

#### useLogCallback(callback: function, type: string, data: object): function

Wrap the `callback` and return a function that will send an event after the original callback call.

```js
function MyComponent({ onClick }) {
  const loggableClick = useLogCallback(onClick, TelemetryEvents.UI, {
    zone: TelemetryEnumZones.BLOG,
  })

  return <button onClick={loggableClick}>Hello</button>
}
```

#### **useLogEffect(type: string, data: object, dependencies: array = []): void**

Send an event when the dependencies change or when the component is mounted

#### **useTelemetry(): {sendEvent: function}**

This hook will retrieve the `sendEvent` method from the context. Try to use the other hooks as much as possible before using this one.

```js
function MyComponent({ onClick }) {
  const { sendEvent } = useTelemetry()

  return <button onClick={() => sendEvent('ui', {})}>Hello</button>
}
```

### HOC

Hooks are a good way to inject the logger faster, but it's not always the best way to handle things. With HOC you can easily decorate external components.

#### Loggable(component, type: string)

Wraps a component and inject a `log` function as a prop that can be used to send events.

```jsx
function MyComponent({ log }) {
  return <button onMouseUp={log({ component: 'button' })}>Click me</button>
}

const MyComponentWithLog = Loggable(MyComponent, 'ui')
```

#### Loggable(component, type: string, trigger: string)

Wraps a component and wraps the `on{Trigger}` props

```jsx
// my-components.jsx
function MyComponent({ onClick }) {
  return <button onClick={onClick}>Click me</button>
}

export const MyComponentWithLog = Loggable(MyComponent, 'ui', 'click')

// app.jsx
return <MyComponentWithLog onClick={(e) => doSomething()} />
// An event will be emitted after the doSomething call
```

You can add additional information using props prefixed by "telemetry".

```jsx
return (
  <MyComponentWithLog
    telemetryZone={TelemetryEnumZones.LINK}
    onClick={(e) => doSomething()}
  />
)
```

#### WithTelemetryContext(component, data: object)

Wraps a component with a TelemetryProvider

```jsx
// The goal is to avoid repeating provider
;<TelemetryProvider component="sidebar">
  <Sidebar />
</TelemetryProvider>

// Instead we can export an already contextualized sidebar
const Sidebar = WithTelemetryContext(SidebarPure, { component: 'sidebar' })
// Then you can simply use <Sidebar/>
```

#### WithLogEffect(component, eventName: string, data: object, deps = array)

Wrap a component with an `useLogEffect`. It is useful when we need to trigger
a display log when component is mounted for example.

```jsx
import { Multi } from 'qwant-ia'

const LoggableMulti = WithLogEffect(
  Multi,
  TelemetryEvents.DISPLAY_ELEMENT,
  {
    ia: TelemetryEnumIA.MAPS_MULTI,
  },
  ['myDeps']
)

function MapsPhoenix() {
  /* ... */

  if (places.length > 1) {
    return <LoggableMulti /* ... */ />
  }
}
```