Skip to content

Commit d97ee2e

Browse files
authored
Adds brave-instrumentation-http with classes for instrumenting.. http (#420)
This reduces the scope of the core brave jar Fixes #419
1 parent 5f2eae3 commit d97ee2e

49 files changed

Lines changed: 312 additions & 223 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ Zipkin is based on [Dapper](http://research.google.com/pubs/pub36356.html). Dapp
1010

1111
## What's included
1212

13+
Brave's dependency-free [tracer library](brave/) works against JRE6+.
14+
This is the underlying api that instrumentation use to time operations
15+
and add tags that describe them. This library also includes code that
16+
parses `X-B3-TraceId` headers.
17+
1318
Most users won't write tracing code directly. Rather, they reuse instrumentation
1419
code others have written. Check for [instrumentation written here](instrumentation/) and [Zipkin's list](http://zipkin.io/pages/existing_instrumentations.html)
1520
before rolling your own. Common tracing libraries like JDBC, Servlet
@@ -26,17 +31,12 @@ You may want to put trace IDs into your log files, or change thread local
2631
behavior. Look at our [context libraries](context/), for integration with
2732
tools such as SLF4J.
2833

29-
Brave's dependency-free [tracer library](brave/) works against JRE6+.
30-
This is the underlying api that instrumentation use to time operations
31-
and add tags that describe them. This library also includes code that
32-
parses `X-B3-TraceId` headers.
33-
3434
## Writing new instrumentation
3535
We worked very hard to make writing new instrumentation easy and efficient.
3636
Most of our built-in instrumentation are 50-100 lines of code, yet allow
3737
flexible configuration of tags and sampling policy.
3838

39-
If you need to write new http instrumentation, check [our docs](instrumentation/README.md),
39+
If you need to write new http instrumentation, check [our docs](instrumentation/http/README.md),
4040
as this shows how to write it in a way that is least effort for you and
4141
easy for others to configure. For example, we have a standard [test suite](instrumentation/http-tests)
4242
you can use to make sure things interop, and standard configuration works.

instrumentation/README.md

Lines changed: 19 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -3,191 +3,22 @@ This module a redo of all major instrumentation libraries since Brave 3.
33
Artifacts have the naming convention "brave-instrumentation-XXX": for
44
example, the directory "servlet" includes the artifact "brave-instrumentation-servlet".
55

6-
Notably, this adds a more `HttpTracing` component to configure http client
7-
and server tracing. It also adds support for async servlet and apache http
8-
client, and tests edge cases like multiple servlet versions. Finally, it
9-
tests and benchmarks every http component, so that people are aware of
10-
overhead is involved in tracing.
11-
12-
Here's an example of configuring OkHttp. Note that all instrumentation
13-
have the same naming policy TracingXXX, where XXX is usually the same
14-
as the type returned.
15-
16-
```java
17-
tracing = Tracing.newBuilder()
18-
.localServiceName("my-service")
19-
.reporter(reporter)
20-
.build();
21-
httpTracing = HttpTracing.newBuilder(tracing).serverName("github").build();
22-
okhttp = TracingCallFactory.create(httpTracing, new OkHttpClient());
23-
```
24-
25-
# Http tracing
26-
Most instrumentation are based on http communication. For this reason,
27-
we have specialized handlers for http clients and servers. All of these
28-
are configured with `HttpTracing`.
29-
30-
The `HttpTracing` class holds a reference to a tracing component,
31-
instructions on what to put into http spans, and sampling policy.
32-
33-
## Span data policy
34-
By default, the following are added to both http client and server spans:
35-
* Span.name as the http method in lowercase: ex "get"
36-
* Tags/binary annotations:
37-
* "http.path", which does not include query parameters.
38-
* "http.status_code" when the status us not success.
39-
* "error", when there is an exception or status is >=400
40-
* Remote IP and port information
41-
42-
Naming and tags are configurable in a library-agnostic way. For example,
43-
the same `HttpTracing` component configures OkHttp or Apache HttpClient
44-
identically.
45-
46-
For example, to change the span and tag naming policy for clients, you
47-
can do something like this:
48-
49-
```java
50-
httpTracing = httpTracing.toBuilder()
51-
.clientParser(new HttpClientParser() {
52-
@Override
53-
public <Req> void request(HttpAdapter<Req, ?> adapter, Req req, SpanCustomizer customizer) {
54-
customizer.name(adapter.method(req).toLowerCase() + " " + adapter.path(req));
55-
customizer.tag(TraceKeys.HTTP_URL, adapter.url(req)); // the whole url, not just the path
56-
}
57-
})
58-
.build();
59-
60-
apache = TracingHttpClientBuilder.create(httpTracing.clientOf("s3"));
61-
okhttp = TracingCallFactory.create(httpTracing.clientOf("sqs"), new OkHttpClient());
62-
```
63-
64-
If you just want to control span naming policy, override `spanName` in
65-
your client or server parser.
66-
67-
Ex:
68-
```java
69-
overrideSpanName = new HttpClientParser() {
70-
@Override public <Req> String spanName(HttpAdapter<Req, ?> adapter, Req req) {
71-
return adapter.method(req).toLowerCase() + " " + adapter.path(req);
72-
}
73-
};
74-
```
75-
76-
## Sampling Policy
77-
The default sampling policy is to use the default (trace ID) sampler for
78-
server and client requests.
79-
80-
For example, if there's a incoming request that has no trace IDs in its
81-
headers, the sampler indicated by `Tracing.Builder.sampler` decides whether
82-
or not to start a new trace. Once a trace is in progress, it is used for
83-
any outgoing http client requests.
84-
85-
On the other hand, you may have http client requests that didn't originate
86-
from a server. For example, you may be bootstrapping your application,
87-
and that makes an http call to a system service. The default policy will
88-
start a trace for any http call, even ones that didn't come from a server
89-
request.
90-
91-
You can change the sampling policy by specifying it in the `HttpTracing`
92-
component. Here's an example which doesn't start new traces for requests
93-
to favicon (which many browsers automatically fetch).
94-
95-
```java
96-
httpTracing = httpTracing.toBuilder()
97-
.serverSampler(new HttpSampler() {
98-
@Override public <Req> Boolean trySample(HttpAdapter<Req, ?> adapter, Req request) {
99-
if (adapter.path(request).startsWith("/favicon")) return false;
100-
return null; // defer decision to probabilistic on trace ID
101-
}
102-
})
103-
.build();
104-
```
105-
106-
# Developing new instrumentation
107-
108-
## Http Client
109-
110-
The first step in developing http client instrumentation is implementing
111-
a `HttpClientAdapter` for your native library. This ensures users can
112-
portably control tags using `HttpClientParser`.
113-
114-
Next, you'll need to indicate how to insert trace IDs into the outgoing
115-
request. Often, this is as simple as `Request::setHeader`.
116-
117-
With these two items, you now have the most important parts needed to
118-
trace your server library. You'll likely initialize the following in a
119-
constructor like so:
120-
```java
121-
MyTracingFilter(HttpTracing httpTracing) {
122-
tracer = httpTracing.tracing().tracer();
123-
handler = HttpClientHandler.create(httpTracing, new MyHttpClientAdapter());
124-
extractor = httpTracing.tracing().propagation().injector(Request::setHeader);
125-
}
126-
```
127-
128-
### Synchronous Interceptors
129-
130-
Synchronous interception is the most straight forward instrumentation.
131-
You generally need to...
132-
1. Start the span and add trace headers to the request
133-
2. Put the span in scope so things like log integration works
134-
3. Invoke the request
135-
4. Catch any errors
136-
5. Complete the span
137-
138-
```java
139-
Span span = handler.handleSend(injector, request); // 1.
140-
Throwable error = null;
141-
try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) { // 2.
142-
response = invoke(request); // 3.
143-
} catch (RuntimeException | Error e) {
144-
error = e; // 4.
145-
throw e;
146-
} finally {
147-
handler.handleReceive(response, error, span); // 5.
148-
}
149-
```
150-
151-
## Http Server
152-
153-
The first step in developing http server instrumentation is implementing
154-
a `HttpServerAdapter` for your native library. This ensures users can
155-
portably control tags using `HttpServerParser`. See [HttpServletAdapter](./servlet/src/main/java/brave/servlet/HttpServletAdapter.java)
156-
as an example (you may even be able to use it!).
157-
158-
Next, you'll need to indicate how to extract trace IDs from the incoming
159-
request. Often, this is as simple as `Request::getHeader`.
160-
161-
With these two items, you now have the most important parts needed to
162-
trace your server library. You'll likely initialize the following in a
163-
constructor like so:
164-
```java
165-
MyTracingInterceptor(HttpTracing httpTracing) {
166-
tracer = httpTracing.tracing().tracer();
167-
handler = HttpServerHandler.create(httpTracing, new MyHttpServerAdapter());
168-
extractor = httpTracing.tracing().propagation().extractor(Request::getHeader);
169-
}
170-
```
171-
172-
### Synchronous Interceptors
173-
174-
Synchronous interception is the most straight forward instrumentation.
175-
You generally need to...
176-
1. Extract any trace IDs from headers and start the span
177-
2. Put the span in scope so things like log integration works
178-
3. Invoke the request
179-
4. Catch any errors
180-
5. Complete the span
181-
182-
```java
183-
Span span = handler.handleReceive(extractor, request); // 1.
184-
Throwable error = null;
185-
try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) { // 2.
186-
response = invoke(request); // 3.
187-
} catch (RuntimeException | Error e) {
188-
error = e; // 4.
189-
throw e;
190-
} finally {
191-
handler.handleSend(response, error, span); // 5.
192-
}
193-
```
6+
Here's a brief overview of what's packaged here:
7+
8+
* [grpc](grpc/README.md) - Tracing client and server interceptors for [grpc](github.com/grpc/grpc-java)
9+
* [httpasyncclient](httpasyncclient/README.md) - Tracing decorator for [Apache HttpClient](https://hc.apache.org/httpcomponents-asyncclient-dev/) 4.0+
10+
* [httpclient](httpclient/README.md) - Tracing decorator for [Apache HttpClient](http://hc.apache.org/httpcomponents-client-4.4.x/index.html) 4.3+
11+
* [jaxrs2](jaxrs2/README.md) - Tracing filters and a feature to automatically configure them
12+
* [mysql](mysql/README.md) - Tracing MySQL statement interceptor
13+
* [okhttp3](okhttp3/README.md) - Tracing decorators for [OkHttp](https://github.com/square/okhttp) 3.x
14+
* [p6spy](p6spy/README.md) - Tracing event listener for [P6Spy](https://github.com/p6spy/p6spy) (a proxy for calls to your JDBC driver)
15+
* [servlet](servlet/README.md) - Tracing filter for Servlet 2.5+ (including Async)
16+
* [sparkjava](sparkjava/README.md) - Tracing filters and exception handlers for [SparkJava](http://sparkjava.com/)
17+
* [spring-web](spring-web/README.md) - Tracing interceptor for [Spring RestTemplate](https://spring.io/guides/gs/consuming-rest/)
18+
* [spring-webmvc](spring-webmvc/README.md) - Tracing interceptor for [Spring WebMVC](https://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html)
19+
20+
Here are other tools we provide for configuring or testing instrumentation:
21+
* [http](http/README.md) - `HttpTracing` that allows portable configuration of http instrumentation
22+
* [http-tests](http-tests/README.md) - Interop test suit that all http client and server instrumentation must pass
23+
* [spring-beans](../spring-beans/README.md) - This allows you to setup tracing with XML instead of custom code.
24+
* [benchmarks](benchmarks/README.md) - JMH microbenchmarks that measure instrumentation overhead

instrumentation/benchmarks/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
<dependency>
3535
<groupId>${project.groupId}</groupId>
36-
<artifactId>brave</artifactId>
36+
<artifactId>brave-instrumentation-http</artifactId>
3737
</dependency>
3838

3939
<dependency>

instrumentation/http-tests/pom.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<modelVersion>4.0.0</modelVersion>
99

1010
<artifactId>brave-instrumentation-http-tests</artifactId>
11-
<name>Brave Instrumentation: Http Tests</name>
11+
<name>Brave Instrumentation: Http Interop Tests</name>
1212

1313
<properties>
1414
<main.basedir>${project.basedir}/../..</main.basedir>
@@ -17,6 +17,10 @@
1717
</properties>
1818

1919
<dependencies>
20+
<dependency>
21+
<groupId>${project.groupId}</groupId>
22+
<artifactId>brave-instrumentation-http</artifactId>
23+
</dependency>
2024
<dependency>
2125
<groupId>junit</groupId>
2226
<artifactId>junit</artifactId>

0 commit comments

Comments
 (0)