Skip to content

Commit

Permalink
Merge pull request #22 from Moesif/moesif-servlet-samplerate
Browse files Browse the repository at this point in the history
cleanup and add support for using fine grained sampling
  • Loading branch information
dgilling authored Aug 14, 2019
2 parents eaf23c4 + dc8da35 commit 1fc49b6
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 57 deletions.
4 changes: 2 additions & 2 deletions moesif-servlet/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.moesif.servlet</groupId>
<artifactId>moesif-servlet</artifactId>
<version>1.6.0</version>
<version>1.6.1</version>
<packaging>jar</packaging>
<name>moesif-servlet</name>
<description>Moesif SDK for Java Servlet to log and analyze API calls</description>
Expand Down Expand Up @@ -61,7 +61,7 @@
<dependency>
<groupId>com.moesif.api</groupId>
<artifactId>moesifapi</artifactId>
<version>1.6.3</version>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
Expand Down
85 changes: 36 additions & 49 deletions moesif-servlet/src/main/java/com/moesif/servlet/MoesifFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@

import com.moesif.api.models.*;

import com.moesif.api.APIHelper;
import com.moesif.api.MoesifAPIClient;
import com.moesif.api.http.client.APICallBack;
import com.moesif.api.http.client.HttpContext;
import com.moesif.api.http.response.HttpResponse;
import com.moesif.api.controllers.APIController;
import com.moesif.api.Configuration;
import com.moesif.api.IpAddress;
import com.moesif.api.BodyParser;

