mirror of https://github.com/OpenVidu/openvidu.git
openvidu-server: fix CDR logback file. Add CDR test
parent
a6b9e802c7
commit
9cdca285a2
|
@ -1,20 +1,18 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
|
|
||||||
|
<springProperty scope="context" name="cdrEnabled" source="OPENVIDU_CDR" />
|
||||||
<springProperty scope="context" name="cdrPath" source="OPENVIDU_CDR_PATH" />
|
<springProperty scope="context" name="cdrPath" source="OPENVIDU_CDR_PATH" />
|
||||||
<timestamp key="myTimestamp" timeReference="contextBirth" datePattern="HH-mm-ss" />
|
<timestamp key="myTimestamp" timeReference="contextBirth" datePattern="HH-mm-ss" />
|
||||||
|
|
||||||
<appender name="STDOUT"
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<encoder>
|
<encoder>
|
||||||
<if
|
<if condition='property("logging.colors").equalsIgnoreCase("true")'>
|
||||||
condition='property("logging.colors").equalsIgnoreCase("true")'>
|
|
||||||
<then>
|
<then>
|
||||||
<pattern>%black(%highlight([%p]) %d{dd MMM HH:mm:ss.SSS} %magenta([%.80t]) \(%file:%line\) - %msg%n)</pattern>
|
<pattern>%black(%highlight([%p]) %d{dd MMM HH:mm:ss.SSS} %magenta([%.80t]) \(%file:%line\) - %msg%n)</pattern>
|
||||||
</then>
|
</then>
|
||||||
<else>
|
<else>
|
||||||
<pattern>[%p] %d [%.80t] %c - %msg%n
|
<pattern>[%p] %d [%.80t] %c - %msg%n</pattern>
|
||||||
</pattern>
|
|
||||||
</else>
|
</else>
|
||||||
</if>
|
</if>
|
||||||
</encoder>
|
</encoder>
|
||||||
|
@ -44,12 +42,10 @@
|
||||||
<appender-ref ref="STDOUT" />
|
<appender-ref ref="STDOUT" />
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
<if condition='property("OPENVIDU_CDR").equalsIgnoreCase("true")'>
|
<if condition='property("cdrEnabled").equalsIgnoreCase("true")'>
|
||||||
<then>
|
<then>
|
||||||
<appender name="CDR"
|
<appender name="CDR" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
class="ch.qos.logback.core.rolling.RollingFileAppender">
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
<rollingPolicy
|
|
||||||
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
|
||||||
<FileNamePattern>${cdrPath}/CDR.%d{yyyy-MM-dd}_${myTimestamp}.log
|
<FileNamePattern>${cdrPath}/CDR.%d{yyyy-MM-dd}_${myTimestamp}.log
|
||||||
</FileNamePattern>
|
</FileNamePattern>
|
||||||
<MaxHistory>30</MaxHistory>
|
<MaxHistory>30</MaxHistory>
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
package io.openvidu.test.browsers.utils.webhook;
|
package io.openvidu.test.browsers.utils.webhook;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
@ -25,7 +27,6 @@ import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.LinkedBlockingDeque;
|
import java.util.concurrent.LinkedBlockingDeque;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
|
@ -49,7 +50,7 @@ public class CustomWebhook {
|
||||||
|
|
||||||
public static CountDownLatch initLatch;
|
public static CountDownLatch initLatch;
|
||||||
public static int accumulatedNumberOfEvents = 0;
|
public static int accumulatedNumberOfEvents = 0;
|
||||||
public final static ConcurrentMap<String, AtomicInteger> accumulatedEvents = new ConcurrentHashMap<>();
|
public final static ConcurrentMap<String, List<JsonObject>> accumulatedEvents = new ConcurrentHashMap<>();
|
||||||
static final ConcurrentMap<String, BlockingQueue<JsonObject>> events = new ConcurrentHashMap<>();
|
static final ConcurrentMap<String, BlockingQueue<JsonObject>> events = new ConcurrentHashMap<>();
|
||||||
static final BlockingQueue<JsonObject> eventsInOrder = new LinkedBlockingDeque<>();
|
static final BlockingQueue<JsonObject> eventsInOrder = new LinkedBlockingDeque<>();
|
||||||
|
|
||||||
|
@ -156,9 +157,8 @@ public class CustomWebhook {
|
||||||
accumulatedNumberOfEvents++;
|
accumulatedNumberOfEvents++;
|
||||||
eventsInOrder.add(event);
|
eventsInOrder.add(event);
|
||||||
final String eventName = event.get("event").getAsString();
|
final String eventName = event.get("event").getAsString();
|
||||||
if (accumulatedEvents.putIfAbsent(eventName, new AtomicInteger(1)) != null) {
|
accumulatedEvents.putIfAbsent(eventName, new LinkedList<>());
|
||||||
accumulatedEvents.get(eventName).incrementAndGet();
|
accumulatedEvents.get(eventName).add(event);
|
||||||
}
|
|
||||||
final BlockingQueue<JsonObject> queue = new LinkedBlockingDeque<>();
|
final BlockingQueue<JsonObject> queue = new LinkedBlockingDeque<>();
|
||||||
if (!CustomWebhook.events.computeIfAbsent(eventName, e -> {
|
if (!CustomWebhook.events.computeIfAbsent(eventName, e -> {
|
||||||
queue.add(event);
|
queue.add(event);
|
||||||
|
|
|
@ -6,6 +6,9 @@ import java.awt.Point;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -22,6 +25,7 @@ import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
@ -38,6 +42,7 @@ import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParser;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
|
|
||||||
import info.debatty.java.stringsimilarity.Cosine;
|
import info.debatty.java.stringsimilarity.Cosine;
|
||||||
|
@ -52,6 +57,7 @@ import io.openvidu.java.client.Recording;
|
||||||
import io.openvidu.java.client.Session;
|
import io.openvidu.java.client.Session;
|
||||||
import io.openvidu.test.browsers.utils.CustomHttpClient;
|
import io.openvidu.test.browsers.utils.CustomHttpClient;
|
||||||
import io.openvidu.test.browsers.utils.Unzipper;
|
import io.openvidu.test.browsers.utils.Unzipper;
|
||||||
|
import io.openvidu.test.browsers.utils.webhook.CustomWebhook;
|
||||||
|
|
||||||
public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
||||||
|
|
||||||
|
@ -91,6 +97,119 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("CDR")
|
||||||
|
void cdrTest() throws Exception {
|
||||||
|
|
||||||
|
log.info("CDR test");
|
||||||
|
|
||||||
|
CountDownLatch initLatch = new CountDownLatch(1);
|
||||||
|
io.openvidu.test.browsers.utils.webhook.CustomWebhook.main(new String[0], initLatch);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (!initLatch.await(30, TimeUnit.SECONDS)) {
|
||||||
|
Assertions.fail("Timeout waiting for webhook springboot app to start");
|
||||||
|
CustomWebhook.shutDown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomHttpClient restClient = new CustomHttpClient(OpenViduTestAppE2eTest.OPENVIDU_URL, "OPENVIDUAPP",
|
||||||
|
OpenViduTestAppE2eTest.OPENVIDU_SECRET);
|
||||||
|
JsonObject config = restClient.rest(HttpMethod.GET, "/openvidu/api/config", HttpURLConnection.HTTP_OK);
|
||||||
|
|
||||||
|
String defaultOpenViduCdrPath = null;
|
||||||
|
String defaultOpenViduWebhookEndpoint = null;
|
||||||
|
if (config.has("OPENVIDU_CDR_PATH")) {
|
||||||
|
defaultOpenViduCdrPath = config.get("OPENVIDU_CDR_PATH").getAsString();
|
||||||
|
}
|
||||||
|
if (config.has("OPENVIDU_WEBHOOK_ENDPOINT")) {
|
||||||
|
defaultOpenViduWebhookEndpoint = config.get("OPENVIDU_WEBHOOK_ENDPOINT").getAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
final String CDR_PATH = "/opt/openvidu/custom-cdr-path";
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileUtils.deleteDirectory(new File(CDR_PATH));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Error trying to clean path " + CDR_PATH + ": " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Map<String, Object> newConfig = Map.of("OPENVIDU_CDR", true, "OPENVIDU_CDR_PATH", CDR_PATH,
|
||||||
|
"OPENVIDU_WEBHOOK", true, "OPENVIDU_WEBHOOK_ENDPOINT", "http://127.0.0.1:7777/webhook");
|
||||||
|
restartOpenViduServer(newConfig);
|
||||||
|
|
||||||
|
Set<Path> cdrFiles = Files.list(Paths.get(CDR_PATH)).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
Assertions.assertEquals(1, cdrFiles.size(), "Wrong number of CDR files");
|
||||||
|
|
||||||
|
Path cdrFile = cdrFiles.iterator().next();
|
||||||
|
String absolutePath = cdrFile.toAbsolutePath().toString();
|
||||||
|
|
||||||
|
if (!Files.exists(cdrFile)) {
|
||||||
|
Assertions.fail("CDR file does not exist at " + absolutePath);
|
||||||
|
} else if (!Files.isRegularFile(cdrFile)) {
|
||||||
|
Assertions.fail("CDR file is not a regular file at " + absolutePath);
|
||||||
|
} else if (!Files.isReadable(cdrFile)) {
|
||||||
|
Assertions.fail("CDR file is not readable at " + absolutePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenViduTestappUser user = setupBrowserAndConnectToOpenViduTestapp("chrome");
|
||||||
|
user.getDriver().findElement(By.id("add-user-btn")).click();
|
||||||
|
user.getDriver().findElement(By.className("join-btn")).click();
|
||||||
|
|
||||||
|
user.getEventManager().waitUntilEventReaches("connectionCreated", 1);
|
||||||
|
user.getEventManager().waitUntilEventReaches("accessAllowed", 1);
|
||||||
|
user.getEventManager().waitUntilEventReaches("streamCreated", 1);
|
||||||
|
user.getEventManager().waitUntilEventReaches("streamPlaying", 1);
|
||||||
|
|
||||||
|
gracefullyLeaveParticipants(user, 1);
|
||||||
|
|
||||||
|
CustomWebhook.waitForEvent("sessionDestroyed", 1);
|
||||||
|
|
||||||
|
List<String> lines = Files.readAllLines(cdrFile);
|
||||||
|
Map<String, List<JsonObject>> accumulatedWebhookEvents = CustomWebhook.accumulatedEvents;
|
||||||
|
|
||||||
|
Assertions.assertEquals(lines.size(),
|
||||||
|
accumulatedWebhookEvents.values().stream().mapToInt(i -> i.size()).sum(),
|
||||||
|
"CDR events and Webhook events should be equal size");
|
||||||
|
|
||||||
|
for (int i = lines.size() - 1; i >= 0; i--) {
|
||||||
|
JsonObject cdrEvent = JsonParser.parseString(lines.get(i)).getAsJsonObject();
|
||||||
|
Assertions.assertEquals(1, cdrEvent.entrySet().size(),
|
||||||
|
"A CDR event should only have 1 root property");
|
||||||
|
String cdrEventType = cdrEvent.entrySet().iterator().next().getKey();
|
||||||
|
JsonObject webhookEvent = accumulatedWebhookEvents.get(cdrEventType)
|
||||||
|
.remove(accumulatedWebhookEvents.get(cdrEventType).size() - 1);
|
||||||
|
cdrEvent = cdrEvent.remove(cdrEventType).getAsJsonObject();
|
||||||
|
webhookEvent.remove("event");
|
||||||
|
Assertions.assertEquals(webhookEvent, cdrEvent);
|
||||||
|
}
|
||||||
|
accumulatedWebhookEvents.entrySet().forEach(entry -> Assertions.assertTrue(entry.getValue().isEmpty()));
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
Map<String, Object> oldConfig = new HashMap<>();
|
||||||
|
oldConfig.put("OPENVIDU_CDR", false);
|
||||||
|
oldConfig.put("OPENVIDU_WEBHOOK", false);
|
||||||
|
if (defaultOpenViduCdrPath != null) {
|
||||||
|
oldConfig.put("OPENVIDU_CDR_PATH", defaultOpenViduCdrPath);
|
||||||
|
}
|
||||||
|
if (defaultOpenViduWebhookEndpoint != null) {
|
||||||
|
oldConfig.put("OPENVIDU_WEBHOOK_ENDPOINT", defaultOpenViduWebhookEndpoint);
|
||||||
|
}
|
||||||
|
restartOpenViduServer(oldConfig);
|
||||||
|
try {
|
||||||
|
FileUtils.deleteDirectory(new File(CDR_PATH));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Error trying to clean path " + CDR_PATH + ": " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
CustomWebhook.shutDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Individual dynamic record")
|
@DisplayName("Individual dynamic record")
|
||||||
void individualDynamicRecordTest() throws Exception {
|
void individualDynamicRecordTest() throws Exception {
|
||||||
|
|
Loading…
Reference in New Issue