Własne komendy w Splunk

Rozwijając temat Splunk DB Connect, można wysnuć wniosek, że możemy analizować dane niezależnie od technologii ich przechowywania… i tak rzeczywiście jest. Robi się naprawdę ciekawie jeśli pomyślimy tutaj o odpytywaniu ze Splunka klastra elasticsearch’a…

Specjalnie nie poszedłem tak daleko, ale tutaj znajdziecie mój autorski przykład. 90% nagiosów zbiera dane wydajnościowe w plikach rrd (Round Robin Database).

Wykorzystując tą informację stworzyłem własny zestaw komend:
1

2

Co więcej wynik takiego zapytania możemy za darmo zindeksować… Ale o tym w następnym poście.

W tym momencie po chwili zabawy otrzymujemy grafy o którym w przeciętnym nagiosie możemy pomarzyć:
3

4

Jak czas pozwoli, postaram się stworzyć jakieś łatwe narzędzie do obsługi webservice’ów (REST API).

W obronie Splunka…

Taki artykuł pewnie nie spodoba się samemu Splunkowi, ale powszechna, bardzo uproszczona, definicja Splunka powoduje, że jest on uważany za „drogi”. Dlaczego? Splunk na rynku przypiął sobie łatkę zbieracza logów, z miniaturową bazą wiedzy (w porównaniu do SIEMów), wymagającego sporej wiedzy do poprawnego wdrożenia i utrzymania.
Patrząc z tej perspektywy faktycznie – jeśli licencjonujemy dzienny przyrost danych w MB, to nawet wskazywałoby że takie cel przyświeca producentowi.
Pierwszy poważny zarzut to fakt że w razie awarii liczba danych potrafi wzrosnąć kilkukrotnie, więc musimy mieć licencję z „górką”. Nie jest to prawdą, Splunk pozwala na 5 (w przypadku wersji licencjonowanej) lub 3 (licencja free – 500MB bez autoryzacji webowej…) wykroczenia. I to czy zindeksujemy w tym dniu 1000 nowych serwerów wieloletnią historią, czy przekroczymy o 1MB nie ma znaczenia.
Drugi jeszcze poważniejszy, że Splunk nie dostarcza bazy wiedzy, więc nie jest SIEMem. To niestety fakt, trzeba się trochę nagimnastykować, Splunk nie mówi jak, Splunk tylko mówi że można by to zrobić w taki albo inny sposób. Tutaj nie ma co dyskutować, tak jest i koniec. No ok, SIEM jest super robi wszystko sam… o ile mamy same rozwiązania wiodących producentów – i tu jest pole popisu Splunka, nie spotkałem na razie żadnej dużej firmy, która nie napisała by chociażby kilku stron własnego kodu, który nie jest wspierany przez SIEMy – a w Splunku nie robi to różnicy (w końcu i tak trzeba coś wyskrobać).
Ale nie o tym. Poza tymi dwoma typami licencji ciekawszym typem jest licencja „Forwarder”, która daje możliwość autoryzacji, ale nie pozwala indeksować. Zapala się lampka, zbieracz logów nie zbierający logów, po co to komu?! Żeby było śmiesznie Splunk pozwala na analizę danych nie tylko indeksowanych. Wszystko co poniżej można zrobić również na płatnych licencjach, ale niekoniecznie…

Pierwszy gwóźdź do trumny Splunk wbija sobie sam:
Splunk DB Connect

Splunk DB Connect jest pierwszym z pomysłów na co komu licencja bez indeksowania (oczywiście na głównej instancji, a nie na „przepychaczu” logów). Spotkałem się kilkukrotnie z tym, że część logów jest w tabelach baz danych, raczej administratorzy nie uśmiechają się do robienia dblinków więc jeden select żeby coś skorelować odpada, a nawet trudno o dobre analityczne narzędzie. I tak o to mamy odpowiedź – Splunk na froncie sqli, pozwalający ustanowić kilka połączeń bazodanowych, zebrać wyniki, skorelować po dowolnym polu i pokazać ładny wykres dla biznesu.
No ok, mówiłem że nie do logów, a teraz cały czas logi i logi. Ale może to być równie dobrze tabela z zamówieniami od klientów, cennikami dostawców… sky is the limit.

Jak Splunk to robi – kawałek kodu pozwalający na wykorzystanie JDBC do połączenia z bazami danych i efekt jak się patrzy (w dużym przybliżeniu). Byłbym trochę nieuczciwy, gdybym nie wspomniał o managerze i diagnostyce połączeń, które robią dobre wrażenie.

Pytanie w tym momencie powinno brzmieć tak, jak Splunk zmodyfikował sam siebie tak bardzo aplikacją, a no… nie zmodyfikował – wszystko znajduje się w jednym katalogu i jest jedynie konfiguracją, zbiorem dashboardów, dodatkowych komend. To można coś takiego zrobić? Jak najbardziej i jest to niezły pomysł na Splunka. Niebawem pochwalę się tutaj moimi pomysłami na Splunka, wymagającymi 0MB danych zaindeksowanych.

