Enable X-Ray for Crystal

The AWS X-Ray daemon is a software application that listens for traffic on UDP port 2000, gathers raw segment data, and relays it to the AWS X-Ray API. The daemon works in conjunction with the AWS X-Ray SDKs and must be running so that data sent by the SDKs can reach the X-Ray service.

  • Register a new task definition to add the x-ray container, and enable tracing for the Envoy container.
# Define variables #
TASK_DEF_ARN=$(aws ecs list-task-definitions | \
  jq -r ' .taskDefinitionArns[] | select( . | contains("crystal"))' | tail -1)
TASK_DEF_OLD=$(aws ecs describe-task-definition --task-definition $TASK_DEF_ARN);
TASK_DEF_NEW=$(echo $TASK_DEF_OLD \
  | jq ' .taskDefinition' \
  | jq ' .containerDefinitions |= map(
        if .name == "envoy" then .environment +=
          [
            {
              "name": "ENABLE_ENVOY_XRAY_TRACING",
              "value": "1"
            }
          ]
        else . end) ' \
  | jq ' .containerDefinitions +=
        [
          {
            "image": "amazon/aws-xray-daemon",
            "essential": true,
            "name": "xray",
            "portMappings": [
              {
                "hostPort": 2000,
                "protocol": "udp",
                "containerPort": 2000
              }
            ],
            "healthCheck": {
              "retries": 3,
              "command": [
                "CMD-SHELL",
                "timeout 1 /bin/bash -c \"</dev/udp/localhost/2000\""
              ],
              "timeout": 2,
              "interval": 5,
              "startPeriod": 10
            }
          }
        ]' \
  | jq ' del(.status, .compatibilities, .taskDefinitionArn, .requiresAttributes, .revision) '
); \
TASK_DEF_FAMILY=$(echo $TASK_DEF_ARN | cut -d"/" -f2 | cut -d":" -f1);
echo $TASK_DEF_NEW > /tmp/$TASK_DEF_FAMILY.json &&
# Register ecs task definition #
aws ecs register-task-definition \
  --cli-input-json file:///tmp/$TASK_DEF_FAMILY.json
  • Update the service.
CLUSTER_NAME=$(jq < cfn-output.json -r '.EcsClusterName');
TASK_DEF_ARN=$(aws ecs list-task-definitions | \
  jq -r ' .taskDefinitionArns[] | select( . | contains("crystal"))' | tail -1)
aws ecs update-service \
  --cluster $CLUSTER_NAME \
  --service crystal-service-lb \
  --task-definition "$(echo $TASK_DEF_ARN)"
  • Wait for the service tasks to be in a running state.
# Define variables #
CLUSTER_NAME=$(jq < cfn-output.json -r '.EcsClusterName');
TASK_DEF_ARN=$(aws ecs list-task-definitions | \
  jq -r ' .taskDefinitionArns[] | select( . | contains("crystal"))' | tail -1);
# Get task state #
_list_tasks() {
   aws ecs list-tasks \
     --cluster $CLUSTER_NAME \
     --service crystal-service-lb | \
   jq -r ' .taskArns | @text' | \
     while read taskArns; do
       aws ecs describe-tasks --cluster $CLUSTER_NAME --tasks $taskArns;
     done | \
   jq -r --arg TASK_DEF_ARN $TASK_DEF_ARN \
     ' [.tasks[] | select( (.taskDefinitionArn == $TASK_DEF_ARN)
                     and (.lastStatus == "RUNNING" ))] | length'
}
until [ $(_list_tasks) == "3" ]; do
  echo "Tasks are starting ..."
  sleep 10s
  if [ $(_list_tasks) == "3" ]; then
    echo "Tasks started"
    break
  fi
done