diff --git a/core/src/emitter.rs b/core/src/emitter.rs index 6ea56f3..10ac113 100644 --- a/core/src/emitter.rs +++ b/core/src/emitter.rs @@ -36,8 +36,8 @@ impl<'a, T: Emitter + ?Sized> Emitter for &'a T { } } -#[cfg(feature = "std")] -impl<'a, T: Emitter + ?Sized + 'a> Emitter for Box { +#[cfg(feature = "alloc")] +impl<'a, T: Emitter + ?Sized + 'a> Emitter for alloc::boxed::Box { fn emit(&self, evt: &Event

) { (**self).emit(evt) } diff --git a/core/src/filter.rs b/core/src/filter.rs index 3ca2c34..5b2e0f9 100644 --- a/core/src/filter.rs +++ b/core/src/filter.rs @@ -38,8 +38,8 @@ impl<'a, F: Filter + ?Sized> Filter for &'a F { } } -#[cfg(feature = "std")] -impl<'a, F: Filter + ?Sized + 'a> Filter for Box { +#[cfg(feature = "alloc")] +impl<'a, F: Filter + ?Sized + 'a> Filter for alloc::boxed::Box { fn matches(&self, evt: &Event

) -> bool { (**self).matches(evt) } diff --git a/core/src/template.rs b/core/src/template.rs index 99ca328..ed6c575 100644 --- a/core/src/template.rs +++ b/core/src/template.rs @@ -184,6 +184,9 @@ impl<'a, W: Write + ?Sized> Write for &'a mut W { } } +#[cfg(feature = "alloc")] +impl Write for alloc::string::String {} + impl<'a> Write for fmt::Formatter<'a> { fn write_hole_value(&mut self, _: &str, value: Value) -> fmt::Result { fmt::Display::fmt(&value, self) diff --git a/macros/src/format.rs b/macros/src/format.rs new file mode 100644 index 0000000..c3c77f2 --- /dev/null +++ b/macros/src/format.rs @@ -0,0 +1,45 @@ +use proc_macro2::TokenStream; +use syn::{parse::Parse, FieldValue}; + +use crate::{ + args::{self}, + template, +}; + +pub struct ExpandTokens { + pub input: TokenStream, +} + +struct Args {} + +impl Parse for Args { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + args::set_from_field_values( + input.parse_terminated(FieldValue::parse, Token![,])?.iter(), + [], + )?; + + Ok(Args {}) + } +} + +pub fn expand_tokens(opts: ExpandTokens) -> Result { + let (_, template, props) = template::parse2::(opts.input, true)?; + + let props_match_input_tokens = props.match_input_tokens(); + let props_match_binding_tokens = props.match_binding_tokens(); + let props_tokens = props.match_bound_tokens(); + + let template_tokens = template.template_tokens(); + + Ok(quote!({ + match (#(#props_match_input_tokens),*) { + (#(#props_match_binding_tokens),*) => { + emit::__private::__private_format( + #template_tokens, + #props_tokens, + ) + } + } + })) +} diff --git a/macros/src/lib.rs b/macros/src/lib.rs index d3baeb8..22cdff8 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -20,6 +20,7 @@ mod capture; mod emit; mod filter; mod fmt; +mod format; mod hook; mod in_ctxt; mod key; @@ -30,6 +31,17 @@ mod util; use util::ResultToTokens; +/** +Format a template. +*/ +#[proc_macro] +pub fn format(item: proc_macro::TokenStream) -> proc_macro::TokenStream { + format::expand_tokens(format::ExpandTokens { + input: TokenStream::from(item), + }) + .unwrap_or_compile_error() +} + /** Emit a debug record. */ @@ -62,18 +74,6 @@ pub fn error(item: proc_macro::TokenStream) -> proc_macro::TokenStream { emit(quote!(Error), TokenStream::from(item)) } -/** -Format a template. -*/ -#[proc_macro] -pub fn format(item: proc_macro::TokenStream) -> proc_macro::TokenStream { - emit::expand_tokens(emit::ExpandTokens { - level: quote!(default()), - input: TokenStream::from(item), - }) - .unwrap_or_compile_error() -} - /** Construct a set of properties. */ diff --git a/src/macro_hooks.rs b/src/macro_hooks.rs index 32f96c6..2a52942 100644 --- a/src/macro_hooks.rs +++ b/src/macro_hooks.rs @@ -432,6 +432,14 @@ impl<'a> __PrivateKeyHook for Str<'a> { } } +#[track_caller] +pub fn __private_format(tpl: Template, props: impl Props) -> String { + let mut s = String::new(); + tpl.render(props).write(&mut s).expect("infallible write"); + + s +} + #[track_caller] pub fn __private_emit( to: impl Emitter, diff --git a/targets/otlp/src/data/logs.rs b/targets/otlp/src/data/logs.rs index 44e75a9..03a7afa 100644 --- a/targets/otlp/src/data/logs.rs +++ b/targets/otlp/src/data/logs.rs @@ -2,7 +2,6 @@ mod export_logs_service; mod log_record; use emit_batcher::BatchError; -use prost::Message; pub use self::{export_logs_service::*, log_record::*}; @@ -63,6 +62,8 @@ pub(crate) fn encode_request( } pub(crate) fn decode_response(body: Result<&[u8], &[u8]>) { + use prost::Message; + match body { Ok(body) => { let response = @@ -75,10 +76,8 @@ pub(crate) fn decode_response(body: Result<&[u8], &[u8]>) { } Err(body) => { let response = - crate::data::generated::collector::logs::v1::ExportLogsServiceResponse::decode( - body, - ) - .unwrap(); + crate::data::generated::collector::logs::v1::ExportLogsPartialSuccess::decode(body) + .unwrap(); emit::warn!(rt: emit::runtime::INTERNAL.get(), "received {#[emit::as_debug] response}"); } diff --git a/targets/otlp/src/data/traces.rs b/targets/otlp/src/data/traces.rs index 1feefd2..9407a05 100644 --- a/targets/otlp/src/data/traces.rs +++ b/targets/otlp/src/data/traces.rs @@ -66,5 +66,26 @@ pub(crate) fn encode_request( } pub(crate) fn decode_response(body: Result<&[u8], &[u8]>) { - println!("body: {:?}", body); + use prost::Message; + + match body { + Ok(body) => { + let response = + crate::data::generated::collector::trace::v1::ExportTraceServiceResponse::decode( + body, + ) + .unwrap(); + + emit::debug!(rt: emit::runtime::INTERNAL.get(), "received {#[emit::as_debug] response}"); + } + Err(body) => { + let response = + crate::data::generated::collector::trace::v1::ExportTracePartialSuccess::decode( + body, + ) + .unwrap(); + + emit::warn!(rt: emit::runtime::INTERNAL.get(), "received {#[emit::as_debug] response}"); + } + } } diff --git a/targets/otlp/src/data/traces/span.rs b/targets/otlp/src/data/traces/span.rs index 50c55f2..5f25af7 100644 --- a/targets/otlp/src/data/traces/span.rs +++ b/targets/otlp/src/data/traces/span.rs @@ -179,12 +179,14 @@ impl sval::Value for PropsSpanAttributes