Inżynier

Praca inżynierska wycięła mnie z bloga na kilka miesięcy. W tym czasie co prawda udało mi się napisać kilka artykułów na monitoringserwerow.pl, ale jedynie w listopadzie.
W między czasie odbyłem szereg szkoleń ze Splunka, co tylko utwierdziło mnie w przekonaniu o możliwościach tego rozwiązania.

Wracając do pracy inżynierskiej, jej tematem była „Konwersja monitoringu sieciowego Tkined/scotty do aplikacji www”. Jest ona upubliczniona na wydziałowej stronie internetowej (jak wszystkie prace inżynierskie) – misio.fis.agh.edu.pl.
Dzień po zdanym egzaminie inżynierskim zaczyna mi w głowie kiełkować pomysł na studia magisterskie, niestety w trybie niestacjonarnym.

Sockety UNIXowe w C part 2

Jako, że temat klienta jest dość prosty ze względu na jednowątkowość (w przypadku serwera tak naprawdę każdy połączony miał osobny proces) postanowiłem, że jednak jeszcze dzisiaj go zamieszczę:

Zaczynając:
1. zestaw nagłówków, analogicznie jak w przypadku serwera:
#include <sys/socket.h>
#include <stdio.h>
#include <linux/un.h>
#include <unistd.h>
#include <string.h>[/code]
2. deklaracje
struct sockaddr_un address;
int socket_fd, nbytes;
char buffer[256], buf[256];

3. funkcja socket:
socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if(socket_fd < 0)
{
printf("socket() failed\n");
return 1;
}

4. memset - wyczyśćmy naszą strukturę:
memset(&address, 0, sizeof(struct sockaddr_un));
5. i ustawmy:
address.sun_family = AF_UNIX;
snprintf(address.sun_path, UNIX_PATH_MAX, "./nasz_socket");

6. łączymy
if(connect(socket_fd,
(struct sockaddr *) &address,
sizeof(struct sockaddr_un)) != 0)
{
printf("connect() failed\n");
return 1;
}

7.pętla napisz odczytaj
while (1){
scanf("%s", buf);
nbytes = snprintf(buffer, 256, buf);
write(socket_fd, buffer, nbytes);
nbytes = read(socket_fd, buffer, 256);
buffer[nbytes] = 0;
printf("MESSAGE FROM SERVER: %s\n", buffer);
}

Całość razem:

#include <stdio.h>
#include <sys/socket.h>
#include <linux/un.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
struct sockaddr_un address;
int socket_fd, nbytes;
char buffer[256], buf[256];

socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if(socket_fd < 0)
{
printf("socket() failed\n");
return 1;
}

/* start with a clean address structure */
memset(&address, 0, sizeof(struct sockaddr_un));

address.sun_family = AF_UNIX;
snprintf(address.sun_path, UNIX_PATH_MAX, "./demo_socket");
if(connect(socket_fd,
(struct sockaddr *) &address,
sizeof(struct sockaddr_un)) != 0)
{
printf("connect() failed\n");
return 1;
}

/* nbytes = snprintf(buffer, 256, "hello from a client");
write(socket_fd, buffer, nbytes);
nbytes = read(socket_fd, buffer, 256);
buffer[nbytes] = 0;
printf("MESSAGE FROM SERVER: %s\n", buffer); */
while (1){
scanf("%s", buf);
nbytes = snprintf(buffer, 256, buf);
write(socket_fd, buffer, nbytes);
nbytes = read(socket_fd, buffer, 256);
buffer[nbytes] = 0;
printf("MESSAGE FROM SERVER: %s\n", buffer);
}

close(socket_fd);

return 0;
}

Pozdrawiam i życzę miłego wieczoru :)

Sockety unixowe w C

Nie wiem jak na innych uczelniach, ale przynajmniej u mnie, moim zdaniem, w trakcie nauki C popełniano spory błąd. Widząc Java trendy na świeci raczej jest to domena wszelkich kursów C. Jaki to błąd? Założenie że kod ma być przenośny, cokolwiek to znaczy. Kod nigdy nie będzie przenośny, jeśli nie napiszemy kilku wariantów, albo… uruchomimy pamięciożerną maszynę wirtualną. Ale czy oby na pewno kod samej maszyny jest przenośny?
Koniec rozważań. Dzisiaj chciałbym zbliżyć temat socketów unix.
Czym jest taki socket? Jak wszystko w systemie linux – plikiem!

[psciegienny@laptop3 sockets]$ ls -las nasz_socket
0 srwxrwxr-x 1 psciegienny psciegienny 0 08-26 21:14 nasz_socket

