Skip to content
This repository was archived by the owner on Dec 23, 2023. It is now read-only.

Commit f692aae

Browse files
authored
update readme file with example for generic http client and server. (#1669)
1 parent 10736c9 commit f692aae

File tree

1 file changed

+142
-4
lines changed

1 file changed

+142
-4
lines changed

contrib/http_util/README.md

Lines changed: 142 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

2929
For 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

Comments
 (0)