-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add GlobalPropagationDataStorage as well as ExporterService and HttpServlet * integrate BrowserPropagationHttpExporterService into configuration * add additional browser-propagation to DataSettings * fix down-propagation of disabled browserPropagationData * change data-format of BrowserPropagationServlet to EntrySet * little refactor * update DynamicallyActivatableServiceObserverTest * add BrowserPropagation tests * update documentation * add requested changes * add BrowserPropagationSessionStorage * add scheduled method to clean up BrowserPropagationDataStorages * fix makeActive() * add requested changed * add limitations to keys and values of data storages * disable scheduler test * enable runtime updates of the session limit
- Loading branch information
Showing
25 changed files
with
1,158 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
...rc/main/java/rocks/inspectit/ocelot/config/model/exporters/tags/HttpExporterSettings.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package rocks.inspectit.ocelot.config.model.exporters.tags; | ||
|
||
import lombok.Data; | ||
import rocks.inspectit.ocelot.config.model.exporters.ExporterEnabledState; | ||
|
||
/** | ||
* Settings for the HTTP-server tags exporter. | ||
*/ | ||
@Data | ||
public class HttpExporterSettings { | ||
|
||
/** | ||
* Whether the exporter should be started. | ||
*/ | ||
private ExporterEnabledState enabled; | ||
|
||
/** | ||
* The host of the HTTP-server | ||
*/ | ||
private String host; | ||
|
||
/** | ||
* The port of the HTTP-server | ||
*/ | ||
private int port; | ||
|
||
/** | ||
* The path for the endpoint of the HTTP-server | ||
*/ | ||
private String path; | ||
|
||
/** | ||
* How many sessions can be stored at the same time | ||
*/ | ||
private int sessionLimit; | ||
|
||
/** | ||
* How long the data should be stored in the server | ||
*/ | ||
private int timeToLive; | ||
} |
14 changes: 14 additions & 0 deletions
14
...rc/main/java/rocks/inspectit/ocelot/config/model/exporters/tags/TagsExporterSettings.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package rocks.inspectit.ocelot.config.model.exporters.tags; | ||
|
||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
|
||
import javax.validation.Valid; | ||
|
||
@Data | ||
@NoArgsConstructor | ||
public class TagsExporterSettings { | ||
|
||
@Valid | ||
private HttpExporterSettings http; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
...main/java/rocks/inspectit/ocelot/core/exporter/BrowserPropagationHttpExporterService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package rocks.inspectit.ocelot.core.exporter; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import org.eclipse.jetty.server.Server; | ||
import org.eclipse.jetty.servlet.ServletContextHandler; | ||
import org.eclipse.jetty.servlet.ServletHolder; | ||
import org.springframework.scheduling.annotation.EnableScheduling; | ||
import org.springframework.scheduling.annotation.Scheduled; | ||
import org.springframework.stereotype.Component; | ||
import rocks.inspectit.ocelot.config.model.InspectitConfig; | ||
import rocks.inspectit.ocelot.config.model.exporters.tags.HttpExporterSettings; | ||
import rocks.inspectit.ocelot.core.instrumentation.browser.BrowserPropagationSessionStorage; | ||
import rocks.inspectit.ocelot.core.service.DynamicallyActivatableService; | ||
|
||
import javax.servlet.http.HttpServlet; | ||
import java.net.InetSocketAddress; | ||
|
||
/** | ||
* Tags HTTP-Server to "export" data-tags to browsers | ||
* The server contains two endpoints: | ||
* 1. GET: To query propagation data | ||
* 2. PUT: To overwrite propagation data | ||
*/ | ||
|
||
@Slf4j | ||
@Component | ||
@EnableScheduling | ||
public class BrowserPropagationHttpExporterService extends DynamicallyActivatableService { | ||
private Server server; | ||
private BrowserPropagationSessionStorage sessionStorage; | ||
private BrowserPropagationServlet httpServlet; | ||
|
||
/** | ||
* Stores a reference of the InspectITConfig to enable runtime updates of the session limit | ||
*/ | ||
private InspectitConfig inspectitConfig; | ||
|
||
/** | ||
* Delay to rerun the scheduled method after the method finished in milliseconds | ||
*/ | ||
private static final int FIXED_DELAY = 10000; | ||
|
||
/** | ||
* Time to live for browser propagation data in seconds | ||
*/ | ||
private int timeToLive = 300; | ||
|
||
public BrowserPropagationHttpExporterService() { | ||
super("exporters.tags.http"); | ||
} | ||
|
||
@Override | ||
protected boolean checkEnabledForConfig(InspectitConfig configuration) { | ||
return !configuration.getExporters() | ||
.getTags() | ||
.getHttp() | ||
.getEnabled() | ||
.isDisabled(); | ||
} | ||
|
||
@Override | ||
protected boolean doEnable(InspectitConfig configuration) { | ||
HttpExporterSettings settings = configuration.getExporters().getTags().getHttp(); | ||
|
||
String host = settings.getHost(); | ||
int port = settings.getPort(); | ||
String path = settings.getPath(); | ||
int sessionLimit = settings.getSessionLimit(); | ||
timeToLive = settings.getTimeToLive(); | ||
sessionStorage = BrowserPropagationSessionStorage.getInstance(); | ||
sessionStorage.setSessionLimit(sessionLimit); | ||
httpServlet = new BrowserPropagationServlet(); | ||
inspectitConfig = configuration; | ||
|
||
return startServer(host, port, path, httpServlet); | ||
} | ||
|
||
@Override | ||
protected boolean doDisable() { | ||
if(server != null) { | ||
try { | ||
log.info("Stopping Tags HTTP-Server"); | ||
server.stop(); | ||
sessionStorage.clearDataStorages(); | ||
} catch (Exception e) { | ||
log.error("Error disabling Tags HTTP-Server", e); | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
protected boolean startServer(String host, int port, String path, HttpServlet servlet) { | ||
server = new Server(new InetSocketAddress(host, port)); | ||
String contextPath = ""; | ||
ServletContextHandler contextHandler = new ServletContextHandler(server, contextPath); | ||
contextHandler.addServlet(new ServletHolder(servlet), path); | ||
server.setStopAtShutdown(true); | ||
|
||
try { | ||
log.info("Starting Tags HTTP-Server on {}:{}{} ", host, port, path); | ||
server.start(); | ||
} catch (Exception e) { | ||
log.warn("Starting of Tags HTTP-Server failed"); | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
/** | ||
* Updates the session storage: | ||
* 1. Browser propagation data is cached for a specific amount of time (timeToLive) | ||
* If the time expires, clean up the storage | ||
* 2. Update the session limit | ||
* Note that this will not delete any active sessions, if the new session limit is exceeded | ||
*/ | ||
@Scheduled(fixedDelay = FIXED_DELAY) | ||
public void updateSessionStorage() { | ||
if(httpServlet == null) return; | ||
sessionStorage.cleanUpData(timeToLive); | ||
|
||
if(inspectitConfig == null) return; | ||
int sessionLimit = inspectitConfig.getExporters().getTags().getHttp().getSessionLimit(); | ||
sessionStorage.setSessionLimit(sessionLimit); | ||
} | ||
} |
100 changes: 100 additions & 0 deletions
100
...ot-core/src/main/java/rocks/inspectit/ocelot/core/exporter/BrowserPropagationServlet.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package rocks.inspectit.ocelot.core.exporter; | ||
|
||
import com.fasterxml.jackson.core.type.TypeReference; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import lombok.extern.slf4j.Slf4j; | ||
import rocks.inspectit.ocelot.core.instrumentation.browser.BrowserPropagationDataStorage; | ||
import rocks.inspectit.ocelot.core.instrumentation.browser.BrowserPropagationSessionStorage; | ||
|
||
import javax.servlet.http.HttpServlet; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* REST-API to expose browser propagation data | ||
* Additionally, data can be overwritten from outside | ||
* To access a data storage, a sessionID has to be provided, which references a data storage | ||
* <p> | ||
* The expected data format to receive and export data are EntrySets, for example: | ||
* [{"key1": "123"}, {"key2": "321"}] | ||
*/ | ||
@Slf4j | ||
public class BrowserPropagationServlet extends HttpServlet { | ||
|
||
private final ObjectMapper mapper; | ||
private final BrowserPropagationSessionStorage sessionStorage; | ||
|
||
public BrowserPropagationServlet() { | ||
mapper = new ObjectMapper(); | ||
sessionStorage = BrowserPropagationSessionStorage.getInstance(); | ||
} | ||
|
||
@Override | ||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { | ||
log.debug("Tags HTTP-server received GET-request"); | ||
String sessionID = request.getHeader("cookie"); | ||
if(sessionID == null) { | ||
log.warn("Request misses session ID"); | ||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST); | ||
} | ||
else { | ||
BrowserPropagationDataStorage dataStorage = sessionStorage.getDataStorage(sessionID); | ||
|
||
if(dataStorage == null) { | ||
log.warn("Data storage with session id " + sessionID + " not found"); | ||
response.setStatus(HttpServletResponse.SC_NOT_FOUND); | ||
} | ||
else { | ||
dataStorage.updateTimestamp(System.currentTimeMillis()); | ||
Map<String, Object> propagationData = dataStorage.readData(); | ||
String res = mapper.writeValueAsString(propagationData.entrySet()); | ||
response.setContentType("application/json"); | ||
response.setStatus(HttpServletResponse.SC_OK); | ||
response.getWriter().write(res); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
protected void doPut(HttpServletRequest request, HttpServletResponse response) { | ||
log.debug("Tags HTTP-server received PUT-request"); | ||
String sessionID = request.getHeader("cookie"); | ||
if(sessionID == null) { | ||
log.warn("Request misses session ID"); | ||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST); | ||
} | ||
else { | ||
BrowserPropagationDataStorage dataStorage = sessionStorage.getDataStorage(sessionID); | ||
|
||
if(dataStorage == null) { | ||
log.warn("Data storage with session id " + sessionID + " not found"); | ||
response.setStatus(HttpServletResponse.SC_NOT_FOUND); | ||
} | ||
else { | ||
dataStorage.updateTimestamp(System.currentTimeMillis()); | ||
Map<String, String> newPropagationData = getRequestBody(request); | ||
if(newPropagationData != null) { | ||
dataStorage.writeData(newPropagationData); | ||
response.setStatus(HttpServletResponse.SC_OK); | ||
} | ||
else response.setStatus(HttpServletResponse.SC_BAD_REQUEST); | ||
} | ||
} | ||
} | ||
|
||
private Map<String, String> getRequestBody(HttpServletRequest request) { | ||
try (BufferedReader reader = request.getReader()) { | ||
Set<Map.Entry<String,String>> entrySet = mapper.readValue(reader, new TypeReference<Set<Map.Entry<String,String>>>() {}); | ||
return entrySet.stream() | ||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); | ||
} catch (Exception e) { | ||
log.info("Request failed"); | ||
return null; | ||
} | ||
} | ||
} |
Oops, something went wrong.