Merge pull request #23 from medici/litmus-executor

Litmus executor with fixed thread pool
This commit is contained in:
chandresh pancholi
2022-12-22 15:25:50 +05:30
committed by GitHub Enterprise
35 changed files with 370 additions and 204 deletions

View File

@@ -1,5 +1,5 @@
FROM 193044292705.dkr.ecr.ap-south-1.amazonaws.com/common/maven:3.8.3-openjdk-17-slim as builder
ARG ARTIFACT_VERSION=2.0.5-RELEASE
ARG ARTIFACT_VERSION=2.0.6-RELEASE
RUN mkdir -p /build
WORKDIR /build
COPY . /build
@@ -7,7 +7,7 @@ RUN mvn clean install
RUN mvn clean verify -DskipTests -Dartifact.version=${ARTIFACT_VERSION}
FROM 193044292705.dkr.ecr.ap-south-1.amazonaws.com/common/openjdk:17-slim-bullseye
ARG ARTIFACT_VERSION=2.0.5-RELEASE
ARG ARTIFACT_VERSION=2.0.6-RELEASE
RUN mkdir -p /usr/local
RUN apt-get update -y && apt-get -y install fontconfig libpng-dev
WORKDIR /usr/local/

View File

@@ -1,5 +1,5 @@
FROM 193044292705.dkr.ecr.ap-south-1.amazonaws.com/common/maven:3.8.3-openjdk-17-slim as builder
ARG ARTIFACT_VERSION=2.0.5-RELEASE
ARG ARTIFACT_VERSION=2.0.6-RELEASE
RUN mkdir -p /build
WORKDIR /build
COPY . /build
@@ -7,7 +7,7 @@ RUN mvn clean install -DskipTests
RUN mvn clean verify -DskipTests -Dartifact.version=${ARTIFACT_VERSION}
FROM 193044292705.dkr.ecr.ap-south-1.amazonaws.com/common/openjdk:17-slim-bullseye
ARG ARTIFACT_VERSION=2.0.5-RELEASE
ARG ARTIFACT_VERSION=2.0.6-RELEASE
RUN mkdir -p /usr/local
RUN apt-get update -y && apt-get -y install fontconfig libpng-dev
WORKDIR /usr/local/

26
docker-compose.yaml Normal file
View File

@@ -0,0 +1,26 @@
version: '3.0'
services:
db:
image: "postgres:11"
ports:
- "5432:5432"
environment:
- POSTGRES_DB=communication-service-test
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=admin
spring-boot-app:
depends_on:
- db
image: "maven:3.8.3-openjdk-17-slim"
ports:
- "8080:8080"
environment:
- DATASOURCE_URL=jdbc:postgresql://db:5432/litmus
- DATASOURCE_USERNAME=litmus-test
- DATASOURCE_PASSWORD=litmus-test
volumes:
- .:/app
working_dir: /app
command: mvn clean verify

View File

@@ -4,11 +4,11 @@
<parent>
<artifactId>litmus</artifactId>
<groupId>com.navi.medici</groupId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</parent>
<artifactId>litmus-cache</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
<packaging>jar</packaging>
<name>litmus-cache</name>

View File

@@ -5,11 +5,11 @@
<parent>
<artifactId>litmus</artifactId>
<groupId>com.navi.medici</groupId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</parent>
<artifactId>litmus-client</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
<packaging>jar</packaging>
<name>litmus-client</name>
@@ -43,7 +43,7 @@
<dependency>
<groupId>com.navi.medici</groupId>
<artifactId>litmus-model</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</dependency>
<dependency>

View File

