การวิเคราะห์บันทึก Nginx โดยใช้ Amazon Athena และ Cube.js

โดยทั่วไปแล้ว ผลิตภัณฑ์เชิงพาณิชย์หรือทางเลือกโอเพ่นซอร์สสำเร็จรูป เช่น Prometheus + Grafana จะถูกใช้ในการติดตามและวิเคราะห์การทำงานของ Nginx นี่เป็นตัวเลือกที่ดีสำหรับการติดตามหรือการวิเคราะห์แบบเรียลไทม์ แต่ไม่สะดวกสำหรับการวิเคราะห์ในอดีต ในทรัพยากรยอดนิยมใดๆ ปริมาณข้อมูลจากบันทึก nginx กำลังเติบโตอย่างรวดเร็ว และในการวิเคราะห์ข้อมูลจำนวนมาก การใช้สิ่งที่พิเศษกว่านั้นก็สมเหตุสมผล

ในบทความนี้ฉันจะบอกคุณว่าคุณสามารถใช้งานได้อย่างไร Athena เพื่อวิเคราะห์บันทึก โดยใช้ Nginx เป็นตัวอย่าง และผมจะแสดงวิธีประกอบแดชบอร์ดการวิเคราะห์จากข้อมูลนี้โดยใช้เฟรมเวิร์ก cube.js แบบโอเพ่นซอร์ส นี่คือสถาปัตยกรรมโซลูชันที่สมบูรณ์:

การวิเคราะห์บันทึก Nginx โดยใช้ Amazon Athena และ Cube.js

TL:DR;
ลิงก์ไปยังแดชบอร์ดที่เสร็จแล้ว.

เพื่อรวบรวมข้อมูลที่เราใช้ คล่องแคล่วสำหรับการประมวลผล - AWS Kinesis Data Firehose и AWS กาวสำหรับการจัดเก็บ - AWS S3. เมื่อใช้บันเดิลนี้ คุณจะไม่เพียงแต่สามารถจัดเก็บบันทึก nginx เท่านั้น แต่ยังรวมถึงกิจกรรมอื่นๆ ตลอดจนบันทึกของบริการอื่นๆ ด้วย คุณสามารถแทนที่บางส่วนด้วยชิ้นส่วนที่คล้ายกันสำหรับสแต็กของคุณ ตัวอย่างเช่น คุณสามารถเขียนบันทึกไปยัง kinesis ได้โดยตรงจาก nginx ข้าม fluentd หรือใช้ logstash สำหรับสิ่งนี้

กำลังรวบรวมบันทึก Nginx

ตามค่าเริ่มต้น บันทึก Nginx จะมีลักษณะดังนี้:

4/9/2019 12:58:17 PM1.1.1.1 - - [09/Apr/2019:09:58:17 +0000] "GET /sign-up HTTP/2.0" 200 9168 "https://example.com/sign-in" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" "-"
4/9/2019 12:58:17 PM1.1.1.1 - - [09/Apr/2019:09:58:17 +0000] "GET /sign-in HTTP/2.0" 200 9168 "https://example.com/sign-up" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" "-"

สามารถแยกวิเคราะห์ได้ แต่จะง่ายกว่ามากในการแก้ไขการกำหนดค่า Nginx เพื่อให้สร้างบันทึกใน JSON:

log_format json_combined escape=json '{ "created_at": "$msec", '
            '"remote_addr": "$remote_addr", '
            '"remote_user": "$remote_user", '
            '"request": "$request", '
            '"status": $status, '
            '"bytes_sent": $bytes_sent, '
            '"request_length": $request_length, '
            '"request_time": $request_time, '
            '"http_referrer": "$http_referer", '
            '"http_x_forwarded_for": "$http_x_forwarded_for", '
            '"http_user_agent": "$http_user_agent" }';

access_log  /var/log/nginx/access.log  json_combined;

S3 สำหรับการจัดเก็บ

ในการจัดเก็บบันทึก เราจะใช้ S3 ซึ่งช่วยให้คุณจัดเก็บและวิเคราะห์บันทึกได้ในที่เดียว เนื่องจาก Athena สามารถทำงานกับข้อมูลใน S3 ได้โดยตรง ต่อไปในบทความ ฉันจะบอกวิธีเพิ่มและประมวลผลบันทึกอย่างถูกต้อง แต่ก่อนอื่นเราจำเป็นต้องมีบัคเก็ตที่สะอาดใน S3 ซึ่งจะไม่มีการจัดเก็บอย่างอื่นอีก การพิจารณาล่วงหน้าว่าจะสร้างบัคเก็ตในภูมิภาคใด เนื่องจาก Athena อาจไม่มีให้บริการในทุกภูมิภาค

