Skip to content

Commit

Permalink
improved service, incorporating feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonEntholzer committed Sep 26, 2024
1 parent 7c972b8 commit 8cb8520
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package de.tum.cit.aet.artemis.core.service.telemetry;

import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_SCHEDULING;

import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
Expand All @@ -9,6 +11,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
Expand All @@ -22,6 +25,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

@Profile(PROFILE_SCHEDULING)
@Service
public class EurekaClientService {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,25 +70,67 @@ public TelemetrySendingService(Environment env, RestTemplate restTemplate, Eurek
@Value("${spring.datasource.url}")
private String datasourceUrl;

@Value("${artemis.continuous-integration.concurrent-build-size}")
@Value("${artemis.continuous-integration.concurrent-build-size:0}")
private long buildAgentCount;

/**
* Assembles the telemetry data, and sends it to the external telemetry server.
* Sends telemetry data to a specified destination via an HTTP POST request asynchronously.
* The telemetry includes information about the application version, environment, data source,
* and optionally, administrator details. If Eureka is enabled, the number of registered
* instances is also included.
*
* @throws Exception if the writing the telemetry data to a json format fails, or the connection to the telemetry server fails
* <p>
* The method constructs the telemetry data, converts it to JSON, and sends it to a
* telemetry server. The request is sent asynchronously due to the {@code @Async} annotation.
*
* @param eurekaEnabled a flag indicating whether Eureka is enabled. If {@code true},
* the method retrieves the number of instances registered with Eureka.
* @param sendAdminDetails a flag indicating whether to include administrator details in the
* telemetry data (such as contact information and admin name).
* @throws Exception if an error occurs while sending the telemetry data or constructing the request.
*/
@Async
public void sendTelemetryByPostRequest(boolean eurekaEnabled, boolean sendAdminDetails) throws Exception {
public void sendTelemetryByPostRequest(boolean eurekaEnabled, boolean sendAdminDetails, long waitInSeconds) throws Exception {

long numberOfInstances = 1;

if (eurekaEnabled) {
try {
log.info("Wait {} seconds before querying Eureka.", waitInSeconds);
Thread.sleep(waitInSeconds * 1000);
}
catch (InterruptedException e) {
log.warn("Waiting for other instances to spin up was interrupted.");
}

log.info("Querying other instances from Eureka...");
numberOfInstances = eurekaClientService.getNumberOfReplicas();
}

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
ObjectWriter objectWriter = new ObjectMapper().writer().withDefaultPrettyPrinter();

var telemetryJson = objectWriter.writeValueAsString(buildTelemetryData(sendAdminDetails, numberOfInstances));
HttpEntity<String> requestEntity = new HttpEntity<>(telemetryJson, headers);
var response = restTemplate.postForEntity(destination + "/api/telemetry", requestEntity, String.class);
log.info("Successfully sent telemetry data. {}", response.getBody());
}

/**
* Retrieves telemetry data for the current system configuration, including details
* about the active profiles, data source type, and optionally admin contact details.
*
* @param sendAdminDetails whether to include admin contact information in the telemetry data
* @param numberOfInstances the number of instances to include in the telemetry data
* @return an instance of {@link TelemetryData} containing the gathered telemetry information
*/
private TelemetryData buildTelemetryData(boolean sendAdminDetails, long numberOfInstances) {

TelemetryData telemetryData;
var dataSource = datasourceUrl.startsWith("jdbc:mysql") ? "mysql" : "postgresql";
List<String> activeProfiles = Arrays.asList(env.getActiveProfiles());

String contact = null;
String adminName = null;
if (sendAdminDetails) {
Expand All @@ -97,14 +139,6 @@ public void sendTelemetryByPostRequest(boolean eurekaEnabled, boolean sendAdminD
}
telemetryData = new TelemetryData(version, serverUrl, operator, activeProfiles, profileService.isProductionActive(), dataSource, numberOfInstances, buildAgentCount,
contact, adminName);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
ObjectWriter objectWriter = new ObjectMapper().writer().withDefaultPrettyPrinter();

var telemetryJson = objectWriter.writeValueAsString(telemetryData);
HttpEntity<String> requestEntity = new HttpEntity<>(telemetryJson, headers);
var response = restTemplate.postForEntity(destination + "/api/telemetry", requestEntity, String.class);
log.info("Successfully sent telemetry data. {}", response.getBody());
return telemetryData;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public class TelemetryService {
@Value("${eureka.client.enabled}")
public boolean eurekaEnabled;

public long eurekaQueryDelaySeconds = 120;

public TelemetryService(ProfileService profileService, TelemetrySendingService telemetrySendingService) {
this.profileService = profileService;
this.telemetrySendingService = telemetrySendingService;
Expand All @@ -48,13 +50,13 @@ public TelemetryService(ProfileService profileService, TelemetrySendingService t
*/
@EventListener(ApplicationReadyEvent.class)
public void sendTelemetry() {
if (!useTelemetry || profileService.isDevActive()) {
if (!useTelemetry) { // || profileService.isDevActive()) {
return;
}

log.info("Sending telemetry information");
try {
telemetrySendingService.sendTelemetryByPostRequest(eurekaEnabled, sendAdminDetails);
telemetrySendingService.sendTelemetryByPostRequest(eurekaEnabled, sendAdminDetails, eurekaQueryDelaySeconds);
}
catch (JsonProcessingException e) {
log.warn("JsonProcessingException in sendTelemetry.", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class TelemetryServiceTest extends AbstractSpringIntegrationIndependentTest {
private String destination;

@Value("${eureka.client.service-url.defaultZone}")
private String defaultZoneUrl;
private String eurekaDefaultZoneUrl;

private String eurekaRequestUrl;

Expand All @@ -62,7 +62,7 @@ class TelemetryServiceTest extends AbstractSpringIntegrationIndependentTest {
@BeforeEach
void init() throws JsonProcessingException {
try {
var eurekaURI = new URI(defaultZoneUrl);
var eurekaURI = new URI(eurekaDefaultZoneUrl);
eurekaRequestUrl = eurekaURI.getScheme() + "://" + eurekaURI.getAuthority() + "/api/eureka/applications";

}
Expand All @@ -75,6 +75,7 @@ void init() throws JsonProcessingException {

telemetryServiceSpy.useTelemetry = true;
telemetryServiceSpy.eurekaEnabled = true;
telemetryServiceSpy.eurekaQueryDelaySeconds = 1;
}

@Test
Expand Down

0 comments on commit 8cb8520

Please sign in to comment.