@@ -16,22 +16,160 @@ For Maven add to your `pom.xml`:
1616 <dependency >
1717 <groupId >io.opencensus</groupId >
1818 <artifactId >opencensus-api</artifactId >
19- <version >0.18 .0</version >
19+ <version >0.19 .0</version >
2020 </dependency >
2121 <dependency >
2222 <groupId >io.opencensus</groupId >
2323 <artifactId >opencensus-contrib-http-util</artifactId >
24- <version >0.18 .0</version >
24+ <version >0.19 .0</version >
2525 </dependency >
2626</dependencies >
2727```
2828
2929For Gradle add to your dependencies:
3030``` gradle
31- compile 'io.opencensus:opencensus-api:0.18 .0'
32- compile 'io.opencensus:opencensus-contrib-http-util:0.18 .0'
31+ compile 'io.opencensus:opencensus-api:0.19 .0'
32+ compile 'io.opencensus:opencensus-contrib-http-util:0.19 .0'
3333```
3434
35+ ## Instrumenting HTTP libraries/frameworks
36+
37+ ### customization for libraries/frameworks
38+
39+ Users can implement ` HttpExtractor ` to customize what information are extracted from the HTTP
40+ request/response entity.
41+
42+ If context propagation is enabled, users need to provide framework specific ` TextFormat.Setter `
43+ and ` TextFormat.Getter ` . They are used to inject/extract information into/from the ` Carrier ` of
44+ the request. The ` Carrier ` can be the request itself or other objects, as long as it provides
45+ functionalities of setting/getting HTTP attributes.
46+
47+ Below is an example of how the customization for libraries/frameworks should be done:
48+
49+ ``` java
50+ // // Http request entity in the library/framework.
51+ // public class HttpRequest {
52+ // ...
53+ // }
54+ //
55+ // // Http response entity in the library/framework.
56+ // public class HttpResponse {
57+ // ...
58+ // }
59+
60+ // use the HttpRequest itself as Carrier.
61+ TextFormat . Setter<HttpRequest > myTextFormatSetter =
62+ new TextFormat .Setter<HttpRequest > () {
63+ @Override
64+ public void put (HttpRequest carrier , String key , String value ) {
65+ carrier. setHeader(key, value);
66+ }
67+ };
68+ TextFormat . Getter<HttpRequest > myTextFormatGetter =
69+ new TextFormat .Getter<HttpRequest > () {
70+ @Override
71+ public String get (HttpRequest carrier , String key ) {
72+ return carrier. getHeader(key);
73+ }
74+ };
75+ HttpExtractor<HttpRequest , HttpResponse > extractor =
76+ new HttpExtractor<HttpRequest , HttpResponse > () {
77+ @Override
78+ public Integer getStatusCode (HttpResponse response ) {
79+ return response. getStatusCode();
80+ }
81+
82+ // other methods that need to be overridden
83+ // ...
84+ };
85+ ```
86+
87+ ### Client
88+
89+ Users can create a ` HttpClientHandler ` to help instrument client-side HTTP request/response.
90+
91+ An example usage of the handler would be:
92+
93+ ``` java
94+ HttpClientHandler<HttpRequest , HttpResponse , HttpRequest > handler =
95+ new HttpClientHandler<HttpRequest , HttpResponse > (
96+ tracer, extractor, myTextFormat, myTextFormatSetter);
97+
98+ // Use #handleStart in client to start a new span.
99+ // Use `null` if you want to use current Span as the parent Span.
100+ HttpRequestContext context = handler. handleStart(null , request, request);
101+ HttpResponse response = null ;
102+ Throwable error = null ;
103+ try {
104+ // Do something to send the request, and get response code from the server
105+ response = getResponse(request);
106+
107+ // Optionally, use #handleMessageSent in client to log a SENT event and its size.
108+ handler. handleMessageSent(context, request. getContentLength());
109+
110+ // Optionally, use #handleMessageReceived in client to log a RECEIVED event and message size.
111+ handler. handleMessageReceived(context, response. getContentLength());
112+ } catch (Throwable e) {
113+ error = e;
114+ } finally {
115+ // Use #handleEnd in client to close the span.
116+ handler. handleEnd(context, request, response, error);
117+ }
118+ ```
119+
120+ ### Server
121+
122+ Users can create a ` HttpServerHandler ` to help instrument server-side HTTP request/response.
123+
124+ An example usage of the handler would be:
125+
126+ ``` java
127+ HttpServerHandler<HttpRequest , HttpResponse > handler =
128+ new HttpServerHandler<HttpRequest , HttpResponse , HttpRequest > (
129+ tracer, extractor, myTextFormat, myTextFormatGetter,
130+ false /* true if it is public endpoint */ );
131+
132+ // Use #handleStart in server to start a new span.
133+ HttpRequestContext context = handler. handleStart(request, request);
134+ HttpResponse response = constructResponse();
135+ Throwable error = null ;
136+ try (Scope scope = tracer. withSpan(handler. getSpanFromContext(context))) {
137+ // Do something to decide whether to serve the request or early exit.
138+ // For example, client may expect a 100 Continue before sending the message body.
139+ if (extractor. getRequestSize(request) > REQUEST_LIMIT ) {
140+ response. setStatus(413 );
141+ } else {
142+ response. setStatus(100 );
143+ String content = request. getContent();
144+
145+ // Optionally, use #handleMessageReceived in server to log a RECEIVED event and its size.
146+ handler. handleMessageReceived(context, request. getContentLength());
147+
148+ // Do something to prepare the response or exception.
149+ response. setStatus(201 );
150+ response. write(" OK" );
151+ response. flush();
152+
153+ // Optionally, use #handleMessageSent in server to log a SENT message event and its message size.
154+ handler. handleMessageSent(context, response. getContentLength());
155+ } catch (Throwable e) {
156+ error = e;
157+ } finally {
158+ // Use #handleEnd in server to close the span.
159+ handler. handleEnd(context, request, response, error);
160+ }
161+ }
162+ ```
163+
164+ ### handling async calls
165+
166+ In asynchronous HTTP calls, message receiving and sending may happen in different
167+ threads. Users need to ensure the started span (as well as scope, if any) is
168+ closed or ended no matter the call is successful or not.
169+
170+ To do that, store current scope and span somewhere, e.g. the context of the channel,
171+ and close them before the channel exits.
172+
35173[ travis-image ] : https://travis-ci.org/census-instrumentation/opencensus-java.svg?branch=master
36174[ travis-url ] : https://travis-ci.org/census-instrumentation/opencensus-java
37175[ appveyor-image ] : https://ci.appveyor.com/api/projects/status/hxthmpkxar4jq4be/branch/master?svg=true
0 commit comments