@@ -284,7 +284,13 @@ impl Processor {
284284 ///
285285 /// This is used to create a cold start span, since this telemetry event does not
286286 /// provide a `request_id`, we try to guess which invocation is the cold start.
287- pub fn on_platform_init_start ( & mut self , time : DateTime < Utc > ) {
287+ pub fn on_platform_init_start ( & mut self , time : DateTime < Utc > , runtime_version : Option < String > ) {
288+ if runtime_version
289+ . as_deref ( )
290+ . is_some_and ( |rv| rv. contains ( "DurableFunction" ) )
291+ {
292+ self . enhanced_metrics . set_durable_function_tag ( ) ;
293+ }
288294 let start_time: i64 = SystemTime :: from ( time)
289295 . duration_since ( UNIX_EPOCH )
290296 . expect ( "time went backwards" )
@@ -1714,6 +1720,108 @@ mod tests {
17141720 ) ,
17151721 }
17161722
1723+ #[ tokio:: test]
1724+ async fn test_on_platform_init_start_sets_durable_function_tag ( ) {
1725+ let mut processor = setup ( ) ;
1726+ let time = Utc :: now ( ) ;
1727+
1728+ processor. on_platform_init_start (
1729+ time,
1730+ Some ( "python:3.14.DurableFunction.v6" . to_string ( ) ) ,
1731+ ) ;
1732+
1733+ let now: i64 = std:: time:: UNIX_EPOCH
1734+ . elapsed ( )
1735+ . expect ( "unable to poll clock, unrecoverable" )
1736+ . as_secs ( )
1737+ . try_into ( )
1738+ . unwrap_or_default ( ) ;
1739+ processor. enhanced_metrics . increment_invocation_metric ( now) ;
1740+
1741+ let ts = ( now / 10 ) * 10 ;
1742+ let durable_tags = dogstatsd:: metric:: SortedTags :: parse ( "durable_function:true" ) . ok ( ) ;
1743+ let entry = processor
1744+ . enhanced_metrics
1745+ . aggr_handle
1746+ . get_entry_by_id (
1747+ crate :: metrics:: enhanced:: constants:: INVOCATIONS_METRIC . into ( ) ,
1748+ durable_tags,
1749+ ts,
1750+ )
1751+ . await
1752+ . unwrap ( ) ;
1753+ assert ! (
1754+ entry. is_some( ) ,
1755+ "Expected durable_function:true tag on enhanced metric"
1756+ ) ;
1757+ }
1758+
1759+ #[ tokio:: test]
1760+ async fn test_on_platform_init_start_no_durable_function_tag_for_regular_runtime ( ) {
1761+ let mut processor = setup ( ) ;
1762+ let time = Utc :: now ( ) ;
1763+
1764+ processor. on_platform_init_start ( time, Some ( "python:3.12.v10" . to_string ( ) ) ) ;
1765+
1766+ let now: i64 = std:: time:: UNIX_EPOCH
1767+ . elapsed ( )
1768+ . expect ( "unable to poll clock, unrecoverable" )
1769+ . as_secs ( )
1770+ . try_into ( )
1771+ . unwrap_or_default ( ) ;
1772+ processor. enhanced_metrics . increment_invocation_metric ( now) ;
1773+
1774+ let ts = ( now / 10 ) * 10 ;
1775+ let durable_tags = dogstatsd:: metric:: SortedTags :: parse ( "durable_function:true" ) . ok ( ) ;
1776+ let entry = processor
1777+ . enhanced_metrics
1778+ . aggr_handle
1779+ . get_entry_by_id (
1780+ crate :: metrics:: enhanced:: constants:: INVOCATIONS_METRIC . into ( ) ,
1781+ durable_tags,
1782+ ts,
1783+ )
1784+ . await
1785+ . unwrap ( ) ;
1786+ assert ! (
1787+ entry. is_none( ) ,
1788+ "Expected no durable_function:true tag for regular runtime"
1789+ ) ;
1790+ }
1791+
1792+ #[ tokio:: test]
1793+ async fn test_on_platform_init_start_no_durable_function_tag_when_runtime_version_is_none ( ) {
1794+ let mut processor = setup ( ) ;
1795+ let time = Utc :: now ( ) ;
1796+
1797+ processor. on_platform_init_start ( time, None ) ;
1798+
1799+ let now: i64 = std:: time:: UNIX_EPOCH
1800+ . elapsed ( )
1801+ . expect ( "unable to poll clock, unrecoverable" )
1802+ . as_secs ( )
1803+ . try_into ( )
1804+ . unwrap_or_default ( ) ;
1805+ processor. enhanced_metrics . increment_invocation_metric ( now) ;
1806+
1807+ let ts = ( now / 10 ) * 10 ;
1808+ let durable_tags = dogstatsd:: metric:: SortedTags :: parse ( "durable_function:true" ) . ok ( ) ;
1809+ let entry = processor
1810+ . enhanced_metrics
1811+ . aggr_handle
1812+ . get_entry_by_id (
1813+ crate :: metrics:: enhanced:: constants:: INVOCATIONS_METRIC . into ( ) ,
1814+ durable_tags,
1815+ ts,
1816+ )
1817+ . await
1818+ . unwrap ( ) ;
1819+ assert ! (
1820+ entry. is_none( ) ,
1821+ "Expected no durable_function:true tag when runtime_version is None"
1822+ ) ;
1823+ }
1824+
17171825 #[ tokio:: test]
17181826 async fn test_is_managed_instance_mode_returns_true ( ) {
17191827 use crate :: config:: aws:: LAMBDA_MANAGED_INSTANCES_INIT_TYPE ;
0 commit comments