เราแก้ปัญหาที่ใช้งานได้จริงใน Zabbix โดยใช้ JavaScript

เราแก้ปัญหาที่ใช้งานได้จริงใน Zabbix โดยใช้ JavaScript
ทิฆอน ยูสคอฟ, วิศวกรทีมบูรณาการ Zabbix

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

JavaScript สำหรับ Zabbix

ในเดือนเมษายน 2019 ได้เปิดตัว Zabbix 4.2 ที่มีการประมวลผลล่วงหน้าของ JavaScript หลายคนตื่นเต้นกับแนวคิดที่จะละทิ้งการเขียนสคริปต์ที่นำข้อมูลไปไว้ที่ใดที่หนึ่ง ย่อยและจัดเตรียมในรูปแบบที่ Zabbix เข้าใจ และทำการตรวจสอบง่ายๆ ที่จะได้รับข้อมูลที่ Zabbix ไม่พร้อมสำหรับการจัดเก็บและประมวลผล และ จากนั้นประมวลผลสตรีมข้อมูลนี้โดยใช้เครื่องมือ Zabbix และ JavaScript เมื่อรวมกับการค้นหาระดับต่ำและรายการที่ต้องพึ่งพาซึ่งปรากฏใน Zabbix 3.4 เราได้รับแนวคิดที่ค่อนข้างยืดหยุ่นสำหรับการจัดเรียงและจัดการข้อมูลที่ได้รับ

ใน Zabbix 4.4 ซึ่งเป็นความต่อเนื่องทางตรรกะของการประมวลผลล่วงหน้าใน JavaScript วิธีการแจ้งเตือนใหม่ปรากฏขึ้น - Webhook ซึ่งสามารถใช้เพื่อรวมการแจ้งเตือน Zabbix กับแอปพลิเคชันของบุคคลที่สามได้อย่างง่ายดาย

JavaScript และ Duktapes

เหตุใดจึงเลือก JavaScript และ Duktape มีการพิจารณาตัวเลือกต่าง ๆ สำหรับภาษาและเอ็นจิ้น:

  • หลัว - หลัว 5.1
  • หลัว-หลัวจิต
  • Javascript - ดุ๊กเทป
  • จาวาสคริปต์ – JerryScript
  • งูหลามฝังตัว
  • Perl ฝังตัว

เกณฑ์การคัดเลือกหลัก ได้แก่ ความแพร่หลาย ความง่ายในการรวมเครื่องยนต์เข้ากับผลิตภัณฑ์ การใช้ทรัพยากรต่ำและประสิทธิภาพโดยรวมของเครื่องยนต์ และความปลอดภัยของการนำโค้ดในภาษานี้เข้าสู่การตรวจสอบ จากการรวมกันของตัวบ่งชี้ JavaScript ชนะในเอ็นจิ้น Duktape

เราแก้ปัญหาที่ใช้งานได้จริงใน Zabbix โดยใช้ JavaScript

เกณฑ์การคัดเลือกและการทดสอบประสิทธิภาพ

คุณสมบัติของ Duktape:

- มาตรฐาน ECMAScript E5/E5.1
— โมดูล Zabbix สำหรับ Duktape:

  • Zabbix.log() - ช่วยให้คุณเขียนข้อความที่มีรายละเอียดในระดับต่างๆ ลงในบันทึกเซิร์ฟเวอร์ Zabbix ได้โดยตรง ซึ่งทำให้สามารถเชื่อมโยงข้อผิดพลาดได้ เช่น ใน Webhook กับสถานะเซิร์ฟเวอร์
  • CurlHttpRequest() - อนุญาตให้คุณส่งคำขอ HTTP ไปยังเครือข่ายซึ่งใช้ Webhook เป็นพื้นฐาน
  • atob() และ btoa() - ให้คุณเข้ารหัสและถอดรหัสสตริงในรูปแบบ Base64