การสร้างวงจรในคอนโซล Athena

มาสร้างตารางใน Athena สำหรับบันทึกกันดีกว่า จำเป็นสำหรับทั้งการเขียนและการอ่านหากคุณวางแผนที่จะใช้ Kinesis Firehose เปิดคอนโซล Athena และสร้างตาราง:

การสร้างตาราง SQL

CREATE EXTERNAL TABLE `kinesis_logs_nginx`(
  `created_at` double, 
  `remote_addr` string, 
  `remote_user` string, 
  `request` string, 
  `status` int, 
  `bytes_sent` int, 
  `request_length` int, 
  `request_time` double, 
  `http_referrer` string, 
  `http_x_forwarded_for` string, 
  `http_user_agent` string)
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.ql.io.orc.OrcSerde' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat'
LOCATION
  's3://<YOUR-S3-BUCKET>'
TBLPROPERTIES ('has_encrypted_data'='false');

การสร้างสตรีม Kinesis Firehose

Kinesis Firehose จะเขียนข้อมูลที่ได้รับจาก Nginx ไปยัง S3 ในรูปแบบที่เลือก โดยแบ่งออกเป็นไดเร็กทอรีในรูปแบบ YYYY/MM/DD/HH สิ่งนี้จะมีประโยชน์เมื่ออ่านข้อมูล แน่นอนคุณสามารถเขียนโดยตรงไปยัง S3 จาก fluentd ได้ แต่ในกรณีนี้ คุณจะต้องเขียน JSON และนี่จะไม่มีประสิทธิภาพเนื่องจากไฟล์มีขนาดใหญ่ นอกจากนี้ เมื่อใช้ PrestoDB หรือ Athena JSON คือรูปแบบข้อมูลที่ช้าที่สุด ดังนั้นให้เปิดคอนโซล Kinesis Firehose คลิก “สร้างสตรีมการจัดส่ง” เลือก “Direct PUT” ในช่อง “การจัดส่ง”:

การวิเคราะห์บันทึก Nginx โดยใช้ Amazon Athena และ Cube.js

ในแท็บถัดไป เลือก "การแปลงรูปแบบบันทึก" - "เปิดใช้งาน" และเลือก "Apache ORC" เป็นรูปแบบการบันทึก ตามการวิจัยบางอย่าง โอเว่น โอ'มัลลีย์นี่เป็นรูปแบบที่เหมาะสมที่สุดสำหรับ PrestoDB และ Athena เราใช้ตารางที่เราสร้างขึ้นด้านบนเป็นสคีมา โปรดทราบว่าคุณสามารถระบุตำแหน่ง S3 ใดๆ ใน kinesis ได้ โดยจะใช้เฉพาะสคีมาจากตารางเท่านั้น แต่หากคุณระบุตำแหน่ง S3 อื่น คุณจะไม่สามารถอ่านบันทึกเหล่านี้จากตารางนี้ได้

การวิเคราะห์บันทึก Nginx โดยใช้ Amazon Athena และ Cube.js

เราเลือก S3 สำหรับพื้นที่จัดเก็บและบัคเก็ตที่เราสร้างไว้ก่อนหน้านี้ AWS Glue Crawler ซึ่งฉันจะพูดถึงในภายหลัง ไม่สามารถทำงานกับคำนำหน้าในบัคเก็ต S3 ได้ ดังนั้นจึงเป็นเรื่องสำคัญที่จะต้องปล่อยว่างไว้

การวิเคราะห์บันทึก Nginx โดยใช้ Amazon Athena และ Cube.js

ตัวเลือกที่เหลือสามารถเปลี่ยนแปลงได้ขึ้นอยู่กับโหลดของคุณ ฉันมักจะใช้ตัวเลือกเริ่มต้น โปรดทราบว่าการบีบอัด S3 ไม่พร้อมใช้งาน แต่ ORC จะใช้การบีบอัดแบบเนทิฟตามค่าเริ่มต้น

คล่องแคล่ว

