Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![en](https://img.shields.io/badge/lang-en-red.svg)](https://github.com/qa-guru/allure-notifications/blob/master/README.en.md)

# Allure notifications
**Allure notifications** - это библиотека, позволяющая выполнять автоматическое оповещение о результатах прохождения автотестов, которое направляется в нужный вам мессенджер (Telegram, Slack, ~~Skype~~, Email, Mattermost, Discord, Loop, Rocket.Chat, Zoho Cliq).
**Allure notifications** - это библиотека, позволяющая выполнять автоматическое оповещение о результатах прохождения автотестов, которое направляется в нужный вам мессенджер (Telegram, Slack, ~~Skype~~, Email, Mattermost, Discord, Loop, Rocket.Chat, Zoho Cliq) или TSDB InfluxDB.

Languages: 🇬🇧 🇫🇷 🇷🇺 🇺🇦 🇧🇾 🇨🇳

Expand Down Expand Up @@ -141,6 +141,18 @@ Languages: 🇬🇧 🇫🇷 🇷🇺 🇺🇦 🇧🇾 🇨🇳
"port": 0,
"username": "",
"password": ""
},
"influxdb": {
"url": "",
"org": "",
"bucket": "",
"token": "",
"measurement": "",
"tags": {
"tag1": "val1",
"tag2": "val2",
"tag3": "val3"
}
}
}
```
Expand Down Expand Up @@ -351,3 +363,18 @@ java "-DconfigFile=notifications/config.json" -jar ../allure-notifications-4.2.1
</ul>
Для получения дополнительной информации об API Zoho Cliq посетите <a href="https://www.zoho.com/cliq/help/restapi/v2/" target="_blank">официальную документацию</a>.
</details>
+ <details>
<summary>Influxdb config</summary>
Для включения отправки в InfluxDB необходимо предоставить следующие параметры конфигурации:
<ul>
<li><code>enabled</code> - Признак отправки в InfluxDB</li>
<li><code>url</code> - адрес инстанса InfluxDB</li>
<li><code>org</code> - имя организации в InfluxDB</li>
<li><code>token</code> - Ваш API токен в InfluxDB</li>
<li><code>bucket</code> - Имя корзины (InfluxDB2) / базы данных (InfluxDB3)</li>
<li><code>measurement</code> - имя метрики (InfluxDB2) / таблицы (InfluxDB3)</li>
<li><code>tags</code> - набор тегов метрики</li>
</ul>
Fields, которые отправляются в InfluxDB, включают поля из класса Statistic.
Timestamp берется из поля stop класса Time.
</details>
2 changes: 2 additions & 0 deletions allure-notifications-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ dependencies {
implementation('com.fasterxml.jackson.core:jackson-databind')
implementation('com.fasterxml.jackson.dataformat:jackson-dataformat-properties')

implementation('com.influxdb:influxdb-client-java:7.3.0')

testImplementation('org.junit.jupiter:junit-jupiter:5.13.4')
testRuntimeOnly('org.junit.platform:junit-platform-launcher')
testImplementation('net.bytebuddy:byte-buddy:1.17.7')
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package guru.qa.allure.notifications.clients;

import guru.qa.allure.notifications.clients.influxdb.InfluxdbClient;
import guru.qa.allure.notifications.clients.rocket.RocketChatClient;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -41,6 +42,9 @@ public static List<Notifier> from(Config config) {
if (config.getCliq() != null) {
notifiers.add(new CliqClient(config.getCliq(), config.getProxy()));
}
if (config.getInfluxdb() != null && Boolean.TRUE.equals(config.getInfluxdb().getEnabled())) {
notifiers.add(new InfluxdbClient(config.getInfluxdb()));
}
return notifiers;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package guru.qa.allure.notifications.clients.influxdb;

import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.InfluxDBClientFactory;
import com.influxdb.client.WriteApiBlocking;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
import guru.qa.allure.notifications.clients.Notifier;
import guru.qa.allure.notifications.config.influxdb.Influxdb;
import guru.qa.allure.notifications.exceptions.MessagingException;
import guru.qa.allure.notifications.model.summary.Statistic;
import guru.qa.allure.notifications.model.summary.Time;
import guru.qa.allure.notifications.template.data.MessageData;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;

@Slf4j
public class InfluxdbClient implements Notifier {
private final Influxdb influxdb;

public InfluxdbClient(Influxdb influxdb) {
this.influxdb = influxdb;
}

@Override
public void sendText(MessageData messageData) throws MessagingException {
send(messageData);
}

@Override
public void sendPhoto(MessageData messageData, byte[] chartImage) throws MessagingException {
send(messageData);
}

@SneakyThrows
private void send(MessageData messageData) {
try (InfluxDBClient influxDBClient = InfluxDBClientFactory.create(influxdb.getUrl(), influxdb.getToken().toCharArray(), influxdb.getOrg(), influxdb.getBucket());){
WriteApiBlocking writeApi = influxDBClient.getWriteApiBlocking();
Point point = buildPoint(messageData);
log.info("Sending data to InfluxDB {}", influxdb.getUrl());
writeApi.writePoint(point);
} catch (Exception e) {
log.error("error", e);
}
}

private Point buildPoint(MessageData messageData) {
Point point = Point.measurement(influxdb.getMeasurement());
influxdb.getTags().forEach(point::addTag);
Statistic stat = (Statistic) messageData.getValues().get("statistic");
Time time = (Time) messageData.getValues().get("timeData");

Arrays.stream(stat.getClass().getDeclaredFields()).forEach(field -> {
field.setAccessible(true);
try {
point.addField(field.getName(), (Integer) field.get(stat));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});

point.addField("duration", time.getDuration());

if (time.getStop() != null) point.time(time.getStop(), WritePrecision.MS);

return point;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import guru.qa.allure.notifications.config.base.Base;
import guru.qa.allure.notifications.config.cliq.Cliq;
import guru.qa.allure.notifications.config.discord.Discord;
import guru.qa.allure.notifications.config.influxdb.Influxdb;
import guru.qa.allure.notifications.config.loop.Loop;
import guru.qa.allure.notifications.config.mail.Mail;
import guru.qa.allure.notifications.config.mattermost.Mattermost;
Expand All @@ -29,4 +30,5 @@ public class Config {
private RocketChat rocketChat;
private Cliq cliq;
private Proxy proxy;
private Influxdb influxdb;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package guru.qa.allure.notifications.config.influxdb;

import lombok.Data;

import java.util.Map;

@Data
public class Influxdb {
private Boolean enabled = true;
private String url;
private String token;
private String org;
private String bucket;
private String measurement;
private Map<String, String> tags;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@
public class Time {
@SerializedName("duration")
private Long duration;
@SerializedName("stop")
private Long stop;
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public Map<String, Object> getValues() {
data.put("customData", base.getCustomData());

data.put("time", Formatters.formatDuration(summary.getTime().getDuration(), base.getDurationFormat()));
data.put("timeData", summary.getTime());
data.put("statistic", summary.getStatistic());

data.put("suitesSummaryJson", suitesSummaryJson);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package guru.qa.allure.notifications.clients.influxdb;

import guru.qa.allure.notifications.clients.ClientFactory;
import guru.qa.allure.notifications.clients.Notifier;
import guru.qa.allure.notifications.config.Config;
import guru.qa.allure.notifications.config.influxdb.Influxdb;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;

class ClientFactoryInfluxdbTest {

@Test
void shouldCreateInfluxdbClientWhenEnabled() {
Config config = new Config();
Influxdb influxdb = buildInfluxConfig(true);
config.setInfluxdb(influxdb);

List<Notifier> notifiers = ClientFactory.from(config);

assertEquals(1, notifiers.size(), "Only InfluxdbClient expected");
assertInstanceOf(InfluxdbClient.class, notifiers.get(0));
}

@Test
void shouldNotCreateInfluxdbClientWhenDisabled() {
Config config = new Config();
Influxdb influxdb = buildInfluxConfig(false);
influxdb.setEnabled(false);
config.setInfluxdb(influxdb);

List<Notifier> notifiers = ClientFactory.from(config);

assertTrue(notifiers.isEmpty(), "No clients expected when Influxdb disabled");
}

@Test
void shouldNotCreateInfluxdbClientWhenConfigNull() {
Config config = new Config();

List<Notifier> notifiers = ClientFactory.from(config);

assertTrue(notifiers.isEmpty(), "No clients expected when Influxdb config absent");
}

private Influxdb buildInfluxConfig(boolean enabled) {
Map<String, String> tags = new HashMap<>();
tags.put("env", "test");

Influxdb influxdb = new Influxdb();
influxdb.setEnabled(enabled);
influxdb.setUrl("http://localhost:8086");
influxdb.setToken("test-token");
influxdb.setOrg("test-org");
influxdb.setBucket("test-bucket");
influxdb.setMeasurement("test-measurement");
influxdb.setTags(tags);
return influxdb;
}
}

Loading
Loading