Skip to content

Commit

Permalink
Add support for Sentry monitoring
Browse files Browse the repository at this point in the history
Includes addition to documentation.
  • Loading branch information
pvannierop committed Oct 4, 2024
1 parent 0753e5a commit 85b2f7f
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 6 deletions.
51 changes: 45 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
# RADAR-Gateway

REST Gateway to the Apache Kafka, similar to the REST Proxy provided by Confluent. In addition, it does authentication and authorization, content validation and decompression if needed. It is available as a [docker image](https://hub.docker.com/r/radarbase/radar-gateway).
REST Gateway to the Apache Kafka, similar to the REST Proxy provided by Confluent. In addition, it does authentication
and authorization, content validation and decompression if needed. It is available as
a [docker image](https://hub.docker.com/r/radarbase/radar-gateway).

<!-- TOC -->
* [RADAR-Gateway](#radar-gateway)
* [Configuration](#configuration)
* [Usage](#usage)
* [Sentry monitoring](#sentry-monitoring)
<!-- TOC -->

## Configuration

The [RADAR-Auth] library is used for authentication and authorization of users. Refer to the documentation there for a full description of the configuration options.
The [RADAR-Auth] library is used for authentication and authorization of users. Refer to the documentation there for a
full description of the configuration options.

## Usage

Expand All @@ -21,22 +31,51 @@ TOPIC=test
docker-compose exec kafka-1 kafka-topics --create --topic $TOPIC --bootstrap-server kafka-1:9092
```

Now the gateway is accessible through <http://localhost:8090/radar-gateway/> and the [ManagementPortal] is available through <http://localhost:8080/managementportal/>
Now the gateway is accessible through <http://localhost:8090/radar-gateway/> and the [ManagementPortal] is available
through <http://localhost:8080/managementportal/>

The access token should be generated by the aforementioned Management portal. The access token is a JWT (JSON Web Token) that should contain the `MEASUREMENT.CREATE` scope for resource `res_gateway`, and list all applicable sources to submit data for. The gateway does content validation for posted data. It requires to use the Avro format with JSON serialization, using the `application/vnd.kafka.avro.v1+json` or `application/vnd.kafka.avro.v2+json` media types, as described in the [REST Proxy documentation]. It also requires messages to have both a key and a value with schemas. The key should have a `userId` and `sourceId` field. The `userId` should match the `sub` field in the OAuth2 JWT access token. That JWT should also contain a `sources` array claim which should contain the given `sourceId`. Sources can be added in the ManagementPortal or be generated by the app dynamically and then registered with the ManagementPortal.
The access token should be generated by the aforementioned Management portal. The access token is a JWT (JSON Web Token)
that should contain the `MEASUREMENT.CREATE` scope for resource `res_gateway`, and list all applicable sources to submit
data for. The gateway does content validation for posted data. It requires to use the Avro format with JSON
serialization, using the `application/vnd.kafka.avro.v1+json` or `application/vnd.kafka.avro.v2+json` media types, as
described in the [REST Proxy documentation]. It also requires messages to have both a key and a value with schemas. The
key should have a `userId` and `sourceId` field. The `userId` should match the `sub` field in the OAuth2 JWT access
token. That JWT should also contain a `sources` array claim which should contain the given `sourceId`. Sources can be
added in the ManagementPortal or be generated by the app dynamically and then registered with the ManagementPortal.

Now you can access the gateway:

```shell
TOKEN=<access token from management portal>
curl -H "Authorization: Bearer $TOKEN" http://localhost:8090/radar-gateway/topics
```

Data compressed with GZIP is decompressed if the `Content-Encoding: gzip` header is present. With `curl`, use the `-H "Content-Encoding: gzip" --data-binary @data.json.gz` flags. It can be activated in `radar-commons` Java `RestClient` by setting `RestClient.Builder.gzipCompression(true)`. Likewise it accepts Apple LZFSE encoded data by adding the header `Content-Encoding: lzfse`.
Data compressed with GZIP is decompressed if the `Content-Encoding: gzip` header is present. With `curl`, use the
`-H "Content-Encoding: gzip" --data-binary @data.json.gz` flags. It can be activated in `radar-commons` Java
`RestClient` by setting `RestClient.Builder.gzipCompression(true)`. Likewise it accepts Apple LZFSE encoded data by
adding the header `Content-Encoding: lzfse`.

Otherwise, it accepts all the same Avro messages and headers as specified in the Kafka [REST Proxy documentation].

Finally, the gateway accepts a custom binary format for data ingestion. The data must follow the binary Avro serialization of the [RecordSet schema](https://github.com/RADAR-base/RADAR-Schemas/blob/master/commons/kafka/record_set.avsc). Data in this format can be posted by using the content type `application/vnd.radarbase.avro.v1+binary`. It will construct an `ObservationKey` based on the user data in the `RecordSet`, and read the binary data values using the schema version provided in the `RecordSet`. This data sending mode can be activated in Java by using radar-commons `RestSender.Builder.useBinaryContent(true)`. Using binary mode has the added benefit of having a much more efficient GZIP encoding for many datasets.
Finally, the gateway accepts a custom binary format for data ingestion. The data must follow the binary Avro
serialization of
the [RecordSet schema](https://github.com/RADAR-base/RADAR-Schemas/blob/master/commons/kafka/record_set.avsc). Data in
this format can be posted by using the content type `application/vnd.radarbase.avro.v1+binary`. It will construct an
`ObservationKey` based on the user data in the `RecordSet`, and read the binary data values using the schema version
provided in the `RecordSet`. This data sending mode can be activated in Java by using radar-commons
`RestSender.Builder.useBinaryContent(true)`. Using binary mode has the added benefit of having a much more efficient
GZIP encoding for many datasets.

[REST Proxy documentation]: https://docs.confluent.io/current/kafka-rest/api.html

[RADAR-Auth]: https://github.com/RADAR-base/ManagementPortal/tree/master/radar-auth

[ManagementPortal]: https://github.com/RADAR-base/ManagementPortal

## Sentry monitoring

To enable Sentry monitoring:

1. Set a `SENTRY_DSN` environment variable that points to the desired Sentry DSN.
2. (Optional) Set the `SENTRY_LOG_LEVEL` environment variable to control the minimum log level of events sent to Sentry.
The default log level for Sentry is `WARN`. Possible values are `TRACE`, `DEBUG`, `INFO`, `WARN`, and `ERROR`.
3 changes: 3 additions & 0 deletions radar-gateway/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ plugins {
application
kotlin("plugin.serialization") version Versions.kotlin
id("com.avast.gradle.docker-compose") version Versions.dockerCompose
// TODO Remove this when new release of radar-commons is available and used in this project.
// This version has Sentry support built in for radar-kotlin plugin.
id("io.sentry.jvm.gradle") version "4.11.0"
}

description = "RADAR Gateway to handle secured data flow to backend."
Expand Down
39 changes: 39 additions & 0 deletions radar-gateway/src/main/resources/log4j2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
~ /*
~ * Copyright 2024 The Hyve
~ *
~ * Licensed under the Apache License, Version 2.0 (the "License");
~ * you may not use this file except in compliance with the License.
~ * You may obtain a copy of the License at
~ *
~ * http://www.apache.org/licenses/LICENSE-2.0
~ *
~ * Unless required by applicable law or agreed to in writing, software
~ * distributed under the License is distributed on an "AS IS" BASIS,
~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ * See the License for the specific language governing permissions and
~ * limitations under the License.
~ */
-->

<configuration status="INFO">
<appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout
pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"
/>
</Console>
<!-- For Sentry to work the DSN must be set via SENTRY_DSN environment variable
When SENTRY_DSN is empty string, the Sentry SDK is disabled -->
<Sentry name="Sentry" debug="false"/>
</appenders>

<loggers>
<root level="INFO">
<appender-ref ref="Console" />
<!-- Note that the Sentry logging threshold is at WARN level by default -->
<appender-ref ref="Sentry" level="${env:SENTRY_LOG_LEVEL:-WARN}" />
</root>
</loggers>
</configuration>

0 comments on commit 85b2f7f

Please sign in to comment.