ตอนนี้เราได้กำหนดค่าการจัดเก็บและรับบันทึกแล้ว เราจำเป็นต้องกำหนดค่าการส่ง เราจะใช้ คล่องแคล่วเพราะฉันชอบ Ruby แต่คุณสามารถใช้ Logstash หรือส่งบันทึกไปที่ kinesis ได้โดยตรง เซิร์ฟเวอร์ Fluentd สามารถเปิดใช้งานได้หลายวิธี ฉันจะบอกคุณเกี่ยวกับนักเทียบท่าเพราะมันง่ายและสะดวก

ก่อนอื่น เราต้องการไฟล์คอนฟิกูเรชัน fluent.conf สร้างมันและเพิ่มแหล่งที่มา:

ชนิด ข้างหน้า
พอร์ต 24224
ผูกมัด 0.0.0.0

ตอนนี้คุณสามารถเริ่มเซิร์ฟเวอร์ Fluentd ได้แล้ว หากคุณต้องการการกำหนดค่าขั้นสูงกว่านี้ ให้ไปที่ ศูนย์กลางนักเทียบท่า มีคำแนะนำโดยละเอียด รวมถึงวิธีประกอบภาพของคุณ

$ docker run 
  -d 
  -p 24224:24224 
  -p 24224:24224/udp 
  -v /data:/fluentd/log 
  -v <PATH-TO-FLUENT-CONF>:/fluentd/etc fluentd 
  -c /fluentd/etc/fluent.conf
  fluent/fluentd:stable

การกำหนดค่านี้ใช้เส้นทาง /fluentd/log เพื่อแคชบันทึกก่อนส่ง คุณสามารถทำได้โดยไม่ต้องทำสิ่งนี้ แต่เมื่อคุณรีสตาร์ท คุณจะสูญเสียทุกสิ่งที่แคชไว้ด้วยงานที่หนักหน่วง คุณยังสามารถใช้พอร์ตใดก็ได้ โดย 24224 เป็นพอร์ต Fluentd เริ่มต้น

ตอนนี้เมื่อเราใช้งาน Fluentd แล้ว เราก็สามารถส่งบันทึก Nginx ไปที่นั่นได้ โดยปกติเราจะรัน Nginx ในคอนเทนเนอร์ Docker ซึ่งในกรณีนี้ Docker มีไดรเวอร์การบันทึกดั้งเดิมสำหรับ Fluentd:

$ docker run 
--log-driver=fluentd 
--log-opt fluentd-address=<FLUENTD-SERVER-ADDRESS>
--log-opt tag="{{.Name}}" 
-v /some/content:/usr/share/nginx/html:ro 
-d 
nginx

หากคุณเรียกใช้ Nginx แตกต่างออกไป คุณสามารถใช้ไฟล์บันทึกได้ตามที่ Fluentd มี ปลั๊กอินส่วนท้ายของไฟล์.

มาเพิ่มการแยกวิเคราะห์บันทึกที่กำหนดค่าด้านบนให้กับการกำหนดค่า Fluent:

<filter YOUR-NGINX-TAG.*>
  @type parser
  key_name log
  emit_invalid_record_to_error false
  <parse>
    @type json
  </parse>
</filter>

และส่งบันทึกไปยัง Kinesis โดยใช้ ปลั๊กอิน kinesis firehose:

<match YOUR-NGINX-TAG.*>
    @type kinesis_firehose
    region region
    delivery_stream_name <YOUR-KINESIS-STREAM-NAME>
    aws_key_id <YOUR-AWS-KEY-ID>
    aws_sec_key <YOUR_AWS-SEC_KEY>
</match>

Athena

หากคุณกำหนดค่าทุกอย่างถูกต้อง หลังจากนั้นไม่นาน (โดยค่าเริ่มต้น บันทึก Kinesis จะได้รับข้อมูลทุกๆ 10 นาที) คุณจะเห็นไฟล์บันทึกใน S3 ในเมนู “การตรวจสอบ” ของ Kinesis Firehose คุณสามารถดูจำนวนข้อมูลที่บันทึกไว้ใน S3 รวมถึงข้อผิดพลาดได้ อย่าลืมให้สิทธิ์การเขียนในบัคเก็ต S3 แก่บทบาท Kinesis หาก Kinesis ไม่สามารถแยกวิเคราะห์บางสิ่งได้ ระบบจะเพิ่มข้อผิดพลาดลงในบัคเก็ตเดียวกัน

