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; package com.appsmith.server.domains;
import com.appsmith.external.models.BaseDomain; import com.appsmith.external.models.BaseDomain;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
@ -12,6 +13,7 @@ import org.springframework.data.mongodb.core.mapping.Document;
@Setter @Setter
@ToString @ToString
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor
@Document @Document
public class Config extends BaseDomain { public class Config extends BaseDomain {
JSONObject config; 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; package com.appsmith.server.solutions;
import com.appsmith.server.services.ConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -19,28 +21,38 @@ import java.util.Map;
@Component @Component
@ConditionalOnProperty(prefix = "is", name = "self-hosted") @ConditionalOnProperty(prefix = "is", name = "self-hosted")
@Slf4j @Slf4j
@RequiredArgsConstructor
public class PingScheduledTask { public class PingScheduledTask {
private final ConfigService configService;
public static final URI GET_IP_URI = URI.create("https://api6.ipify.org"); 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. * 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. // 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() { public void pingSchedule() {
getInstallationId() Mono.zip(getInstanceId(), getAddress())
.flatMap(this::doPing) .flatMap(tuple -> doPing(tuple.getT1(), tuple.getT2()))
.doOnError(error -> log.debug("Error pinging home", error))
.subscribeOn(Schedulers.single()) .subscribeOn(Schedulers.single())
.subscribe(); .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. * This method hits an API endpoint that returns the external IP address of this server instance.
*
* @return A publisher that yields the IP address. * @return A publisher that yields the IP address.
*/ */
private Mono<String> getInstallationId() { private Mono<String> getAddress() {
return WebClient return WebClient
.create() .create()
.get() .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 * 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. * 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. * @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 // 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 // environment specific values, instead, they are common values for all self-hosted environments. As such, they
// are not intended to be configurable. // are not intended to be configurable.
@ -66,7 +80,9 @@ public class PingScheduledTask {
.header("Authorization", "Basic QjJaM3hXRThXdDRwYnZOWDRORnJPNWZ3VXdnYWtFbk06") .header("Authorization", "Basic QjJaM3hXRThXdDRwYnZOWDRORnJPNWZ3VXdnYWtFbk06")
.contentType(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(Map.of( .body(BodyInserters.fromValue(Map.of(
"userId", userId, "userId", instanceId,
"context", Map.of("ip", ipAddress),
"properties", Map.of("ip", ipAddress),
"event", "Instance Active" "event", "Instance Active"
))) )))
.retrieve() .retrieve()