11/*
2- * Copyright 2023 The gRPC Authors
2+ * Copyright 2024 The gRPC Authors
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
1919import io .grpc .Grpc ;
2020import io .grpc .InsecureServerCredentials ;
2121import io .grpc .Server ;
22+ import io .grpc .ServerBuilder ;
2223import io .grpc .examples .helloworld .GreeterGrpc ;
2324import io .grpc .examples .helloworld .HelloReply ;
2425import io .grpc .examples .helloworld .HelloRequest ;
26+ import io .grpc .opentelemetry .GrpcOpenTelemetry ;
2527import io .grpc .stub .StreamObserver ;
28+ import io .opentelemetry .exporter .prometheus .PrometheusHttpServer ;
29+ import io .opentelemetry .sdk .OpenTelemetrySdk ;
30+ import io .opentelemetry .sdk .metrics .SdkMeterProvider ;
2631import java .io .IOException ;
32+ import java .util .concurrent .TimeUnit ;
2733import java .util .logging .Logger ;
2834
2935/**
30- * Server that manages startup/shutdown of a {@code Greeter} server. This also uses a
31- * {@link OAuth2ServerInterceptor} to intercept the OAuth2 token passed .
36+ * gRPC server that manages startup/shutdown of a {@code Greeter} server and generates
37+ * gRPC OpenTelemetry metrics data based on the configuration .
3238 */
3339public class AuthServer {
34-
3540 private static final Logger logger = Logger .getLogger (AuthServer .class .getName ());
3641
3742 private Server server ;
38- private int port ;
39-
40- public AuthServer (int port ) {
41- this .port = port ;
42- }
43-
44- private void start () throws IOException {
45- server = Grpc .newServerBuilderForPort (port , InsecureServerCredentials .create ())
46- .addService (new GreeterImpl ())
47- .intercept (new OAuth2ServerInterceptor ())
48- .build ()
49- .start ();
43+ private void start (int port ) throws IOException {
44+ ServerBuilder <?> serverBuilder = Grpc .newServerBuilderForPort (port , InsecureServerCredentials .create ())
45+ .addService (new GreeterImpl ());
46+ server = serverBuilder .intercept (new OAuth2ServerInterceptor ())
47+ .build ()
48+ .start ();
5049 logger .info ("Server started, listening on " + port );
51- Runtime .getRuntime ().addShutdownHook (new Thread () {
52- @ Override
53- public void run () {
54- // Use stderr here since the logger may have been reset by its JVM shutdown hook.
55- System .err .println ("*** shutting down gRPC server since JVM is shutting down" );
56- AuthServer .this .stop ();
57- System .err .println ("*** server shut down" );
58- }
59- });
6050 }
6151
62- private void stop () {
52+ private void stop () throws InterruptedException {
6353 if (server != null ) {
64- server .shutdown ();
54+ server .shutdown (). awaitTermination ( 30 , TimeUnit . SECONDS ) ;
6555 }
6656 }
6757
@@ -78,19 +68,72 @@ private void blockUntilShutdown() throws InterruptedException {
7868 * Main launches the server from the command line.
7969 */
8070 public static void main (String [] args ) throws IOException , InterruptedException {
71+ // The port on which the server should run.
72+ int port = 50051 ;
73+ // The port on which prometheus metrics are exposed.
74+ int prometheusPort = 9464 ;
8175
82- // The port on which the server should run
83- int port = 50051 ; // default
8476 if (args .length > 0 ) {
77+ if ("--help" .equals (args [0 ])) {
78+ System .err .println ("Usage: [port [prometheus_port]]" );
79+ System .err .println ("" );
80+ System .err .println (" port The port on which server will run. Defaults to " + port );
81+ System .err .println (" prometheusPort The port to expose prometheus metrics. Defaults to " + prometheusPort );
82+ System .exit (1 );
83+ }
8584 port = Integer .parseInt (args [0 ]);
8685 }
86+ if (args .length > 1 ) {
87+ prometheusPort = Integer .parseInt (args [1 ]);
88+ }
89+
90+ // Adds a PrometheusHttpServer to convert OpenTelemetry metrics to Prometheus format and
91+ // expose these via a HttpServer exporter to the SdkMeterProvider.
92+ SdkMeterProvider sdkMeterProvider = SdkMeterProvider .builder ()
93+ .registerMetricReader (
94+ PrometheusHttpServer .builder ().setPort (prometheusPort ).build ())
95+ .build ();
96+
97+ // Initialize OpenTelemetry SDK with MeterProvider configured with Prometheus metrics exporter
98+ OpenTelemetrySdk openTelemetrySdk =
99+ OpenTelemetrySdk .builder ().setMeterProvider (sdkMeterProvider ).build ();
100+
101+ // Initialize gRPC OpenTelemetry.
102+ // Following client metrics are enabled by default :
103+ // 1. grpc.server.call.started
104+ // 2. grpc.server.call.sent_total_compressed_message_size
105+ // 3. grpc.server.call.rcvd_total_compressed_message_size
106+ // 4. grpc.server.call.duration
107+ GrpcOpenTelemetry grpcOpenTelmetry = GrpcOpenTelemetry .newBuilder ()
108+ .sdk (openTelemetrySdk )
109+ .build ();
110+ // Registers gRPC OpenTelemetry globally.
111+ grpcOpenTelmetry .registerGlobal ();
112+
113+ final AuthServer server = new AuthServer ();
114+ server .start (port );
115+
116+ Runtime .getRuntime ().addShutdownHook (new Thread () {
117+ @ Override
118+ public void run () {
119+ System .err .println ("*** shutting down gRPC server since JVM is shutting down" );
120+ try {
121+ server .stop ();
122+ } catch (InterruptedException e ) {
123+ e .printStackTrace (System .err );
124+ }
125+ // Shut down OpenTelemetry SDK.
126+ openTelemetrySdk .close ();
127+
128+ System .err .println ("*** server shut down" );
129+ }
130+ });
87131
88- final AuthServer server = new AuthServer (port );
89- server .start ();
90132 server .blockUntilShutdown ();
91133 }
92134
93135 static class GreeterImpl extends GreeterGrpc .GreeterImplBase {
136+
94137 @ Override
95138 public void sayHello (HelloRequest req , StreamObserver <HelloReply > responseObserver ) {
96139 // get client id added to context by interceptor
0 commit comments