@@ -236,6 +236,23 @@ impl TelemetryCrashUploader {
236236 Ok ( s)
237237 }
238238
239+ /// Send a general (non crash report, non crash ping) log message to the telemetry log intake.
240+ pub async fn upload_general_log (
241+ & self ,
242+ message : String ,
243+ tags : String ,
244+ level : LogLevel ,
245+ ) -> anyhow:: Result < ( ) > {
246+ let tracer_time = SystemTime :: now ( )
247+ . duration_since ( SystemTime :: UNIX_EPOCH )
248+ . map ( |d| d. as_secs ( ) )
249+ . unwrap_or ( 0 ) ;
250+
251+ self . send_log_payload ( message, tags, tracer_time, level, false , false )
252+ . await
253+ }
254+
255+ /// Send a crash ping telemetry log to indicate that crash processing has started
239256 pub async fn upload_crash_ping ( & self , crash_ping : & CrashPing ) -> anyhow:: Result < ( ) > {
240257 let tags = self . build_crash_ping_tags ( crash_ping. crash_uuid ( ) , crash_ping. siginfo ( ) ) ;
241258 let tracer_time = SystemTime :: now ( )
@@ -255,44 +272,8 @@ impl TelemetryCrashUploader {
255272 . await
256273 }
257274
258- fn build_crash_ping_tags ( & self , crash_uuid : & str , sig_info : Option < & SigInfo > ) -> String {
259- let metadata = & self . metadata ;
260- let mut tags = format ! (
261- "uuid:{},is_crash_ping:true,service:{},language_name:{},language_version:{},tracer_version:{}" ,
262- crash_uuid,
263- metadata. application. service_name,
264- metadata. application. language_name,
265- metadata. application. language_version,
266- metadata. application. tracer_version
267- ) ;
268-
269- if let Some ( sig_info) = sig_info {
270- tags. push_str ( & format ! (
271- ",si_code_human_readable:{:?},si_signo:{},si_signo_human_readable:{:?}" ,
272- sig_info. si_code_human_readable,
273- sig_info. si_signo,
274- sig_info. si_signo_human_readable
275- ) ) ;
276- }
277-
278- self . append_optional_tags ( & mut tags) ;
279- tags
280- }
281-
282- fn append_optional_tags ( & self , tags : & mut String ) {
283- let metadata = & self . metadata ;
284- if let Some ( env) = & metadata. application . env {
285- tags. push_str ( & format ! ( ",env:{env}" ) ) ;
286- }
287- if let Some ( runtime_name) = & metadata. application . runtime_name {
288- tags. push_str ( & format ! ( ",runtime_name:{runtime_name}" ) ) ;
289- }
290- if let Some ( runtime_version) = & metadata. application . runtime_version {
291- tags. push_str ( & format ! ( ",runtime_version:{runtime_version}" ) ) ;
292- }
293- }
294-
295- pub async fn upload_to_telemetry ( & self , crash_info : & CrashInfo ) -> anyhow:: Result < ( ) > {
275+ /// Send a crash info telemetry log to indicate that crash processing has completed
276+ pub async fn upload_crash_info ( & self , crash_info : & CrashInfo ) -> anyhow:: Result < ( ) > {
296277 let message = serde_json:: to_string ( crash_info) ?;
297278 let tags = extract_crash_info_tags ( crash_info) . unwrap_or_default ( ) ;
298279 let tracer_time = crash_info. timestamp . parse :: < DateTime < Utc > > ( ) . map_or_else (
@@ -316,6 +297,8 @@ impl TelemetryCrashUploader {
316297 . await
317298 }
318299
300+ /// Shared helper that builds `data::Telemetry` payload and calls `send_telemetry_payload`
301+ /// to send the payload to the telemetry log intake.
319302 async fn send_log_payload (
320303 & self ,
321304 message : String ,
@@ -347,6 +330,7 @@ impl TelemetryCrashUploader {
347330 self . send_telemetry_payload ( & payload) . await
348331 }
349332
333+ /// Helper to perform actual HTTP (or file) submission via configured telemetry client
350334 async fn send_telemetry_payload ( & self , payload : & data:: Telemetry < ' _ > ) -> anyhow:: Result < ( ) > {
351335 let client = libdd_telemetry:: worker:: http_client:: from_config ( & self . cfg ) ;
352336 let req = request_builder ( & self . cfg ) ?
@@ -379,6 +363,43 @@ impl TelemetryCrashUploader {
379363
380364 Ok ( ( ) )
381365 }
366+
367+ fn build_crash_ping_tags ( & self , crash_uuid : & str , sig_info : Option < & SigInfo > ) -> String {
368+ let metadata = & self . metadata ;
369+ let mut tags = format ! (
370+ "uuid:{},is_crash_ping:true,service:{},language_name:{},language_version:{},tracer_version:{}" ,
371+ crash_uuid,
372+ metadata. application. service_name,
373+ metadata. application. language_name,
374+ metadata. application. language_version,
375+ metadata. application. tracer_version
376+ ) ;
377+
378+ if let Some ( sig_info) = sig_info {
379+ tags. push_str ( & format ! (
380+ ",si_code_human_readable:{:?},si_signo:{},si_signo_human_readable:{:?}" ,
381+ sig_info. si_code_human_readable,
382+ sig_info. si_signo,
383+ sig_info. si_signo_human_readable
384+ ) ) ;
385+ }
386+
387+ self . append_optional_tags ( & mut tags) ;
388+ tags
389+ }
390+
391+ fn append_optional_tags ( & self , tags : & mut String ) {
392+ let metadata = & self . metadata ;
393+ if let Some ( env) = & metadata. application . env {
394+ tags. push_str ( & format ! ( ",env:{env}" ) ) ;
395+ }
396+ if let Some ( runtime_name) = & metadata. application . runtime_name {
397+ tags. push_str ( & format ! ( ",runtime_name:{runtime_name}" ) ) ;
398+ }
399+ if let Some ( runtime_version) = & metadata. application . runtime_version {
400+ tags. push_str ( & format ! ( ",runtime_version:{runtime_version}" ) ) ;
401+ }
402+ }
382403}
383404
384405fn extract_crash_info_tags ( crash_info : & CrashInfo ) -> anyhow:: Result < String > {
@@ -423,6 +444,7 @@ mod tests {
423444 use super :: TelemetryCrashUploader ;
424445 use crate :: crash_info:: { test_utils:: TestInstance , CrashInfo , CrashInfoBuilder , Metadata } ;
425446 use libdd_common:: Endpoint ;
447+ use libdd_telemetry:: data:: LogLevel ;
426448 use std:: { collections:: HashSet , fs} ;
427449 use uuid:: Uuid ;
428450
@@ -469,7 +491,7 @@ mod tests {
469491 . unwrap ( ) ;
470492 let test_instance = super :: CrashInfo :: test_instance ( seed) ;
471493
472- t. upload_to_telemetry ( & test_instance) . await . unwrap ( ) ;
494+ t. upload_crash_info ( & test_instance) . await . unwrap ( ) ;
473495
474496 let payload: serde_json:: value:: Value =
475497 serde_json:: de:: from_str ( & fs:: read_to_string ( & output_filename) . unwrap ( ) ) . unwrap ( ) ;
@@ -877,4 +899,48 @@ mod tests {
877899 . contains( "crash processing started" ) ) ;
878900 Ok ( ( ) )
879901 }
902+
903+ #[ tokio:: test]
904+ #[ cfg_attr( miri, ignore) ]
905+ async fn test_general_log_upload ( ) -> anyhow:: Result < ( ) > {
906+ let tmp = tempfile:: tempdir ( ) . unwrap ( ) ;
907+ let output_filename = {
908+ let mut p = tmp. keep ( ) ;
909+ p. push ( "general_log_upload" ) ;
910+ p
911+ } ;
912+
913+ let mut uploader = new_test_uploader ( 7 ) ;
914+ uploader
915+ . cfg
916+ . set_host_from_url ( & format ! ( "file://{}" , output_filename. to_str( ) . unwrap( ) ) ) ?;
917+
918+ uploader
919+ . upload_general_log (
920+ "hello general log" . to_string ( ) ,
921+ "service:foo,env:bar,crash_uuid:1234567890" . to_string ( ) ,
922+ LogLevel :: Warn ,
923+ )
924+ . await ?;
925+
926+ let payload: serde_json:: value:: Value =
927+ serde_json:: de:: from_str ( & fs:: read_to_string ( & output_filename) . unwrap ( ) ) ?;
928+ println ! ( "payload: {:?}" , payload. to_string( ) ) ;
929+
930+ assert_eq ! ( payload[ "api_version" ] , "v2" ) ;
931+ assert_eq ! ( payload[ "request_type" ] , "logs" ) ;
932+ assert_eq ! ( payload[ "origin" ] , "Crashtracker" ) ;
933+
934+ let log_entry = & payload[ "payload" ] [ 0 ] ;
935+ assert_eq ! ( log_entry[ "level" ] , "WARN" ) ;
936+ assert_eq ! ( log_entry[ "is_sensitive" ] , false ) ;
937+ assert_eq ! ( log_entry[ "is_crash" ] , false ) ;
938+ assert_eq ! ( log_entry[ "message" ] , "hello general log" ) ;
939+ let tags = log_entry[ "tags" ] . as_str ( ) . unwrap ( ) ;
940+ assert ! ( tags. contains( "service:foo" ) ) ;
941+ assert ! ( tags. contains( "env:bar" ) ) ;
942+ assert ! ( tags. contains( "crash_uuid:1234567890" ) ) ;
943+
944+ Ok ( ( ) )
945+ }
880946}
0 commit comments