11mod host;
22
3- use std:: {
4- sync:: { Arc , RwLock } ,
5- } ;
6-
73use anyhow:: bail;
84use indexmap:: IndexMap ;
95use opentelemetry:: {
106 trace:: { SpanContext , SpanId , TraceContextExt } ,
117 Context ,
128} ;
9+ use opentelemetry_otlp:: MetricExporter ;
1310use opentelemetry_sdk:: {
14- resource:: { EnvResourceDetector , TelemetryResourceDetector } ,
15- trace:: { BatchSpanProcessor , SpanProcessor } ,
11+ resource:: { EnvResourceDetector , ResourceDetector , TelemetryResourceDetector } ,
12+ runtime:: Tokio ,
13+ trace:: { span_processor_with_async_runtime:: BatchSpanProcessor , SpanProcessor } ,
1614 Resource ,
1715} ;
1816use spin_factors:: { Factor , FactorData , PrepareContext , RuntimeFactors , SelfInstanceBuilder } ;
1917use spin_telemetry:: { detector:: SpinResourceDetector , env:: OtlpProtocol } ;
18+ use std:: sync:: { Arc , RwLock } ;
2019use tracing_opentelemetry:: OpenTelemetrySpanExt ;
2120
2221pub struct OtelFactor {
23- processor : Arc < BatchSpanProcessor > ,
22+ span_processor : Arc < BatchSpanProcessor < Tokio > > ,
23+ metric_exporter : Arc < MetricExporter > ,
2424}
2525
2626impl Factor for OtelFactor {
@@ -30,6 +30,7 @@ impl Factor for OtelFactor {
3030
3131 fn init ( & mut self , ctx : & mut impl spin_factors:: InitContext < Self > ) -> anyhow:: Result < ( ) > {
3232 ctx. link_bindings ( spin_world:: wasi:: otel:: tracing:: add_to_linker :: < _ , FactorData < Self > > ) ?;
33+ ctx. link_bindings ( spin_world:: wasi:: otel:: metrics:: add_to_linker :: < _ , FactorData < Self > > ) ?;
3334 Ok ( ( ) )
3435 }
3536
@@ -49,15 +50,31 @@ impl Factor for OtelFactor {
4950 guest_span_contexts : Default :: default ( ) ,
5051 original_host_span_id : None ,
5152 } ) ) ,
52- processor : self . processor . clone ( ) ,
53+ span_processor : self . span_processor . clone ( ) ,
54+ metric_exporter : self . metric_exporter . clone ( ) ,
5355 } )
5456 }
5557}
5658
5759impl OtelFactor {
5860 pub fn new ( ) -> anyhow:: Result < Self > {
61+ // This is a hack b/c we know the version of this crate will be the same as the version of Spin
62+ let spin_version = env ! ( "CARGO_PKG_VERSION" ) . to_string ( ) ;
63+
64+ let resource = Resource :: builder ( )
65+ . with_detectors ( & [
66+ // Set service.name from env OTEL_SERVICE_NAME > env OTEL_RESOURCE_ATTRIBUTES > spin
67+ // Set service.version from Spin metadata
68+ Box :: new ( SpinResourceDetector :: new ( spin_version) ) as Box < dyn ResourceDetector > ,
69+ // Sets fields from env OTEL_RESOURCE_ATTRIBUTES
70+ Box :: new ( EnvResourceDetector :: new ( ) ) ,
71+ // Sets telemetry.sdk{name, language, version}
72+ Box :: new ( TelemetryResourceDetector ) ,
73+ ] )
74+ . build ( ) ;
75+
5976 // This will configure the exporter based on the OTEL_EXPORTER_* environment variables.
60- let exporter = match OtlpProtocol :: traces_protocol_from_env ( ) {
77+ let span_exporter = match OtlpProtocol :: traces_protocol_from_env ( ) {
6178 OtlpProtocol :: Grpc => opentelemetry_otlp:: SpanExporter :: builder ( )
6279 . with_tonic ( )
6380 . build ( ) ?,
@@ -67,32 +84,31 @@ impl OtelFactor {
6784 OtlpProtocol :: HttpJson => bail ! ( "http/json OTLP protocol is not supported" ) ,
6885 } ;
6986
70- let mut processor = opentelemetry_sdk :: trace :: BatchSpanProcessor :: builder ( exporter ) . build ( ) ;
87+ let mut span_processor = BatchSpanProcessor :: builder ( span_exporter , Tokio ) . build ( ) ;
7188
72- // This is a hack b/c we know the version of this crate will be the same as the version of Spin
73- let spin_version = env ! ( "CARGO_PKG_VERSION" ) . to_string ( ) ;
89+ span_processor. set_resource ( & resource) ;
7490
75- let detectors: & [ Box < dyn opentelemetry_sdk:: resource:: ResourceDetector > ; 3 ] = & [
76- // Set service.name from env OTEL_SERVICE_NAME > env OTEL_RESOURCE_ATTRIBUTES > spin
77- // Set service.version from Spin metadata
78- Box :: new ( SpinResourceDetector :: new ( spin_version) ) ,
79- // Sets fields from env OTEL_RESOURCE_ATTRIBUTES
80- Box :: new ( EnvResourceDetector :: new ( ) ) ,
81- // Sets telemetry.sdk{name, language, version}
82- Box :: new ( TelemetryResourceDetector ) ,
83- ] ;
84-
85- processor. set_resource ( & Resource :: builder ( ) . with_detectors ( detectors) . build ( ) ) ;
91+ let metric_exporter = match OtlpProtocol :: metrics_protocol_from_env ( ) {
92+ OtlpProtocol :: Grpc => opentelemetry_otlp:: MetricExporter :: builder ( )
93+ . with_tonic ( )
94+ . build ( ) ?,
95+ OtlpProtocol :: HttpProtobuf => opentelemetry_otlp:: MetricExporter :: builder ( )
96+ . with_http ( )
97+ . build ( ) ?,
98+ OtlpProtocol :: HttpJson => bail ! ( "http/json OTLP protocol is not supported" ) ,
99+ } ;
86100
87101 Ok ( Self {
88- processor : Arc :: new ( processor) ,
102+ span_processor : Arc :: new ( span_processor) ,
103+ metric_exporter : Arc :: new ( metric_exporter) ,
89104 } )
90105 }
91106}
92107
93108pub struct InstanceState {
94109 pub ( crate ) state : Arc < RwLock < State > > ,
95- pub ( crate ) processor : Arc < BatchSpanProcessor > ,
110+ pub ( crate ) span_processor : Arc < BatchSpanProcessor < Tokio > > ,
111+ pub ( crate ) metric_exporter : Arc < MetricExporter > ,
96112}
97113
98114impl SelfInstanceBuilder for InstanceState { }
0 commit comments