Chúng tôi giải quyết các vấn đề thực tế trong Zabbix bằng JavaScript

Chúng tôi giải quyết các vấn đề thực tế trong Zabbix bằng JavaScript
Tikhon Uskov, Kỹ sư nhóm tích hợp Zabbix

Zabbix là một nền tảng có thể tùy chỉnh được sử dụng để giám sát mọi loại dữ liệu. Kể từ các phiên bản đầu tiên của Zabbix, quản trị viên giám sát đã có khả năng chạy các tập lệnh khác nhau thông qua Hoạt động để kiểm tra các nút mạng mục tiêu. Đồng thời, việc khởi chạy các tập lệnh dẫn đến một số khó khăn, bao gồm nhu cầu hỗ trợ các tập lệnh, việc phân phối chúng tới các nút và proxy giao tiếp, cũng như hỗ trợ cho các phiên bản khác nhau.

JavaScript cho Zabbix

Vào tháng 2019 năm 4.2, Zabbix 3.4 đã được giới thiệu với tính năng tiền xử lý JavaScript. Nhiều người đã hào hứng với ý tưởng từ bỏ việc viết các tập lệnh lấy dữ liệu ở đâu đó, phân tích và cung cấp ở định dạng mà Zabbix hiểu và thực hiện các kiểm tra đơn giản sẽ nhận dữ liệu chưa sẵn sàng để Zabbix lưu trữ và xử lý, và sau đó xử lý luồng dữ liệu này bằng công cụ Zabbix và JavaScript. Cùng với các mục phụ thuộc và khám phá cấp thấp xuất hiện trong Zabbix XNUMX, chúng tôi có một khái niệm khá linh hoạt để sắp xếp và quản lý dữ liệu nhận được.

Trong Zabbix 4.4, như một sự tiếp nối hợp lý của quá trình tiền xử lý trong JavaScript, một phương thức thông báo mới đã xuất hiện - Webhook, có thể được sử dụng để dễ dàng tích hợp thông báo Zabbix với các ứng dụng của bên thứ ba.

JavaScript và Duktapes

Tại sao JavaScript và Duktape được chọn? Các tùy chọn khác nhau cho ngôn ngữ và công cụ đã được xem xét:

  • Lua - Lua 5.1
  • Lua - LuaJIT
  • Javascript - Duktape
  • Javascript - JerryScript
  • Python nhúng
  • Perl nhúng

Các tiêu chí lựa chọn chính là mức độ phổ biến, dễ tích hợp động cơ vào sản phẩm, mức tiêu thụ tài nguyên thấp và hiệu suất tổng thể của động cơ cũng như sự an toàn khi đưa mã bằng ngôn ngữ này vào giám sát. Dựa trên sự kết hợp của các chỉ số, JavaScript đã giành chiến thắng trên công cụ Duktape.

Chúng tôi giải quyết các vấn đề thực tế trong Zabbix bằng JavaScript

Tiêu chí lựa chọn và kiểm tra hiệu suất

Các tính năng của Duktape:

- Tiêu chuẩn ECMAScript E5/E5.1
- Mô-đun Zabbix cho Duktape:

  • Zabbix.log() - cho phép bạn viết thông báo với các mức độ chi tiết khác nhau trực tiếp vào nhật ký Máy chủ Zabbix, giúp bạn có thể liên kết các lỗi, chẳng hạn như trong Webhook, với trạng thái máy chủ.
  • CurlHttpRequest() - cho phép bạn thực hiện các yêu cầu HTTP tới mạng dựa trên việc sử dụng Webhook.
  • atob() và btoa() - cho phép bạn mã hóa và giải mã các chuỗi ở định dạng Base64.

CHÚ Ý. Duktape tuân thủ các tiêu chuẩn ACME. Zabbix sử dụng phiên bản 2015 của tập lệnh. Những thay đổi sau đó là nhỏ, vì vậy chúng có thể được bỏ qua..

ma thuật JavaScript

Tất cả sự kỳ diệu của JavaScript nằm ở kiểu gõ động và kiểu truyền: chuỗi, số và boolean.

Điều này có nghĩa là không cần phải khai báo trước kiểu mà biến sẽ trả về giá trị.