ตอนนี้คุณสามารถดูข้อมูลใน Athena ได้แล้ว มาดูคำขอล่าสุดที่เราส่งคืนข้อผิดพลาด:

SELECT * FROM "db_name"."table_name" WHERE status > 499 ORDER BY created_at DESC limit 10;

สแกนบันทึกทั้งหมดสำหรับแต่ละคำขอ

ขณะนี้บันทึกของเราได้รับการประมวลผลและจัดเก็บไว้ใน S3 ใน ORC แล้ว บีบอัดและพร้อมสำหรับการวิเคราะห์ Kinesis Firehose ยังจัดระเบียบพวกมันเป็นไดเร็กทอรีสำหรับแต่ละชั่วโมง อย่างไรก็ตาม ตราบใดที่ตารางไม่ได้ถูกแบ่งพาร์ติชัน Athena จะโหลดข้อมูลตลอดเวลาในทุกคำขอ โดยมีข้อยกเว้นที่ไม่ค่อยเกิดขึ้น นี่เป็นปัญหาใหญ่ด้วยเหตุผลสองประการ:

  • ปริมาณข้อมูลมีการเติบโตอย่างต่อเนื่อง ส่งผลให้การสืบค้นช้าลง
  • Athena จะเรียกเก็บเงินตามปริมาณข้อมูลที่สแกน โดยมีขั้นต่ำ 10 MB ต่อคำขอ

เพื่อแก้ไขปัญหานี้ เราใช้ AWS Glue Crawler ซึ่งจะรวบรวมข้อมูลใน S3 และเขียนข้อมูลพาร์ติชันลงใน Glue Metastore สิ่งนี้จะทำให้เราสามารถใช้พาร์ติชั่นเป็นตัวกรองเมื่อทำการสืบค้น Athena และจะสแกนเฉพาะไดเร็กทอรีที่ระบุในการสืบค้นเท่านั้น

การตั้งค่าโปรแกรมรวบรวมข้อมูล Amazon Glue

Amazon Glue Crawler สแกนข้อมูลทั้งหมดในบัคเก็ต S3 และสร้างตารางที่มีพาร์ติชัน สร้าง Glue Crawler จากคอนโซล AWS Glue และเพิ่มบัคเก็ตที่คุณจัดเก็บข้อมูล คุณสามารถใช้โปรแกรมรวบรวมข้อมูลหนึ่งรายการสำหรับที่เก็บข้อมูลหลายรายการ ซึ่งในกรณีนี้โปรแกรมจะสร้างตารางในฐานข้อมูลที่ระบุพร้อมชื่อที่ตรงกับชื่อของที่เก็บข้อมูล หากคุณวางแผนที่จะใช้ข้อมูลนี้เป็นประจำ อย่าลืมกำหนดค่ากำหนดการเปิดตัวของ Crawler ให้เหมาะกับความต้องการของคุณ เราใช้โปรแกรมรวบรวมข้อมูลหนึ่งรายการสำหรับตารางทั้งหมด ซึ่งทำงานทุกชั่วโมง

ตารางที่แบ่งพาร์ติชัน

หลังจากเปิดตัวโปรแกรมรวบรวมข้อมูลครั้งแรก ตารางสำหรับที่เก็บข้อมูลที่สแกนแต่ละรายการควรปรากฏในฐานข้อมูลที่ระบุในการตั้งค่า เปิดคอนโซล Athena และค้นหาตารางที่มีบันทึก Nginx ลองอ่านอะไรบางอย่าง:

SELECT * FROM "default"."part_demo_kinesis_bucket"
WHERE(
  partition_0 = '2019' AND
  partition_1 = '04' AND
  partition_2 = '08' AND
  partition_3 = '06'
  );

แบบสอบถามนี้จะเลือกบันทึกทั้งหมดที่ได้รับระหว่างเวลา 6 น. ถึง 7 น. ของวันที่ 8 เมษายน 2019 แต่สิ่งนี้จะมีประสิทธิภาพมากกว่าการอ่านจากตารางที่ไม่แบ่งพาร์ติชันมากแค่ไหน? เรามาค้นหาและเลือกบันทึกเดียวกันโดยกรองตามการประทับเวลา:

การวิเคราะห์บันทึก Nginx โดยใช้ Amazon Athena และ Cube.js

ข้อมูล 3.59 วินาทีและ 244.34 เมกะไบต์บนชุดข้อมูลที่มีบันทึกเพียงหนึ่งสัปดาห์ ลองใช้ตัวกรองตามพาร์ติชัน:

