Skip to content

Commit

Permalink
docs: Improved client docs (#99)
Browse files Browse the repository at this point in the history
* docs: add python client example

* docs: add skeleton for clients

* docs: add golang client docs

* docs: clients: add python and golang docs

* docs: clients: add javascript client docs

* docs: clients: add java client docs

* docs: clients: show line numbers in quickstart examples

* docs: simplify quickstart

* docs: clients: overview: add details about wire and serialization types

* docs: clients: golang: add explanation for serializer

* docs: quickstart: fix event example
  • Loading branch information
turtleDev authored Sep 23, 2024
1 parent a94d6f2 commit 71e2612
Show file tree
Hide file tree
Showing 7 changed files with 463 additions and 330 deletions.
119 changes: 119 additions & 0 deletions docs/docs/clients/golang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Golang

## Requirements
Make sure that Go >= `1.16` is installed on your system. See [installation instructions](https://go.dev/doc/install) on Go's website for more info.

## Installation
Install Raccoon's Go client using
```bash
$ go get github.com/raystack/raccoon/clients/go
```
## Usage

### Quickstart

Below is a self contained example of Raccoon's Go client that uses the Websocket API to publish events

```go title="quickstart.go" showLineNumbers
package main

import (
"fmt"
"log"
raccoon "github.com/raystack/raccoon/clients/go"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/google/uuid"
"github.com/raystack/raccoon/clients/go/serializer"
"github.com/raystack/raccoon/clients/go/testdata"
"github.com/raystack/raccoon/clients/go/ws"
)

func main() {
client, err := ws.New(
ws.WithUrl("ws://localhost:8080/api/v1/events"),
ws.WithHeader("x-user-id", "123"),
ws.WithHeader("x-user-type", "ACME"),
ws.WithSerializer(serializer.JSON),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()
_, err = client.Send([]*raccoon.Event{
{
Type: "page",
Data: &testdata.PageEvent{
EventGuid: uuid.NewString(),
EventName: "clicked",
SentTime: timestamppb.Now(),
},
},
})
if err != nil {
log.Fatal(err)
}
fmt.Println(<-client.EventAcks())
}
```

### Guide

#### Creating a client

Raccoon's API is exposed over 3 different protocols.
Depending on which protocol you wish to utilise to publish events to Raccoon, you will need to intantiate a different client.

Following is a table describing which package you should use for a given protocol.

| Protocol | Package |
| --- | --- |
| Websocket | `github.com/raystack/raccoon/clients/go/ws` |
| REST | `github.com/raystack/raccoon/clients/go/rest` |
| gRPC | `github.com/raystack/raccoon/clients/go/grpc` |

For instance, you can create a client over REST API using:
```go
import "github.com/raystack/raccoon/clients/go/rest"

func main() {
client, err := rest.New(
rest.WithURL("http://localhost:8080/api/v1/events"),
rest.WithHeader("x-user-id", "123")
)
if err != nil {
panic(err)
}

// use the client here
}
```

Depending on which protocol client you create, specifying the URL or the address of the server is mandatory.

For `REST` and `Websocket` clients, this can be done via the `WithUrl` option. For `gRPC` server you must use the `WithAddr` option.

#### Sending events

Event's can be sent using `client.Send(events []*raccoon.Event)`. The return signature of the `Send` method depends on the type of Client.

| Type | Signature |
| --- | --- |
| `REST`, `gRPC` | `Send([]*raccoon.Event) (string, *raccoon.Response, error)` |
| `Websocket` | `Send([]*raccoon.Event) (string, error)` |

For `gRPC` and `REST` clients, the response is returned synchronously. For `Websocket` the responses are returned asynchronously via a channel returned by `EventAcks()`.

`Event` structu has two fields: `Type` and `Data`.
`Type` denotes the event type. This is used by raccoon to route the event to a specific topic downstream. `Data` field contains the payload. This data is serialised by the `serializer` that's configured on the client. The serializer can be configured by using the `WithSerializer()` option of the respective clients.

The following table lists which serializer to use for a given payload type.

| Message Type | Serializer |
| --- | --- |
| JSON | `Serializer.JSON` |
| Protobuf | `Serializer.PROTO`|

Once a client is constructed with a specific kind of serializer, you may only pass it events of that specific type. In particular, for `JSON` serialiser the event data must be a value that can be encoded by `json.Marshal`. While for `PROTOBUF` serialiser the event data must be a protobuf message.

### Examples
You can find examples of client usage over different protocols [here](https://github.com/raystack/raccoon/tree/main/clients/go/examples)
97 changes: 97 additions & 0 deletions docs/docs/clients/java.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Java

## Requirements
Make sure you have Java JDK `>=8` and Gradle `>=7` installed on your system. See installation instructions for [openjdk](https://openjdk.org/install/) and [gradle](https://gradle.org/install/) for more information.
## Installation

In your `build.gradle` file add `io.odpf.raccoon` as a dependency.
```groovy
dependencies {
implementation group: 'io.odpf', name: 'raccoon', version: '0.1.5-rc'
}
```

## Usage

### Quickstart

Below is a self contained example of Raccoon's Java client that uses the REST API to publish events
```java title="App.java" showLineNumbers
package org.example;

import io.odpf.raccoon.client.RestConfig;
import io.odpf.raccoon.client.RaccoonClient;
import io.odpf.raccoon.client.RaccoonClientFactory;
import io.odpf.raccoon.model.Event;
import io.odpf.raccoon.model.Response;
import io.odpf.raccoon.model.ResponseStatus;
import io.odpf.raccoon.serializer.JsonSerializer;
import io.odpf.raccoon.wire.ProtoWire;

public class App {

public static void main(String[] args) {
RestConfig config = RestConfig.builder()
.url("http://localhost:8080/api/v1/events")
.header("x-user-id", "123")
.serializer(new JsonSerializer()) // default is Json
.marshaler(new ProtoWire()) // default is Json
.retryMax(5) // default is 3
.retryWait(2000) // default is one second
.build();

// get the rest client instance.
RaccoonClient Client = RaccoonClientFactory.getRestClient(config);

Response res = Client.send(new Event[]{
new Event("page", "EVENT".getBytes())
});

if (res.isSuccess() && res.getStatus() == ResponseStatus.STATUS_SUCCESS) {
System.out.println("The event was sent successfully");
}
}
}

```

### Guide

#### Creating a client

Raccoon's Java client only supports sending events over Raccoon's HTTP/JSON (REST) API.

To create a client, you must pass the `io.odpf.raccoon.client.RestConfig` object to the client factory `io.odpf.raccoon.client.RaccoonClientFactory.getRestClient()`.

You can use `RestConfig.builder()` as a convenient way of building the config object.

Here's a minimal example of what it looks like:
```java
RestConfig config = RestConfig.builder()
.url("http://localhost:8080/api/v1/events")
.build();
RacconClient client = RaccoonClientFactory.getRestClient(config);
```

#### Sending events

Events can be sent to raccoon use `RestClient.send()` method. The `send()` methods accepts an array of `io.odpf.raccoon.model.Event`

Here's a minimal example of what this could look like:
```java
Event[] events = new Event[]{
new Event("event_type", obj)
};
client.send(events);
```

Each event has a `type` and `data` field. `type` denotes the event type. This is used by raccoon to route the event to a specific topic downstream. `data` field contains the payload. This data is serialised by the `serializer` that's configured on the client.

The following table lists which serializer to use for a given payload type.

| Message Type | Serializer |
| --- | --- |
| JSON | `io.odpf.raccoon.serializer.JsonSerializer` |
| Protobuf | `io.odpf.raccoon.serializer.ProtoSerializer`|

Once a client is constructed with a specific kind of serializer, you may only pass it events of that specific type. In particular, for `JSON` serialiser the event data must be a Java object. While for `PROTOBUF` serialiser the event data must be a protobuf message object
97 changes: 97 additions & 0 deletions docs/docs/clients/javascript.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Javascript

## Requirements
Make sure that Nodejs >= `20.0` is installed on your system. See [installation instructions](https://nodejs.org/en/download/package-manager) on Nodejs's website for more info.

## Installation
Install Raccoon's Javascript client using npm
```javascript
$ npm install --save @raystack/raccoon
```
## Usage

### Quickstart

Below is a self contained example of Raccoon's Javascript client that uses Raccoon's REST API to publish events.

```javascript title="quickstart.js" showLineNumbers
import { RaccoonClient, SerializationType, WireType } from '@raystack/raccoon';

const jsonEvents = [
{
type: 'test-topic1',
data: { key1: 'value1', key2: ['a', 'b'] }
},
{
type: 'test-topic2',
data: { key1: 'value2', key2: { key3: 'value3', key4: 'value4' } }
}
];

const raccoonClient = new RaccoonClient({
serializationType: SerializationType.JSON,
wireType: WireType.JSON,
timeout: 5000,
url: 'http://localhost:8080/api/v1/events',
headers: {
'X-User-ID': 'user-1'
}
});

raccoonClient
.send(jsonEvents)
.then((result) => {
console.log('Result:', result);
})
.catch((error) => {
console.error('Error:', error);
});
```

### Guide

#### Creating a client
Raccoon's Javascript client only supports sending event's over Raccoon's HTTP/JSON (REST) API.

To create the client, use `new RaccoonClient(options)`. `options` is javascript object that contains the following properites:

| Property | Description |
| --- | --- |
| url | (required) The base URL for the API requests |
| serializationType | (required) The serialization type to use, either 'protobuf' or 'json' |
| wireType | The wire configuration, containing ContentType (default: `wireType.JSON`)|
| headers | Custom headers to be included in the HTTP requests (default: `{}`)|
| retryMax | The maximum number of retry attempts for failed requests (default: `3`) |
| retryWait | The time in milliseconds to wait between retry attempts (default: `1000`)|
| timeout | The timeout in milliseconds (default: `1000`)|
| logger | Logger object for logging (default: `global.console`)

#### Publishing events
To publish events, create an array of objects and pass it to `RaccoonClient#send()`. The return value is a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).

```js
const events = [
{
type: "event_type",
data: {},
}
];

client.send(events)
.then(result => console.log(result))
.catch(err => console.error(err))
```

`type` denotes the event type. This is used by raccoon to route the event to a specific topic downstream. `data` field contains the payload. This data is serialised by the `serializerType` that's configured on the client.

The following table lists which serializer to use for a given payload type.

| Message Type | Serializer |
| --- | --- |
| JSON | `SerializationType.JSON` |
| Protobuf | `SerializationType.PROTOBUF`|

Once a client is constructed with a specific kind of serializer, you may only pass it events of that specific type. In particular, for `JSON` serialiser the event data must be a javascript object. While for `PROTOBUF` serialiser the event data must be a protobuf message.

## Examples
You can find examples of client usage [here](https://github.com/raystack/raccoon/tree/main/clients/js/examples)
33 changes: 33 additions & 0 deletions docs/docs/clients/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Overview

## Introduction
Raccoon provides a suite of client libraries designed to help developers easily send clickstream events to its low-latency, high-throughput event ingestion service. Whether you’re building real-time analytics, tracking user behavior, or processing large-scale event data, Raccoon's clients offer flexible and efficient integration via WebSocket, REST, and gRPC APIs.

## Key Features

- **Multi-Protocol Support**: WebSocket, REST, and gRPC are available in all clients, allowing you to choose the best fit for your application’s needs.
- **Ease of Integration**: Designed with simplicity in mind, the clients integrate easily into existing projects with minimal configuration.
- **Reliability**: Each client includes retry mechanisms and error handling to ensure events are delivered reliably, even in the face of transient failures.

## Wire and Serialization Types

A concept that exists in all the Client libraries is that of wire type and serialization type.

Raccoon's API accepts both JSON and Protobuf requests. These are differentiated by the `Content-Type` header (in case of REST & gRPC protocols) and by `MessageType` for Websocket requests.

`Wire` denotes what the request payload is serialised as. If wire type is `JSON` the request is sent as a JSON-encoded string. If it's `Protobuf` the request is the serialized bytes of [`SendEventRequest`](https://github.com/raystack/proton/blob/main/raystack/raccoon/v1beta1/raccoon.proto#L23) proto

`Serialization` is how data in individual events is encoded. Just like wire type, it also supports `JSON` and `Protobuf` encoding.

You may use any combination of wire and serialization type that suits your needs.

## Getting Started

To start using Raccoon's client libraries, check out the detailed installation and usage instructions for each supported language:

- [Golang](clients/golang.md)
- [Python](clients/python.md)
- [Java](clients/java.md)
- [JavaScript](clients/javascript.md)

By leveraging Raccoon’s clients, you can focus on building your applications while Raccoon efficiently handles the ingestion of your clickstream events.
Loading

0 comments on commit 71e2612

Please sign in to comment.