diff --git a/openvidu-server/src/main/resources/logback-spring.xml b/openvidu-server/src/main/resources/logback-spring.xml index bbac4f09..c11f84c8 100644 --- a/openvidu-server/src/main/resources/logback-spring.xml +++ b/openvidu-server/src/main/resources/logback-spring.xml @@ -1,20 +1,18 @@ + - + - + %black(%highlight([%p]) %d{dd MMM HH:mm:ss.SSS} %magenta([%.80t]) \(%file:%line\) - %msg%n) - [%p] %d [%.80t] %c - %msg%n - + [%p] %d [%.80t] %c - %msg%n @@ -35,7 +33,7 @@ --> - + @@ -44,12 +42,10 @@ - + - - + + ${cdrPath}/CDR.%d{yyyy-MM-dd}_${myTimestamp}.log 30 diff --git a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/webhook/CustomWebhook.java b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/webhook/CustomWebhook.java index 0c276edc..48024a09 100644 --- a/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/webhook/CustomWebhook.java +++ b/openvidu-test-browsers/src/main/java/io/openvidu/test/browsers/utils/webhook/CustomWebhook.java @@ -18,6 +18,8 @@ package io.openvidu.test.browsers.utils.webhook; import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -25,7 +27,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicInteger; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @@ -49,7 +50,7 @@ public class CustomWebhook { public static CountDownLatch initLatch; public static int accumulatedNumberOfEvents = 0; - public final static ConcurrentMap accumulatedEvents = new ConcurrentHashMap<>(); + public final static ConcurrentMap> accumulatedEvents = new ConcurrentHashMap<>(); static final ConcurrentMap> events = new ConcurrentHashMap<>(); static final BlockingQueue eventsInOrder = new LinkedBlockingDeque<>(); @@ -156,9 +157,8 @@ public class CustomWebhook { accumulatedNumberOfEvents++; eventsInOrder.add(event); final String eventName = event.get("event").getAsString(); - if (accumulatedEvents.putIfAbsent(eventName, new AtomicInteger(1)) != null) { - accumulatedEvents.get(eventName).incrementAndGet(); - } + accumulatedEvents.putIfAbsent(eventName, new LinkedList<>()); + accumulatedEvents.get(eventName).add(event); final BlockingQueue queue = new LinkedBlockingDeque<>(); if (!CustomWebhook.events.computeIfAbsent(eventName, e -> { queue.add(event); diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java index 252e65bb..0f90e777 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduProTestAppE2eTest.java @@ -6,6 +6,9 @@ import java.awt.Point; import java.io.File; import java.io.FileReader; 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.Arrays; import java.util.HashMap; @@ -22,6 +25,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -38,6 +42,7 @@ import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import com.google.gson.stream.JsonReader; 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.test.browsers.utils.CustomHttpClient; import io.openvidu.test.browsers.utils.Unzipper; +import io.openvidu.test.browsers.utils.webhook.CustomWebhook; public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest { @@ -91,6 +97,119 @@ public class OpenViduProTestAppE2eTest extends AbstractOpenViduTestappE2eTest { 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 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 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 lines = Files.readAllLines(cdrFile); + Map> 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 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 @DisplayName("Individual dynamic record") void individualDynamicRecordTest() throws Exception {