การวิเคราะห์บันทึก Nginx โดยใช้ Amazon Athena และ Cube.js

เร็วขึ้นเล็กน้อย แต่ที่สำคัญที่สุด - ข้อมูลเพียง 1.23 เมกะไบต์! มันจะถูกกว่ามากถ้าไม่ใช่สำหรับราคาขั้นต่ำ 10 เมกะไบต์ต่อคำขอ แต่ก็ยังดีกว่ามาก และสำหรับชุดข้อมูลขนาดใหญ่ ความแตกต่างจะน่าประทับใจยิ่งกว่ามาก

การสร้างแดชบอร์ดโดยใช้ Cube.js

ในการประกอบแดชบอร์ด เราใช้เฟรมเวิร์กการวิเคราะห์ Cube.js มีฟังก์ชั่นค่อนข้างมาก แต่เราสนใจสองประการ: ความสามารถในการใช้ตัวกรองพาร์ติชันและการรวมข้อมูลล่วงหน้าโดยอัตโนมัติ มันใช้สคีมาข้อมูล สคีมาข้อมูลเขียนด้วย Javascript เพื่อสร้าง SQL และดำเนินการสืบค้นฐานข้อมูล เราจำเป็นต้องระบุวิธีใช้ตัวกรองพาร์ติชันในสคีมาข้อมูลเท่านั้น

มาสร้างแอปพลิเคชัน Cube.js ใหม่กันดีกว่า เนื่องจากเราใช้ AWS Stack อยู่แล้ว การใช้ Lambda ในการปรับใช้จึงสมเหตุสมผล คุณสามารถใช้เทมเพลตด่วนสำหรับการสร้างได้ หากคุณวางแผนที่จะโฮสต์แบ็กเอนด์ Cube.js ใน Heroku หรือ Docker เอกสารประกอบจะอธิบายรายละเอียดอื่นๆ วิธีการโฮสต์.

$ npm install -g cubejs-cli
$ cubejs create nginx-log-analytics -t serverless -d athena

ตัวแปรสภาพแวดล้อมใช้เพื่อกำหนดค่าการเข้าถึงฐานข้อมูลใน cube.js ตัวสร้างจะสร้างไฟล์ .env ซึ่งคุณสามารถระบุคีย์ของคุณได้ Athena.

ตอนนี้เราต้องการ สคีมาข้อมูลซึ่งเราจะระบุอย่างชัดเจนถึงวิธีการจัดเก็บบันทึกของเรา คุณยังสามารถระบุวิธีคำนวณเมตริกสำหรับแดชบอร์ดได้จากที่นั่น

ในไดเรกทอรี schema, สร้างไฟล์ Logs.js. นี่คือตัวอย่างโมเดลข้อมูลสำหรับ nginx:

รหัสรุ่น

const partitionFilter = (from, to) => `
    date(from_iso8601_timestamp(${from})) <= date_parse(partition_0 || partition_1 || partition_2, '%Y%m%d') AND
    date(from_iso8601_timestamp(${to})) >= date_parse(partition_0 || partition_1 || partition_2, '%Y%m%d')
    `

cube(`Logs`, {
  sql: `
  select * from part_demo_kinesis_bucket
  WHERE ${FILTER_PARAMS.Logs.createdAt.filter(partitionFilter)}
  `,

  measures: {
    count: {
      type: `count`,
    },

    errorCount: {
      type: `count`,
      filters: [
        { sql: `${CUBE.isError} = 'Yes'` }
      ]
    },

    errorRate: {
      type: `number`,
      sql: `100.0 * ${errorCount} / ${count}`,
      format: `percent`
    }
  },

  dimensions: {
    status: {
      sql: `status`,
      type: `number`
    },

    isError: {
      type: `string`,
      case: {
        when: [{
          sql: `${CUBE}.status >= 400`, label: `Yes`
        }],
        else: { label: `No` }
      }
    },

    createdAt: {
      sql: `from_unixtime(created_at)`,
      type: `time`
    }
  }
});

ที่นี่เราใช้ตัวแปร FILTER_PARAMSเพื่อสร้างแบบสอบถาม SQL พร้อมตัวกรองพาร์ติชัน

