4
4
// This source code is licensed under the BSD-style license found in the
5
5
// LICENSE file in the root directory of this source tree.
6
6
7
+ use core:: net:: SocketAddr ;
7
8
use std:: collections:: HashMap ;
8
9
use std:: sync:: Arc ;
9
10
use std:: time:: Duration ;
10
11
use std:: time:: Instant ;
11
12
12
13
use anyhow:: Result ;
14
+ use askama:: Template ;
15
+ use axum:: { response:: Html , routing:: get, Router } ;
16
+ use gethostname:: gethostname;
13
17
use log:: { error, info} ;
14
18
use structopt:: StructOpt ;
15
19
use tokio:: sync:: broadcast;
16
20
use tokio:: sync:: Mutex ;
17
21
use tokio:: task:: JoinSet ;
18
22
use tokio:: time:: sleep;
23
+ use tonic:: service:: Routes ;
19
24
use tonic:: transport:: Server ;
20
25
use tonic:: { Request , Response , Status } ;
21
26
@@ -191,11 +196,33 @@ impl Lighthouse {
191
196
}
192
197
193
198
async fn _run_grpc ( self : Arc < Self > ) -> Result < ( ) > {
194
- let bind = self . opt . bind . parse ( ) ?;
195
- info ! ( "Lighthouse listening on {}" , bind) ;
199
+ let bind: SocketAddr = self . opt . bind . parse ( ) ?;
200
+ info ! (
201
+ "Lighthouse listening on: http://{}:{}" ,
202
+ gethostname( ) . into_string( ) . unwrap( ) ,
203
+ bind. port( )
204
+ ) ;
205
+
206
+ let self_clone = self . clone ( ) ;
207
+
208
+ // Setup HTTP endpoints
209
+ let app = Router :: new ( )
210
+ . route (
211
+ "/" ,
212
+ get ( || async { Html ( IndexTemplate { } . render ( ) . unwrap ( ) ) } ) ,
213
+ )
214
+ . route (
215
+ "/status" ,
216
+ get ( move || async { self_clone. get_status ( ) . await } ) ,
217
+ ) ;
218
+
219
+ // register the GRPC service
220
+ let routes = Routes :: from ( app) . add_service ( LighthouseServiceServer :: new ( self ) ) ;
196
221
197
222
Server :: builder ( )
198
- . add_service ( LighthouseServiceServer :: new ( self ) )
223
+ // allow non-GRPC connections
224
+ . accept_http1 ( true )
225
+ . add_routes ( routes)
199
226
. serve ( bind)
200
227
. await
201
228
. map_err ( |e| e. into ( ) )
@@ -213,6 +240,19 @@ impl Lighthouse {
213
240
}
214
241
Ok ( ( ) )
215
242
}
243
+
244
+ async fn get_status ( self : Arc < Self > ) -> Html < String > {
245
+ let template = {
246
+ let state = self . state . lock ( ) . await ;
247
+
248
+ StatusTemplate {
249
+ quorum_id : state. quorum_id ,
250
+ prev_quorum : state. prev_quorum . clone ( ) ,
251
+ heartbeats : state. heartbeats . clone ( ) ,
252
+ }
253
+ } ;
254
+ Html ( template. render ( ) . unwrap ( ) )
255
+ }
216
256
}
217
257
218
258
#[ tonic:: async_trait]
@@ -271,6 +311,18 @@ impl LighthouseService for Arc<Lighthouse> {
271
311
}
272
312
}
273
313
314
+ #[ derive( Template ) ]
315
+ #[ template( path = "index.html" ) ]
316
+ struct IndexTemplate { }
317
+
318
+ #[ derive( Template ) ]
319
+ #[ template( path = "status.html" ) ]
320
+ struct StatusTemplate {
321
+ prev_quorum : Option < Quorum > ,
322
+ quorum_id : i64 ,
323
+ heartbeats : HashMap < String , Instant > ,
324
+ }
325
+
274
326
#[ cfg( test) ]
275
327
mod tests {
276
328
use super :: * ;
0 commit comments