Use a unique instance ID for pinging home (#566)

* Use a unique instance ID for pinging home

* Fix event name
This commit is contained in:
Shrikant Sharat Kandula 2020-09-18 06:38:53 +05:30 committed by GitHub
parent 437eb05f19
commit 19bd7d272a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 8 deletions

View File

@ -1,6 +1,7 @@
package com.appsmith.server.domains;
import com.appsmith.external.models.BaseDomain;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@ -12,6 +13,7 @@ import org.springframework.data.mongodb.core.mapping.Document;
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Document
public class Config extends BaseDomain {
JSONObject config;

View File

@ -916,4 +916,12 @@ public class DatabaseChangelog {
}
}
@ChangeSet(order = "025", id = "generate-unique-id-for-instance", author = "")
public void generateUniqueIdForInstance(MongoTemplate mongoTemplate) {
mongoTemplate.insert(new Config(
new JSONObject(Map.of("value", new ObjectId().toHexString())),
"instance-id"
));
}
}

View File

@ -1,5 +1,7 @@
package com.appsmith.server.solutions;
import com.appsmith.server.services.ConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.MediaType;
@ -19,28 +21,38 @@ import java.util.Map;
@Component
@ConditionalOnProperty(prefix = "is", name = "self-hosted")
@Slf4j
@RequiredArgsConstructor
public class PingScheduledTask {
private final ConfigService configService;
public static final URI GET_IP_URI = URI.create("https://api6.ipify.org");
/**
* Gets the external IP address of this server and pings a data point to indicate that this server instance is live.
* We use an initial delay of two minutes to roughly wait for the application along with the migrations are finished
* and ready.
*/
// Number of milliseconds between the start of each scheduled calls to this method.
@Scheduled(fixedRate = 6 * 60 * 60 * 1000 /* six hours */)
@Scheduled(initialDelay = 2 * 60 * 1000 /* two minutes */, fixedRate = 6 * 60 * 60 * 1000 /* six hours */)
public void pingSchedule() {
getInstallationId()
.flatMap(this::doPing)
.doOnError(error -> log.debug("Error pinging home", error))
Mono.zip(getInstanceId(), getAddress())
.flatMap(tuple -> doPing(tuple.getT1(), tuple.getT2()))
.subscribeOn(Schedulers.single())
.subscribe();
}
private Mono<String> getInstanceId() {
return configService.getByName("instance-id")
.map(config -> config.getConfig().getAsString("value"));
}
/**
* This method hits an API endpoint that returns the external IP address of this server instance.
*
* @return A publisher that yields the IP address.
*/
private Mono<String> getInstallationId() {
private Mono<String> getAddress() {
return WebClient
.create()
.get()
@ -52,10 +64,12 @@ public class PingScheduledTask {
/**
* Given a unique ID (called a `userId` here), this method hits the Segment API to save a data point on this server
* instance being live.
* @param userId A unique identifier for this server instance (usually, the external IP address of the server).
*
* @param instanceId A unique identifier for this server instance, usually generated at the server's first start.
* @param ipAddress The external IP address of this instance's machine.
* @return A publisher that yields the string response of recording the data point.
*/
private Mono<String> doPing(String userId) {
private Mono<String> doPing(String instanceId, String ipAddress) {
// Note: Hard-coding Segment auth header and the event name intentionally. These are not intended to be
// environment specific values, instead, they are common values for all self-hosted environments. As such, they
// are not intended to be configurable.
@ -66,7 +80,9 @@ public class PingScheduledTask {
.header("Authorization", "Basic QjJaM3hXRThXdDRwYnZOWDRORnJPNWZ3VXdnYWtFbk06")
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(Map.of(
"userId", userId,
"userId", instanceId,
"context", Map.of("ip", ipAddress),
"properties", Map.of("ip", ipAddress),
"event", "Instance Active"
)))
.retrieve()