Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make LogRecord fields private and add getters for encapsulation #2314

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions opentelemetry-appender-log/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -830,11 +830,11 @@ mod tests {

assert_eq!(logs.len(), 5);
for log in logs {
let body: String = match log.record.body.as_ref().unwrap() {
let body: String = match log.record.body().unwrap() {
super::AnyValue::String(s) => s.to_string(),
_ => panic!("AnyValue::String expected"),
};
assert_eq!(body, log.record.severity_text.unwrap());
assert_eq!(body, log.record.severity_text().unwrap());
}
}

Expand Down
38 changes: 14 additions & 24 deletions opentelemetry-appender-tracing/src/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,10 @@ mod tests {

// Validate common fields
assert_eq!(log.instrumentation.name(), "opentelemetry-appender-tracing");
assert_eq!(log.record.severity_number, Some(Severity::Error));
assert_eq!(log.record.severity_number(), Some(Severity::Error));

// Validate trace context is none.
assert!(log.record.trace_context.is_none());
assert!(log.record.trace_context().is_none());

// Validate attributes
#[cfg(not(feature = "experimental_metadata_attributes"))]
Expand Down Expand Up @@ -429,25 +429,20 @@ mod tests {

// validate common fields.
assert_eq!(log.instrumentation.name(), "opentelemetry-appender-tracing");
assert_eq!(log.record.severity_number, Some(Severity::Error));
assert_eq!(log.record.severity_number(), Some(Severity::Error));

// validate trace context.
assert!(log.record.trace_context.is_some());
assert!(log.record.trace_context().is_some());
assert_eq!(
log.record.trace_context.as_ref().unwrap().trace_id,
log.record.trace_context().unwrap().trace_id,
trace_id_expected
);
assert_eq!(
log.record.trace_context.as_ref().unwrap().span_id,
log.record.trace_context().unwrap().span_id,
span_id_expected
);
assert_eq!(
log.record
.trace_context
.as_ref()
.unwrap()
.trace_flags
.unwrap(),
log.record.trace_context().unwrap().trace_flags.unwrap(),
TraceFlags::SAMPLED
);

Expand Down Expand Up @@ -527,10 +522,10 @@ mod tests {

// Validate common fields
assert_eq!(log.instrumentation.name(), "opentelemetry-appender-tracing");
assert_eq!(log.record.severity_number, Some(Severity::Error));
assert_eq!(log.record.severity_number(), Some(Severity::Error));

// Validate trace context is none.
assert!(log.record.trace_context.is_none());
assert!(log.record.trace_context().is_none());

// Attributes can be polluted when we don't use this feature.
#[cfg(feature = "experimental_metadata_attributes")]
Expand Down Expand Up @@ -606,25 +601,20 @@ mod tests {

// validate common fields.
assert_eq!(log.instrumentation.name(), "opentelemetry-appender-tracing");
assert_eq!(log.record.severity_number, Some(Severity::Error));
assert_eq!(log.record.severity_number(), Some(Severity::Error));

// validate trace context.
assert!(log.record.trace_context.is_some());
assert!(log.record.trace_context().is_some());
assert_eq!(
log.record.trace_context.as_ref().unwrap().trace_id,
log.record.trace_context().unwrap().trace_id,
trace_id_expected
);
assert_eq!(
log.record.trace_context.as_ref().unwrap().span_id,
log.record.trace_context().unwrap().span_id,
span_id_expected
);
assert_eq!(
log.record
.trace_context
.as_ref()
.unwrap()
.trace_flags
.unwrap(),
log.record.trace_context().unwrap().trace_flags.unwrap(),
TraceFlags::SAMPLED
);

Expand Down
23 changes: 13 additions & 10 deletions opentelemetry-proto/src/transform/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ pub mod tonic {

impl From<&opentelemetry_sdk::logs::LogRecord> for LogRecord {
fn from(log_record: &opentelemetry_sdk::logs::LogRecord) -> Self {
let trace_context = log_record.trace_context.as_ref();
let severity_number = match log_record.severity_number {
let trace_context = log_record.trace_context();
let severity_number = match log_record.severity_number() {
Some(Severity::Trace) => SeverityNumber::Trace,
Some(Severity::Trace2) => SeverityNumber::Trace2,
Some(Severity::Trace3) => SeverityNumber::Trace3,
Expand Down Expand Up @@ -88,8 +88,8 @@ pub mod tonic {
};

LogRecord {
time_unix_nano: log_record.timestamp.map(to_nanos).unwrap_or_default(),
observed_time_unix_nano: to_nanos(log_record.observed_timestamp.unwrap()),
time_unix_nano: log_record.timestamp().map(to_nanos).unwrap_or_default(),
observed_time_unix_nano: to_nanos(log_record.observed_timestamp().unwrap()),
attributes: {
let attributes: Vec<KeyValue> = log_record
.attributes_iter()
Expand All @@ -102,7 +102,7 @@ pub mod tonic {
.collect();
#[cfg(feature = "populate-logs-event-name")]
{
if let Some(event_name) = &log_record.event_name {
if let Some(event_name) = &log_record.event_name() {
let mut attributes_with_name = attributes;
attributes_with_name.push(KeyValue {
key: "event.name".into(),
Expand All @@ -119,8 +119,11 @@ pub mod tonic {
attributes
},
severity_number: severity_number.into(),
severity_text: log_record.severity_text.map(Into::into).unwrap_or_default(),
body: log_record.body.clone().map(Into::into),
severity_text: log_record
.severity_text()
.map(Into::into)
.unwrap_or_default(),
body: log_record.body().cloned().map(Into::into),
dropped_attributes_count: 0,
flags: trace_context
.map(|ctx| {
Expand Down Expand Up @@ -170,7 +173,7 @@ pub mod tonic {
.schema_url()
.map(ToOwned::to_owned)
.unwrap_or_default(),
scope: Some((instrumentation, log_record.target.clone()).into()),
scope: Some((instrumentation, log_record.target().cloned()).into()),
log_records: vec![log_record.into()],
}],
}
Expand All @@ -193,8 +196,8 @@ pub mod tonic {
>,
(log_record, instrumentation)| {
let key = log_record
.target
.clone()
.target()
.cloned()
.unwrap_or_else(|| Cow::Owned(instrumentation.name().to_owned()));
scope_map
.entry(key)
Expand Down
65 changes: 57 additions & 8 deletions opentelemetry-sdk/src/logs/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,28 @@ pub(crate) type LogRecordAttributes =
/// is provided to `LogExporter`s as input.
pub struct LogRecord {
/// Event name. Optional as not all the logging API support it.
pub event_name: Option<&'static str>,
pub(crate) event_name: Option<&'static str>,

/// Target of the log record
pub target: Option<Cow<'static, str>>,
pub(crate) target: Option<Cow<'static, str>>,

/// Record timestamp
pub timestamp: Option<SystemTime>,
pub(crate) timestamp: Option<SystemTime>,

/// Timestamp for when the record was observed by OpenTelemetry
pub observed_timestamp: Option<SystemTime>,
pub(crate) observed_timestamp: Option<SystemTime>,

/// Trace context for logs associated with spans
pub trace_context: Option<TraceContext>,
pub(crate) trace_context: Option<TraceContext>,

/// The original severity string from the source
pub severity_text: Option<&'static str>,
pub(crate) severity_text: Option<&'static str>,

/// The corresponding severity value, normalized
pub severity_number: Option<Severity>,
pub(crate) severity_number: Option<Severity>,

/// Record body
pub body: Option<AnyValue>,
pub(crate) body: Option<AnyValue>,

/// Additional attributes associated with this record
pub(crate) attributes: LogRecordAttributes,
Expand Down Expand Up @@ -118,7 +118,56 @@ impl opentelemetry::logs::LogRecord for LogRecord {
}

impl LogRecord {
/// Returns the event name
#[inline]
pub fn event_name(&self) -> Option<&'static str> {
self.event_name
}

/// Returns the target
#[inline]
pub fn target(&self) -> Option<&Cow<'static, str>> {
self.target.as_ref()
}
Copy link
Member Author

@lalitb lalitb Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning &str would simplify the API, but want to preserve the ability for consumers(i.e., exporter) to optimize based on whether the target is a static string.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could favor simplicity of the API here and use &str as the return type. The current exporters that we have cannot utilize the static str reference to their benefit anyway.

Only exporters that would benefit from Cow<'static, str> would be the ones that hold these values in memory for some reason as they could then avoid the cost to clone a static str.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a strong opinion here as it's mainly used by exporters and not end users. We can expect exporter authors to work with Cow<'static,str>.

Copy link
Member Author

@lalitb lalitb Nov 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a strong opinion here as it's mainly used by exporters and not end users. We can expect exporter authors to work with Cow<'static,str>.

Yes, that's what I thought - keeping it for the custom export authors if they want to reap the benefit of static target. Existing exporter (in main and contrib repo) won't get the benefit as they serialize the data to be sent across.


/// Returns the timestamp
#[inline]
pub fn timestamp(&self) -> Option<SystemTime> {
self.timestamp
}

/// Returns the observed timestamp
#[inline]
pub fn observed_timestamp(&self) -> Option<SystemTime> {
self.observed_timestamp
}

/// Returns the trace context
#[inline]
pub fn trace_context(&self) -> Option<&TraceContext> {
self.trace_context.as_ref()
}

/// Returns the severity text
#[inline]
pub fn severity_text(&self) -> Option<&'static str> {
self.severity_text
}

/// Returns the severity number
#[inline]
pub fn severity_number(&self) -> Option<Severity> {
self.severity_number
}

/// Returns the body
#[inline]
pub fn body(&self) -> Option<&AnyValue> {
self.body.as_ref()
}

/// Provides an iterator over the attributes.
#[inline]
pub fn attributes_iter(&self) -> impl Iterator<Item = &(Key, AnyValue)> {
self.attributes.iter().filter_map(|opt| opt.as_ref())
}
Expand Down
16 changes: 8 additions & 8 deletions opentelemetry-stdout/src/logs/exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,34 +69,34 @@ fn print_logs(batch: LogBatch<'_>) {
for (i, log) in batch.iter().enumerate() {
println!("Log #{}", i);
let (record, _library) = log;
if let Some(event_name) = record.event_name {
if let Some(event_name) = record.event_name() {
println!("\t EventName: {:?}", event_name);
}
if let Some(target) = &record.target {
if let Some(target) = record.target() {
println!("\t Target (Scope): {:?}", target);
}
if let Some(trace_context) = &record.trace_context {
if let Some(trace_context) = record.trace_context() {
println!("\t TraceId: {:?}", trace_context.trace_id);
println!("\t SpanId: {:?}", trace_context.span_id);
}
if let Some(timestamp) = record.timestamp {
if let Some(timestamp) = record.timestamp() {
let datetime: DateTime<Utc> = timestamp.into();
println!("\t Timestamp: {}", datetime.format("%Y-%m-%d %H:%M:%S%.6f"));
}
if let Some(timestamp) = record.observed_timestamp {
if let Some(timestamp) = record.observed_timestamp() {
let datetime: DateTime<Utc> = timestamp.into();
println!(
"\t Observed Timestamp: {}",
datetime.format("%Y-%m-%d %H:%M:%S%.6f")
);
}
if let Some(severity) = record.severity_text {
if let Some(severity) = record.severity_text() {
println!("\t SeverityText: {:?}", severity);
}
if let Some(severity) = record.severity_number {
if let Some(severity) = record.severity_number() {
println!("\t SeverityNumber: {:?}", severity);
}
if let Some(body) = &record.body {
if let Some(body) = record.body() {
println!("\t Body: {:?}", body);
}

Expand Down
Loading