Name Date Size #Lines LOC

..--

src/H25-Apr-2025-3,0751,920

Android.bpH A D25-Apr-20251.2 KiB4239

README.mdH A D25-Apr-20256.2 KiB180147

build.gradleH A D25-Apr-2025405 1712

README.md

1# OpenCensus HTTP Util
2[![Build Status][travis-image]][travis-url]
3[![Windows Build Status][appveyor-image]][appveyor-url]
4[![Maven Central][maven-image]][maven-url]
5
6The *OpenCensus HTTP Util for Java* is a collection of utilities for trace instrumentation when
7working with HTTP.
8
9## Quickstart
10
11### Add the dependencies to your project
12
13For Maven add to your `pom.xml`:
14```xml
15<dependencies>
16  <dependency>
17    <groupId>io.opencensus</groupId>
18    <artifactId>opencensus-api</artifactId>
19    <version>0.28.3</version>
20  </dependency>
21  <dependency>
22    <groupId>io.opencensus</groupId>
23    <artifactId>opencensus-contrib-http-util</artifactId>
24    <version>0.28.3</version>
25  </dependency>
26</dependencies>
27```
28
29For Gradle add to your dependencies:
30```groovy
31compile 'io.opencensus:opencensus-api:0.28.3'
32compile 'io.opencensus:opencensus-contrib-http-util:0.28.3'
33```
34
35## Instrumenting HTTP libraries/frameworks
36
37### customization for libraries/frameworks
38
39Users can implement `HttpExtractor` to customize what information are extracted from the HTTP
40request/response entity.
41
42If context propagation is enabled, users need to provide framework specific `TextFormat.Setter`
43and `TextFormat.Getter`. They are used to inject/extract information into/from the `Carrier` of
44the request. The `Carrier` can be the request itself or other objects, as long as it provides
45functionalities of setting/getting HTTP attributes.
46
47Below 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.
61TextFormat.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    };
68TextFormat.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    };
75HttpExtractor<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
89Users can create a `HttpClientHandler` to help instrument client-side HTTP request/response.
90
91An example usage of the handler would be:
92
93```java
94HttpClientHandler<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.
100HttpRequestContext context = handler.handleStart(null, request, request);
101HttpResponse response = null;
102Throwable error = null;
103try {
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
122Users can create a `HttpServerHandler` to help instrument server-side HTTP request/response.
123
124An example usage of the handler would be:
125
126```java
127HttpServerHandler<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.
133HttpRequestContext context = handler.handleStart(request, request);
134HttpResponse response = constructResponse();
135Throwable error = null;
136try (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
166In asynchronous HTTP calls, message receiving and sending may happen in different
167threads. Users need to ensure the started span (as well as scope, if any) is
168closed or ended no matter the call is successful or not.
169
170To do that, store current scope and span somewhere, e.g. the context of the channel,
171and close them before the channel exits.
172
173[travis-image]: https://travis-ci.org/census-instrumentation/opencensus-java.svg?branch=master
174[travis-url]: https://travis-ci.org/census-instrumentation/opencensus-java
175[appveyor-image]: https://ci.appveyor.com/api/projects/status/hxthmpkxar4jq4be/branch/master?svg=true
176[appveyor-url]: https://ci.appveyor.com/project/opencensusjavateam/opencensus-java/branch/master
177[maven-image]: https://maven-badges.herokuapp.com/maven-central/io.opencensus/opencensus-contrib-grpc-util/badge.svg
178[maven-url]: https://maven-badges.herokuapp.com/maven-central/io.opencensus/opencensus-contrib-grpc-util
179[grpc-url]: https://github.com/grpc/grpc-java
180