Expand All @@ -41,8 +39,8 @@ public class MoesifFilter implements Filter {
private MoesifAPIClient moesifApi;
private boolean debug;
private boolean logBody;
private int samplingPercentage;
private Map<String, Map<String, Object>> configDict;
private AppConfigModel appConfigModel;
private String cachedConfigEtag;
private Date lastUpdatedTime;

/**
Expand Down Expand Up @@ -172,14 +170,8 @@ public void init(FilterConfig filterConfig) throws ServletException {
this.logBody = false;
}
}

// Global dict
this.configDict = new HashMap<String, Map<String, Object>>();
try {
this.samplingPercentage = getAppConfig(null);
} catch (Throwable t) {
this.samplingPercentage = 100;
}

getAndUpdateAppConfig();
}

@Override
Expand All @@ -189,41 +181,26 @@ public void destroy() {
}
}

// Get Config
public int getAppConfig(String cachedConfigEtag) throws Throwable {
int sampleRate = 100;
// Get Config. called only when configEtagChange is detected
public void getAndUpdateAppConfig() {
try {
// Calling the api
HttpResponse configApiResponse = moesifApi.getAPI().getAppConfig();
// Fetch the response ETag
String responseConfigEtag = configApiResponse.getHeaders().get("x-moesif-config-etag");

if(cachedConfigEtag != null && !cachedConfigEtag.isEmpty() && this.configDict.containsKey(cachedConfigEtag)) {
// Remove from the cache
this.configDict.remove(cachedConfigEtag);
}

// Read the response body
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> jsonMap = mapper.readValue(configApiResponse.getRawBody(), Map.class);

// Add to the global dict
this.configDict.put(responseConfigEtag, jsonMap);

try {
Map<String, Object> appConfig = this.configDict.get(responseConfigEtag);
// Get the sample rate and update last updated time
if (!appConfig.isEmpty() && appConfig.containsKey("sample_rate")) {
sampleRate = (Integer) appConfig.get("sample_rate");
}
} catch(Exception e) {
logger.warning("getConfig() call failed " + e.toString());
}
} catch(Exception e) {
// Calling the api
HttpResponse configApiResponse = moesifApi.getAPI().getAppConfig();
// Fetch the response ETag
String responseConfigEtag = configApiResponse.getHeaders().get("x-moesif-config-etag");

// Read the response body
ObjectMapper mapper = new ObjectMapper();
AppConfigModel newConfig = mapper.readValue(configApiResponse.getRawBody(), AppConfigModel.class);

this.appConfigModel = newConfig;
this.cachedConfigEtag = responseConfigEtag;
} catch(Throwable e) {
logger.warning("getConfig() call failed " + e.toString());
this.appConfigModel = new AppConfigModel();
this.appConfigModel.setSampleRate(100);
}
this.lastUpdatedTime = new Date();
return sampleRate;
}

public void updateUser(UserModel userModel) throws Throwable{
Expand Down Expand Up @@ -504,13 +481,13 @@ public void onFailure(HttpContext context, Throwable error) {

// Generate random number
double randomPercentage = Math.random() * 100;


int samplingPercentage = getSampleRateToUse(userId, companyId);

// Compare percentage to send event
if (this.samplingPercentage >= randomPercentage) {
if (samplingPercentage >= randomPercentage) {
// Send Event
Map<String, String> eventApiResponse = moesifApi.getAPI().createEvent(maskedEvent);
// Get the key from the global dict
String cachedConfigEtag = this.configDict.keySet().iterator().next();
// Get the etag from event api response
String eventResponseConfigEtag = eventApiResponse.get("x-moesif-config-etag");

Expand All @@ -519,7 +496,7 @@ public void onFailure(HttpContext context, Throwable error) {
&& !(eventResponseConfigEtag.equals(cachedConfigEtag))
&& new Date().after(new Date(this.lastUpdatedTime.getTime() + 5 * 60 * 1000))) {
// Call api to update samplingPercentage
this.samplingPercentage = getAppConfig(cachedConfigEtag);
getAndUpdateAppConfig();
}

if (debug) {
Expand All @@ -528,7 +505,7 @@ && new Date().after(new Date(this.lastUpdatedTime.getTime() + 5 * 60 * 1000))) {
}
else {
if(debug) {
logger.info("Skipped Event due to SamplingPercentage " + this.samplingPercentage + " and randomPercentage " + randomPercentage);
logger.info("Skipped Event due to SamplingPercentage " + samplingPercentage + " and randomPercentage " + randomPercentage);
}
}

Expand All @@ -543,6 +520,16 @@ && new Date().after(new Date(this.lastUpdatedTime.getTime() + 5 * 60 * 1000))) {
}
}

public int getSampleRateToUse(String userId, String companyId) {
int sampleRate = appConfigModel.getSampleRate();
if (userId != null && appConfigModel.getUserSampleRate().containsKey(userId)) {
sampleRate = appConfigModel.getUserSampleRate().get(userId);
} else if (companyId != null && appConfigModel.getCompanySampleRate().containsKey(companyId)) {
sampleRate = appConfigModel.getCompanySampleRate().get(companyId);
}
return sampleRate;
}

static String getFullURL(HttpServletRequest request) {
StringBuffer requestURL = request.getRequestURL();
String queryString = request.getQueryString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
import com.moesif.api.models.UserBuilder;
import junit.framework.TestCase;
import org.mockito.Mockito;
import com.moesif.servlet.MoesifFilter;
import com.moesif.servlet.MoesifConfiguration;
import com.moesif.api.models.UserModel;
import static org.mockito.Mockito.when;

Expand Down Expand Up @@ -227,7 +225,7 @@ public void testUpdateCompaniesBatch() throws Throwable {

public void testGetAppConfig() throws Throwable{
filter.init(filterConfig);
int sampleRate = filter.getAppConfig(null);
int sampleRate = filter.getSampleRateToUse(null, null);
assertTrue("Sample Rate should be less than equal to 100", 100 >= sampleRate);
}
}
4 changes: 2 additions & 2 deletions moesif-springrequest/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.moesif.springrequest</groupId>
<artifactId>moesif-springrequest</artifactId>
<version>1.0.4</version>
<version>1.0.5</version>
<packaging>jar</packaging>
<name>moesif-springrequest</name>
<description>Moesif SDK for Java to log and analyze outgoing API calls</description>
Expand Down Expand Up @@ -56,7 +56,7 @@
<dependency>
<groupId>com.moesif.api</groupId>
<artifactId>moesifapi</artifactId>
<version>1.6.3</version>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttp

eventModel = config.maskContent(eventModel);

if (api.shouldSendSampledEvent()) {
if (api.shouldSendSampledEvent(eventModel)) {
try {
APICallBack<HttpResponse> callback = new APICallBack<HttpResponse>() {
public void onSuccess(HttpContext context, HttpResponse response) {
Expand Down

0 comments on commit 1fc49b6

Please sign in to comment.