Skip to content

Commit aa58f2d

Browse files
feat: unify Azure tags (#1553)
# What does this PR do? Unifies the azure tags used by profiling and tracing # Motivation The tags had diverged, we should have one source of truth. # Additional Notes ## Profiling only: aas.environment.extension_version ## Tracing only: aas.environment.runtime aas.environment.runtime_version aas.environment.function_runtime ## Shared tags aas.resource.id aas.environment.instance_id aas.environment.instance_name aas.environment.os aas.resource.group aas.site.name aas.site.kind aas.site.type aas.subscription.id # How to test the change? Describe here in detail how the change can be validated. Co-authored-by: kathiehuang <kathie.huang@datadoghq.com> Co-authored-by: daniel.schwartznarbonne <daniel.schwartznarbonne@datadoghq.com>
1 parent 367c8b2 commit aa58f2d

File tree

3 files changed

+207
-54
lines changed

3 files changed

+207
-54
lines changed

libdd-common/src/azure_app_services.rs

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,53 @@ impl AzureMetadata {
263263
pub fn get_function_runtime_version(&self) -> &str {
264264
get_value_or_unknown!(self.function_runtime_version)
265265
}
266+
267+
/// Returns Azure App Services tags as an iterator of (tag_name, tag_value) tuples.
268+
/// These tags are specific to Azure App Services.
269+
pub fn get_app_service_tags(&self) -> impl ExactSizeIterator<Item = (&'static str, &str)> {
270+
[
271+
(
272+
"aas.environment.extension_version",
273+
self.get_extension_version(),
274+
),
275+
("aas.environment.instance_id", self.get_instance_id()),
276+
("aas.environment.instance_name", self.get_instance_name()),
277+
("aas.environment.os", self.get_operating_system()),
278+
("aas.resource.group", self.get_resource_group()),
279+
("aas.resource.id", self.get_resource_id()),
280+
("aas.site.kind", self.get_site_kind()),
281+
("aas.site.name", self.get_site_name()),
282+
("aas.site.type", self.get_site_type()),
283+
("aas.subscription.id", self.get_subscription_id()),
284+
]
285+
.into_iter()
286+
}
287+
288+
/// Returns Azure Functions tags as an iterator of (tag_name, tag_value) tuples.
289+
/// These tags are specific to Azure Functions.
290+
pub fn get_function_tags(&self) -> impl ExactSizeIterator<Item = (&'static str, &str)> {
291+
[
292+
("aas.environment.instance_id", self.get_instance_id()),
293+
("aas.environment.instance_name", self.get_instance_name()),
294+
("aas.environment.os", self.get_operating_system()),
295+
("aas.environment.runtime", self.get_runtime()),
296+
(
297+
"aas.environment.runtime_version",
298+
self.get_runtime_version(),
299+
),
300+
(
301+
"aas.environment.function_runtime",
302+
self.get_function_runtime_version(),
303+
),
304+
("aas.resource.group", self.get_resource_group()),
305+
("aas.resource.id", self.get_resource_id()),
306+
("aas.site.kind", self.get_site_kind()),
307+
("aas.site.name", self.get_site_name()),
308+
("aas.site.type", self.get_site_type()),
309+
("aas.subscription.id", self.get_subscription_id()),
310+
]
311+
.into_iter()
312+
}
266313
}
267314

268315
pub static AAS_METADATA: LazyLock<Option<AzureMetadata>> =
@@ -712,6 +759,158 @@ mod tests {
712759
assert_eq!(expected_runtime_version, metadata.get_runtime_version());
713760
}
714761

762+
#[test]
763+
fn test_get_app_service_tags() {
764+
let expected_site_name = "my_site_name";
765+
let expected_resource_group = "my_resource_group";
766+
let expected_site_version = "v42";
767+
let expected_operating_system = "FreeBSD";
768+
let expected_instance_name = "my_instance_name";
769+
let expected_instance_id = "my_instance_id";
770+
let expected_subscription_id = "sub-123";
771+
let expected_resource_id = "/subscriptions/sub-123/resourcegroups/my_resource_group/providers/microsoft.web/sites/my_site_name";
772+
773+
let mocked_env = MockEnv::new(&[
774+
(WEBSITE_SITE_NAME, expected_site_name),
775+
(WEBSITE_RESOURCE_GROUP, expected_resource_group),
776+
(SITE_EXTENSION_VERSION, expected_site_version),
777+
(WEBSITE_OS, expected_operating_system),
778+
(INSTANCE_NAME, expected_instance_name),
779+
(INSTANCE_ID, expected_instance_id),
780+
(SERVICE_CONTEXT, "1"),
781+
(
782+
WEBSITE_OWNER_NAME,
783+
&format!("{}+rg-webspace", expected_subscription_id),
784+
),
785+
]);
786+
787+
let metadata = AzureMetadata::new(mocked_env).unwrap();
788+
789+
// Collect tags into a HashMap for easy lookup
790+
let tags: std::collections::HashMap<&str, &str> = metadata.get_app_service_tags().collect();
791+
792+
// Verify all 10 App Service tags are present
793+
assert_eq!(tags.len(), 10);
794+
assert_eq!(tags.get("aas.resource.id"), Some(&expected_resource_id));
795+
assert_eq!(
796+
tags.get("aas.environment.extension_version"),
797+
Some(&expected_site_version)
798+
);
799+
assert_eq!(
800+
tags.get("aas.environment.instance_id"),
801+
Some(&expected_instance_id)
802+
);
803+
assert_eq!(
804+
tags.get("aas.environment.instance_name"),
805+
Some(&expected_instance_name)
806+
);
807+
assert_eq!(
808+
tags.get("aas.environment.os"),
809+
Some(&expected_operating_system)
810+
);
811+
assert_eq!(
812+
tags.get("aas.resource.group"),
813+
Some(&expected_resource_group)
814+
);
815+
assert_eq!(tags.get("aas.site.name"), Some(&expected_site_name));
816+
assert_eq!(tags.get("aas.site.kind"), Some(&"app"));
817+
assert_eq!(tags.get("aas.site.type"), Some(&"app"));
818+
assert_eq!(
819+
tags.get("aas.subscription.id"),
820+
Some(&expected_subscription_id)
821+
);
822+
823+
// Verify runtime tags are NOT present
824+
assert_eq!(tags.get("aas.environment.runtime"), None);
825+
assert_eq!(tags.get("aas.environment.runtime_version"), None);
826+
assert_eq!(tags.get("aas.environment.function_runtime"), None);
827+
828+
// Verify it's an ExactSizeIterator
829+
let iter = metadata.get_app_service_tags();
830+
assert_eq!(iter.len(), 10);
831+
}
832+
833+
#[test]
834+
fn test_get_function_tags() {
835+
let expected_site_name = "my_site_name";
836+
let expected_resource_group = "my_resource_group";
837+
let expected_operating_system = "FreeBSD";
838+
let expected_instance_name = "my_instance_name";
839+
let expected_instance_id = "my_instance_id";
840+
let expected_function_extension_version = "~4";
841+
let expected_runtime = "node";
842+
let expected_runtime_version = "18";
843+
let expected_subscription_id = "sub-123";
844+
let expected_resource_id = "/subscriptions/sub-123/resourcegroups/my_resource_group/providers/microsoft.web/sites/my_site_name";
845+
846+
let mocked_env = MockEnv::new(&[
847+
(WEBSITE_SITE_NAME, expected_site_name),
848+
(WEBSITE_RESOURCE_GROUP, expected_resource_group),
849+
(WEBSITE_OS, expected_operating_system),
850+
(INSTANCE_NAME, expected_instance_name),
851+
(INSTANCE_ID, expected_instance_id),
852+
(SERVICE_CONTEXT, "1"),
853+
(
854+
FUNCTIONS_EXTENSION_VERSION,
855+
expected_function_extension_version,
856+
),
857+
(FUNCTIONS_WORKER_RUNTIME, expected_runtime),
858+
(FUNCTIONS_WORKER_RUNTIME_VERSION, expected_runtime_version),
859+
(
860+
WEBSITE_OWNER_NAME,
861+
&format!("{}+rg-webspace", expected_subscription_id),
862+
),
863+
]);
864+
865+
let metadata = AzureMetadata::new(mocked_env).unwrap();
866+
867+
// Collect tags into a HashMap for easy lookup
868+
let tags: std::collections::HashMap<&str, &str> = metadata.get_function_tags().collect();
869+
870+
// Verify all 12 Function tags are present
871+
assert_eq!(tags.len(), 12);
872+
assert_eq!(tags.get("aas.resource.id"), Some(&expected_resource_id));
873+
assert_eq!(
874+
tags.get("aas.environment.instance_id"),
875+
Some(&expected_instance_id)
876+
);
877+
assert_eq!(
878+
tags.get("aas.environment.instance_name"),
879+
Some(&expected_instance_name)
880+
);
881+
assert_eq!(
882+
tags.get("aas.environment.os"),
883+
Some(&expected_operating_system)
884+
);
885+
assert_eq!(tags.get("aas.environment.runtime"), Some(&expected_runtime));
886+
assert_eq!(
887+
tags.get("aas.environment.runtime_version"),
888+
Some(&expected_runtime_version)
889+
);
890+
assert_eq!(
891+
tags.get("aas.environment.function_runtime"),
892+
Some(&expected_function_extension_version)
893+
);
894+
assert_eq!(
895+
tags.get("aas.resource.group"),
896+
Some(&expected_resource_group)
897+
);
898+
assert_eq!(tags.get("aas.site.name"), Some(&expected_site_name));
899+
assert_eq!(tags.get("aas.site.kind"), Some(&"functionapp"));
900+
assert_eq!(tags.get("aas.site.type"), Some(&"function"));
901+
assert_eq!(
902+
tags.get("aas.subscription.id"),
903+
Some(&expected_subscription_id)
904+
);
905+
906+
// Verify extension_version tag is NOT present
907+
assert_eq!(tags.get("aas.environment.extension_version"), None);
908+
909+
// Verify it's an ExactSizeIterator
910+
let iter = metadata.get_function_tags();
911+
assert_eq!(iter.len(), 12);
912+
}
913+
715914
#[test]
716915
fn test_get_trimmed_env_var_empty_string() {
717916
env::remove_var("TEST_VAR_NONE");

libdd-profiling/src/exporter/profile_exporter.rs

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -110,31 +110,9 @@ impl ProfileExporter {
110110

111111
// Add Azure App Services tags if available
112112
if let Some(aas) = &*azure_app_services::AAS_METADATA {
113-
let aas_tags = [
114-
("aas.resource.id", aas.get_resource_id()),
115-
(
116-
"aas.environment.extension_version",
117-
aas.get_extension_version(),
118-
),
119-
("aas.environment.instance_id", aas.get_instance_id()),
120-
("aas.environment.instance_name", aas.get_instance_name()),
121-
("aas.environment.os", aas.get_operating_system()),
122-
("aas.resource.group", aas.get_resource_group()),
123-
("aas.site.name", aas.get_site_name()),
124-
("aas.site.kind", aas.get_site_kind()),
125-
("aas.site.type", aas.get_site_type()),
126-
("aas.subscription.id", aas.get_subscription_id()),
127-
];
128-
129-
// Avoid infallible allocation paths when adding the Azure tags.
130-
// This is an upper bound since Tag::new can fail and we'll skip invalid tags.
131-
tags.try_reserve(aas_tags.len())?;
132-
133-
tags.extend(
134-
aas_tags
135-
.into_iter()
136-
.filter_map(|(name, value)| Tag::new(name, value).ok()),
137-
);
113+
let aas_tags_iter = aas.get_app_service_tags();
114+
tags.try_reserve(aas_tags_iter.len())?;
115+
tags.extend(aas_tags_iter.filter_map(|(name, value)| Tag::new(name, value).ok()));
138116
}
139117

140118
// Precompute the base tags string (includes configured tags + Azure App Services tags)

libdd-trace-utils/src/trace_utils.rs

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -555,35 +555,11 @@ pub fn enrich_span_with_azure_function_metadata(span: &mut pb::Span) {
555555
}
556556

557557
if let Some(aas_metadata) = &*azure_app_services::AAS_METADATA_FUNCTION {
558-
let aas_tags = [
559-
("aas.resource.id", aas_metadata.get_resource_id()),
560-
(
561-
"aas.environment.instance_id",
562-
aas_metadata.get_instance_id(),
563-
),
564-
(
565-
"aas.environment.instance_name",
566-
aas_metadata.get_instance_name(),
567-
),
568-
("aas.subscription.id", aas_metadata.get_subscription_id()),
569-
("aas.environment.os", aas_metadata.get_operating_system()),
570-
("aas.environment.runtime", aas_metadata.get_runtime()),
571-
(
572-
"aas.environment.runtime_version",
573-
aas_metadata.get_runtime_version(),
574-
),
575-
(
576-
"aas.environment.function_runtime",
577-
aas_metadata.get_function_runtime_version(),
578-
),
579-
("aas.resource.group", aas_metadata.get_resource_group()),
580-
("aas.site.name", aas_metadata.get_site_name()),
581-
("aas.site.kind", aas_metadata.get_site_kind()),
582-
("aas.site.type", aas_metadata.get_site_type()),
583-
];
584-
aas_tags.into_iter().for_each(|(name, value)| {
585-
span.meta.insert(name.to_string(), value.to_string());
586-
});
558+
span.meta.extend(
559+
aas_metadata
560+
.get_function_tags()
561+
.map(|(name, value)| (name.to_string(), value.to_string())),
562+
);
587563
}
588564
}
589565

0 commit comments

Comments
 (0)