Przyjrzyjmy się srwxrwxr. W przypadku zwykłych plików zwykle widujemy tutaj -, a w przypadku katalogów d. Tym razem s pozwoli nam zauważyć że nie jest to zwykły plik.

[psciegienny@laptop3 sockets]$ file nasz_socket
nasz_socket: socket

No to teraz jeszcze kwestia jak tego używać. Idea jest dość prosta, chodzi o coś analogicznego do socketów TCP/IP. Jedna aplikacja tworzy gniazdo do którego mogą podłączyć się inne. Także będziemy mieli do czynienia z architekturą klient serwer.
Zacznijmy od serwera napisanego w C.

Po pierwsze nagłówki

#include <stdio.h>
#include <sys/socket.h>
#include <linux/un.h>
#include <string.h>
#include <unistd.h>

stdio.h przydaje się zwykle (snprintf etc), string.h przyda się np. ze względu na funkcję memset, linux/un.h – dla makra UNIX_PATH_MAX (zwykle równego 108), unistd.h do obsługi wątków i pisania i sys/socket.h do właściwej działalności.

Kolejna potrzebny nam element to „handler” dla połączenia. Nic innego jak funkcja która uruchamia się jako wątek klienta. Przykładowo

int handler(int fd)
{
int nbytes;
char buf[256];
nbytes = read(fd, buf, 256);
buf[nbytes] = 0;
printf("%s\n", buf);
write(fd, buf, nbytes);
close(fd);
return 0;
}

Jak widzimy realizujemy serwer echo. wiadomość odczytana jest wysyłana z powrotem. Możemy sobie wyobrazić prosty komunikator/broadcast gdy mielibyśmy dostęp do wszystkich fd (co oczywiście jest możliwe do zrealizowania).

No i nasza właściwa funkcja main:


int main(void)
{
struct sockaddr_un address;
int socket_fd, connection_fd;
socklen_t address_length;
pid_t child;

socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
if(socket_fd < 0){ fprintf(stderr, "socket() failed\n"); return 1; } unlink("./nasz_socket"); memset(&address, 0, sizeof(struct sockaddr_un));
address.sun_family = AF_UNIX;

snprintf(address.sun_path, UNIX_PATH_MAX, "./nasz_socket");
if(bind(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0){
fprintf(stderr, "bind() failed\n");
return 1;
}
if(listen(socket_fd, 10) != 0){
fprintf(stderr, "listen() failed\n");
return 1;
}
while((connection_fd = accept(socket_fd, (struct sockaddr *) &address, &address_length)) > -1){
child = fork();
if(child == 0){
return handler(connection_fd);
}
close(connection_fd);
}
close(socket_fd);
unlink("./nasz_socket");
return 0;
}

Widzimy kilka funkcji które są ciekawe: bind, listen, accept, fork.

bind pochodzi z sys/socket.h służy związaniu lokalnego adresu (struktury sockaddr) z deskryptorem socket_fd.
listen jest odpowiedzialna za uruchomienie akceptacji połączeń socketu z deskryptora. Dodatkowy argument informuje o limicie oczekujących połączeń z socketem.
accept już niejako obsługuje połączenie, nadaje unikatowy deskryptor dla połączenia przychodzącego
fork (z unistd.h) tworzy nowy proces, który jest kopią swojego rodzica. Dlatego tak istotne jest sprawdzenie numeru ID procesu. Dzięki temu handler jest odpalany jedynie w dodatkowych wątkach.

Jak już wiemy jak napisać serwer to jutro zajmiemy się napisaniem do niego klienta.

GnuWin32

Rzutem na taśmę na koniec tygodnia pojawił się dość ciekawy dla mnie temat.
Dzisiaj pierwszy raz nie czułem obrzydzenia korzystając z Windowsowego wiersza poleceń „cmd”.
Wszystko to stało się za sprawą projektu GnuWin32

Ale co i dlaczego dla mnie było takie przyjemne. A no dostałem do sparsowania wynik polecenia wlbs query który zwraca informacje o stanie nodów windowsowego network load balancer’a. NLB nie jest tematem tej wypowiedzi.
Dla mnie, osoby nieznającej PowerShell’a (i na razie chyba się nic nie zmieni w tym temacie), zadanie wydało się niemożliwe, aż tu wpisałem w wujka google zapytanie „grep Windows” pierwszy wynik, zależało mi na braku instalatorów etc. wybrałem więc wersję binary i… brakuje bibliotek… Na stronie jednak jest jeszcze „dependencies”, rozpakowałem w katalogu binary brakujące pliki dll. I grep działa. W przypadku awk nie zostałem już poinformowany o braku bibliotek, a taila znalazłem w paczce CoreUtils razem z wc.

I niech mi ktoś powie, że nie jestem hipisem, skoro na windowsie piszę w ten sposób:

wlbs query|grep Host|tail -1|awk "{print $2}"

Nawet Windows może zrozumieć normalne polecenia – polecam

uname -a