Created
March 10, 2020 21:42
-
-
Save nathanleclaire/c2faa9c90a0a717fadbce0544ebba573 to your computer and use it in GitHub Desktop.
Generic filter with context injection - Honeycomb Java Beeline implementation
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
package com.mycompany.config.filters; | |
import io.honeycomb.libhoney.ResponseObserver; | |
import io.honeycomb.libhoney.responses.ClientRejected; | |
import io.honeycomb.libhoney.responses.ServerAccepted; | |
import io.honeycomb.libhoney.responses.ServerRejected; | |
import io.honeycomb.libhoney.responses.Unknown; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import org.springframework.http.HttpStatus; | |
public class DebugResponseObserver implements ResponseObserver { | |
private static final Logger LOG = LoggerFactory.getLogger(DebugResponseObserver.class); | |
protected static final String ERROR_TEMPLATE_401 = "Server responded with a 401 HTTP error code to a batch request." + | |
" This is likely caused by using an incorrect 'Team Write Key'. Check https://ui.honeycomb.io/account to verify your " + | |
"team write key. Rejected event: {}"; | |
@Override | |
public void onServerAccepted(final ServerAccepted serverAccepted) { | |
LOG.trace("Event successfully sent to Honeycomb: {}", serverAccepted); | |
} | |
@Override | |
public void onServerRejected(final ServerRejected serverRejected) { | |
if (serverRejected.getBatchData().getBatchStatusCode() == HttpStatus.UNAUTHORIZED.value()) { | |
handle401(serverRejected); | |
} else { | |
LOG.debug("Event rejected by Honeycomb server: {}", serverRejected); | |
} | |
} | |
@Override | |
public void onClientRejected(final ClientRejected clientRejected) { | |
LOG.debug("Event rejected on the client side: {}", clientRejected); | |
} | |
@Override | |
public void onUnknown(final Unknown unknown) { | |
LOG.debug("Received an unknown error while trying to send Event to Honeycomb: {}", unknown); | |
} | |
protected void handle401(final ServerRejected serverRejected) { | |
LOG.debug(ERROR_TEMPLATE_401, serverRejected); | |
} | |
} | |
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
package com.mycompany.config.filters; | |
import io.honeycomb.beeline.DefaultBeeline; | |
import javax.servlet.http.HttpServletRequest; | |
import io.honeycomb.beeline.tracing.Beeline; | |
import io.honeycomb.beeline.tracing.Span; | |
import io.honeycomb.beeline.tracing.SpanBuilderFactory; | |
import io.honeycomb.beeline.tracing.SpanPostProcessor; | |
import io.honeycomb.beeline.tracing.Tracer; | |
import io.honeycomb.beeline.tracing.Tracing; | |
import io.honeycomb.beeline.tracing.sampling.Sampling; | |
import io.honeycomb.libhoney.HoneyClient; | |
import io.honeycomb.libhoney.LibHoney; | |
import io.honeycomb.libhoney.TransportOptions; | |
import io.honeycomb.libhoney.shaded.org.apache.http.HttpHeaders; | |
import io.honeycomb.libhoney.shaded.org.apache.http.HttpHost; | |
import io.honeycomb.libhoney.shaded.org.apache.http.auth.AuthScope; | |
import io.honeycomb.libhoney.shaded.org.apache.http.auth.Credentials; | |
import io.honeycomb.libhoney.shaded.org.apache.http.auth.UsernamePasswordCredentials; | |
import io.honeycomb.libhoney.shaded.org.apache.http.client.CredentialsProvider; | |
import io.honeycomb.libhoney.shaded.org.apache.http.impl.client.BasicCredentialsProvider; | |
import java.io.IOException; | |
import java.net.URI; | |
import java.net.URISyntaxException; | |
import javax.servlet.Filter; | |
import javax.servlet.FilterChain; | |
import javax.servlet.FilterConfig; | |
import javax.servlet.ServletContext; | |
import javax.servlet.ServletException; | |
import javax.servlet.ServletRequest; | |
import javax.servlet.ServletResponse; | |
import javax.servlet.http.HttpServletResponse; | |
public class HoneycombFilter implements Filter { | |
protected ServletContext servletContext; | |
Beeline beeline; | |
final String DATASET = "traces"; | |
final String WRITE_KEY = "$WRITEKEY"; | |
@Override | |
public void init(FilterConfig filterConfig) { | |
servletContext = filterConfig.getServletContext(); | |
HttpHost proxy = HttpHost.create("http://proxy.com:80"); | |
BasicCredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider(); | |
AuthScope authScope = new AuthScope(proxy); | |
UsernamePasswordCredentials usernamePassword = new UsernamePasswordCredentials("proxy_username", "proxy_pass"); | |
basicCredentialsProvider.setCredentials(authScope, usernamePassword); | |
TransportOptions transportOptions = LibHoney.transportOptions().setProxy(proxy).setCredentialsProvider(basicCredentialsProvider).build(); | |
HoneyClient client = LibHoney.create(LibHoney.options().setDataset(DATASET).setWriteKey(WRITE_KEY).build(), transportOptions); | |
client.addResponseObserver(new DebugResponseObserver()); | |
SpanPostProcessor postProcessor = Tracing.createSpanProcessor(client, Sampling.alwaysSampler()); | |
SpanBuilderFactory factory = Tracing.createSpanBuilderFactory(postProcessor, Sampling.alwaysSampler()); | |
Tracer tracer = Tracing.createTracer(factory); | |
beeline = Tracing.createBeeline(tracer, factory); | |
} | |
@Override | |
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | |
throws IOException, ServletException { | |
final HttpServletRequest httpServletRequest = (HttpServletRequest) request; | |
final HttpServletResponse httpServletResponse = (HttpServletResponse) response; | |
SpanBuilderFactory spanBuilderFactory = beeline.getSpanBuilderFactory(); | |
Span rootSpan = spanBuilderFactory.createBuilder() | |
.setSpanName(httpServletRequest.getServletPath()) | |
.setServiceName("serviceName") | |
.build(); | |
Tracer tracer = beeline.getTracer(); | |
tracer.startTrace(rootSpan); | |
rootSpan.addField("request.host", request.getServerName()); | |
rootSpan.addField("request.http_version", request.getProtocol()); | |
rootSpan.addField("request.method", httpServletRequest.getMethod()); | |
rootSpan.addField("request.path", httpServletRequest.getServletPath()); | |
rootSpan.addField("request.query", httpServletRequest.getQueryString()); | |
rootSpan.addField("request.header.accept", httpServletRequest.getHeader(HttpHeaders.ACCEPT)); | |
rootSpan.addField("request.header.user_agent", httpServletRequest.getHeader(HttpHeaders.USER_AGENT)); | |
rootSpan.addField("request.content_length", request.getContentLength()); // FIXME: gets set to -1 | |
try { | |
request.setAttribute("beeline", beeline); | |
chain.doFilter(request, response); | |
rootSpan.addField("response.header_content_type", httpServletResponse.getHeader(HttpHeaders.CONTENT_TYPE)); | |
rootSpan.addField("response.status_code", httpServletResponse.getStatus()); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} finally { | |
rootSpan.close(); | |
beeline.getTracer().endTrace(); | |
} | |
} | |
@Override | |
public void destroy() { | |
servletContext = null; | |
} | |
} |
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
package com.mycompany.config.filters; | |
import io.honeycomb.beeline.DefaultBeeline; | |
import org.springframework.boot.web.servlet.FilterRegistrationBean; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.annotation.Configuration; | |
@Configuration | |
public class HoneycombFilterRegistration { | |
@Bean | |
public FilterRegistrationBean honeycomb() { | |
return new FilterRegistrationBean(new HoneycombFilter()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
code example of custom field/span: