Skip to content

Commit b9c4f25

Browse files
Fixed issues validating tracing pages which were converted to page iterators (#3311)
- Re-add the span when converting from `Init` state on a continuation token; - Cleaned up lifetime of `MockSpan` to have it be dropped when the actual span goes out of scope (also verified that the same "end on drop" behavior occurs with an OpenTelemetry `Span`). - Added a `Debug` requirement for the `C` parameter so it can be printed successfully. - Added a simple test for verifying the spans coming from an `ItemIterator` converted immediately to a `PageIterator`. Created as Draft so it doesn't conflict with releases of various non-core crates. --------- Co-authored-by: Copilot <[email protected]>
1 parent 8dfa19b commit b9c4f25

File tree

9 files changed

+407
-149
lines changed

9 files changed

+407
-149
lines changed

sdk/core/azure_core/src/http/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub use response::{AsyncRawResponse, AsyncResponse, RawResponse, Response};
2323
pub use typespec_client_core::http::response;
2424
pub use typespec_client_core::http::{
2525
new_http_client, AppendToUrlQuery, Context, DeserializeWith, Format, HttpClient, JsonFormat,
26-
Method, NoFormat, StatusCode, Url, UrlExt,
26+
Method, NoFormat, Sanitizer, StatusCode, Url, UrlExt,
2727
};
2828

2929
pub use crate::error::check_success;

sdk/core/azure_core/src/http/pager.rs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -811,14 +811,33 @@ impl<P> fmt::Debug for PageIterator<P> {
811811
}
812812
}
813813

814-
#[derive(Debug, Clone, Eq)]
815-
enum State<C> {
814+
#[derive(Clone, Eq)]
815+
enum State<C>
816+
where
817+
C: AsRef<str>,
818+
{
816819
Init,
817820
More(C),
818821
Done,
819822
}
820823

821-
impl<C> PartialEq for State<C> {
824+
impl<C> fmt::Debug for State<C>
825+
where
826+
C: AsRef<str>,
827+
{
828+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
829+
match self {
830+
State::Init => write!(f, "Init"),
831+
State::More(c) => f.debug_tuple("More").field(&c.as_ref()).finish(),
832+
State::Done => write!(f, "Done"),
833+
}
834+
}
835+
}
836+
837+
impl<C> PartialEq for State<C>
838+
where
839+
C: AsRef<str>,
840+
{
822841
fn eq(&self, other: &Self) -> bool {
823842
// Only needs to compare if both states are Init or Done; internally, we don't care about any other states.
824843
matches!(
@@ -829,7 +848,10 @@ impl<C> PartialEq for State<C> {
829848
}
830849

831850
#[derive(Debug)]
832-
struct StreamState<'a, C, F> {
851+
struct StreamState<'a, C, F>
852+
where
853+
C: AsRef<str>,
854+
{
833855
state: State<C>,
834856
make_request: F,
835857
continuation_token: Arc<Mutex<Option<String>>>,
@@ -863,9 +885,21 @@ where
863885
added_span: false,
864886
},
865887
|mut stream_state| async move {
888+
// When in the "Init" state, we are either starting fresh or resuming from a continuation token. In either case,
889+
// attach a span to the context for the entire paging operation.
890+
if stream_state.state == State::Init {
891+
tracing::debug!("establish a public API span for new pager.");
892+
893+
// At the very start of polling, create a span for the entire request, and attach it to the context
894+
let span = create_public_api_span(&stream_state.ctx, None, None);
895+
if let Some(ref s) = span {
896+
stream_state.added_span = true;
897+
stream_state.ctx = stream_state.ctx.with_value(s.clone());
898+
}
899+
}
900+
866901
// Get the `continuation_token` to pick up where we left off, or None for the initial page,
867902
// but don't override the terminal `State::Done`.
868-
869903
if stream_state.state != State::Done {
870904
let result = match stream_state.continuation_token.lock() {
871905
Ok(next_token) => match next_token.as_deref() {
@@ -895,12 +929,6 @@ where
895929
let result = match stream_state.state {
896930
State::Init => {
897931
tracing::debug!("initial page request");
898-
// At the very start of polling, create a span for the entire request, and attach it to the context
899-
let span = create_public_api_span(&stream_state.ctx, None, None);
900-
if let Some(ref s) = span {
901-
stream_state.added_span = true;
902-
stream_state.ctx = stream_state.ctx.with_value(s.clone());
903-
}
904932
(stream_state.make_request)(PagerState::Initial, stream_state.ctx.clone()).await
905933
}
906934
State::More(n) => {

sdk/core/azure_core/src/http/policies/instrumentation/public_api_instrumentation.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -555,8 +555,7 @@ mod tests {
555555
status: SpanStatus::Unset,
556556
kind: SpanKind::Internal,
557557
span_id: Uuid::new_v4(),
558-
parent_id: None,
559-
attributes: vec![],
558+
..Default::default()
560559
}],
561560
}],
562561
)
@@ -599,9 +598,9 @@ mod tests {
599598
span_name: "MyClient.MyApi",
600599
status: SpanStatus::Unset,
601600
span_id: Uuid::new_v4(),
602-
parent_id: None,
603601
kind: SpanKind::Internal,
604602
attributes: vec![(AZ_NAMESPACE_ATTRIBUTE, "test namespace".into())],
603+
..Default::default()
605604
}],
606605
}],
607606
);
@@ -652,6 +651,7 @@ mod tests {
652651
(AZ_NAMESPACE_ATTRIBUTE, "test namespace".into()),
653652
(ERROR_TYPE_ATTRIBUTE, "500".into()),
654653
],
654+
..Default::default()
655655
}],
656656
}],
657657
);
@@ -701,6 +701,7 @@ mod tests {
701701
(AZ_NAMESPACE_ATTRIBUTE, "test.namespace".into()),
702702
("az.fake_attribute", "attribute value".into()),
703703
],
704+
..Default::default()
704705
},
705706
ExpectedSpanInformation {
706707
span_name: "PUT",
@@ -716,6 +717,7 @@ mod tests {
716717
("server.port", 80.into()),
717718
("http.response.status_code", 200.into()),
718719
],
720+
..Default::default()
719721
},
720722
],
721723
}],