@@ -3,51 +3,40 @@ package com.navi.medici.client;
import com.navi.medici.clickstream.ClickStreamPayload;
import com.navi.medici.config.LitmusConfig;
import com.navi.medici.response.LitmusExperimentResponse;
import com.navi.medici.util.JacksonUtils;
import io.micrometer.core.annotation.Timed;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import lombok.extern.log4j.Log4j2;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import static com.navi.medici.util.MetricsUtils.counterMetrics;
@Log4j2
public class ClickStreamClient {
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
private final String clickStreamAPI;
private final String appName;
private final String vertical;
private final MeterRegistry meterRegistry;
private final LitmusConfig litmusConfig;
public ClickStreamClient(String clickStreamAPI, String appName,
String vertical, MeterRegistry meterRegistry) {
this.clickStreamAPI = clickStreamAPI;
this.appName = appName;
this.vertical = vertical;
this.meterRegistry = meterRegistry;
public ClickStreamClient(LitmusConfig litmusConfig) {
this.litmusConfig = litmusConfig;
}
@Timed(value = "litmus_client_click_stream_publish_latency", percentiles = {0.90, 0.95, 0.99})
public <T> void publish(String experimentName, ClickStreamPayload<T> payload) {
String requestBody = JacksonUtils.objectToString(payload);
Request request = new Request.Builder()
.url(clickStreamAPI)
.url(litmusConfig.getClickStreamAPI())
.post(RequestBody.create(JSON, requestBody))
.build();
try(Response response = OkHttpClientContainer.getInstance().newCall(request).execute()) {
Counter.builder("litmus_client_click_stream_event_ingestion")
.tag("vertical", vertical)
counterMetrics(litmusConfig, "litmus_client_click_stream_event_ingestion")
.tag("status", String.valueOf(response.code()))
.tag("experiment_name", experimentName)
.tag("app_name", appName)
.register(meterRegistry)
.register(litmusConfig.getMeterRegistry())
.increment();
if (response.code() < 300) {
var responseBody = response.body();
@@ -59,12 +48,10 @@ public class ClickStreamClient {
}
} catch (Exception e) {
log.error("clickstream event ingestion failed. ", e);
Counter.builder("litmus_client_click_stream_event_ingestion_failed")
.tag("vertical", vertical)
counterMetrics(litmusConfig, "litmus_client_click_stream_event_ingestion_failed")
.tag("experiment_name", experimentName)
.tag("app_name", appName)
.tag("exception", e.getMessage())
.register(meterRegistry)
.register(litmusConfig.getMeterRegistry())
.increment();
}
}

View File

@@ -5,15 +5,12 @@ import com.navi.medici.exception.LitmusException;
import com.navi.medici.request.v1.LitmusExperiment;
import com.navi.medici.response.LitmusExperimentCollection;
import com.navi.medici.util.JacksonUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.core.util.IOUtils;
@@ -42,7 +39,7 @@ public class ExperimentBackupHandlerFile implements ExperimentBackupHandler {
return JacksonUtils.stringToObject(data, LitmusExperimentCollection.class);
} catch (FileNotFoundException e) {
log.info(
" Litmus could not find the backup-file '"
"Litmus could not find the backup-file '"
+ backupFile
+ ". This is expected behavior the first time litmus runs in a new environment.");
} catch (IOException | IllegalStateException e) {

View File

@@ -6,54 +6,34 @@ import com.navi.medici.response.LitmusExperimentCollection;
import com.navi.medici.response.LitmusExperimentResponse;
import com.navi.medici.response.LitmusResponse;
import com.navi.medici.util.JacksonUtils;
import com.navi.medici.util.LitmusURLs;
import io.micrometer.core.annotation.Timed;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import java.net.URL;
import lombok.extern.log4j.Log4j2;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import static com.navi.medici.util.MetricsUtils.counterMetrics;
@Log4j2
public class HttpExperimentFetcher implements ExperimentFetcher {
private final LitmusConfig litmusConfig;
private final LitmusURLs litmusURLs;
private final String appName;
private final String projectNamePrefix;
private final String projectName;
private final String vertical;
private final MeterRegistry meterRegistry;
public HttpExperimentFetcher(LitmusURLs litmusURLs,
String appName,
String projectNamePrefix,
String projectName,
String vertical,
MeterRegistry meterRegistry) {
this.litmusURLs = litmusURLs;
this.appName = appName;
this.projectNamePrefix = projectNamePrefix;
this.projectName = projectName;
this.vertical = vertical;
this.meterRegistry = meterRegistry;
public HttpExperimentFetcher(LitmusConfig litmusConfig) {
this.litmusConfig = litmusConfig;
}
@Override
@Timed(value = "litmus_client_fetch_experiments_latency", percentiles = {0.90, 0.95, 0.99})
public LitmusExperimentResponse fetchExperiments(String vertical, Long pollingTime) throws LitmusException {
URL experimentUrl = litmusURLs
.getLitmusExperimentsURL(projectName, projectNamePrefix);
URL experimentUrl = litmusConfig.getLitmusURLs()
.getLitmusExperimentsURL(litmusConfig.getProjectName(), litmusConfig.getNamePrefix());
Request request = new Request.Builder()
.url(String.format("%s/vertical?vertical=%s&polling_time=%s", experimentUrl, vertical, pollingTime))
.build();
try (Response response = OkHttpClientContainer.getInstance().newCall(request).execute()) {
Counter.builder("litmus_client_fetch_experiment_polling")
.tag("vertical", this.vertical)
.tag("app_name", this.appName)
.register(this.meterRegistry)
counterMetrics(litmusConfig, "litmus_client_fetch_experiment_polling")
.register(litmusConfig.getMeterRegistry())
.increment();
if (response.code() < 300) {
@@ -62,41 +42,34 @@ public class HttpExperimentFetcher implements ExperimentFetcher {
LitmusExperimentCollection experiments = JacksonUtils.stringToObject(responseBody.string(), LitmusExperimentCollection.class);
Counter.builder("litmus_client_fetch_experiment_polling_total_request")
.tag("vertical", vertical)
counterMetrics(litmusConfig, "litmus_client_fetch_experiment_polling_total_request")
.tag("status", String.valueOf(response.code()))
.tag("experiment_state", LitmusExperimentResponse.Status.CHANGED.name())
.tag("app_name", this.appName)
.register(this.meterRegistry)
.register(litmusConfig.getMeterRegistry())
.increment();
return new LitmusExperimentResponse(LitmusExperimentResponse.Status.CHANGED, experiments);
} else if (response.code() == 304) {
Counter.builder("litmus_client_fetch_experiment_polling_request_status")
.tag("vertical", vertical)
.tag("app_name", this.appName)
counterMetrics(litmusConfig, "litmus_client_fetch_experiment_polling_request_status")
.tag("status", String.valueOf(response.code()))
.tag("experiment_state", LitmusExperimentResponse.Status.NOT_CHANGED.name())
.register(this.meterRegistry)
.register(litmusConfig.getMeterRegistry())
.increment();
return new LitmusExperimentResponse(LitmusExperimentResponse.Status.NOT_CHANGED, response.code());
} else {
Counter.builder("litmus_client_fetch_experiment_polling_request_status")
.tag("vertical", this.vertical)
.tag("app_name", this.appName)
counterMetrics(litmusConfig, "litmus_client_fetch_experiment_polling_request_status")
.tag("status", String.valueOf(response.code()))
.tag("experiment_state", LitmusExperimentResponse.Status.NOT_CHANGED.name())
.register(this.meterRegistry)
.register(litmusConfig.getMeterRegistry())
.increment();
return new LitmusExperimentResponse(LitmusExperimentResponse.Status.UNAVAILABLE, response.code());
}
} catch (Exception e) {
Counter.builder("litmus_client_fetch_experiment_polling_request_failed")
.tag("vertical", this.vertical)
.tag("app_name", this.appName)
.register(this.meterRegistry)
counterMetrics(litmusConfig, "litmus_client_fetch_experiment_polling_request_failed")
.tag("exception", e.getMessage())
.register(litmusConfig.getMeterRegistry())
.increment();
throw new LitmusException("fetch experiments failed.", e);
}
@@ -104,7 +77,7 @@ public class HttpExperimentFetcher implements ExperimentFetcher {
@Timed(value = "litmus_client_segment_id_exists_latency", percentiles = {0.90, 0.95, 0.99})
public LitmusResponse<Boolean> segmentIdExists(String segmentName, String id) {
URL segmentIdUrl = this.litmusURLs.getSegmentIdURL();
URL segmentIdUrl = litmusConfig.getLitmusURLs().getSegmentIdURL();
Request request = new Request.Builder()
.url(String.format("%s?segment_name=%s&id=%s", segmentIdUrl, segmentName, id))
.build();
@@ -113,20 +86,16 @@ public class HttpExperimentFetcher implements ExperimentFetcher {
var responseBody = response.body();
assert responseBody != null;
Counter.builder("litmus_client_segment_id_exist_request")
.tag("vertical", this.vertical)
.tag("app_name", this.appName)
.tag("status", String.valueOf(response.code()))
.register(this.meterRegistry)
.increment();
counterMetrics(litmusConfig, "litmus_client_segment_id_exist_request")
.tag("status", String.valueOf(response.code()))
.register(litmusConfig.getMeterRegistry())
.increment();
return JacksonUtils.stringToObject(responseBody.string(), LitmusResponse.class);
} catch (Exception e) {
Counter.builder("litmus_client_segment_id_exist_request_failed")
.tag("vertical", this.vertical)
counterMetrics(litmusConfig, "litmus_client_segment_id_exist_request_failed")
.tag("segment_name", segmentName)
.tag("app_name", this.appName)
.tag("exception", e.getMessage())
.register(this.meterRegistry)
.register(litmusConfig.getMeterRegistry())
.increment();
throw new LitmusException("segment name to id matching doesn't exists.", e);

View File

@@ -7,6 +7,7 @@ import com.navi.medici.scheduler.LitmusScheduledExecutor;
import com.navi.medici.scheduler.LitmusScheduledExecutorImpl;
import com.navi.medici.strategy.Strategy;
import com.navi.medici.strategy.UnknownStrategy;
import com.navi.medici.util.LitmusProperties;
import com.navi.medici.util.LitmusURLs;
import io.micrometer.core.instrument.MeterRegistry;
import java.io.File;
@@ -15,6 +16,13 @@ import java.net.URI;
import java.net.UnknownHostException;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import lombok.Setter;
public class LitmusConfig {
@@ -41,7 +49,11 @@ public class LitmusConfig {
private final String clickStreamAPI;
private final String vertical;
private final MeterRegistry meterRegistry;
private final ExecutorService executorService;
private final String litmusClientVersion;
private final boolean enableClickStream;
private LitmusConfig(
URI litmusAPI,
@@ -58,7 +70,10 @@ public class LitmusConfig {
LitmusExperimentBootstrapProvider litmusBootstrapProvider,
String clickStreamAPI,
String vertical,
MeterRegistry meterRegistry) {
MeterRegistry meterRegistry,
ExecutorService executorService,
String litmusClientVersion,
boolean enableClickStream) {
if (appName == null) {
throw new IllegalStateException("You are required to specify the litmus appName");
@@ -88,6 +103,13 @@ public class LitmusConfig {
throw new IllegalStateException("You are required to specify meter registry");
}
if (executorService == null) {
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();
executorService = new ThreadPoolExecutor(20, 20,
5000L, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(1000, true), handler);
}
this.fallbackStrategy = Objects.requireNonNullElseGet(fallbackStrategy, UnknownStrategy::new);
@@ -106,6 +128,9 @@ public class LitmusConfig {
this.clickStreamAPI = clickStreamAPI;
this.vertical = vertical;
this.meterRegistry = meterRegistry;
this.executorService = executorService;
this.litmusClientVersion = LitmusProperties.getProperty("litmus.client.version");
this.enableClickStream = enableClickStream;
}
public static Builder builder() {
@@ -125,6 +150,7 @@ public class LitmusConfig {
return instanceId;
}
//schedule periodic experiment poll interval in seconds
public long getFetchLitmusExperimentsInterval() {
return fetchLitmusExperimentsInterval;
}
@@ -177,6 +203,17 @@ public class LitmusConfig {
return meterRegistry;
}
public ExecutorService getExecutorService() {
return executorService;
}
public String getLitmusClientVersion() {
return litmusClientVersion;
}
public boolean isEnableClickStream() {
return enableClickStream;
}
public static class Builder {
private URI litmusAPI;
@@ -195,6 +232,12 @@ public class LitmusConfig {
private String vertical;
private MeterRegistry meterRegistry;
private ExecutorService executorService;
private String litmusClientVersion;
private boolean enableClickStream;
private static String getHostname() {
String hostName = System.getProperty("hostname");
if (hostName == null || hostName.length() == 0) {
@@ -291,6 +334,20 @@ public class LitmusConfig {
return this;
}
public Builder executorService(ExecutorService executorService) {
this.executorService = executorService;
return this;
}
public Builder getLitmusClient(String litmusClientVersion) {
this.litmusClientVersion = litmusClientVersion;
return this;
}
public Builder enableClickStream(boolean enableClickStream) {
this.enableClickStream = enableClickStream;
return this;
}
private String getBackupFile() {
if (backupFile != null) {
@@ -319,14 +376,10 @@ public class LitmusConfig {
litmusExperimentBootstrapProvider,
clickStreamAPI,
vertical,
meterRegistry);
}
public String getDefaultSdkVersion() {
String version =
Optional.ofNullable(getClass().getPackage().getImplementationVersion())
.orElse("development");
return "litmus-client:" + version;
meterRegistry,
executorService,
litmusClientVersion,
enableClickStream);
}
}
}

View File

@@ -22,8 +22,7 @@ public class EventDispatcher {
private final LitmusConfig litmusConfig;
public EventDispatcher(LitmusConfig litmusConfig) {
this.clickStreamClient = new ClickStreamClient(litmusConfig.getClickStreamAPI(), litmusConfig.getAppName(),
litmusConfig.getVertical(), litmusConfig.getMeterRegistry());
this.clickStreamClient = new ClickStreamClient(litmusConfig);
this.litmusConfig = litmusConfig;
}
@@ -56,14 +55,14 @@ public class EventDispatcher {
clickStreamPayload.setClickStreamEvent(List.of(event));
clickStreamPayload.setSource("Litmus");
clickStreamPayload.setUser(User.builder()
.customerReferenceId(litmusContext.getUserId().orElse(""))
.customerReferenceId(litmusContext.getUserId()
.orElse(""))
.build());
CompletableFuture.supplyAsync(() -> {
CompletableFuture.runAsync(() -> {
litmusConfig.getMeterRegistry().timer("litmus_client_click_stream_publish_latency")
.record(() -> clickStreamClient.publish(litmusExperiment.getName(), clickStreamPayload));
return null;
});
}, litmusConfig.getExecutorService());
}
}

View File

@@ -2,7 +2,6 @@ package com.navi.medici.litmus;
import com.navi.medici.annotation.Nullable;
import com.navi.medici.client.ClickStreamClient;
import com.navi.medici.client.ExperimentBackupHandlerFile;
import com.navi.medici.client.HttpExperimentFetcher;
import com.navi.medici.config.LitmusConfig;
@@ -13,6 +12,7 @@ import com.navi.medici.provider.LitmusContextProvider;
import com.navi.medici.repository.ExperimentRepository;
import com.navi.medici.repository.LitmusExperimentRepository;
import com.navi.medici.request.v1.LitmusExperiment;
import com.navi.medici.strategy.CustomParameterWithIdStrategy;
import com.navi.medici.strategy.DefaultStrategy;
import com.navi.medici.strategy.DeviceWithIdStrategy;
import com.navi.medici.strategy.FlexibleRolloutStrategy;
@@ -23,21 +23,16 @@ import com.navi.medici.strategy.UserWithIdStrategy;
import com.navi.medici.util.VariantUtil;
import com.navi.medici.variants.Variant;
import io.micrometer.core.instrument.Counter;
import java.io.IOException;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import lombok.extern.log4j.Log4j2;
import static com.navi.medici.util.MetricsUtils.counterMetrics;
@Log4j2
public class DefaultLitmus implements Litmus {
@@ -53,8 +48,7 @@ public class DefaultLitmus implements Litmus {
private static ExperimentRepository defaultExperimentRepository(LitmusConfig litmusConfig) {
return new LitmusExperimentRepository(
litmusConfig,
new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(),
litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry()),
new HttpExperimentFetcher(litmusConfig),
new ExperimentBackupHandlerFile(litmusConfig)) {
};
}
@@ -146,8 +140,7 @@ public class DefaultLitmus implements Litmus {
}
} else {
enabled =
litmusExperiment.getStrategies().stream()
enabled = litmusExperiment.getStrategies().stream()
.anyMatch(
strategy -> {
Strategy configuredStrategy =
@@ -157,20 +150,23 @@ public class DefaultLitmus implements Litmus {
experimentName, strategy.getName());
}
return configuredStrategy.isEnabled(
strategy.getParameters(),
context,
strategy.getConstraints());
boolean result = configuredStrategy.isEnabled(strategy.getParameters(),
context, strategy.getConstraints());
log.debug("experiment_name: {}, strategy: {}, result: {}",
litmusExperiment.getName(), configuredStrategy.getName(), result);
return result;
});
}
Counter.builder("litmus_client_experiment_check_enabled")
counterMetrics(config, "litmus_client_experiment_check_enabled")
.tag("experiment_name", experimentName)
.tag("result", String.valueOf(enabled))
.register(this.config.getMeterRegistry())
.increment();
this.eventDispatcher.publish(context, litmusExperiment, enabled, null);
if (config.isEnableClickStream()) {
this.eventDispatcher.publish(context, litmusExperiment, enabled, null);
}
log.info("experiment_name: {}, result: {}", experimentName, enabled);
return enabled;
@@ -183,14 +179,13 @@ public class DefaultLitmus implements Litmus {
Arrays.asList(
new DefaultStrategy(),
new UserWithIdStrategy(new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(),
litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry())),
new UserWithIdStrategy(new HttpExperimentFetcher(litmusConfig)),
new DeviceWithIdStrategy(new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(),
litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry())),
new DeviceWithIdStrategy(new HttpExperimentFetcher(litmusConfig)),
new PhoneNumberStrategy(new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(),
litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry())),
new PhoneNumberStrategy(new HttpExperimentFetcher(litmusConfig)),
new CustomParameterWithIdStrategy(new HttpExperimentFetcher(litmusConfig)),
new FlexibleRolloutStrategy());
@@ -228,10 +223,13 @@ public class DefaultLitmus implements Litmus {
? VariantUtil.selectVariant(litmusExperiment, context, defaultValue)
: defaultValue;
this.eventDispatcher.publish(context, litmusExperiment, enabled, variant);
if (config.isEnableClickStream()) {
this.eventDispatcher.publish(context, litmusExperiment, enabled, variant);
}
log.info("experiment_name: {}, result: {}", experimentName, variant.toString());
Counter.builder("litmus_client_experiment_variant")
counterMetrics(config, "litmus_client_experiment_variant")
.tag("experiment_name", experimentName)
.tag("result", String.valueOf(enabled))
.tag("variant", variant.getName())
@@ -257,13 +255,9 @@ public class DefaultLitmus implements Litmus {
* Emit litmus version to prometheus to track litmus-client version used by services
*/
private void trackVersion(LitmusConfig litmusConfig) {
Counter.builder("litmus_client_version")
.tag("vertical", litmusConfig.getVertical())
.tag("app_name", litmusConfig.getAppName())
.tag("version", "2.0.5-RELEASE")
counterMetrics(config, "litmus_client_version")
.register(litmusConfig.getMeterRegistry())
.increment();
}
}

View File

@@ -0,0 +1,66 @@
package com.navi.medici.strategy;
import com.navi.medici.client.HttpExperimentFetcher;
import com.navi.medici.context.LitmusContext;
import com.navi.medici.util.StrategyUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
import java.util.Optional;
import static com.navi.medici.strategy.FlexibleRolloutStrategy.GROUP_ID;
import static com.navi.medici.strategy.FlexibleRolloutStrategy.PERCENTAGE;
public class CustomParameterWithIdStrategy implements Strategy {
private static final String STRATEGY_NAME = "customWithId";
private static final String SEGMENT = "segment";
private static final String CUSTOM_PARAMETER_NAME = "customParameter";
private final HttpExperimentFetcher experimentFetcher;
public CustomParameterWithIdStrategy(HttpExperimentFetcher experimentFetcher) {
this.experimentFetcher = experimentFetcher;
}
@Override
public String getName() {
return STRATEGY_NAME;
}
@Override
public boolean isEnabled(Map<String, String> parameters) {
return false;
}
@Override
public boolean isEnabled(Map<String, String> parameters, LitmusContext litmusContext) {
if (StringUtils.isBlank(parameters.get(PERCENTAGE))) {
return customWithIdSegmentCheck(parameters, litmusContext);
} else {
return segmentCheckWithRollout(parameters, litmusContext);
}
}
private boolean customWithIdSegmentCheck(Map<String, String> parameters, LitmusContext litmusContext) {
var customParameterId = litmusContext.getProperties().get(CUSTOM_PARAMETER_NAME);
var segmentName = parameters.get(SEGMENT);
var result = experimentFetcher.segmentIdExists(segmentName, customParameterId);
return result.getData() != null && (Boolean) result.getData();
}
private boolean segmentCheckWithRollout(Map<String, String> parameters, LitmusContext litmusContext) {
var customParameterId = litmusContext.getProperties().get(CUSTOM_PARAMETER_NAME);
var percentage = StrategyUtils.getPercentage(parameters.get(PERCENTAGE));
var groupId = parameters.getOrDefault(GROUP_ID, "");
var norm = StrategyUtils.getNormalizedNumber(customParameterId, groupId);
return Optional.of(customWithIdSegmentCheck(parameters, litmusContext))
.map(r -> r && percentage > 0 && norm <= percentage)
.orElse(false);
}
}

View File

@@ -41,19 +41,19 @@ public class PhoneNumberStrategy implements Strategy {
}
private boolean phoneNumberSegmentCheck(Map<String, String> parameters, LitmusContext litmusContext) {
var userId = litmusContext.getUserId().orElse(null);
var phoneNumber = litmusContext.getPhoneNumber().orElse(null);
var segmentName = parameters.get(SEGMENT);
var result = experimentFetcher.segmentIdExists(segmentName, userId);
var result = experimentFetcher.segmentIdExists(segmentName, phoneNumber);
return result.getData() != null && (Boolean) result.getData();
}
private boolean segmentCheckWithRollout(Map<String, String> parameters, LitmusContext litmusContext) {
var userId = litmusContext.getUserId().orElse(null);
var phoneNumber = litmusContext.getPhoneNumber().orElse(null);
var percentage = StrategyUtils.getPercentage(parameters.get(PERCENTAGE));
var groupId = parameters.getOrDefault(GROUP_ID, "");
var norm = StrategyUtils.getNormalizedNumber(userId, groupId);
var norm = StrategyUtils.getNormalizedNumber(phoneNumber, groupId);
return Optional.of(phoneNumberSegmentCheck(parameters, litmusContext))
.map(r -> r && percentage > 0 && norm <= percentage)

View File

@@ -0,0 +1,23 @@
package com.navi.medici.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class LitmusProperties {
static Properties appProperties;
static {
try (InputStream is = LitmusProperties.class.getClassLoader().getResourceAsStream("app.properties")) {
appProperties = new Properties();
appProperties.load(is);
} catch (IOException ioException) {
appProperties = new Properties();
appProperties.setProperty("litmus.client.version", "0.0.0-default");
}
}
public static String getProperty(String propName) {
return appProperties.getProperty(propName);
}
}

View File

@@ -0,0 +1,13 @@
package com.navi.medici.util;
import com.navi.medici.config.LitmusConfig;
import io.micrometer.core.instrument.Counter;
public class MetricsUtils {
public static Counter.Builder counterMetrics(LitmusConfig litmusConfig, String name) {
return Counter.builder(name)
.tag("vertical", litmusConfig.getVertical())
.tag("app_name", litmusConfig.getAppName())
.tag("litmus_client_version", litmusConfig.getLitmusClientVersion());
}
}

View File

@@ -1 +0,0 @@
Implementation-Version: 2.0.5-RELEASE

View File

@@ -0,0 +1 @@
litmus.client.version=2.0.6-RELEASE

View File

@@ -53,8 +53,7 @@ public class ClickStreamClientTest extends WireMockRules {
.build();
var clickStreamPayload = clickStreamPayload();
client = new ClickStreamClient(litmusConfig.getClickStreamAPI(), litmusConfig.getAppName(),
litmusConfig.getVertical(), litmusConfig.getMeterRegistry());
client = new ClickStreamClient(litmusConfig);
wireMockRule.stubFor(post("/events/json").withRequestBody(equalToJson(new ObjectMapper().writeValueAsString(clickStreamPayload)))
.willReturn(aResponse()
@@ -74,8 +73,7 @@ public class ClickStreamClientTest extends WireMockRules {
.build();
var clickStreamPayload = clickStreamPayload();
client = new ClickStreamClient(litmusConfig.getClickStreamAPI(), litmusConfig.getAppName(),
litmusConfig.getVertical(), litmusConfig.getMeterRegistry());
client = new ClickStreamClient(litmusConfig);
wireMockRule.stubFor(post("/events/json").withRequestBody(equalToJson(new ObjectMapper().writeValueAsString(clickStreamPayload)))
.willReturn(aResponse()

View File

@@ -35,15 +35,14 @@ public class HttpExperimentFetcherTest extends WireMockRules {
File file =
new File(getClass().getClassLoader().getResource("unleash-repo-v1.json").toURI());
String response = TestUtils.fileToString(file);
wireMockRule.stubFor(get( "/litmus-core/v1/experiments?vertical=test-experiment&polling_time=20")
wireMockRule.stubFor(get( "/litmus-core/v1/experiments/vertical?vertical=test-experiment&polling_time=20")
.willReturn(aResponse()
.withHeader("Content-Type", "application/json")
.withStatus(200)
.withBody(response)));
httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(),
litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry());
httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig);
var litmusResponse = httpExperimentFetcher.fetchExperiments("test-experiment", 20L );
assertEquals(litmusResponse.getExperimentCollection().getLitmusExperiments().size(), 3);
@@ -61,13 +60,12 @@ public class HttpExperimentFetcherTest extends WireMockRules {
.litmusAPI("http://localhost:" + wireMockRule.port() + "/litmus-core/v1")
.build();
stubFor(get("/litmus-core/v1/experiments?vertical=test-experiment&polling_time=20")
stubFor(get("/litmus-core/v1/experiments/vertical?vertical=test-experiment&polling_time=20")
.willReturn(aResponse()
.withHeader("Content-Type", "application/json")
.withStatus(304)));
httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(),
litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry());
httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig);
var litmusResponse = httpExperimentFetcher.fetchExperiments("test-experiment", 20L );
assertEquals(litmusResponse.getExperimentCollection().getLitmusExperiments().size(), 0);
@@ -85,18 +83,17 @@ public class HttpExperimentFetcherTest extends WireMockRules {
.litmusAPI("http://localhost:" + wireMockRule.port() + "/litmus-core/v1")
.build();
stubFor(get("/litmus-core/v1/experiments?vertical=test-experiment&polling_time=20")
stubFor(get("/litmus-core/v1/experiments/vertical?vertical=test-experiment&polling_time=20")
.willReturn(aResponse()
.withHeader("Content-Type", "application/json")
.withStatus(500)));
httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(),
litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry());
httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig);
var litmusResponse = httpExperimentFetcher.fetchExperiments("test-experiment", 20L );
assertEquals(litmusResponse.getExperimentCollection().getLitmusExperiments().size(), 0);
assertEquals(litmusResponse.getHttpStatusCode(), 500);
assertEquals(litmusResponse.getStatus(), Status.UNAVAILABLE);
assertEquals(500, litmusResponse.getHttpStatusCode());
assertEquals(Status.UNAVAILABLE, litmusResponse.getStatus());
}
@Test
@@ -120,8 +117,7 @@ public class HttpExperimentFetcherTest extends WireMockRules {
.withStatus(200)
.withBody(response)));
httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(),
litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry());
httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig);
var result = httpExperimentFetcher.segmentIdExists(segmentName, id);
assertTrue(result.getData());
@@ -144,8 +140,7 @@ public class HttpExperimentFetcherTest extends WireMockRules {
.willReturn(aResponse()
.withStatus(200)));
httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(),
litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry());
httpExperimentFetcher = new HttpExperimentFetcher(litmusConfig);
Exception e = assertThrows(LitmusException.class, () ->
httpExperimentFetcher.segmentIdExists(segmentName, id)

View File

@@ -15,6 +15,8 @@ import com.navi.medici.context.LitmusContext;
import com.navi.medici.enums.ExperimentType;
import com.navi.medici.request.v1.LitmusExperiment;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -36,6 +38,7 @@ public class EventDispatcherTest {
@Test
public void testEventDispatchWithoutClickStreamPayload() {
when(litmusConfig.getExecutorService()).thenReturn(Executors.newFixedThreadPool(1));
LitmusContext litmusContext = LitmusContext.builder()
.appName("test-app")
.userId("test-user-id")
@@ -58,7 +61,7 @@ public class EventDispatcherTest {
@Test
public void testEventDispatchWithClickStreamPayload() {
when(litmusConfig.getExecutorService()).thenReturn(Executors.newFixedThreadPool(1));
LitmusContext litmusContext = buildLitmusContext();
LitmusExperiment litmusExperiment = LitmusExperiment.builder()

View File

@@ -3,8 +3,12 @@ package com.navi.medici.litmus;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.navi.medici.context.LitmusContext;
@@ -71,7 +75,7 @@ public class DefaultLitmusTest {
.deviceId("test-device-id")
.build());
var result = litmus.isEnabled("experiment-1");
assertTrue(result);
assertFalse(result);
}
@Test
@@ -156,6 +160,8 @@ public class DefaultLitmusTest {
public void testExperimentPresentWithStrategy100RolloutVariant() {
var litmusConfigBuilder = TestUtils.buildLitmusConfig();
litmusConfigBuilder.litmusContextProvider(litmusContextProvider);
litmusConfigBuilder.enableClickStream(true);
litmus = new DefaultLitmus(litmusConfigBuilder.build(), litmusExperimentRepository);
when(litmusExperimentRepository.getLitmusExperiment(anyString())).thenReturn(LitmusExperiment.builder()
@@ -184,4 +190,38 @@ public class DefaultLitmusTest {
assertTrue(result.isEnabled());
assertEquals(result.getName(), "variant-1");
}
@Test
public void testClickStreamKillSwitch() {
var litmusConfigBuilder = TestUtils.buildLitmusConfig();
litmusConfigBuilder.litmusContextProvider(litmusContextProvider);
litmus = new DefaultLitmus(litmusConfigBuilder.build(), litmusExperimentRepository);
when(litmusExperimentRepository.getLitmusExperiment(anyString())).thenReturn(LitmusExperiment.builder()
.name("experiment-1")
.enabled(Boolean.TRUE)
.vertical("PL")
.experimentId("test-experiment-id")
.type(ExperimentType.EXPERIMENT)
.strategies(List.of(ActivationStrategy.builder()
.name("flexibleRollout")
.parameters(Map.of("rollout", "100", "stickiness", "userId", "groupId", "test-group-id"))
.build()))
.variants(List.of(VariantDefinition.builder()
.name("variant-1")
.weight(100)
.stickiness("userId")
.overrides(List.of())
.build()))
.build());
when(litmusContextProvider.getContext()).thenReturn(LitmusContext.builder()
.userId("test-user-id")
.deviceId("test-device-id")
.build());
var result = litmus.getVariant("experiment-1");
assertTrue(result.isEnabled());
assertEquals(result.getName(), "variant-1");
verify(eventDispatcher, times(0)).publish(any(), any(), any(), any());
}
}

View File

@@ -46,8 +46,7 @@ public class LitmusExperimentRepositoryTest {
public void noBackUpAndNoRepositoryAvailable() {
LitmusConfig litmusConfig = TestUtils.buildLitmusConfig().build();
ExperimentFetcher experimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(),
litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry());
ExperimentFetcher experimentFetcher = new HttpExperimentFetcher(litmusConfig);
ExperimentBackupHandler experimentBackupHandler = new ExperimentBackupHandlerFile(litmusConfig);
LitmusExperimentRepository litmusExperimentRepository = new LitmusExperimentRepository(litmusConfig, experimentFetcher, experimentBackupHandler);
@@ -63,8 +62,7 @@ public class LitmusExperimentRepositoryTest {
ExperimentBackupHandler experimentBackupHandler = mock(ExperimentBackupHandlerFile.class);
when(experimentBackupHandler.read()).thenReturn(new LitmusExperimentCollection(Collections.emptyList(), 1));
ExperimentFetcher experimentFetcher = new HttpExperimentFetcher(litmusConfig.getLitmusURLs(), litmusConfig.getAppName(), litmusConfig.getNamePrefix(),
litmusConfig.getProjectName(), litmusConfig.getVertical(), litmusConfig.getMeterRegistry());
ExperimentFetcher experimentFetcher = new HttpExperimentFetcher(litmusConfig);
LitmusScheduledExecutor litmusScheduledExecutor = mock(LitmusScheduledExecutor.class);
@@ -141,12 +139,12 @@ public class LitmusExperimentRepositoryTest {
LitmusExperimentRepository experimentRepository = new LitmusExperimentRepository(config, executor, experimentFetcher, experimentBackupHandler);
verify(executor).setInterval(runnableArgumentCaptor.capture(), anyLong(), anyLong());
verify(experimentFetcher, times(0)).fetchExperiments(anyString(), anyLong());
verify(experimentFetcher, times(1)).fetchExperiments(anyString(), anyLong());
runnableArgumentCaptor.getValue().run();
verify(experimentBackupHandler, times(1)).read();
verify(experimentFetcher, times(1)).fetchExperiments(anyString(), anyLong());
verify(experimentFetcher, times(2)).fetchExperiments(anyString(), anyLong());
assertTrue(experimentRepository.getLitmusExperiment("experiment-name1").isEnabled());
}

View File

@@ -21,10 +21,15 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class DeviceWithIdStrategyTest {
@Spy
ObjectMapper objectMapper;
@Mock
HttpExperimentFetcher httpExperimentFetcher;
@@ -39,7 +44,7 @@ public class DeviceWithIdStrategyTest {
@Test
public void testWithoutContext() throws Exception {
String parameters = " {\"groupId\": \"new-home-page-group-id\", \"rollout\": \"100\", \"segment\": \"test-segment\"}";
HashMap<String, String> params = new ObjectMapper().readValue(parameters, HashMap.class);
HashMap<String, String> params = objectMapper.readValue(parameters, HashMap.class);
assertFalse(deviceWithIdStrategy.isEnabled(params));
}
@@ -47,7 +52,7 @@ public class DeviceWithIdStrategyTest {
@Test
public void testStrategyWithRollout() throws Exception {
String parameters = " {\"groupId\": \"new-home-page-group-id\", \"rollout\": \"100\", \"segment\": \"test-segment\"}";
HashMap<String, String> params = new ObjectMapper().readValue(parameters, HashMap.class);
HashMap<String, String> params = objectMapper.readValue(parameters, HashMap.class);
var context = TestUtils.buildLitmusContext();
when(httpExperimentFetcher.segmentIdExists(anyString(), anyString()))
@@ -60,7 +65,7 @@ public class DeviceWithIdStrategyTest {
@Test
public void testStrategyWithoutRollout() throws Exception {
String parameters = " {\"groupId\": \"new-home-page-group-id\", \"segment\": \"test-segment\"}";
HashMap<String, String> params = new ObjectMapper().readValue(parameters, HashMap.class);
HashMap<String, String> params = objectMapper.readValue(parameters, HashMap.class);
var context = TestUtils.buildLitmusContext();
when(httpExperimentFetcher.segmentIdExists(anyString(), anyString()))

View File

@@ -15,7 +15,8 @@ public class TestUtils {
.clickStreamAPI("http://localhost")
.vertical("PL")
.appName("test-app")
.litmusAPI("http://localhost:8080/litmus-core/v1");
.litmusAPI("http://localhost:8080/litmus-core/v1")
.synchronousFetchOnInitialisation(true);
}
public static LitmusContext buildLitmusContext() {

View File

@@ -5,11 +5,11 @@
<parent>
<artifactId>litmus</artifactId>
<groupId>com.navi.medici</groupId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</parent>
<artifactId>litmus-core</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
<packaging>jar</packaging>
<name>litmus-core</name>
@@ -31,25 +31,25 @@
<dependency>
<groupId>com.navi.medici</groupId>
<artifactId>litmus-model</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</dependency>
<dependency>
<groupId>com.navi.medici</groupId>
<artifactId>litmus-db</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</dependency>
<dependency>
<groupId>com.navi.medici</groupId>
<artifactId>litmus-cache</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</dependency>
<dependency>
<groupId>com.navi.medici</groupId>
<artifactId>litmus-util</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</dependency>
<dependency>

View File

@@ -1,6 +1,5 @@
package com.navi.medici.controller.v1;
import com.navi.medici.entity.ExperimentEntity;
import com.navi.medici.request.v1.LitmusExperiment;
import com.navi.medici.request.v1.LitmusExperimentStrategyUpdate;
import com.navi.medici.request.v1.VerticalUpdateRequest;

View File

@@ -4,11 +4,11 @@
<parent>
<artifactId>litmus</artifactId>
<groupId>com.navi.medici</groupId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</parent>
<artifactId>litmus-db</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
<packaging>jar</packaging>
<name>litmus-db</name>
@@ -27,7 +27,7 @@
<dependency>
<groupId>com.navi.medici</groupId>
<artifactId>litmus-model</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</dependency>
</dependencies>

View File

@@ -4,11 +4,11 @@
<parent>
<artifactId>litmus</artifactId>
<groupId>com.navi.medici</groupId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</parent>
<artifactId>litmus-liquibase</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
<packaging>jar</packaging>
<name>litmus-liquibase</name>

View File

@@ -4,11 +4,11 @@
<parent>
<artifactId>litmus</artifactId>
<groupId>com.navi.medici</groupId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</parent>
<artifactId>litmus-mock</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
<packaging>jar</packaging>
<name>litmus-mock</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>com.navi.medici</groupId>
<artifactId>litmus-model</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</dependency>
<dependency>
<groupId>com.navi.medici</groupId>
<artifactId>litmus-client</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</dependency>
<dependency>

View File

@@ -15,9 +15,9 @@ public class CustomLitmusContextProvider implements LitmusContextProvider {
@Override
public LitmusContext getContext() {
return LitmusContext.builder()
.userId(new Random().nextInt() + "")
.deviceId(new Random().nextInt() + "")
.clickStreamPayload("{\"app\":{\"name\":\"NaviDebug\",\"version\":\"77\",\"version_name\":\"1.9.3-cug-1-debug\"},\"client_ts\":\"1633768839907\",\"device\":{\"advertising_id\":\"8835d2b0-5615-412e-b133-8f8dc28e228e\",\"device_id\":\"9a14136215e76324\",\"manufacturer\":\"vivo\",\"model\":\"V2040\",\"os\":\"Android\",\"os_version\":\"30\"},\"events\":[{\"event_name\":\"splash\",\"timestamp\":1633768835058},{\"event_name\":\"home_activity\",\"timestamp\":1633768839791},{\"event_name\":\"home\",\"timestamp\":1633768839860},{\"event_name\":\"full_page_loader_shown\",\"timestamp\":1633768839868}],\"location\":{\"latitude\":\"null\",\"longitude\":\"null\"},\"network\":{\"carrier\":\"\",\"type\":\"Wifi\"},\"source\":\"SyncTimer\",\"user\":{}}")
.addProperty("loanOfferReferenceId", "873a0877-51a7-4acf-96f6-66eb6ac80652")
// .deviceId(new Random().nextInt() + "")
// .clickStreamPayload("{\"app\":{\"name\":\"NaviDebug\",\"version\":\"77\",\"version_name\":\"1.9.3-cug-1-debug\"},\"client_ts\":\"1633768839907\",\"device\":{\"advertising_id\":\"8835d2b0-5615-412e-b133-8f8dc28e228e\",\"device_id\":\"9a14136215e76324\",\"manufacturer\":\"vivo\",\"model\":\"V2040\",\"os\":\"Android\",\"os_version\":\"30\"},\"events\":[{\"event_name\":\"splash\",\"timestamp\":1633768835058},{\"event_name\":\"home_activity\",\"timestamp\":1633768839791},{\"event_name\":\"home\",\"timestamp\":1633768839860},{\"event_name\":\"full_page_loader_shown\",\"timestamp\":1633768839868}],\"location\":{\"latitude\":\"null\",\"longitude\":\"null\"},\"network\":{\"carrier\":\"\",\"type\":\"Wifi\"},\"source\":\"SyncTimer\",\"user\":{}}")
.build();
}
}

View File

@@ -18,7 +18,7 @@ public class MockContainer {
.instanceId("test-instance")
.litmusContextProvider(new CustomLitmusContextProvider())
.clickStreamAPI("https://dev-janus.np.navi-tech.in/events/json")
.vertical("PL")
.vertical("SA")
.meterRegistry(meterRegistry)
.synchronousFetchOnInitialisation(true)
.build();

View File

@@ -5,11 +5,11 @@
<parent>
<artifactId>litmus</artifactId>
<groupId>com.navi.medici</groupId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</parent>
<artifactId>litmus-model</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
<packaging>jar</packaging>
<name>litmus-model</name>

View File

@@ -4,11 +4,11 @@
<parent>
<artifactId>litmus</artifactId>
<groupId>com.navi.medici</groupId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</parent>
<artifactId>litmus-proxy</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
<packaging>jar</packaging>
<name>litmus-proxy</name>
@@ -17,19 +17,19 @@
<dependency>
<groupId>com.navi.medici</groupId>
<artifactId>litmus-model</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</dependency>
<dependency>
<groupId>com.navi.medici</groupId>
<artifactId>litmus-client</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</dependency>
<dependency>
<groupId>com.navi.medici</groupId>
<artifactId>litmus-util</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</dependency>
<dependency>

View File

@@ -4,11 +4,11 @@
<parent>
<artifactId>litmus</artifactId>
<groupId>com.navi.medici</groupId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
</parent>
<artifactId>litmus-util</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
<name>litmus-util</name>

View File

@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.navi.medici</groupId>
<artifactId>litmus</artifactId>
<version>2.0.5-RELEASE</version>
<version>2.0.6-RELEASE</version>
<packaging>pom</packaging>
<name>litmus</name>