@@ -270,17 +270,37 @@ impl Default for OpenTelemetryHandle {
270270const DEFAULT_OTLP_SERVICE_NAME : & str = "amaru" ;
271271const DEFAULT_OTLP_METRIC_URL : & str = "http://localhost:4318/v1/metrics" ;
272272
273+ /// Context hints supplied by the caller to refine observability defaults.
274+ pub trait ObservabilityHints {
275+ /// The address the node will listen on, if known at this point.
276+ /// Used to build the default `service.instance.id` resource attribute.
277+ fn listen_address ( & self ) -> Option < & str > ;
278+ }
279+
280+
273281#[ expect( clippy:: panic) ]
274- pub fn setup_open_telemetry ( subscriber : & mut TracingSubscriber < Registry > ) -> ( OpenTelemetryHandle , DelayedWarning ) {
282+ pub fn setup_open_telemetry (
283+ subscriber : & mut TracingSubscriber < Registry > ,
284+ hints : & impl ObservabilityHints ,
285+ ) -> ( OpenTelemetryHandle , DelayedWarning ) {
275286 use opentelemetry:: KeyValue ;
276287 use opentelemetry_sdk:: { Resource , metrics:: Temporality } ;
277288
278289 let service_name =
279290 var ( "OTEL_SERVICE_NAME" ) . unwrap_or_else ( |_| DEFAULT_OTLP_SERVICE_NAME . to_string ( ) ) . trim ( ) . to_string ( ) ;
280- let service_instance_id = var ( "OTEL_SERVICE_INSTANCE_ID" ) . ok ( ) ;
291+ let service_instance_id: Option < String > = var ( "OTEL_SERVICE_INSTANCE_ID" )
292+ . ok ( )
293+ . map ( |v| v. trim ( ) . to_string ( ) )
294+ . filter ( |v| !v. is_empty ( ) )
295+ . or_else ( || {
296+ let listen_addr = hints. listen_address ( ) ?;
297+ let hostname = sysinfo:: System :: host_name ( ) . unwrap_or_else ( || "localhost" . to_string ( ) ) ;
298+ let port = listen_addr. trim ( ) . rsplit ( ':' ) . next ( ) ?;
299+ Some ( format ! ( "{hostname}:{port}" ) )
300+ } ) ;
281301 let mut attributes = vec ! [ KeyValue :: new( SERVICE_NAME , service_name. clone( ) ) ] ;
282- if let Some ( id ) = service_instance_id. filter ( |value| !value . trim ( ) . is_empty ( ) ) {
283- attributes. push ( KeyValue :: new ( SERVICE_INSTANCE_ID , id ) ) ;
302+ if let Some ( instance_id ) = service_instance_id {
303+ attributes. push ( KeyValue :: new ( SERVICE_INSTANCE_ID , instance_id ) ) ;
284304 }
285305 let resource = Resource :: builder ( ) . with_attributes ( attributes) . build ( ) ;
286306
@@ -465,11 +485,12 @@ pub fn setup_observability(
465485 with_open_telemetry : bool ,
466486 with_json_traces : bool ,
467487 color : bool ,
488+ hints : & impl ObservabilityHints ,
468489) -> ( Option < SdkMeterProvider > , Box < dyn FnOnce ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > > ) {
469490 let mut subscriber = TracingSubscriber :: new ( ) ;
470491
471492 let ( OpenTelemetryHandle { metrics, teardown } , warning_otlp) = if with_open_telemetry {
472- setup_open_telemetry ( & mut subscriber)
493+ setup_open_telemetry ( & mut subscriber, hints )
473494 } else {
474495 ( OpenTelemetryHandle :: default ( ) , None )
475496 } ;
0 commit comments