{ name: "exception", time_unix_nano: self.time_unix_nano, dropped_attributes_count: 0, - attributes: &[KeyValue { - key: "exception.message", - value: AnyValue::<_, (), (), ()>::String(sval::Display::new_borrowed( - &err, - )), - }], + attributes: &InlineEventAttributes { + attributes: &[KeyValue { + key: "exception.message", + value: AnyValue::<_, (), (), ()>::String( + sval::Display::new_borrowed(&err), + ), + }], + }, }]) }, )?; @@ -236,9 +238,9 @@ const EVENT_ATTRIBUTES_LABEL: sval::Label = const EVENT_ATTRIBUTES_INDEX: sval::Index = sval::Index::new(3); #[derive(Value)] -pub struct InlineEventAttributes<'a> { +pub struct InlineEventAttributes<'a, A: ?Sized = [KeyValue<&'a str, &'a AnyValue<'a>>]> { #[sval(label = EVENT_ATTRIBUTES_LABEL, index = EVENT_ATTRIBUTES_INDEX)] - pub attributes: &'a [KeyValue<&'a str, &'a AnyValue<'a>>], + pub attributes: &'a A, } pub struct PropsEventAttributes

(pub P); diff --git a/targets/term/src/lib.rs b/targets/term/src/lib.rs index 79eb968..0ffcbe3 100644 --- a/targets/term/src/lib.rs +++ b/targets/term/src/lib.rs @@ -4,7 +4,7 @@ use core::{fmt, str, time::Duration}; use std::{cell::RefCell, cmp, io::Write, sync::Mutex}; use emit::{ - well_known::{METRIC_KIND_SUM, METRIC_VALUE_KEY, TRACE_ID_KEY, LOCATION_KEY}, + well_known::{LOCATION_KEY, METRIC_KIND_SUM, METRIC_VALUE_KEY, TRACE_ID_KEY}, Event, }; use emit_metrics::{Bucketing, MetricsCollector}; diff --git a/tests/smoke-test/main.rs b/tests/smoke-test/main.rs index 55d723e..3c8804c 100644 --- a/tests/smoke-test/main.rs +++ b/tests/smoke-test/main.rs @@ -11,16 +11,18 @@ extern crate serde_derive; #[tokio::main] async fn main() { + println!("{}", emit::format!("Hello, {x}", x: "world")); + let emitter = emit::setup() .to(emit_otlp::proto() .logs( emit_otlp::logs_http("http://localhost:4318/v1/logs") .body(|evt, f| write!(f, "{}", evt.tpl().braced())), ) - /*.traces( + .traces( emit_otlp::traces_http("http://localhost:4318/v1/traces") .name(|evt, f| write!(f, "{}", evt.tpl().braced())), - )*/ + ) .resource(emit::props! { #[emit::key("service.name")] service_name: "smoke-test-rs",