środa, 5 marca 2014

Zabbix - Interface WEB

Modyfikacje kodu interface WEB

Już od dawna przymierzałem się do drobnych modyfikacji interface webowego Zabbix. Za każdym razem odstraszało mnie przygotowanie środowiska do pracy z PHP. 

Z tego co widzę projekt się nadal rozwija, jednak przy każdych zmianach mam wątpliwości czy aby na pewno słuszny kierunek to obiera.

Na początek powiem, że ogólna koncepcja nie jest zła i dość daleko zaszła. Brakuje zdecydowanie estetycznego dopracowania i stabilności (szczególnie w interface od strony użytkownika). Nie będę sobie zawracał teraz głowy gdzie i kiedy się sypie. W wielu miejscach brakuje prostych filtrów. Przy dużej ilości elementów typu Template, Screen bieda się odnaleźć - właśnie tam nie ma filtrów. Mam wątpliwości co do użyteczności takiego czegoś jak makro.

Takie właśnie drobne rzeczy chciałem sprawdzić czy da się poprawić.

Da się!

Ale o zgrozo zajrzałem w jaki sposób jest budowana formatka i po prostu wolna ameryka!

Wziąłem sobie na pulpit screenconf.php i wzorując się na hosts.php próbowałem go wzbogacić o filtr.

Postaram się opisać jak to zrobiłem i opisać ogólną koncepcję, która jakoś tam się rysuje.

Gdzie sesja

Nie jest to dziwne... w java - Servlet itp takie coś jest jako obiekt. Tu na próżno szukać. Z tego co widzę to do przechowywania takich rzeczy jest CProfile
// aktualizacja wartości w profilu
CProfile::update('web.template.filter_template', $_REQUEST['filter_template'], PROFILE_TYPE_STR);

// pobranie wartości z profilu
CProfile::get('web.template.filter_template')

Filtrowanie parametrów wejściowych

Podejście które autorzy zastosowali polega na przepuszczeniu przez $_REQUEST tylko zadeklarowanych parametrów. Już na wstępie jest robiona walidacja dopuszczalnych wartości w oparciu o tablicę $fields.
Bardzo niewygodne podejście bo już na samym wstępie trzeba wiedzieć jakie będą dopuszczalne parametry i ich typy. Wymaga to wielokrotnej i rozproszonej deklaracji. W pierwszej kolejności na $fields, potem w przepisywaniu parametrów do określonych kolekcji takich jak CProfile reprezentujących profil, czy pola.
Trzeba to mieć na uwadze. Ja się przejechałem nie mogłem dotrzeć dlaczego pomimo tego, że parametry się przesyłają nie widać ich w $_REQUEST. Załatwiała mnie check_fields($fields). Właśnie ta funkcja waliduje co może być w $_REQUEST.

Template

Są ... ale nie jakieś tam cudo. Po prostu jest to taki sam plik php jak główny powiedzmy kontroler. Może różnica jest umowna że w tym template powinniśmy korzystać z $data do dekorowania zawartości.

// render view
$screenView = new CView('configuration.screen.list', $data);
$screenView->render();
$screenView->show();

Jak widać żadnych sensacji. Pliki są czytane z include/views w tym wypadku będzie to

include/views/configuration.screen.list.php

Renderowanie filtrów i elementów

Takie podejście jak tu już się spotkałem w wielu projektach. Klasy odpowiedzialne za generowanie konkretnych elementów HTML. Jednym z trochę już archaicznych rozwiązań z Java to ECS http://jakarta.apache.org/ecs/

Filtrowanie danych

Dane do list są dostarczane przez API. Można powiedzieć że na tym poziomie w ogóle odcinamy się od bazy. Nie posługujemy się ani jak w Java obiektami Query, Connection. Warstwa abstrakcji na tym poziomie wydaje się wystarczająca. 
// pobranie listy temlate
API::Template()->get($options);
Warunki są przekazywane w $options mogą być dość złożone.
Na pierwszy rzut może wydawać się to skomplikowane, ale na szczęście API jest dość dobrze opisane. Można znaleźć na https://www.zabbix.com/documentation/2.0/manual/appendix/api/api
Jeżeli mam się odnieść do pobierania listy template będzie to https://www.zabbix.com/documentation/2.0/manual/appendix/api/template/get, Niestety trzeba się tu zapoznać z pozycjami, które możemy używać w options bo są one różne dla różnych rodzajów danych. Ogólna zasada jest taka: filtrowanie z like wykorzystuje search
// przygotowanie options do wywołania API
$options = array(
 'editable' => 1,
 'sortfield' => $sortfield,
 'sortorder' => $sortorder,
 'limit' => ($config['search_limit']+1),
 'search' => array()
);
// inicjowanie pozycji po których szukamy z like
// tu gdy jest ustawione filter_template to dodane jest szukanie po host
$local_template_name = $_REQUEST['filter_template'];
if (!zbx_empty($local_template_name)) {
 $options['search']['host'] = $local_template_name;
}
W moim odczuciu z opisu API nie do końca wynika co podać jako warunki szukania. Wydaje się jednak dość sensowna metoda polegająca na sprawdzeniu jakie zostanie przygotowane zapytanie.
Można to zrobić wykonując breakpoint-a w klasie wykonującej zapytanie. Ponieważ aktualnie korzystam z mysql-a zrobiłem to w include/db.inc.php w funkcjach DBexecute oraz DBselect niezawodnie można tam sprawdzić query które idzie. 

Standardy

W całym projekcje słabo widać nową technologię - ale nie to jest przecież najważniejsze. Czasem działa dlatego, że nie zostało przeenżynierowane. Ale jednak raczej są to stare techniki MVC i to własnej konstrukcji. Nie mówię że traktuje to jako wadę. Ale patrząc na ilość pracy przy napisaniu większej ilości formatek już może być problem aby to ogarnąć. Jest ogólna separacja, kontroler-a, dostarczenia danych, renderowania rezultatów ale bardzo umowna i raczej słabo przestrzegana.

Wyświetlanie na screen wartości typu plain text

W moim odczuciu w przypadku tego typu informacji powinna być wykonana konwersja podobnie jak w przypadku "Last value" z Latest data (latest.php). Ogólnie wydaje mi się że jest to niespójność dlatego że na wykresie item który ma zdefiniowane unit jest prezentowany z uwzględnieniem konwersji do podanych jednostek (wybierany jest adekwatny dekorator - jeżeli da się to zrobić) W tym miejscu po wybraniu jednostek jako sekundy (wszędzie jest wyświetlane jako czas) ale na screen ze zdefiniowanym "plain text" wyświetla się bez dekoratora (jawny timestamp).

// latest.php
$change=convert_units($db_item['lastvalue']-$db_item['prevvalue'],$db_item['units']);
// include\func.inc.php
// gdy s 
convertUnitsS
 
// include\views\monitoring.screen.php

// include\screens.inc.php
$resourcetype = $screenItem['resourcetype'];
$resourcetype == SCREEN_RESOURCE_PLAIN_TEXT
get_screen_plaintext
$element = get_screen($screen, 0, $effectiveperiod);


get_screen_plaintext
get_item_by_itemid
... oczywiście będzie ciąg dalszy
Zamierzam dodać w tym przykładzie filtry do miejsc które wspomniałem wcześniej.



Brak komentarzy:

Prześlij komentarz