Trong các hoạt động toán học, các giá trị được trả về bởi các toán tử hàm được chuyển thành số. Ngoại lệ đối với các hoạt động như vậy là phép cộng, bởi vì nếu ít nhất một trong số các thuật ngữ là một chuỗi, chuyển đổi chuỗi được áp dụng cho tất cả các thuật ngữ.

CHÚ Ý. Các phương thức chịu trách nhiệm cho các phép biến đổi như vậy thường được triển khai trong các nguyên mẫu gốc của đối tượng, giá trị của и toString. giá trị của được gọi trong quá trình chuyển đổi số và luôn luôn trước phương thức toString. Phương pháp giá trị của phải trả về các giá trị nguyên thủy, nếu không thì kết quả của nó bị bỏ qua.

Một phương thức được gọi trên một đối tượng giá trị của. Nếu nó không được tìm thấy hoặc không trả về giá trị nguyên thủy, phương thức này được gọi là toString. Nếu phương pháp toString không tìm thấy, tìm kiếm giá trị của trong nguyên mẫu của đối tượng và mọi thứ được lặp lại cho đến khi quá trình xử lý giá trị hoàn tất và tất cả các giá trị trong biểu thức được chuyển thành cùng loại. Nếu đối tượng thực hiện một phương pháp toString, trả về một giá trị nguyên thủy, thì nó được sử dụng để chuyển đổi chuỗi. Tuy nhiên, kết quả của việc áp dụng phương pháp này không nhất thiết phải là một chuỗi.

Ví dụ: nếu for for object 'obj' phương pháp được xác định toString,

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

Phương thức toString trả về chính xác một chuỗi và khi thêm một chuỗi với một số, chúng ta sẽ nhận được một chuỗi được dán:

`obj + 1 // '2001'` 

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

Nhưng nếu bạn viết lại toString, để phương thức trả về một số, khi đối tượng được thêm vào, một phép toán có chuyển đổi số sẽ được thực hiện và sẽ thu được kết quả của phép cộng toán học.

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

`obj + 1 // '2001'`

Trong trường hợp này, nếu chúng ta thực hiện phép cộng với một chuỗi, thì quá trình chuyển đổi chuỗi được thực hiện và chúng ta nhận được một chuỗi được dán.

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

Đây là lý do cho một số lượng lớn các lỗi của người dùng JavaScript mới làm quen.

phương pháp toString bạn có thể viết một hàm sẽ tăng giá trị hiện tại của đối tượng lên 1.

Chúng tôi giải quyết các vấn đề thực tế trong Zabbix bằng JavaScript
Thực thi tập lệnh, với điều kiện là biến bằng 3 và nó cũng bằng 4.

Khi so sánh với ép kiểu (==), phương thức được thực thi mỗi lần toString với chức năng gia tăng giá trị. Theo đó, với mỗi lần so sánh tiếp theo, giá trị tăng lên. Điều này có thể tránh được bằng cách sử dụng phép so sánh không ép kiểu (===).

Chúng tôi giải quyết các vấn đề thực tế trong Zabbix bằng JavaScript
So sánh không ép kiểu

CHÚ Ý. Không sử dụng phép so sánh diễn viên một cách không cần thiết.

Đối với các tập lệnh phức tạp, chẳng hạn như Webhook có logic phức tạp, yêu cầu so sánh với truyền kiểu, bạn nên viết trước các kiểm tra cho các giá trị trả về biến và xử lý sự không nhất quán và lỗi.

Phương tiện webhook

Vào cuối năm 2019 và đầu năm 2020, nhóm tích hợp Zabbix đã tích cực phát triển Webhook và các tích hợp sẵn dùng đi kèm với bản phân phối Zabbix.

Chúng tôi giải quyết các vấn đề thực tế trong Zabbix bằng JavaScript
Liên kết đến tài liệu

