2323import java .util .List ;
2424import java .util .Map ;
2525import java .util .Set ;
26+ import java .util .regex .Pattern ;
27+ import java .util .regex .PatternSyntaxException ;
2628import org .assertj .core .api .ThrowingConsumer ;
2729import org .junit .jupiter .api .AfterAll ;
2830import org .junit .jupiter .api .BeforeAll ;
@@ -42,7 +44,10 @@ public abstract class AwsSdkBaseTest extends ContractTestBase {
4244 LocalStackContainer .Service .S3 ,
4345 LocalStackContainer .Service .DYNAMODB ,
4446 LocalStackContainer .Service .SQS ,
45- LocalStackContainer .Service .KINESIS )
47+ LocalStackContainer .Service .KINESIS ,
48+ LocalStackContainer .Service .SECRETSMANAGER ,
49+ LocalStackContainer .Service .IAM ,
50+ LocalStackContainer .Service .STEPFUNCTIONS )
4651 .withEnv ("DEFAULT_REGION" , "us-west-2" )
4752 .withNetwork (network )
4853 .withEnv ("LOCALSTACK_HOST" , "127.0.0.1" )
@@ -102,6 +107,10 @@ protected String getApplicationWaitPattern() {
102107
103108 protected abstract String getBedrockAgentRuntimeSpanNamePrefix ();
104109
110+ protected abstract String getSecretsManagerSpanNamePrefix ();
111+
112+ protected abstract String getStepFunctionsSpanNamePrefix ();
113+
105114 protected abstract String getS3RpcServiceName ();
106115
107116 protected abstract String getDynamoDbRpcServiceName ();
@@ -118,6 +127,10 @@ protected String getApplicationWaitPattern() {
118127
119128 protected abstract String getBedrockAgentRuntimeRpcServiceName ();
120129
130+ protected abstract String getSecretsManagerRpcServiceName ();
131+
132+ protected abstract String getStepFunctionsRpcServiceName ();
133+
121134 private String getS3ServiceName () {
122135 return "AWS::S3" ;
123136 }
@@ -150,6 +163,14 @@ private String getBedrockRuntimeServiceName() {
150163 return "AWS::BedrockRuntime" ;
151164 }
152165
166+ private String getSecretsManagerServiceName () {
167+ return "AWS::SecretsManager" ;
168+ }
169+
170+ private String getStepFunctionsServiceName () {
171+ return "AWS::StepFunctions" ;
172+ }
173+
153174 private String s3SpanName (String operation ) {
154175 return String .format ("%s.%s" , getS3SpanNamePrefix (), operation );
155176 }
@@ -182,10 +203,41 @@ private String bedrockAgentRuntimeSpanName(String operation) {
182203 return String .format ("%s.%s" , getBedrockAgentRuntimeSpanNamePrefix (), operation );
183204 }
184205
206+ private String secretsManagerSpanName (String operation ) {
207+ return String .format ("%s.%s" , getSecretsManagerSpanNamePrefix (), operation );
208+ }
209+
210+ private String stepFunctionsSpanName (String operation ) {
211+ return String .format ("%s.%s" , getStepFunctionsSpanNamePrefix (), operation );
212+ }
213+
214+ private boolean isValidRegex (String pattern ) {
215+ try {
216+ Pattern .compile (pattern );
217+ return true ;
218+ } catch (PatternSyntaxException e ) {
219+ return false ;
220+ }
221+ }
222+
185223 protected ThrowingConsumer <KeyValue > assertAttribute (String key , String value ) {
186224 return (attribute ) -> {
187225 assertThat (attribute .getKey ()).isEqualTo (key );
188- assertThat (attribute .getValue ().getStringValue ()).isEqualTo (value );
226+ var actualValue = attribute .getValue ().getStringValue ();
227+
228+ if (isValidRegex (value )) {
229+ System .out .println ("ASSERTING REGEX: " + actualValue + " equivalent to " + value );
230+ assertThat (actualValue ).matches (value );
231+ if (!actualValue .matches (value )) {
232+ System .out .println ("ASSERTION FAILED between: " + actualValue + " and " + value );
233+ }
234+ } else {
235+ System .out .println ("ASSERTING EXACT: " + actualValue + " equivalent to " + value );
236+ assertThat (actualValue ).isEqualTo (value );
237+ if (!actualValue .equals (value )) {
238+ System .out .println ("ASSERTION FAILED between: " + actualValue + " and " + value );
239+ }
240+ }
189241 };
190242 }
191243
@@ -413,13 +465,14 @@ private void assertAwsAttributes(
413465 .satisfiesOnlyOnce (assertAttribute (AppSignalsConstants .AWS_REMOTE_OPERATION , operation ))
414466 .satisfiesOnlyOnce (assertAttribute (AppSignalsConstants .AWS_REMOTE_SERVICE , service ))
415467 .satisfiesOnlyOnce (assertAttribute (AppSignalsConstants .AWS_SPAN_KIND , spanKind ));
416- if (type != null && identifier != null ) {
468+ if (type != null && identifier != null && clouformationIdentifier != null ) {
417469 assertions .satisfiesOnlyOnce (
418470 assertAttribute (AppSignalsConstants .AWS_REMOTE_RESOURCE_TYPE , type ));
419471 assertions .satisfiesOnlyOnce (
420472 assertAttribute (AppSignalsConstants .AWS_REMOTE_RESOURCE_IDENTIFIER , identifier ));
421473 assertions .satisfiesOnlyOnce (
422- assertAttribute (AppSignalsConstants .AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER , clouformationIdentifier ));
474+ assertAttribute (
475+ AppSignalsConstants .AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER , clouformationIdentifier ));
423476 }
424477 }
425478
@@ -1995,7 +2048,8 @@ protected void doTestBedrockGuardrailId() {
19952048 var localOperation = "GET /bedrock/getguardrail" ;
19962049 String type = "AWS::Bedrock::Guardrail" ;
19972050 String identifier = "test-bedrock-guardrail" ;
1998- String cloudformationIdentifier = "arn:aws:bedrock:us-east-1:000000000000:guardrail/test-bedrock-guardrail" ;
2051+ String cloudformationIdentifier =
2052+ "arn:aws:bedrock:us-east-1:000000000000:guardrail/test-bedrock-guardrail" ;
19992053 assertSpanClientAttributes (
20002054 traces ,
20012055 bedrockSpanName ("GetGuardrail" ),
@@ -2015,7 +2069,8 @@ protected void doTestBedrockGuardrailId() {
20152069 assertAttribute (
20162070 SemanticConventionsConstants .AWS_GUARDRAIL_ID , "test-bedrock-guardrail" ),
20172071 assertAttribute (
2018- SemanticConventionsConstants .AWS_GUARDRAIL_ARN , "arn:aws:bedrock:us-east-1:000000000000:guardrail/test-bedrock-guardrail" )));
2072+ SemanticConventionsConstants .AWS_GUARDRAIL_ARN ,
2073+ "arn:aws:bedrock:us-east-1:000000000000:guardrail/test-bedrock-guardrail" )));
20192074 assertMetricClientAttributes (
20202075 metrics ,
20212076 AppSignalsConstants .LATENCY_METRIC ,
@@ -2185,4 +2240,182 @@ protected void doTestBedrockAgentRuntimeKnowledgeBaseId() {
21852240 cloudformationIdentifier ,
21862241 0.0 );
21872242 }
2243+
2244+ protected void doTestSecretsManagerDescribeSecret () throws Exception {
2245+ appClient .get ("/secretsmanager/describesecret/test-secret-id" ).aggregate ().join ();
2246+ var traces = mockCollectorClient .getTraces ();
2247+ var metrics =
2248+ mockCollectorClient .getMetrics (
2249+ Set .of (
2250+ AppSignalsConstants .ERROR_METRIC ,
2251+ AppSignalsConstants .FAULT_METRIC ,
2252+ AppSignalsConstants .LATENCY_METRIC ));
2253+ var localService = getApplicationOtelServiceName ();
2254+ var localOperation = "GET /secretsmanager/describesecret/:secretId" ;
2255+ var type = "AWS::SecretsManager::Secret" ;
2256+ var identifier = "test-secret-id-[A-Za-z0-9]{6}" ;
2257+ var cloudformationIdentifier =
2258+ "arn:aws:secretsmanager:us-west-2:000000000000:secret:test-secret-id-[A-Za-z0-9]{6}" ;
2259+
2260+ assertSpanClientAttributes (
2261+ traces ,
2262+ secretsManagerSpanName ("DescribeSecret" ),
2263+ getSecretsManagerRpcServiceName (),
2264+ localService ,
2265+ localOperation ,
2266+ getSecretsManagerServiceName (),
2267+ "DescribeSecret" ,
2268+ type ,
2269+ identifier ,
2270+ cloudformationIdentifier ,
2271+ "localstack" ,
2272+ 4566 ,
2273+ "http://localstack:4566" ,
2274+ 200 ,
2275+ List .of (
2276+ assertAttribute (
2277+ SemanticConventionsConstants .AWS_SECRET_ARN ,
2278+ "arn:aws:secretsmanager:us-west-2:000000000000:secret:test-secret-id-[A-Za-z0-9]{6}" )));
2279+ assertMetricClientAttributes (
2280+ metrics ,
2281+ AppSignalsConstants .LATENCY_METRIC ,
2282+ localService ,
2283+ localOperation ,
2284+ getSecretsManagerServiceName (),
2285+ "DescribeSecret" ,
2286+ type ,
2287+ identifier ,
2288+ cloudformationIdentifier ,
2289+ 5000.0 );
2290+ assertMetricClientAttributes (
2291+ metrics ,
2292+ AppSignalsConstants .FAULT_METRIC ,
2293+ localService ,
2294+ localOperation ,
2295+ getSecretsManagerServiceName (),
2296+ "DescribeSecret" ,
2297+ type ,
2298+ identifier ,
2299+ cloudformationIdentifier ,
2300+ 0.0 );
2301+ assertMetricClientAttributes (
2302+ metrics ,
2303+ AppSignalsConstants .ERROR_METRIC ,
2304+ localService ,
2305+ localOperation ,
2306+ getSecretsManagerServiceName (),
2307+ "DescribeSecret" ,
2308+ type ,
2309+ identifier ,
2310+ cloudformationIdentifier ,
2311+ 0.0 );
2312+ }
2313+
2314+ protected void doTestStepFunctionsDescribeStateMachine () throws Exception {
2315+ appClient .get ("/sfn/describestatemachine/test-state-machine" ).aggregate ().join ();
2316+ var traces = mockCollectorClient .getTraces ();
2317+ var metrics =
2318+ mockCollectorClient .getMetrics (
2319+ Set .of (
2320+ AppSignalsConstants .ERROR_METRIC ,
2321+ AppSignalsConstants .FAULT_METRIC ,
2322+ AppSignalsConstants .LATENCY_METRIC ));
2323+
2324+ var localService = getApplicationOtelServiceName ();
2325+ var localOperation = "GET /sfn/describestatemachine/:name" ;
2326+ var type = "AWS::StepFunctions::StateMachine" ;
2327+ var identifier = "test-state-machine" ;
2328+ var cloudformationIdentifier =
2329+ "arn:aws:states:us-west-2:000000000000:stateMachine:test-state-machine" ;
2330+
2331+ assertSpanClientAttributes (
2332+ traces ,
2333+ stepFunctionsSpanName ("DescribeStateMachine" ),
2334+ getStepFunctionsRpcServiceName (),
2335+ localService ,
2336+ localOperation ,
2337+ getStepFunctionsServiceName (),
2338+ "DescribeStateMachine" ,
2339+ type ,
2340+ identifier ,
2341+ cloudformationIdentifier ,
2342+ "localstack" ,
2343+ 4566 ,
2344+ "http://localstack:4566" ,
2345+ 200 ,
2346+ List .of (
2347+ assertAttribute (
2348+ SemanticConventionsConstants .AWS_STATE_MACHINE_ARN ,
2349+ "arn:aws:states:us-west-2:000000000000:stateMachine:test-state-machine" )));
2350+ assertMetricClientAttributes (
2351+ metrics ,
2352+ AppSignalsConstants .LATENCY_METRIC ,
2353+ localService ,
2354+ localOperation ,
2355+ getStepFunctionsServiceName (),
2356+ "DescribeStateMachine" ,
2357+ type ,
2358+ identifier ,
2359+ cloudformationIdentifier ,
2360+ 5000.0 );
2361+ assertMetricClientAttributes (
2362+ metrics ,
2363+ AppSignalsConstants .FAULT_METRIC ,
2364+ localService ,
2365+ localOperation ,
2366+ getStepFunctionsServiceName (),
2367+ "DescribeStateMachine" ,
2368+ type ,
2369+ identifier ,
2370+ cloudformationIdentifier ,
2371+ 0.0 );
2372+ assertMetricClientAttributes (
2373+ metrics ,
2374+ AppSignalsConstants .ERROR_METRIC ,
2375+ localService ,
2376+ localOperation ,
2377+ getStepFunctionsServiceName (),
2378+ "DescribeStateMachine" ,
2379+ type ,
2380+ identifier ,
2381+ cloudformationIdentifier ,
2382+ 0.0 );
2383+ }
2384+
2385+ protected void doTestStepFunctionsDescribeActivity () throws Exception {
2386+ appClient .get ("/sfn/describeactivity/test-activity" ).aggregate ().join ();
2387+ var traces = mockCollectorClient .getTraces ();
2388+ var metrics = mockCollectorClient .getMetrics (
2389+ Set .of (
2390+ AppSignalsConstants .ERROR_METRIC ,
2391+ AppSignalsConstants .FAULT_METRIC ,
2392+ AppSignalsConstants .LATENCY_METRIC ));
2393+
2394+ var localService = getApplicationOtelServiceName ();
2395+ var localOperation = "GET /sfn/describeactivity/:name" ;
2396+ var type = "AWS::StepFunctions::Activity" ;
2397+ var identifier = "test-activity" ;
2398+ var cloudformationIdentifier = "arn:aws:states:us-west-2:000000000000:activity:test-activity" ;
2399+
2400+ assertSpanClientAttributes (
2401+ traces ,
2402+ stepFunctionsSpanName ("DescribeActivity" ),
2403+ getStepFunctionsRpcServiceName (),
2404+ localService ,
2405+ localOperation ,
2406+ getStepFunctionsServiceName (),
2407+ "DescribeActivity" ,
2408+ type ,
2409+ identifier ,
2410+ cloudformationIdentifier ,
2411+ "localstack" ,
2412+ 4566 ,
2413+ "http://localstack:4566" ,
2414+ 200 ,
2415+ List .of (
2416+ assertAttribute (
2417+ SemanticConventionsConstants .AWS_ACTIVITY_ARN ,
2418+ "arn:aws:states:us-west-2:000000000000:activity:test-activity" )));
2419+
2420+ }
21882421}
0 commit comments