หมายเหตุ. Duktape เป็นไปตามมาตรฐาน ACME Zabbix ใช้สคริปต์เวอร์ชัน 2015 การเปลี่ยนแปลงที่ตามมาเป็นเรื่องเล็กน้อย ดังนั้นจึงสามารถละเว้นได้.

JavaScript เมจิค

ความมหัศจรรย์ทั้งหมดของ JavaScript อยู่ที่การพิมพ์แบบไดนามิกและการแคสต์ประเภท: สตริง ตัวเลข และบูลีน

ซึ่งหมายความว่าไม่จำเป็นต้องประกาศล่วงหน้าว่าตัวแปรประเภทใดควรส่งคืนค่า

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

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

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

ตัวอย่างเช่น ถ้าสำหรับสำหรับวัตถุ 'obj' มีการกำหนดวิธีการ ถึงสตริง,

`var obj = { toString() { return "200" }}` 

วิธี ถึงสตริง คืนค่าเป็นสตริง และเมื่อเพิ่มสตริงด้วยตัวเลข เราจะได้สตริงที่ติดกาว:

`obj + 1 // '2001'` 

`obj + 'a' // ‘200a'`

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

`var obj = { toString() { return 200 }}` 

`obj + 1 // '2001'`

ในกรณีนี้ หากเราทำการเพิ่มเติมด้วยสตริง การแปลงสตริงจะดำเนินการ และเราจะได้สตริงที่ติดกาว

`obj + 'a' // ‘200a'`

นี่เป็นสาเหตุของข้อผิดพลาดจำนวนมากโดยผู้ใช้ JavaScript มือใหม่

วิธีการ ถึงสตริง คุณสามารถเขียนฟังก์ชันที่จะเพิ่มมูลค่าปัจจุบันของวัตถุทีละ 1

เราแก้ปัญหาที่ใช้งานได้จริงใน Zabbix โดยใช้ JavaScript
การดำเนินการของสคริปต์โดยมีเงื่อนไขว่าตัวแปรเท่ากับ 3 และเท่ากับ 4 ด้วย

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

เราแก้ปัญหาที่ใช้งานได้จริงใน Zabbix โดยใช้ JavaScript
การเปรียบเทียบโดยไม่มีการหล่อแบบ

หมายเหตุ. อย่าใช้การเปรียบเทียบนักแสดงโดยไม่จำเป็น.

สำหรับสคริปต์ที่ซับซ้อน เช่น Webhooks ที่มีตรรกะที่ซับซ้อน ซึ่งต้องมีการเปรียบเทียบกับการแคสต์ประเภท ขอแนะนำให้เขียนการตรวจสอบล่วงหน้าสำหรับค่าที่ส่งคืนตัวแปรและจัดการความไม่สอดคล้องกันและข้อผิดพลาด

สื่อเว็บฮุค

ในช่วงปลายปี 2019 และต้นปี 2020 ทีมผสานรวม Zabbix ได้พัฒนา Webhooks และการผสานรวมแบบสำเร็จรูปที่มาพร้อมกับการกระจาย Zabbix อย่างแข็งขัน

เราแก้ปัญหาที่ใช้งานได้จริงใน Zabbix โดยใช้ JavaScript
เชื่อมโยงไปยัง เอกสาร

กระบวนการเตรียมการผลิต

  • การถือกำเนิดของการประมวลผลล่วงหน้าใน JavaScript ทำให้สามารถละทิ้งสคริปต์ภายนอกส่วนใหญ่ได้ และในปัจจุบันใน Zabbix คุณสามารถรับค่าใดๆ และแปลงเป็นค่าที่แตกต่างไปจากเดิมอย่างสิ้นเชิง
  • การประมวลผลล่วงหน้าใน Zabbix ดำเนินการโดยโค้ด JavaScript ซึ่งเมื่อคอมไพล์เป็น bytecode แล้ว จะถูกแปลงเป็นฟังก์ชันที่ใช้ค่าเดียวเป็นพารามิเตอร์ ความคุ้มค่า เป็นสตริง (สตริงสามารถมีทั้งตัวเลขและตัวเลข)
  • เนื่องจากเอาต์พุตเป็นฟังก์ชัน จึงจำเป็นต้องต่อท้ายสคริปต์ กลับ.
  • คุณสามารถใช้มาโครแบบกำหนดเองในโค้ดได้
  • ทรัพยากรสามารถถูกจำกัดได้ไม่เฉพาะในระดับระบบปฏิบัติการเท่านั้น แต่ยังรวมถึงทางโปรแกรมด้วย ขั้นตอนการประมวลผลล่วงหน้าได้รับการจัดสรร RAM สูงสุด 10 เมกะไบต์และจำกัดเวลารัน 10 วินาที