Sơ chế

  • Sự ra đời của tiền xử lý trong JavaScript giúp loại bỏ hầu hết các tập lệnh bên ngoài và hiện tại trong Zabbix, bạn có thể nhận bất kỳ giá trị nào và chuyển đổi nó thành một giá trị hoàn toàn khác.
  • Quá trình tiền xử lý trong Zabbix được triển khai bằng mã JavaScript, khi được biên dịch thành mã byte, mã này sẽ được chuyển đổi thành một hàm nhận một giá trị duy nhất làm tham số giá trị dưới dạng một chuỗi (một chuỗi có thể chứa cả chữ số và số).
  • Vì đầu ra là một hàm, nên ở cuối tập lệnh là bắt buộc trở lại.
  • Có thể sử dụng các macro tùy chỉnh trong mã.
  • Tài nguyên có thể bị giới hạn không chỉ ở cấp độ hệ điều hành mà còn theo chương trình. Bước tiền xử lý được phân bổ tối đa 10 megabyte RAM và giới hạn thời gian chạy là 10 giây.

Chúng tôi giải quyết các vấn đề thực tế trong Zabbix bằng JavaScript

CHÚ Ý. Giá trị thời gian chờ 10 giây là khá nhiều, bởi việc thu thập hàng nghìn mục dữ liệu có điều kiện trong 1 giây theo kịch bản tiền xử lý khá “nặng đô” có thể làm chậm Zabbix. Do đó, không nên sử dụng tiền xử lý để thực thi các tập lệnh JavaScript chính thức thông qua cái gọi là phần tử dữ liệu bóng (các mục giả), chỉ được chạy để thực hiện tiền xử lý.

