Skip to content

Commit

Permalink
feat(stepfunctions): support X-Ray tracing (#10371) (#10374)
Browse files Browse the repository at this point in the history
closes #10371

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
humanzz authored Sep 18, 2020
1 parent 9d6817f commit ad011c0
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 28 deletions.
16 changes: 16 additions & 0 deletions packages/@aws-cdk/aws-stepfunctions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,22 @@ new stepfunctions.StateMachine(stack, 'MyStateMachine', {
});
```

## X-Ray tracing

Enable X-Ray tracing for StateMachine:

```ts
const logGroup = new logs.LogGroup(stack, 'MyLogGroup');

new stepfunctions.StateMachine(stack, 'MyStateMachine', {
definition: stepfunctions.Chain.start(new stepfunctions.Pass(stack, 'Pass')),
tracingEnabled: true
});
```

See [the AWS documentation](https://docs.aws.amazon.com/step-functions/latest/dg/concepts-xray-tracing.html)
to learn more about AWS Step Functions's X-Ray support.

## State Machine Permission Grants

IAM roles, users, or groups which need to be able to work with a State Machine should be granted IAM permissions.
Expand Down
75 changes: 48 additions & 27 deletions packages/@aws-cdk/aws-stepfunctions/lib/state-machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ export interface StateMachineProps {
* @default No logging
*/
readonly logs?: LogOptions;

/**
* Specifies whether Amazon X-Ray tracing is enabled for this state machine.
*
* @default false
*/
readonly tracingEnabled?: boolean;
}

/**
Expand Down Expand Up @@ -272,37 +279,13 @@ export class StateMachine extends StateMachineBase {

this.stateMachineType = props.stateMachineType ? props.stateMachineType : StateMachineType.STANDARD;

let loggingConfiguration: CfnStateMachine.LoggingConfigurationProperty | undefined;
if (props.logs) {
const conf = props.logs;
loggingConfiguration = {
destinations: [{ cloudWatchLogsLogGroup: { logGroupArn: conf.destination.logGroupArn } }],
includeExecutionData: conf.includeExecutionData,
level: conf.level || 'ERROR',
};
// https://docs.aws.amazon.com/step-functions/latest/dg/cw-logs.html#cloudwatch-iam-policy
this.addToRolePolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
'logs:CreateLogDelivery',
'logs:GetLogDelivery',
'logs:UpdateLogDelivery',
'logs:DeleteLogDelivery',
'logs:ListLogDeliveries',
'logs:PutResourcePolicy',
'logs:DescribeResourcePolicies',
'logs:DescribeLogGroups',
],
resources: ['*'],
}));
}

const resource = new CfnStateMachine(this, 'Resource', {
stateMachineName: this.physicalName,
stateMachineType: props.stateMachineType ? props.stateMachineType : undefined,
roleArn: this.role.roleArn,
definitionString: Stack.of(this).toJsonString(graph.toGraphJson()),
loggingConfiguration,
loggingConfiguration: props.logs ? this.buildLoggingConfiguration(props.logs) : undefined,
tracingConfiguration: props.tracingEnabled ? this.buildTracingConfiguration() : undefined,
});

resource.node.addDependency(this.role);
Expand All @@ -324,7 +307,7 @@ export class StateMachine extends StateMachineBase {
* Add the given statement to the role's policy
*/
public addToRolePolicy(statement: iam.PolicyStatement) {
this.role.addToPolicy(statement);
this.role.addToPrincipalPolicy(statement);
}

/**
Expand Down Expand Up @@ -404,6 +387,44 @@ export class StateMachine extends StateMachineBase {
public metricTime(props?: cloudwatch.MetricOptions): cloudwatch.Metric {
return this.metric('ExecutionTime', props);
}

private buildLoggingConfiguration(logOptions: LogOptions): CfnStateMachine.LoggingConfigurationProperty {
// https://docs.aws.amazon.com/step-functions/latest/dg/cw-logs.html#cloudwatch-iam-policy
this.addToRolePolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
'logs:CreateLogDelivery',
'logs:GetLogDelivery',
'logs:UpdateLogDelivery',
'logs:DeleteLogDelivery',
'logs:ListLogDeliveries',
'logs:PutResourcePolicy',
'logs:DescribeResourcePolicies',
'logs:DescribeLogGroups',
],
resources: ['*'],
}));

return {
destinations: [{
cloudWatchLogsLogGroup: { logGroupArn: logOptions.destination.logGroupArn },
}],
includeExecutionData: logOptions.includeExecutionData,
level: logOptions.level || 'ERROR',
};
}

private buildTracingConfiguration(): CfnStateMachine.TracingConfigurationProperty {
this.addToRolePolicy(new iam.PolicyStatement({
// https://docs.aws.amazon.com/xray/latest/devguide/security_iam_id-based-policy-examples.html#xray-permissions-resources
actions: ['xray:PutTraceSegments', 'xray:PutTelemetryRecords'],
resources: ['*'],
}));

return {
enabled: true,
};
}
}

/**
Expand Down
40 changes: 39 additions & 1 deletion packages/@aws-cdk/aws-stepfunctions/test/state-machine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,42 @@ describe('State Machine', () => {
});
});

});
test('tracing configuration', () => {
// GIVEN
const stack = new cdk.Stack();

// WHEN
new stepfunctions.StateMachine(stack, 'MyStateMachine', {
definition: stepfunctions.Chain.start(new stepfunctions.Pass(stack, 'Pass')),
tracingEnabled: true,
});

// THEN
expect(stack).toHaveResource('AWS::StepFunctions::StateMachine', {
DefinitionString: '{"StartAt":"Pass","States":{"Pass":{"Type":"Pass","End":true}}}',
TracingConfiguration: {
Enabled: true,
},
});

expect(stack).toHaveResource('AWS::IAM::Policy', {
PolicyDocument: {
Statement: [{
Action: [
'xray:PutTraceSegments',
'xray:PutTelemetryRecords',
],
Effect: 'Allow',
Resource: '*',
}],
Version: '2012-10-17',
},
PolicyName: 'MyStateMachineRoleDefaultPolicyE468EB18',
Roles: [
{
Ref: 'MyStateMachineRoleD59FFEBC',
},
],
});
});
});

0 comments on commit ad011c0

Please sign in to comment.