
เล่นกับ AWS X-Ray เบื้องต้น
Level: Overview - Basic
งานสำคัญอย่างนึงในการพัฒนาระบบคือการตรวจสอบและติดตามหา Root cause ของ error หรือ bug ในโปรแกรม ซึ่งโดยปกติจะมีการนั่งดู log ของ service ต่างๆที่เกี่ยวข้อง แต่สำหรับกรณีที่เราใช้ Serverless หรือ Service ใน AWS นอกจากที่จะเข้าไปตรวจสอบ Log ใน Cloudwatch หรือจุดอื่นๆแล้ว AWS มี Service อีกตัวที่หลายๆคนอาจจะไม่เคยได้ลองเล่น คือ AWS X-Ray ที่ช่วยให้เราสามารถติดตามการทำงานของระบบได้สะดวกมาก และมีประโยชน์ในการวิเคราะห์ว่าการทำงานมีส่วนไปนที่ทำงานผิดพลาดหรือมีคอขวดตรงไหนหรือไม่
โดยในตัวอย่างที่ยกมาจะลองเล่นกับ AWS X-Ray เบื้องต้นซึ่งจะมี Service ต่างๆที่เกี่ยวข้องดังนี้
- API Gateway
- Lambda Function
- S3
- DynamoDB
Architecture
นอกจากการทดสอบระหว่าง API Gateway กับ Lambda แล้ว ในตัวอย่างจะเพิ่มการเชื่อมต่อกับ DynamoDB และ S3 รวมไปถึงการสร้าง DynamoDB Stream และ S3 Event Notification เพื่อเรียก Lambda เพื่อทดสอบดูว่า Trace ไปได้ถึงไหน ในเบื้องต้น
Setup
สร้าง DynamoDB Table ชื่อxray-demo โดยมี partition key ชื่อid
สร้าง S3 Bucket ชื่อxray-demo-20211020 (ถ้าไปทำตามเปลี่ยนชื่อและเปลี่ยนชื่อใน code function xray-demo-s3 ด้วยนะครับ)
สร้าง AWS Lambda Functionxray-demo-dynamo ทำการเขียนข้อมูลลงบน dynamoDB (อย่าลืมเพิ่ม DynamoDB Policy ให้ LambdaExecution Role)
importjsonimportboto3importuuiddeflambda_handler(event,context):client=boto3.resource('dynamodb')table=client.Table('xray-demo')table.put_item(Item={'id':str(uuid.uuid4()),'data':event})return{'statusCode':200,'body':'Wrote to DynamoDB'}
- สร้าง AWS Lambda Functionxray-demo-s3 ทำการเขียนข้อมูลลงบน s3 (อย่าลืมเพิ่ม S3 Policy ให้ LambdaExecution Role)
importjsonimportboto3importuuiddeflambda_handler(event,context):filename=str(uuid.uuid4())s3=boto3.resource('s3')s3.Object('xray-demo-20211020',f'{filename}.json').put(Body=bytes(json.dumps(event).encode('UTF-8')))return{'statusCode':200,'body':'Wrote to S3'}
- สร้าง AWS Lambda Functionxray-demo-logging ทำการเขียน Log บน CloudWatch
importjsondeflambda_handler(event,context):print(event)return{'Status':'Done'}
- สร้าง API Gateway 2 Methods แล้วทำการ Deploy เพื่อใช้ทดสอบ
- GET /dynamodb เพื่อเรียก Lambda Proxy Integrationไปยัง Functionxray-demo-dynamo
- GET /s3 เพื่อเรียก Lambda Proxy Integrationไปยัง Functionxray-demo-s3
- เปิดใช้งาน DynamoDB Stream แล้วให้ Trigger เป็น Lambda Functionxray-demo-loging
- เปิดใช้งาน S3 Event Notification แล้วให้เรียก Lambda Functionxray-demo-logging
การเปิดใช้ X-Ray สำหรับ AWS Lambda
สำหรับ AWS Lambda ทั้ง 3 Functions จะต้องทำการเปิดใช้ X-Ray บน AWS Lambda ก่อน โดยสามารถเปิดใช้งานได้ที่หน้า Configuration > Monitoring and operations tools โดยตัว X-Ray จะใช้ชื่อว่า Active Tracing ซึ่งปกติจะขึ้น Not enabled อยู่ และสามารถกด Edit เพื่อเข้าไปเปิดได้
โดยในการเปิด Active tracing ตัว Lambda จะเพิ่ม Permission ให้โดยอัตโนมัติ
การเปิดใช้ X-Ray สำหรับ API Gateway
สำหรับ API Gateway เมื่อทำการ Deploy API แล้วสามารถเปิดใช้งาน AWS X-Ray ได้ที่หน้า Logs/Tracing ของ Stage นั้นๆ
สำหรับ X-Ray Sampling Rule เพื่อให้ง่ายต่อการทดสอบเฉยๆจะใช้ Default ที่มีอยู่แล้ว (จริงๆคือยังไม่ได้ลอง แหะๆ) ถ้าสนใจรายละเอียดอ่านที่เอกสารของ AWSที่นี่
ทดลองเรียกใช้งานรอบที่ 1
ลองเรียกทั้ง 2 Function ดูแล้วเข้าไปดูที่ AWS X-Ray เพื่อดูผลลัพธ์ดู โดยจะเรียกจาก Postman และดู Header ที่ตอบกลับมา
เรียกAPI GET /dynamodb
จากรูปข้างบนจะเห็นว่าจะมี HeaderX-Amzn-Trace-Id กลับมาด้วย ซึ่งตัวข้อมูลนี้คือค่าที่ X-Ray ใช้ Trace ข้อมูล Request/Response ต่างๆในระบบ ซึ่งเมื่อมีการส่งต่อเลขนี้ไปด้วย
เมื่อเข้าไปดูที่หน้าจอ X-Ray จะสามารถดูรายการ Trace ที่เกิดขึ้นในช่วงระยะเวลาที่เราเลือกได้ (ขวาบน) ซึ่งจะสังเกตได้ว่าเลขอ้างอิง หรือ ID ที่แสดงใน Trace List จะเป็นเลขเดียวกับค่าของX-Amzn-Trace-Id โดยสามารถเข้าไปดูรายละเอียดของ Request นั้นๆและ Service Map ที่แสดงภาพรวมระยะเวลาในการทำงานของ Node ต่างๆได้ด้วยเรียกAPI GET /s3
เพื่อให้เห็นตัวอย่างที่ชัดเจนขึ้นจะทำการแก้ Lambda Function ให้ทำงานผิดพลาด (Lambda Error และ Return 502 จาก API Gateway) 1 รอบ และแก้กลับให้ทำงานปกติ ซึ่งเมื่อดู Trace และ Service Map บน X-Ray จะขึ้นสี เหลือง - Errors (4XX) และ สีแดง - Faults (5XX) ตามลำดับ สำหรับรายการที่ไม่สำเร็จ
การเพิ่มรายละเอียดการ Trace ด้วย Code
จากตัวอย่างการเรียกทั้ง 2 แบบด้านบน จะเห็นว่าข้อมูลการ Trace จบที่ AWS Lambda ไม่แสดงรายละเอียดการเรียกไปยัง DynamoDB และ S3 รวมไปถึงไม่สามารถแสดงกรณีที่ S3 Event หรือ DynamoDB Stream เป็นผู้ Trigger Lambdaxray-demo-logging ได้ ซึ่งการจะแสดงผลให้ละเอียดขึ้นจะต้องทำการเรียกใช้aws-xray-sdk เพื่อให้ทำการเพิ่ม Trace ID ลงบน Header ของการเรียกใช้งาน Service อื่นๆด้วย
ในตัวอย่างจะแสดงการเรียกใช้แบบง่าย ซึ่งถ้าต้องการรายละเอียดเชิงลึกเพิ่มเติมสามารถดูได้ที่เอกสารของ AWSที่นี่ ส่วนถ้าใช้ภาษาอื่นๆนอกเหนือจาก Python สามารถหาข้อมูลต่อได้จาก Link ข้างต้นเหมือนกัน
ในการเรียกaws-xray-sdk บน Lambda เนื่องจาก AWS ไม่ได้ include library ตัวนี้ไว้ใน default runtime ดังนั้นในเบื้องต้นจะมี 2 ทางเลือกคือ
- เขียน Code บนเครื่องพร้อม install package แล้ว upload .zip ขึ้นมายัง Lambda
- เพิ่ม Lambda Layer ที่ติดตั้งaws-xray-sdk ไว้ซึ่งในตัวอย่างจะใช้การทำงานแบบที่ 2 ซึ่งวิธีการสร้าง Lambda Layer ง่ายๆอ่านได้ที่นี่
เมื่อทำการสร้าง Lambda Layer แล้ว ให้ทำการ Attach Layer และแก้ Lambda function สำหรับ dynamodb และ s3 โดยเพิ่ม 3 บรรทัดด้านบนดังนี้
fromaws_xray_sdk.coreimportxray_recorderfromaws_xray_sdk.coreimportpatch_allpatch_all()
ซึ่งเมื่อแก้ไขแล้วจะได้ Code ของ. Function ที่แก้ไขแล้ว
- แก้ไข AWS Lambda Functionxray-demo-dynamo
importjsonimportboto3importuuidfromaws_xray_sdk.coreimportxray_recorderfromaws_xray_sdk.coreimportpatch_allpatch_all()deflambda_handler(event,context):client=boto3.resource('dynamodb')table=client.Table('xray-demo')table.put_item(Item={'id':str(uuid.uuid4()),'data':event})return{'statusCode':200,'body':'Wrote to DynamoDB'}
- แก้ไข Functionxray-demo-s3
importjsonimportboto3importuuidfromaws_xray_sdk.coreimportxray_recorderfromaws_xray_sdk.coreimportpatch_allpatch_all()deflambda_handler(event,context):filename=str(uuid.uuid4())s3=boto3.resource('s3')s3.Object('xray-demo-20211020',f'{filename}.json').put(Body=bytes(json.dumps(event).encode('UTF-8')))return{'statusCode':200,'body':'Wrote to S3'}
ซึ่งการทำงานของคำสั่งpatch_all()
จะไปทำการเพิ่ม Trace Id ใน Header ของทุกคำสั่งที่ X-Ray รองรับ เพื่อให้สามารถ Trace การทำงานได้
ทดลองเรียกใช้งานรอบที่ 2
เรียกAPI GET /dynamodb
เมื่อเรียก API และเปิดดู Service Map จะเห็นว่ามี Node การทำงานของ DynamoDB Table เพิ่มขึ้นมา ซึ่งถ้าดูใน Trace จะแสดง API ที่ถูกเรียกด้วย คือ คำสั่ง PutItem แต่การแสดงข้อมูลการเรียกxray-demo-logging จะถูกแยกออกจาก Trace ของ API ที่เรียกเรียกAPI GET /s3
เมื่อเรียก API และเปิดดู Service Map จะเห็นว่ามี Node การทำงานของ S3 Bucket เพิ่มขึ้นมา ซึ่งถ้าดูใน Trace จะแสดง API ที่ถูกเรียกด้วย คือ คำสั่ง PutObject และการเรียกxray-demo-logging จะแสดงเป็นการถูกเรียกโดย Lambda functionxray-demo-s3 แทน โดยไม่แยกออกจากกันเหมือนกรณี DynamoDB
Limitation
อย่างไรก็ตาม จากตัวอย่างข้างบน 2 รูปแบบ จะเห็นว่าการเรียก xray-demo-logging ซึ่งถูกเรียกโดย DynamoDB Stream จะขึ้น Trace Id แยกออกจากการคำสั่งชุดแรกที่ผ่าน API แต่การเรียกผ่าน S3 Event Notification จะมีการส่งต่อ TraceID เพื่อให้เห็นว่าที่มาของการเกิด Trigger เกิดจากที่ใด
ซึ่งรูปแบบที่แตกต่างกันนี้เกิดขึ้นเนื่องจาก X-Ray ยังไม่รองรับการส่ง Trace Id ผ่าน Dynamo DB แต่สำหรับ S3 มีการรองรับการส่งต่อ Trace ID ไปยังคำสั่งต่อไปแล้ว เพียงแต่จะไม่เห็นว่าต้นทางที่เรียกมาจาก S3 Event Notification โดยรายละเอียดการรองรับการทำงานร่วมกับ X-Ray สามารถอ่านเพิ่มเติมได้ที่เอกสารของ AWSที่นี่
Cost
AWS X-Ray เปิดให้ใช้ฟรีสำหรับการเก็บข้อมูลเดือนละ 100,000 trace และฟรีสำหรับการเรียกข้อมูลหรือสแกนข้อมูลที่บันทึกไว้ 1,000,000 trace หลังจากนั้นจึงคิดเงินเพิ่มตามรูปด้านล่าง
Conclusion
Software developers spend 35-50 percent of their time validating and debugging software. The cost of debugging, testing, and verification is estimated to account for 50-75 percent of the total budget of software development projects
Devon H. O'DellACMQueue
งาน Monitor & Debugging เป็นงานที่สำคัญและกินเวลาของ Developer ค่อนข้างมาก ซึ่งการเลือกเครื่องมือต่างๆมาช่วยให้สามารถตรวจสอบหรือติดตามผลการทำงานของ Software ที่พัฒนาขึ้นมาได้อย่างเหมาะสมจะช่วยลดเวลาและค่าใช้จ่ายในการพัฒนาระบบได้ด้วย ดังนั้น AWS X-Ray จึงเป็นหนึ่งในตัวเลือกที่นักพัฒนาบน AWS ควรจะศึกษาไว้เพื่อให้การทำงานง่ายขึ้น
Top comments(2)

- LocationBangkok
- WorkCloud Solution Architect at Amazon Web Services
- Joined
Nice!
For further actions, you may consider blocking this person and/orreporting abuse