Bạn có thể kiểm tra mã của mình thông qua kiểm tra tiền xử lý hoặc sử dụng tiện ích 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`

Nhiệm vụ thực tế

Nhiệm vụ 1

Thay thế mục được tính toán bằng tiền xử lý.

Tình trạng: Nhận nhiệt độ tính bằng độ F từ cảm biến để lưu trữ tính bằng độ C.

Trước đây, chúng tôi sẽ tạo một mục thu thập nhiệt độ theo độ F. Sau đó, một mục dữ liệu khác (được tính toán) sẽ chuyển đổi độ F thành độ C bằng cách sử dụng công thức.

Vấn đề:

  • Cần nhân bản các phần tử dữ liệu và lưu trữ tất cả các giá trị trong cơ sở dữ liệu.
  • Bạn phải đồng ý về khoảng thời gian cho mục dữ liệu "gốc" được tính toán và sử dụng trong công thức cũng như cho mục dữ liệu được tính toán. Nếu không, mục được tính toán có thể chuyển sang trạng thái không được hỗ trợ hoặc tính toán một giá trị trước đó, điều này sẽ ảnh hưởng đến độ tin cậy của kết quả giám sát.

Một giải pháp là chuyển từ các khoảng thời gian kiểm tra linh hoạt sang các khoảng thời gian cố định để đảm bảo rằng mục được tính toán được đánh giá sau mục nhận dữ liệu (trong trường hợp của chúng tôi là nhiệt độ tính bằng độ F).

Nhưng nếu, ví dụ, chúng tôi sử dụng mẫu để kiểm tra một số lượng lớn thiết bị và quá trình kiểm tra được thực hiện cứ sau 30 giây, thì Zabbix "hack" trong 29 giây và vào giây cuối cùng, nó bắt đầu kiểm tra và tính toán. Điều này tạo ra một hàng đợi và ảnh hưởng đến hiệu suất. Do đó, chỉ nên sử dụng các khoảng thời gian cố định nếu thực sự cần thiết.

Trong vấn đề này, giải pháp tối ưu là tiền xử lý JavaScript một dòng để chuyển đổi độ F thành độ C:

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

Thật nhanh chóng và dễ dàng, bạn không cần tạo các mục dữ liệu không cần thiết và lưu giữ lịch sử trên chúng, đồng thời bạn cũng có thể sử dụng các khoảng thời gian linh hoạt để kiểm tra.

Chúng tôi giải quyết các vấn đề thực tế trong Zabbix bằng JavaScript

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

Tuy nhiên, nếu trong một tình huống giả định, cần phải thêm phần tử dữ liệu đã nhận, ví dụ, với bất kỳ hằng số nào được xác định trong macro, thì phải tính đến tham số đó giá trị mở rộng thành một chuỗi. Trong thao tác cộng chuỗi, hai chuỗi đơn giản được kết hợp thành một.

Chúng tôi giải quyết các vấn đề thực tế trong Zabbix bằng JavaScript

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

Để có được kết quả của một phép toán, cần phải chuyển đổi các loại giá trị thu được sang định dạng số. Đối với điều này, bạn có thể sử dụng chức năng parseInt (), tạo ra một số nguyên, một hàm parseFloat (), tạo ra một số thập phân hoặc một hàm con số, trả về một số nguyên hoặc số thập phân.

Nhiệm vụ 2

Nhận thời gian tính bằng giây cho đến khi kết thúc chứng chỉ.

Tình trạng: dịch vụ đưa ra ngày hết hạn chứng chỉ ở định dạng "Ngày 12 tháng 12 33:56:2022 XNUMX GMT".

Trong ECMAScript5 Ngày.parse () chấp nhận ngày ở định dạng ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ). Cần truyền một chuỗi tới nó ở định dạng MMM DD YYYY HH:mm:ss ZZ

vấn đề: Giá trị tháng được thể hiện dưới dạng văn bản, không phải dưới dạng số. Duktape không chấp nhận dữ liệu ở định dạng này.

Ví dụ giải pháp:

  • Trước hết, một biến được khai báo để nhận một giá trị (toàn bộ tập lệnh là khai báo các biến được liệt kê cách nhau bởi dấu phẩy).

  • Trong dòng đầu tiên, chúng tôi nhận được ngày trong tham số giá trị và tách nó bằng khoảng trắng bằng phương pháp chia. Do đó, chúng ta có một mảng, trong đó mỗi phần tử của mảng, bắt đầu từ chỉ số 0, tương ứng với một phần tử ngày trước và sau một khoảng trắng. tách(0) - tháng, tách(1) - con số, tách(2) - một chuỗi có thời gian, v.v. Sau đó, mỗi phần tử của ngày có thể được truy cập bằng chỉ mục trong mảng.

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

  • Mỗi tháng (theo thứ tự thời gian) tương ứng với chỉ số vị trí của nó trong mảng (từ 0 đến 11). Để chuyển đổi một giá trị văn bản thành một giá trị số, một giá trị được thêm vào chỉ mục tháng (vì các tháng được đánh số bắt đầu từ 1). Trong trường hợp này, biểu thức có thêm một được đặt trong ngoặc, vì nếu không sẽ nhận được một chuỗi chứ không phải một số. Cuối cùng chúng tôi làm lát cắt() - cắt mảng từ cuối để chỉ còn lại hai ký tự (điều quan trọng đối với các tháng có hai chữ số).

`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),`

  • Chúng tôi tạo một chuỗi ở định dạng ISO từ các giá trị thu được bằng cách thêm chuỗi thông thường theo thứ tự thích hợp.

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

Dữ liệu ở định dạng kết quả là số giây từ năm 1970 đến một thời điểm nào đó trong tương lai. Hầu như không thể sử dụng dữ liệu ở định dạng nhận được trong trình kích hoạt, vì Zabbix chỉ cho phép bạn thao tác với macro {Ngày} и {Thời gian}, trả về ngày và giờ ở định dạng thân thiện với người dùng.

  • Sau đó, chúng tôi có thể lấy ngày hiện tại bằng JavaScript ở định dạng Dấu thời gian Unix và trừ nó khỏi ngày hết hạn chứng chỉ kết quả để nhận số mili giây từ bây giờ cho đến khi chứng chỉ hết hạn.

`now = Date.now();`

  • Chúng tôi chia giá trị nhận được cho một nghìn để nhận được giây trong Zabbix.

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

Trong trình kích hoạt, bạn có thể chỉ định biểu thức 'cuối cùng' theo sau là một tập hợp các chữ số tương ứng với số giây trong khoảng thời gian mà bạn muốn phản hồi, chẳng hạn như tính theo tuần. Do đó, trình kích hoạt sẽ thông báo rằng chứng chỉ sẽ hết hạn sau một tuần nữa.

CHÚ Ý. Chú ý đến việc sử dụng parseInt () trong chức năng trở lạiđể chuyển đổi số phân số do phép chia mili giây thành số nguyên. Bạn cũng có thể dùng parseFloat () và lưu trữ dữ liệu phân số.

Xem báo cáo

Nguồn: www.habr.com

Thêm một lời nhận xét