@@ -11,10 +11,39 @@ use axum::{
1111 Json ,
1212} ;
1313use core:: fmt;
14+ use metrics:: { counter, describe_counter} ;
15+ use opentelemetry:: trace:: Status ;
1416use serde:: Serialize ;
15- use std:: { future:: Future , pin:: Pin , sync:: Arc } ;
17+ use std:: {
18+ borrow:: Cow ,
19+ future:: Future ,
20+ pin:: Pin ,
21+ sync:: { Arc , LazyLock } ,
22+ } ;
1623use tower:: { Layer , Service } ;
1724use tracing:: info;
25+ use tracing_opentelemetry:: OpenTelemetrySpanExt ;
26+
27+ const ATTEMPTS : & str = "init4.perms.attempts" ;
28+ const ATTEMPTS_DESCR : & str = "Counts the number of builder permissioning attempts" ;
29+
30+ const MISSING_HEADER : & str = "init4.perms.missing_header" ;
31+ const MISSING_HEADER_DESCR : & str =
32+ "Counts the number of requests missing the authentication header" ;
33+
34+ const PERMISSION_DENIED : & str = "init4.perms.permission_denied" ;
35+ const PERMISSION_DENIED_DESCR : & str =
36+ "Counts the number of requests denied due to builder permissioning" ;
37+
38+ const SUCCESS : & str = "init4.perms.success" ;
39+ const SUCCESS_DESCR : & str = "Counts the number of auths allowed due to builder permissioning" ;
40+
41+ static DESCRIBE : LazyLock < ( ) > = LazyLock :: new ( || {
42+ describe_counter ! ( ATTEMPTS , ATTEMPTS_DESCR ) ;
43+ describe_counter ! ( MISSING_HEADER , MISSING_HEADER_DESCR ) ;
44+ describe_counter ! ( PERMISSION_DENIED , PERMISSION_DENIED_DESCR ) ;
45+ describe_counter ! ( SUCCESS , SUCCESS_DESCR ) ;
46+ } ) ;
1847
1948/// Possible API error responses when a builder permissioning check fails.
2049#[ derive( Serialize ) ]
@@ -155,6 +184,8 @@ where
155184 fn call ( & mut self , req : Request ) -> Self :: Future {
156185 let mut this = self . clone ( ) ;
157186
187+ LazyLock :: force ( & DESCRIBE ) ;
188+
158189 Box :: pin ( async move {
159190 let span = tracing:: info_span!(
160191 "builder::permissioning" ,
@@ -167,37 +198,44 @@ where
167198 . calc( )
168199 . current_point_within_slot( )
169200 . expect( "host chain has started" ) ,
170- permissioning_error = tracing:: field:: Empty ,
201+ otel . status_code = tracing:: field:: Empty
171202 ) ;
172203
173204 let guard = span. enter ( ) ;
174205
175- info ! ( "builder permissioning check started" ) ;
206+ counter ! ( ATTEMPTS ) . increment ( 1 ) ;
176207
177208 // Check if the sub is in the header.
178209 let sub = match validate_header_sub ( req. headers ( ) . get ( "x-jwt-claim-sub" ) ) {
179210 Ok ( sub) => sub,
180211 Err ( err) => {
181- span. record ( "permissioning_error" , err. 1 . message ) ;
212+ span. set_status ( Status :: Error {
213+ description : Cow :: Owned ( err. 1 . message . to_string ( ) ) ,
214+ } ) ;
182215 info ! ( api_err = %err. 1 . message, "permission denied" ) ;
216+ counter ! ( "init4.perms.missing_header" ) . increment ( 1 ) ;
183217 return Ok ( err. into_response ( ) ) ;
184218 }
185219 } ;
186220
187221 span. record ( "requesting_builder" , sub) ;
188222
189223 if let Err ( err) = this. builders . is_builder_permissioned ( sub) {
190- span. record ( "permissioning_error" , err. to_string ( ) ) ;
191- info ! ( api_err = %err, "permission denied" ) ;
224+ span. set_status ( Status :: Error {
225+ description : Cow :: Owned ( err. to_string ( ) ) ,
226+ } ) ;
192227
193228 let hint = builder_permissioning_hint ( & err) ;
194229
230+ counter ! ( "init4.perms.permission_denied" , "builder" => sub. to_string( ) )
231+ . increment ( 1 ) ;
232+
195233 return Ok ( ApiError :: permission_denied ( hint) . into_response ( ) ) ;
196234 }
197235
198- info ! ( "builder permissioned successfully" ) ;
199-
200236 drop ( guard) ;
237+ info ! ( "builder permissioned successfully" ) ;
238+ counter ! ( SUCCESS , "builder" => sub. to_string( ) ) . increment ( 1 ) ;
201239
202240 this. inner . call ( req) . await
203241 } )
0 commit comments