
ทิฆอน ยูสคอฟ, วิศวกรทีมบูรณาการ 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

เกณฑ์การคัดเลือกและการทดสอบประสิทธิภาพ
คุณสมบัติของ Duktape:
- มาตรฐาน
— โมดูล 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

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

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

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

หมายเหตุ. ค่าการหมดเวลา 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;`รวดเร็วและง่ายดาย คุณไม่จำเป็นต้องสร้างรายการข้อมูลที่ไม่จำเป็นและเก็บประวัติไว้ และคุณยังสามารถใช้ช่วงเวลาที่ยืดหยุ่นสำหรับการตรวจสอบได้อีกด้วย

`return (parseInt(value) + parseInt("{$EXAMPLE.MACRO}"));`แต่ถ้าในสถานการณ์สมมติ จำเป็นต้องเพิ่มองค์ประกอบข้อมูลที่ได้รับ ตัวอย่างเช่น ด้วยค่าคงที่ใดๆ ที่กำหนดไว้ในมาโคร จะต้องคำนึงถึงว่าพารามิเตอร์ ความคุ้มค่า ขยายเป็นสตริง ในการดำเนินการเพิ่มสตริง สองสตริงจะถูกรวมเป็นหนึ่งเดียว

`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