เราแก้ปัญหาที่ใช้งานได้จริงใน Zabbix โดยใช้ JavaScript

หมายเหตุ. ค่าการหมดเวลา 10 วินาทีนั้นค่อนข้างมาก เนื่องจากการรวบรวมรายการข้อมูลตามเงื่อนไขนับพันรายการใน 1 วินาทีตามสถานการณ์การประมวลผลล่วงหน้าที่ค่อนข้าง "หนัก" อาจทำให้ Zabbix ช้าลงได้ ดังนั้นจึงไม่แนะนำให้ใช้การประมวลผลล่วงหน้าเพื่อเรียกใช้สคริปต์ JavaScript ที่สมบูรณ์ผ่านองค์ประกอบข้อมูลเงาที่เรียกว่า (รายการจำลอง) ซึ่งจะเรียกใช้เพื่อดำเนินการประมวลผลล่วงหน้าเท่านั้น.

คุณสามารถตรวจสอบรหัสของคุณผ่านการทดสอบก่อนการประมวลผลหรือใช้ยูทิลิตี้ zabbix_js:

`zabbix_js -s *script-file -p *input-param* [-l log-level] [-t timeout]`

`zabbix_js -s script-file -i input-file [-l log-level] [-t timeout]`

`zabbix_js -h`

`zabbix_js -V`

งานปฏิบัติ

งาน 1

แทนที่รายการที่คำนวณด้วยการประมวลผลล่วงหน้า

สภาพ: รับอุณหภูมิเป็นฟาเรนไฮต์จากเซ็นเซอร์เพื่อเก็บเป็นเซลเซียส

ก่อนหน้านี้เราจะสร้างรายการที่เก็บอุณหภูมิเป็นองศาฟาเรนไฮต์ หลังจากนั้น รายการข้อมูลอื่น (คำนวณ) ที่จะแปลงฟาเรนไฮต์เป็นเซลเซียสโดยใช้สูตร

ปัญหา:

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

ทางออกหนึ่งคือย้ายจากช่วงการตรวจสอบที่ยืดหยุ่นไปใช้ช่วงเวลาคงที่เพื่อให้แน่ใจว่ารายการที่คำนวณได้รับการประเมินหลังจากรายการที่ได้รับข้อมูล (ในกรณีของเรา อุณหภูมิเป็นองศาฟาเรนไฮต์)

แต่ถ้ายกตัวอย่างเช่น เราใช้เทมเพลตเพื่อตรวจสอบอุปกรณ์จำนวนมาก และทำการตรวจสอบทุกๆ 30 วินาที Zabbix จะ "แฮ็ก" เป็นเวลา 29 วินาที และในวินาทีสุดท้ายจะเริ่มตรวจสอบและคำนวณ สิ่งนี้จะสร้างคิวและส่งผลต่อประสิทธิภาพ ดังนั้น ขอแนะนำให้ใช้ช่วงเวลาคงที่เฉพาะในกรณีที่จำเป็นจริงๆ เท่านั้น

ในปัญหานี้ ทางออกที่ดีที่สุดคือการประมวลผลล่วงหน้าของ JavaScript หนึ่งบรรทัดที่แปลงองศาฟาเรนไฮต์เป็นองศาเซลเซียส:

`return (value - 32) * 5 / 9;`

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

เราแก้ปัญหาที่ใช้งานได้จริงใน Zabbix โดยใช้ JavaScript

