• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019, OpenCensus Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.opencensus.examples.http.jetty.server;
18 
19 import io.opencensus.contrib.http.servlet.OcHttpServletFilter;
20 import io.opencensus.contrib.http.util.HttpViews;
21 import io.opencensus.exporter.stats.prometheus.PrometheusStatsCollector;
22 import io.opencensus.exporter.trace.jaeger.JaegerTraceExporter;
23 import io.opencensus.exporter.trace.logging.LoggingTraceExporter;
24 import io.opencensus.trace.Tracing;
25 import io.opencensus.trace.config.TraceConfig;
26 import io.opencensus.trace.samplers.Samplers;
27 import io.prometheus.client.exporter.HTTPServer;
28 import java.io.BufferedReader;
29 import java.io.IOException;
30 import java.io.PrintWriter;
31 import java.nio.ByteBuffer;
32 import java.nio.charset.StandardCharsets;
33 import java.util.EnumSet;
34 import javax.servlet.AsyncContext;
35 import javax.servlet.DispatcherType;
36 import javax.servlet.ServletException;
37 import javax.servlet.ServletOutputStream;
38 import javax.servlet.WriteListener;
39 import javax.servlet.http.HttpServlet;
40 import javax.servlet.http.HttpServletRequest;
41 import javax.servlet.http.HttpServletResponse;
42 import org.apache.log4j.Logger;
43 import org.eclipse.jetty.server.Request;
44 import org.eclipse.jetty.server.Server;
45 import org.eclipse.jetty.server.handler.AbstractHandler;
46 import org.eclipse.jetty.servlet.ServletContextHandler;
47 import org.eclipse.jetty.servlet.ServletHolder;
48 
49 /** Sample application that shows how to instrument jetty server. */
50 public class HelloWorldServer extends AbstractHandler {
51 
52   private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName());
53 
54   public static class HelloServlet extends HttpServlet {
55 
56     private static String body = "<h1>Hello World Servlet Get</h1>";
57 
58     private static final long serialVersionUID = 1L;
59 
blockingGet(HttpServletRequest request, HttpServletResponse response)60     private void blockingGet(HttpServletRequest request, HttpServletResponse response)
61         throws ServletException, IOException {
62 
63       String str = body.concat("<h3>blocking</h3>");
64       ByteBuffer content = ByteBuffer.wrap(str.getBytes(StandardCharsets.UTF_8));
65 
66       PrintWriter pout = response.getWriter();
67 
68       pout.print("<html><body>");
69       pout.print(str);
70       pout.print("</body></html>");
71       return;
72     }
73 
asyncGet(HttpServletRequest request, HttpServletResponse response)74     private void asyncGet(HttpServletRequest request, HttpServletResponse response)
75         throws ServletException, IOException {
76       String str = body.concat("<h3>async</h3>");
77       ByteBuffer content = ByteBuffer.wrap(str.getBytes(StandardCharsets.UTF_8));
78 
79       AsyncContext async = request.startAsync();
80       response.setContentType("text/html");
81       try {
82         Thread.sleep(100);
83       } catch (Exception e) {
84         logger.info("Error sleeping");
85       }
86       ServletOutputStream out = response.getOutputStream();
87       out.setWriteListener(
88           new WriteListener() {
89             @Override
90             public void onWritePossible() throws IOException {
91               while (out.isReady()) {
92                 if (!content.hasRemaining()) {
93                   response.setStatus(200);
94                   async.complete();
95                   return;
96                 }
97                 out.write(content.get());
98               }
99             }
100 
101             @Override
102             public void onError(Throwable t) {
103               logger.info("Server onError callled");
104               getServletContext().log("Async Error", t);
105               async.complete();
106             }
107           });
108     }
109 
110     @Override
doGet(HttpServletRequest request, HttpServletResponse response)111     protected void doGet(HttpServletRequest request, HttpServletResponse response)
112         throws ServletException, IOException {
113       if (request.getPathInfo().contains("async")) {
114         asyncGet(request, response);
115       } else {
116         blockingGet(request, response);
117       }
118     }
119 
120     @Override
doPost(HttpServletRequest request, HttpServletResponse response)121     protected void doPost(HttpServletRequest request, HttpServletResponse response)
122         throws ServletException, IOException {
123       // Read from request
124       StringBuilder buffer = new StringBuilder();
125       BufferedReader reader = request.getReader();
126       String line;
127       while ((line = reader.readLine()) != null) {
128         buffer.append(line);
129       }
130       String data = buffer.toString();
131 
132       PrintWriter pout = response.getWriter();
133 
134       pout.print("<html><body>");
135       pout.print("<h3>Hello World Servlet Post</h3>");
136       pout.print("</body></html>");
137       return;
138     }
139   }
140 
141   @Override
handle( String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)142   public void handle(
143       String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
144       throws IOException, ServletException {
145     response.setContentType("text/html;charset=utf-8");
146     response.setStatus(HttpServletResponse.SC_OK);
147     baseRequest.setHandled(true);
148     response.getWriter().println("<h1>Hello World. default handler.</h1>");
149   }
150 
initStatsExporter()151   private static void initStatsExporter() throws IOException {
152     HttpViews.registerAllServerViews();
153 
154     // Register Prometheus exporters and export metrics to a Prometheus HTTPServer.
155     // Refer to https://prometheus.io/ to run Prometheus Server.
156     PrometheusStatsCollector.createAndRegister();
157     HTTPServer prometheusServer = new HTTPServer(9090, true);
158   }
159 
initTracing()160   private static void initTracing() {
161     TraceConfig traceConfig = Tracing.getTraceConfig();
162 
163     // default sampler is set to Samplers.alwaysSample() for demonstration. In production
164     // or in high QPS environment please use default sampler.
165     traceConfig.updateActiveTraceParams(
166         traceConfig.getActiveTraceParams().toBuilder().setSampler(Samplers.alwaysSample()).build());
167 
168     // Register LoggingTraceExporter to see traces in logs.
169     LoggingTraceExporter.register();
170 
171     // Register Jaeger Tracing. Refer to https://www.jaegertracing.io/docs/1.8/getting-started/ to
172     // run Jaeger
173     JaegerTraceExporter.createAndRegister("http://localhost:14268/api/traces", "helloworldserver");
174   }
175 
176   /**
177    * HelloWorldServer starts a jetty server that responds to http request sent by {@link
178    * HelloWorldClient}. The server uses http servlet which is instrumented with opencensus to enable
179    * tracing and monitoring stats.
180    */
main(String[] args)181   public static void main(String[] args) throws Exception {
182     initTracing();
183     initStatsExporter();
184 
185     Server server = new Server(8080);
186     ServletContextHandler contextHandler =
187         new ServletContextHandler(ServletContextHandler.SESSIONS);
188     contextHandler.setContextPath("/helloworld");
189     ServletHolder sh = new ServletHolder(new HelloServlet());
190     contextHandler.addServlet(sh, "/request/*");
191 
192     // Enable tracing by adding OcHttpServleFilter for all path
193     contextHandler.addFilter(OcHttpServletFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
194 
195     // Uncomment following line to use B3Format for trace context propagation.
196     // contextHandler.setAttribute(
197     //    OC_TRACE_PROPAGATOR, Tracing.getPropagationComponent().getB3Format());
198 
199     // By default publicEndpoint parameter is set to false and incoming trace context is added as
200     // a parent.
201     // If the endpoint for http request is public then uncomment following line to set the
202     // publicEndpoint parameter to true. When set to true incoming trace context is added as a
203     // parent link instead of as a parent.
204     //
205     // contextHandler.setInitParameter(OC_PUBLIC_ENDPOINT, "true");
206 
207     server.setHandler(contextHandler);
208     try {
209       server.start();
210       server.join();
211     } catch (Exception e) {
212       logger.error("Failed to start application", e);
213     }
214   }
215 }
216