sdk/core/azure_core/src/http/policies/instrumentation/request_instrumentation.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ pub(crate) mod tests {
302302
),
303303
),
304304
],
305+
..Default::default()
305306
}],
306307
}],
307308
);
@@ -388,6 +389,7 @@ pub(crate) mod tests {
388389
AttributeValue::from("https://example.com/client_request_id"),
389390
),
390391
],
392+
..Default::default()
391393
}],
392394
}],
393395
);
@@ -433,6 +435,7 @@ pub(crate) mod tests {
433435
(SERVER_ADDRESS_ATTRIBUTE, AttributeValue::from("host")),
434436
(SERVER_PORT_ATTRIBUTE, AttributeValue::from(8080)),
435437
],
438+
..Default::default()
436439
}],
437440
}],
438441
);
@@ -502,6 +505,7 @@ pub(crate) mod tests {
502505
AttributeValue::from("https://microsoft.com/request_failed.htm"),
503506
),
504507
],
508+
..Default::default()
505509
}],
506510
}],
507511
);

sdk/core/azure_core_opentelemetry/tests/telemetry_service_macros.rs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -685,10 +685,7 @@ mod tests {
685685
let package_version = env!("CARGO_PKG_VERSION").to_string();
686686
azure_core_test::tracing::assert_instrumentation_information(
687687
|tracer_provider| Ok(create_service_client(&ctx, tracer_provider)),
688-
|client| {
689-
let client = client;
690-
Box::pin(async move { client.get("get", None).await })
691-
},
688+
async move |client| client.get("get", None).await,
692689
ExpectedInstrumentation {
693690
package_name,
694691
package_version,
@@ -706,14 +703,11 @@ mod tests {
706703

707704
#[recorded::test()]
708705
async fn test_function_tracing_tests(ctx: TestContext) -> Result<()> {
709-
let package_name = env!("CARGO_PKG_NAME").to_string();
706+
let package_name = ctx.recording().var("CARGO_PKG_NAME", None).to_string();
710707
let package_version = env!("CARGO_PKG_VERSION").to_string();
711708
azure_core_test::tracing::assert_instrumentation_information(
712709
|tracer_provider| Ok(create_service_client(&ctx, tracer_provider)),
713-
|client| {
714-
let client = client;
715-
Box::pin(async move { client.get_with_function_tracing("get", None).await })
716-
},
710+
async move |client| client.get_with_function_tracing("get", None).await,
717711
ExpectedInstrumentation {
718712
package_name,
719713
package_version,
@@ -737,14 +731,11 @@ mod tests {
737731
async fn test_function_tracing_tests_error(ctx: TestContext) -> Result<()> {
738732
use azure_core_test::tracing::ExpectedRestApiSpan;
739733

740-
let package_name = env!("CARGO_PKG_NAME").to_string();
734+
let package_name = ctx.recording().var("CARGO_PKG_NAME", None).to_string();
741735
let package_version = env!("CARGO_PKG_VERSION").to_string();
742736
azure_core_test::tracing::assert_instrumentation_information(
743737
|tracer_provider| Ok(create_service_client(&ctx, tracer_provider)),
744-
|client| {
745-
let client = client;
746-
Box::pin(async move { client.get_with_function_tracing("index.htm", None).await })
747-
},
738+
async move |client| client.get_with_function_tracing("index.htm", None).await,
748739
ExpectedInstrumentation {
749740
package_name,
750741
package_version,

0 commit comments

Comments
 (0)