Skip to content

Commit

Permalink
Server timing header (#1617)
Browse files Browse the repository at this point in the history
* add wrapper classes

* inject wrapper classes and add trace context methods to InspectitContext

* adjust NoopContext

* little refactor

* update dependencies

* update snakeyaml in agent

* change snakeyaml back to 1.33

* change wiremock back to 2.25.0

* split guava-versions

* update documentation, because of ticket 290

* add createTransactionContext()

* remove unnecessary changes

* rename function

* add tests

* add requested changes and documentation

* add configurable session-id-key

* fix cors-errors and add tests

* remove session-id-header from ContextPropagation if exporter is disabled

* update documentation

* fix test

* remove TestPropertySource

* add check for allowed origins

* add error logging for browser propagation with disabled exporter
  • Loading branch information
EddeCCC authored Sep 21, 2023
1 parent fe7abdf commit 7d2a17d
Show file tree
Hide file tree
Showing 27 changed files with 936 additions and 131 deletions.
4 changes: 3 additions & 1 deletion components/inspectit-ocelot-configdocsgenerator/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ dependencies {

'org.mockito:mockito-junit-jupiter',
"org.assertj:assertj-core",
"com.google.guava:guava:${guavaVersion}"
"com.google.guava:guava:${guavaVersionConfigServer}"
)

// This dependency is used by the application.
Expand All @@ -24,6 +24,8 @@ dependencies {
"ch.qos.logback:logback-classic",
"org.apache.commons:commons-lang3",
"commons-beanutils:commons-beanutils:${commonsBeanUtilsVersion}",
// Update dependency, due to Out-of-Support
"org.apache.commons:commons-collections4:${commonsCollectionsVersion}",

"org.springframework.boot:spring-boot-starter-web",
// override snakeyaml due to vulnerabilities in v1.29 used by the SpringBoot version used in this module
Expand Down
4 changes: 2 additions & 2 deletions components/inspectit-ocelot-configurationserver/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ dependencies {

'org.apache.httpcomponents:httpclient', //Required for PATCH-Requests

"org.xerial:sqlite-jdbc",
"org.xerial:sqlite-jdbc:${sqliteVersion}",
"com.github.gwenn:sqlite-dialect:${sqliteDialect}",
"io.jsonwebtoken:jjwt-api:${jsonWebTokenVersion}",
"io.jsonwebtoken:jjwt-impl:${jsonWebTokenVersion}",
Expand All @@ -152,7 +152,7 @@ dependencies {
"org.eclipse.jgit:org.eclipse.jgit:${eclipseJgitVersion}",
"org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:${eclipseJgitVersion}",
"com.google.code.gson:gson",
"com.google.guava:guava:${guavaVersion}",
"com.google.guava:guava:${guavaVersionConfigServer}",

// swagger
"org.springdoc:springdoc-openapi-ui:${springdocOopenapiUiVersion}",
Expand Down
14 changes: 10 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
### https://docs.spring.io/spring-boot/docs/${springBootVersion}/reference/html/dependency-versions.html

# 2.7 is the latest release line which runs on Java 8
springBootVersion=2.7.12
springBootVersion=2.7.15

# Ensure to adapt the netty version when changing the OpenCensus version
openCensusVersion=0.31.1
Expand All @@ -21,25 +21,30 @@ tcnativeVersion=2.0.56.Final
openTelemetryVersion=1.25.0
openTelemetryAlphaVersion=1.25.0-alpha
opentelemetryProtoVersion=1.7.1-alpha
# update okio, due to security concerns
okioVersion=3.5.0

grpcVersion=1.43.1

# snakeYaml version
# We use a newer version as spring-boot because of Security issues
# Version 2.* is not working with the current jackson-dependency of spring 2
snakeYamlVersion=1.33

jsonWebTokenVersion=0.11.5

# If possible keep this version in sync with the assertj-core version used by spring-boot
assertjGuavaVersion=3.24.2

sqliteVersion=3.43.0.0
sqliteDialect=0.1.4

# Starting with version 6.x requires Java 11
eclipseJgitVersion=5.13.1.202206130422-r

springdocOopenapiUiVersion=1.7.0

# Wiremock 3.* doesn't support java 8
wiremockVersion=2.35.0

# We need to use this version, because some database setups do not work
Expand Down Expand Up @@ -77,12 +82,13 @@ protobufJavaUtilVersion=3.22.3
logUnitVersion=1.1.3

commonsBeanUtilsVersion=1.9.4

commonsCollectionsVersion=4.4
commonsIoVersion=2.11.0

commonsMathVersion=3.6.1

guavaVersion=31.1-jre
guavaVersionConfigServer=32.1.2-jre
# ocelot-agent and ocelot-core cannot update guava, because of wiremock
guavaVersionAgent=31.1-jre

### gradle plugin versions
### Check for newer version at https://plugins.gradle.org/
Expand Down
3 changes: 3 additions & 0 deletions inspectit-ocelot-agent/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ dependencies {
"io.opentelemetry:opentelemetry-sdk:${openTelemetryVersion}",
"io.opentelemetry:opentelemetry-opencensus-shim:${openTelemetryAlphaVersion}",
"io.opencensus:opencensus-impl:${openCensusVersion}",
"com.google.guava:guava:${guavaVersionAgent}",
)
annotationProcessor "org.projectlombok:lombok"
testImplementation (
Expand Down Expand Up @@ -137,6 +138,7 @@ dependencies {
systemTestImplementation(
"io.opencensus:opencensus-testing:${openCensusVersion}",
"io.opencensus:opencensus-api:${openCensusVersion}",
"com.google.guava:guava:${guavaVersionAgent}",

// for InMemorySpanExporter
platform("io.opentelemetry:opentelemetry-bom:${openTelemetryVersion}"),
Expand All @@ -151,6 +153,7 @@ dependencies {
"org.assertj:assertj-core",
"org.awaitility:awaitility",
"com.github.tomakehurst:wiremock-jre8:${wiremockVersion}",
"org.yaml:snakeyaml:${snakeYamlVersion}",

"org.apache.httpcomponents:httpclient",
// Switching to spring-boot dependency management excludes somehow magically the transitive
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public Iterable<Map.Entry<String, Object>> getData() {
return Collections.<String, Object>emptyMap().entrySet();
}

@Override
public String createRemoteParentContext() {
return null;
}

@Override
public void makeActive() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ public class NoopLogTraceCorrelator implements LogTraceCorrelator {

@Override
public AutoCloseable startCorrelatedSpanScope(Supplier<? extends AutoCloseable> spanScopeStarter) {
return spanScopeStarter.get();
if(spanScopeStarter != null) return spanScopeStarter.get();
return null;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ public interface InspectitContext {
*/
Iterable<Map.Entry<String, Object>> getData();

/**
* This function should be called in the entry- or pre-entry-phase, to allow the created span to use the context
*
* Creates a SpanContext locally, which the current InspectitContext can use as a remote-parent-context,
* as long as no REMOTE_PARENT_SPAN_CONTEXT_KEY was specified earlier by down-propagation
*
* @return The trace context of the created SpanContext in the W3C-format
*/
String createRemoteParentContext();

/**
* Generates a map representing the globally down-propagated data stored in this context.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import lombok.Data;
import rocks.inspectit.ocelot.config.model.exporters.ExporterEnabledState;

import java.util.List;

/**
* Settings for the HTTP-server tags exporter.
*/
Expand All @@ -29,11 +31,21 @@ public class HttpExporterSettings {
*/
private String path;

/**
* List of allowed Orgins, which are able to access the HTTP-server
*/
private List<String> allowedOrigins;

/**
* How many sessions can be stored at the same time
*/
private int sessionLimit;

/**
* Header, which will be read during browser-propagation to receive the session-ID
*/
private String sessionIdHeader;

/**
* How long the data should be stored in the server
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,21 @@ inspectit:
# settings for tags exporters
tags:
# settings for the http-server exporter
# note that this server does not provide any encryption or performs any authentication
http:
enabled: DISABLED
# the host of the http-server
host: 0.0.0.0
host: 127.0.0.1
# the port of the http-server
port: 9000
# the path for the endpoint of the http-server
path: "/inspectit"
# list of allowed origins, which are able to access the http-server
allowed-origins: ["*"]
# how many sessions can be stored at the same time
# Additional limitations: key-length -> 128, value-length -> 2048, attribute-count -> 128
session-limit: 100
# header, which will be read during browser-propagation to receive the session-ID
session-id-header: "Cookie"
# how long the data should be stored in the server in seconds
time-to-live: 300
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,28 @@ inspectit:
}
}
}
'a_servletapi_remoteParentContext':
docs:
since: '2.5.4'
description: "Writes a parent trace context to the given HttpServletResponse's Server-Timing header"
inputs:
'response': 'The HttpServletResponse to write to'
is-void: true
imports:
- 'javax.servlet'
- 'javax.servlet.http'
input:
'response': 'ServletResponse'
_context: 'InspectitContext'
value-body: |
if(response instanceof HttpServletResponse) {
HttpServletResponse res = (HttpServletResponse) response;
if(!res.isCommitted()) {
String traceContext = _context.createRemoteParentContext();
if(traceContext == null) return;
String key = "Server-Timing";
String value = "traceparent; desc=" + traceContext;
res.addHeader(key, value);
}
}
4 changes: 3 additions & 1 deletion inspectit-ocelot-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ dependencies {
"io.prometheus:simpleclient_httpserver",

// this overwrites version of guava that opencensus-impl pulls in transitively, too.
"com.google.guava:guava:${guavaVersion}",
"com.google.guava:guava:${guavaVersionAgent}",
// we still need the OpenCensus SDK for the metric exporters to work, as the shim only includes opencensus-impl-core
"io.opencensus:opencensus-impl:${openCensusVersion}",

Expand All @@ -106,6 +106,8 @@ dependencies {
"io.opentelemetry:opentelemetry-exporter-jaeger-thrift",
"io.opentelemetry:opentelemetry-exporter-zipkin",
"io.opentelemetry:opentelemetry-exporter-otlp",
// Update okio, due to security concerns
"com.squareup.okio:okio:${okioVersion}",

platform("io.opentelemetry:opentelemetry-bom-alpha:${openTelemetryAlphaVersion}"),
"io.opentelemetry:opentelemetry-exporter-prometheus",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import javax.servlet.http.HttpServlet;
import java.net.InetSocketAddress;
import java.util.List;

/**
* Tags HTTP-Server to "export" data-tags to browsers
Expand All @@ -30,11 +31,6 @@ public class BrowserPropagationHttpExporterService extends DynamicallyActivatabl
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
*/
Expand Down Expand Up @@ -65,12 +61,16 @@ protected boolean doEnable(InspectitConfig configuration) {
String host = settings.getHost();
int port = settings.getPort();
String path = settings.getPath();
int sessionLimit = settings.getSessionLimit();
timeToLive = settings.getTimeToLive();

int sessionLimit = settings.getSessionLimit();
sessionStorage = BrowserPropagationSessionStorage.getInstance();
sessionStorage.setSessionLimit(sessionLimit);
httpServlet = new BrowserPropagationServlet();
inspectitConfig = configuration;
sessionStorage.setExporterActive(true);

String sessionIdHeader = settings.getSessionIdHeader();
List<String> allowedOrigins = settings.getAllowedOrigins();
httpServlet = new BrowserPropagationServlet(sessionIdHeader, allowedOrigins);

return startServer(host, port, path, httpServlet);
}
Expand All @@ -82,6 +82,7 @@ protected boolean doDisable() {
log.info("Stopping Tags HTTP-Server");
server.stop();
sessionStorage.clearDataStorages();
sessionStorage.setExporterActive(false);
} catch (Exception e) {
log.error("Error disabling Tags HTTP-Server", e);
}
Expand All @@ -107,19 +108,13 @@ protected boolean startServer(String host, int port, String path, HttpServlet se
}

/**
* 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
* Updates the session storage
* Browser propagation data is cached for a specific amount of time (timeToLive)
* If the time expires, clean up the storage
*/
@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);
}
}
Loading

0 comments on commit 7d2a17d

Please sign in to comment.