นอกจากนี้เรายังตั้งค่าเมตริกและพารามิเตอร์ที่เราต้องการแสดงบนแดชบอร์ดและระบุการรวมล่วงหน้า Cube.js จะสร้างตารางเพิ่มเติมพร้อมข้อมูลที่รวบรวมไว้ล่วงหน้า และจะอัปเดตข้อมูลโดยอัตโนมัติเมื่อมาถึง สิ่งนี้ไม่เพียงแต่เพิ่มความเร็วในการสืบค้นเท่านั้น แต่ยังช่วยลดต้นทุนในการใช้ Athena อีกด้วย

มาเพิ่มข้อมูลนี้ลงในไฟล์สคีมาข้อมูล:

preAggregations: {
  main: {
    type: `rollup`,
    measureReferences: [count, errorCount],
    dimensionReferences: [isError, status],
    timeDimensionReference: createdAt,
    granularity: `day`,
    partitionGranularity: `month`,
    refreshKey: {
      sql: FILTER_PARAMS.Logs.createdAt.filter((from, to) => 
        `select
           CASE WHEN from_iso8601_timestamp(${to}) + interval '3' day > now()
           THEN date_trunc('hour', now()) END`
      )
    }
  }
}

เราระบุในโมเดลนี้ว่าจำเป็นต้องรวบรวมข้อมูลล่วงหน้าสำหรับตัววัดทั้งหมดที่ใช้ และใช้การแบ่งพาร์ติชันตามเดือน การแบ่งพาร์ติชันก่อนการรวมกลุ่ม สามารถเพิ่มความเร็วในการรวบรวมและอัปเดตข้อมูลได้อย่างมาก

ตอนนี้เราสามารถประกอบแดชบอร์ดได้แล้ว!

แบ็กเอนด์ Cube.js มีให้ REST API และชุดไลบรารีไคลเอนต์สำหรับเฟรมเวิร์กส่วนหน้ายอดนิยม เราจะใช้เวอร์ชัน React ของไคลเอ็นต์เพื่อสร้างแดชบอร์ด Cube.js ให้ข้อมูลเท่านั้น ดังนั้นเราจำเป็นต้องมีไลบรารีการแสดงภาพ ฉันชอบมัน รีชาร์ตแต่คุณสามารถใช้อะไรก็ได้

เซิร์ฟเวอร์ Cube.js ยอมรับคำขอมา รูปแบบ JSONซึ่งระบุเมตริกที่จำเป็น ตัวอย่างเช่น ในการคำนวณจำนวนข้อผิดพลาดที่ Nginx ระบุในแต่ละวัน คุณต้องส่งคำขอต่อไปนี้:

{
  "measures": ["Logs.errorCount"],
  "timeDimensions": [
    {
      "dimension": "Logs.createdAt",
      "dateRange": ["2019-01-01", "2019-01-07"],
      "granularity": "day"
    }
  ]
}

มาติดตั้งไคลเอนต์ Cube.js และไลบรารีส่วนประกอบ React ผ่าน NPM:

$ npm i --save @cubejs-client/core @cubejs-client/react

เรานำเข้าส่วนประกอบ cubejs и QueryRendererเพื่อดาวน์โหลดข้อมูลและรวบรวมแดชบอร์ด:

รหัสแดชบอร์ด

import React from 'react';
import { LineChart, Line, XAxis, YAxis } from 'recharts';
import cubejs from '@cubejs-client/core';
import { QueryRenderer } from '@cubejs-client/react';

const cubejsApi = cubejs(
  'YOUR-CUBEJS-API-TOKEN',
  { apiUrl: 'http://localhost:4000/cubejs-api/v1' },
);

export default () => {
  return (
    <QueryRenderer
      query={{
        measures: ['Logs.errorCount'],
        timeDimensions: [{
            dimension: 'Logs.createdAt',
            dateRange: ['2019-01-01', '2019-01-07'],
            granularity: 'day'
        }]
      }}
      cubejsApi={cubejsApi}
      render={({ resultSet }) => {
        if (!resultSet) {
          return 'Loading...';
        }

        return (
          <LineChart data={resultSet.rawData()}>
            <XAxis dataKey="Logs.createdAt"/>
            <YAxis/>
            <Line type="monotone" dataKey="Logs.errorCount" stroke="#8884d8"/>
          </LineChart>
        );
      }}
    />
  )
}

แหล่งที่มาของแดชบอร์ดมีอยู่ที่ รหัสแซนด์บ็อกซ์.

ที่มา: will.com

เพิ่มความคิดเห็น