`return (parseInt(value) + parseInt("{$EXAMPLE.MACRO}"));`

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

เราแก้ปัญหาที่ใช้งานได้จริงใน Zabbix โดยใช้ JavaScript

`return (value + "{$EXAMPLE.MACRO}");`

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

ภารกิจที่ 2

รับเวลาเป็นวินาทีจนถึงจุดสิ้นสุดของใบรับรอง

สภาพ: บริการออกใบรับรองวันหมดอายุในรูปแบบ "12 ก.พ. 12:33:56 2022 GMT"

ใน ECMAScript5 date.parse() ยอมรับวันที่ในรูปแบบ ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) มีความจำเป็นต้องส่งสตริงในรูปแบบ MMM DD YYYY HH:mm:ss ZZ

ปัญหา: ค่าเดือนจะแสดงเป็นข้อความ ไม่ใช่ตัวเลข Duktape ไม่ยอมรับข้อมูลในรูปแบบนี้

ตัวอย่างโซลูชัน:

  • ก่อนอื่น มีการประกาศตัวแปรที่รับค่า (สคริปต์ทั้งหมดเป็นการประกาศตัวแปรที่แสดงรายการโดยคั่นด้วยเครื่องหมายจุลภาค)

  • ในบรรทัดแรก เราได้รับวันที่ในพารามิเตอร์ ความคุ้มค่า และคั่นด้วยช่องว่างด้วยวิธี แยก. ดังนั้นเราจึงได้อาร์เรย์ที่แต่ละองค์ประกอบของอาร์เรย์เริ่มต้นที่ดัชนี 0 สอดคล้องกับองค์ประกอบวันที่หนึ่งก่อนและหลังช่องว่าง แยก (0) - เดือน, แยก (1) - ตัวเลข, แยก (2) - สตริงที่มีเวลา ฯลฯ หลังจากนั้น แต่ละองค์ประกอบของวันที่สามารถเข้าถึงได้โดยดัชนีในอาร์เรย์

`var split = value.split(' '),`

  • แต่ละเดือน (ตามลำดับเวลา) จะสอดคล้องกับดัชนีของตำแหน่งในอาร์เรย์ (ตั้งแต่ 0 ถึง 11) หากต้องการแปลงค่าข้อความเป็นค่าตัวเลข ให้เพิ่มค่าหนึ่งลงในดัชนีเดือน (เนื่องจากเดือนจะมีหมายเลขเริ่มต้นที่ 1) ในกรณีนี้นิพจน์ที่มีการเพิ่มหนึ่งจะอยู่ในวงเล็บเพราะมิฉะนั้นจะได้รับสตริงไม่ใช่ตัวเลข ในตอนท้ายเราทำ ชิ้น () - ตัดอาร์เรย์จากส่วนท้ายให้เหลือเพียงสองตัว (ซึ่งสำคัญสำหรับเดือนที่มีตัวเลขสองหลัก)

`MONTHS_LIST = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],`

`month_index = ('0' + (MONTHS_LIST.indexOf(split[0]) + 1)).slice(-2),`

  • เราสร้างสตริงในรูปแบบ ISO จากค่าที่ได้รับโดยการเพิ่มสตริงตามปกติในลำดับที่เหมาะสม

`ISOdate = split[3] + '-' + month_index + '-' + split[1] + 'T' + split[2],`

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

  • จากนั้นเราสามารถรับวันที่ปัจจุบันใน JavaScript ในรูปแบบ Unix Timestamp และลบออกจากวันที่หมดอายุของใบรับรองเพื่อให้ได้จำนวนมิลลิวินาทีนับจากนี้ไปจนกว่าใบรับรองจะหมดอายุ

`now = Date.now();`

  • เราหารมูลค่าที่ได้รับด้วยหนึ่งพันเพื่อรับวินาทีใน Zabbix

`return parseInt((Date.parse(ISOdate) - now) / 1000);`

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

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

ดูรายงาน

ที่มา: will.com

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