File: README.md

package info (click to toggle)
opencensus-java 0.24.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 6,044 kB
  • sloc: java: 57,166; xml: 1,020; sh: 117; python: 39; makefile: 5
file content (179 lines) | stat: -rw-r--r-- 6,346 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# OpenCensus HTTP Util
[![Build Status][travis-image]][travis-url]
[![Windows Build Status][appveyor-image]][appveyor-url]
[![Maven Central][maven-image]][maven-url]

The *OpenCensus HTTP Util for Java* is a collection of utilities for trace instrumentation when
working with HTTP.

## Quickstart

### Add the dependencies to your project

For Maven add to your `pom.xml`:
```xml
<dependencies>
  <dependency>
    <groupId>io.opencensus</groupId>
    <artifactId>opencensus-api</artifactId>
    <version>0.23.0</version>
  </dependency>
  <dependency>
    <groupId>io.opencensus</groupId>
    <artifactId>opencensus-contrib-http-util</artifactId>
    <version>0.23.0</version>
  </dependency>
</dependencies>
```

For Gradle add to your dependencies:
```groovy
compile 'io.opencensus:opencensus-api:0.23.0'
compile 'io.opencensus:opencensus-contrib-http-util:0.23.0'
```

## Instrumenting HTTP libraries/frameworks

### customization for libraries/frameworks

Users can implement `HttpExtractor` to customize what information are extracted from the HTTP
request/response entity.

If context propagation is enabled, users need to provide framework specific `TextFormat.Setter`
and `TextFormat.Getter`. They are used to inject/extract information into/from the `Carrier` of
the request. The `Carrier` can be the request itself or other objects, as long as it provides
functionalities of setting/getting HTTP attributes.

Below is an example of how the customization for libraries/frameworks should be done:

```java
// // Http request entity in the library/framework.
// public class HttpRequest {
//   ...
// }
//
// // Http response entity in the library/framework.
// public class HttpResponse {
//   ...
// }

// use the HttpRequest itself as Carrier.
TextFormat.Setter<HttpRequest> myTextFormatSetter =
    new TextFormat.Setter<HttpRequest>() {
      @Override
      public void put(HttpRequest carrier, String key, String value) {
        carrier.setHeader(key, value);
      }
    };
TextFormat.Getter<HttpRequest> myTextFormatGetter =
    new TextFormat.Getter<HttpRequest>() {
      @Override
      public String get(HttpRequest carrier, String key) {
        return carrier.getHeader(key);
      }
    };
HttpExtractor<HttpRequest, HttpResponse> extractor =
    new HttpExtractor<HttpRequest, HttpResponse>() {
      @Override
      public Integer getStatusCode(HttpResponse response) {
        return response.getStatusCode();
      }

      // other methods that need to be overridden
      // ...
    };
```

### Client

Users can create a `HttpClientHandler` to help instrument client-side HTTP request/response.

An example usage of the handler would be:

```java
HttpClientHandler<HttpRequest, HttpResponse, HttpRequest> handler =
    new HttpClientHandler<HttpRequest, HttpResponse>(
        tracer, extractor, myTextFormat, myTextFormatSetter);

// Use #handleStart in client to start a new span.
// Use `null` if you want to use current Span as the parent Span.
HttpRequestContext context = handler.handleStart(null, request, request);
HttpResponse response = null;
Throwable error = null;
try {
  // Do something to send the request, and get response code from the server
  response = getResponse(request);

  // Optionally, use #handleMessageSent in client to log a SENT event and its size.
  handler.handleMessageSent(context, request.getContentLength());

  // Optionally, use #handleMessageReceived in client to log a RECEIVED event and message size.
  handler.handleMessageReceived(context, response.getContentLength());
} catch (Throwable e) {
  error = e;
} finally {
  // Use #handleEnd in client to close the span.
  handler.handleEnd(context, request, response, error);
}
```

### Server

Users can create a `HttpServerHandler` to help instrument server-side HTTP request/response.

An example usage of the handler would be:

```java
HttpServerHandler<HttpRequest, HttpResponse> handler =
    new HttpServerHandler<HttpRequest, HttpResponse, HttpRequest>(
        tracer, extractor, myTextFormat, myTextFormatGetter,
        false /* true if it is public endpoint */);

// Use #handleStart in server to start a new span.
HttpRequestContext context = handler.handleStart(request, request);
HttpResponse response = constructResponse();
Throwable error = null;
try (Scope scope = tracer.withSpan(handler.getSpanFromContext(context))) {
  // Do something to decide whether to serve the request or early exit.
  // For example, client may expect a 100 Continue before sending the message body.
  if (extractor.getRequestSize(request) > REQUEST_LIMIT) {
    response.setStatus(413);
  } else {
    response.setStatus(100);
    String content = request.getContent();

    // Optionally, use #handleMessageReceived in server to log a RECEIVED event and its size.
    handler.handleMessageReceived(context, request.getContentLength());

    // Do something to prepare the response or exception.
    response.setStatus(201);
    response.write("OK");
    response.flush();

    // Optionally, use #handleMessageSent in server to log a SENT message event and its message size.
    handler.handleMessageSent(context, response.getContentLength());
  } catch (Throwable e) {
    error = e;
  } finally {
    // Use #handleEnd in server to close the span.
    handler.handleEnd(context, request, response, error);
  }
}
```

### handling async calls

In asynchronous HTTP calls, message receiving and sending may happen in different
threads. Users need to ensure the started span (as well as scope, if any) is
closed or ended no matter the call is successful or not.

To do that, store current scope and span somewhere, e.g. the context of the channel,
and close them before the channel exits.

[travis-image]: https://travis-ci.org/census-instrumentation/opencensus-java.svg?branch=master
[travis-url]: https://travis-ci.org/census-instrumentation/opencensus-java
[appveyor-image]: https://ci.appveyor.com/api/projects/status/hxthmpkxar4jq4be/branch/master?svg=true
[appveyor-url]: https://ci.appveyor.com/project/opencensusjavateam/opencensus-java/branch/master
[maven-image]: https://maven-badges.herokuapp.com/maven-central/io.opencensus/opencensus-contrib-grpc-util/badge.svg
[maven-url]: https://maven-badges.herokuapp.com/maven-central/io.opencensus/opencensus-contrib-grpc-util
[grpc-url]: https://github.com/grpc/grpc-java