Monitoring API performance with Grafana & Elasticsearch

วันนี้มีพี่ท่านนึงมาถามเรื่อง TSDB: Time Series Database เพื่อจะใช้ในการทำ monitoring ซึ่งก็มีพูดถึงหลายตัวที่เคยใช้งาน เช่น InfluxDB เป็นต้น แต่ว่าหลังๆมีตัวที่ใช้บ่อยกว่าตัวอื่นคือ Elasticsearch เพราะว่า TSDB ส่วนใหญ่ที่มีมันจะยุ่งๆตอนใช้งานหน่อย และมักจะมี cost ในการใช้งานสูง เพราะว่ามักจะถูก capped ด้วย license หรือความยุ่งยากในการ scale วันนี้ระหว่างรอ Apple Special Event เลยเขียน blog อธิบายแบบสั้นๆหน่อย โดยใน blog นี้จะไม่รวมถึงการติดตั้ง Elasticsearch และ Grafana นะครับ :)

1_qIHllZlPx1TwV_pD_a8Dyw

ตัวอย่างของ outcome ที่ทำตามตัวอย่างใน blog นี้
ขั้นตอนในการ implement มีไม่กี่ขั้นตอนนะครับ ซึ่งวันนี้จะใช้ Postman เป็นเครื่องมือในการสร้าง index (database) และ metrics แต่ตอนใช้จริงก็ HTTP Post ไปที่ Elasticsearch ได้เลย มาลองดูได้เลยว่าทำยังไงบ้าง

สร้าง index และ default mappings สำหรับเก็บ metrics
สมมติว่าในการทำ dashboard สำหรับ monitoring ของเราในตัวอย่างนี้ เราจะเก็บข้อมูลต่อไปนี้

name ชื่อของ metrics ที่อยากจะเก็บข้อมูล
endpoint ของ API ที่ถูกเรียกเข้ามา
response time ของ API
timestamp เพื่อใช้เป็นแกนเวลาของ metric เรา
ซึ่งเราก็จะได้ mappings สำหรับ Elasticsearch มาประมาณแบบนี้

{
  "mappings" : {
    "_default_": {
      "properties": {
        "name": {
          "type": "text" 
        },
        "endpoint": {
          "type": "text" 
        },
        "response_time": {
          "type": "float"
        },
        "timestamp" : {
          "type": "date"   , 
          "index" : "true"  
        }
      }
    }
  }
}

ซึ่งเราสามารถที่จะใช้ curl หรือ Postman ส่ง request ด้วย HTTP PUT ไปที่
http://[elastic-search-server][:9200]/[index-name] ได้ตามตัวอย่างดังภาพ ซึ่งผมตั้งชื่อ {index-name} ว่า metrics นะครับ

1_nDzX5I96uWAkDgcspL9XDg

ขั้นตอนแรก สร้าง index ก่อน
2. ทดสอบส่ง metric ไปที่ elasticsearch

จากที่เราสร้าง index ของ metrics เราใน elasticsearch ในขั้นตอนก่อหน้านี้ เราสามารถสร้าง payload ของ metric ออกมาได้หน้าตาประมาณนี้

{
  "name": "test_metric",
  "endpoint": "/test",
  "response_time": 200.10,
  "timestamp": "2018-09-10T12:10:30Z"
}

ซึ่งเราก็สามารถส่ง metric นี้ไปที่ elasticsearch ด้วย HTTP POST method ไปที่ endpoint http://[elasticsearch-server][:9200]/[index-name]/index ได้เลยทันทีตามรูป

1_2c3eDrPUxNQhYMK6cEcXuw

สร้างข้อมูลตัวอย่าง
หลังจากที่เราทดลองสร้าง metric แล้ว ถ้าอยากมั่นใจว่ามีข้อมูลของ metric จริงๆ ก็ลอง query ดูก็ได้นะครับ อย่างน้อยก็น่าจะเห็นข้อมูคล้ายกับภาพตัวอย่างต่อไปนี้

1_oVPAy-oDpIlQsF7Tpb5-bw

ลองเช็คดูหน่อยว่ามีข้อมูลไหม
3. เพิ่ม Elasticsearch ลงไปใน data source ของ Grafana

ในการเพิ่ม Elasticsearch ลงไปเป็น Data Source ของ Grafana ด้วย index ที่เราสร้างเองนั้นมีทริกหลักๆ คือ ในส่วนของ Elasticsearch Detail นั้น ให้เลือกใช้ Pattern เป็น no patternและใช้ชื่อ Index และ Timefield ตามที่เราสร้าง mappings ในขั้นตอนแรก จากนั้นลองบันทึกและทดสอบดู ซึ่งถ้าเราไม่ได้ทำพลาดอะไรไป มันควรจะขึ้นข้อความมาว่าทดสอบแล้วถูกต้องเรียบร้อยดี

1_Gb8PxNUyPS8q0pg6I7LaZQ

Sample configuration สำหรับ Elasticsearch datasource
4. สร้าง Dashbaord ด้วย Lucene Query ใน Grafana

ขั้นตอนในการสร้าง dashboard ด้วยข้อมูลจาก Elasticsearch นั้นก็ไม่ได้ลำบากอะไรนักครับ ด้วยความที่ UI ของ Grafana ช่วยให้สามารถเดาได้ง่าย เช่น ผมต้องการสร้างกราฟ เพื่อแสดงข้อมูลของ metric ที่ชื่อว่า test_metric โดยให้แสดง average ของ response time ก็สามารถทำได้เลยดังนี้

Lucene Query: name: 'test_metric' , Metric ก็ใช้ Aggregate function average บน field response_time และ group ตามเวลาบนฟิลด์ timestamp

1_hyXdD8NdC7KuRdqT4-KoYA

Metric & Query
อย่างที่ผมเคยเล่าให้ฟังบ่อยๆว่า “Measurement is a first step to improve” ผมมักจะแนะนำเพื่อนๆพี่ๆน้องๆ เสมอว่าถ้าไม่อยากปวดหัว ก่อนจะ live อะไรสักอย่าง อย่างน้อยควร define measurement ให้ได้ว่า อะไรที่สำคัญ และมี value พอที่จะวัด และอะไรที่อย่าไปวัดเลย :D

Happy Coding :)

References: