Ukážeme si, ako možno logovať z webovej aplikácie rovno do ElasticSearchu, nad ktorým možno potom fulltextovo vyhľadávať.
Ingrediencie do receptu:
- Maven
- Spring Boot
- SLF4j a Logback
- Logstash
- ElasticSearch
Maven: POM + Spring Boot (+ slf4j
+ Logback
)
Vytvoríme pom.xml
, v ktorom nadeklarujeme závislosť na Spring Boot.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>sk.upjs.ics.novotnyr</groupId>
<artifactId>spring-logstash-es-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.4.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
V rámci Spring Boot automaticky dostaneme závislosť na slf4j
i na Logback
u.
Spring Boot
Vytvoríme kontrolér, v ktorom budeme logovať požiadavky cez slf4j
.
package sk.upjs.ics.novotnyr.sled;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@EnableAutoConfiguration
public class MainController {
private static final Logger logger = LoggerFactory.getLogger(MainController.class);
@RequestMapping("/")
public String handle() {
logger.info("Handling a request");
return "OK";
}
public static void main(String[] args) {
SpringApplication.run(MainController.class);
}
}
Spustíme to!
Spusťme
mvn spring-boot:run
a navštívme
http://localhost:8080/
Uvidíme nápis OK
.
Logstash: agent zbierajúci dáta
- Stiahnime
logstash
z http://logstash.net/ - Rozbaľme ho do vhodného adresára (
C:\java\logstash
)
Agenta Logstash zatiaľ nespúšťame, potrebujeme dokonfigurovať naše demo.
Logstash: prepojenie Logbacku a Logstashu
Teraz nastavíme appendery Logbacku tak, aby posielali dáta cez súbor do agenta Logstashu.
- Poobdivujeme projekt Logstash-Logback-Encoder
Do
pom.xml
dodáme deklaráciu:<dependency> <groupId>net.logstash.logback</groupId> <artifactId>logstash-logback-encoder</artifactId> <version>3.0</version> </dependency>
Vytvoríme
logback.xml
. V ňom vytvoríme appender, ktorý bude logovať do súboru (s dennou rotáciou) vo formáte, ktorému bude rozumieť agent Logstashu. Dosiahneme to použitím encoderaLogstashEncoder
v tradičnom súborovom appenderi.<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern> </encoder> </appender> <appender name="LOGSTASH" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>/var/log/sled/sled.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>/var/log/sled/sled-%d{yyyy-MM-dd}.log</fileNamePattern> </rollingPolicy> <encoder class="net.logstash.logback.encoder.LogstashEncoder" /> </appender> <root level="INFO"> <appender-ref ref="CONSOLE" /> </root> <logger name="sk.upjs.ics.novotnyr.sled" level="DEBUG"> <appender-ref ref="LOGSTASH" /> </logger>
Popri tom vytvoríme druhý appender, ktorý bude logovať na štandardný výstup (inak by sme v konzole toho veľa neuvideli, a museli by sme obdivovať len logstashovský súbor).
Ďalej definujeme dva loggery: koreňový logger bude logovať len hlášky úrovne INFO a vyššej do konzoly, a logger pre aplikáciu začne posielať DEBUG a významnejšie hlášky jednak do konzoly a jednak do Logstashu (kumuláciu appenderov zabezpečuje aditivita appenderov).
Spustíme to!
Spusťme mvn spring-boot:run
, navštívme http://localhost:8080/ a uvidíme, ako prebieha logovanie v JSONovskom formáte. Ukážková hláška vyzerá nasledovne (s formátovaním):
{
"@timestamp": "2014-08-06T10:47:16.236+02:00",
"@version": 1,
"message": "Handling a request",
"logger_name": "sk.upjs.ics.novotnyr.sled.MainController",
"thread_name": "http-nio-8080-exec-1",
"level": "INFO",
"level_value": 20000,
"HOSTNAME": "RN-PC"
}
Logstash: agent zbierajúci dáta a jeho konfigurácia
Konfigurák
V našom deme vytvoríme konfigurák pre logstash: src\main\resources\logstash.conf
. Logstash bude obdivovať súbor sled.log
v duchu unixovského tail
u, a novopríchodzie hlášky bude posielať na konzoli.
Obsahom nech je:
input {
file {
type => "sled-dev"
path => "C:/var/log/sled/sled.log"
codec => "json"
}
}
output {
stdout {}
}
Pokiaľ ste na Windowse, musíte do atribútu path
uviesť absolútnu cestu, s normálnymi lomkami /
a veľkým písmenom jednotky (C:
). V opačnom prípade bude Logstash protestovať, že
Error: Neither current working directory (null) nor pathname (/var/log/sled/sled.log) led to an absolute path {:level=>:error}←[0m
Príčinou je chyba LOGSTASH-430.
Spustenie Logstashu
C:\Projects\spring-logstash-es-demo>C:\java\logstash\bin\logstash agent -f src/main/resources/logstash.conf
Logstash sa spustí:
←[33mUsing milestone 2 input plugin 'file'. This plugin should be stable, but if you see strange behavior, please let us know! For more information on plugin milestones, see http://logstash.net/docs/1.4.2/plugin-milestones {:level=>:warn}←[0m
Loggovod
Ak začneme obnovovať stránku v prehliadači, Logstash začne logovať do svojej konzoly:
2014-08-06T08:58:51.831+0000 RN-PC Handling a request
ElasticSearch
Logstash vie logovať do ElasticSearchu, kde vieme radostne vyhľadávať v logoch, koľko sa zažiada.
Rozbehanie ElasticSearch
- Stiahneme ElasticSearch a rozbalíme napr. do
C:\java\elasticsearch
Stiahneme plugin
elasticsearch-head
, vďaka ktorému dostaneme prehľadné používateľské rozhranie pre dopytovanie sa nad ES.C:\java\elasticsearch\bin\plugin -install mobz/elasticsearch-head
Spustíme ElasticSearch
C:\java\elasticsearch\bin\elasticsearch
Otvoríme GUI:
explorer http://localhost:9200/_plugin/head/
ElasticSearch + Logstash + Demo
Upravíme náš logstash.conf
, kde dodáme logovanie do Elasticu. Je to jednoduché: do output
sekcie dodáme klauzulu pre elasticsearch
:
output {
elasticsearch {
host => localhost
}
stdout {}
}
Reštartnime Logstash.
Obdivujme hlášky
Vojdime do elasticsearch-head. Na karte Browser uvidíme zoznam všetkých indexov a uvidíme, že Logstash automaticky vytvoril nový index. Kliknime naň a uvidíme zoznam hlášok, ktoré vieme obdivovať.
Ak chceme, môžeme sa nad nimi dopytovať pomocou elasticsearchovského jazyka: môžeme nájsť len
{
"query": {
"ids": {
"values": [
"vT9xRynhRp2Hj4_6LBEXRw", "69sa2wTbSWC23anZK_TNaw"
]
}
}
}
To je všetko!
Veľmi rýchlo a elegantne sme skombinovali asi sedemnásť technológií :-) Logovacia hláška zo springovského kontroléra putuje cez:
- slf4j,
- Logback,
- súbor,
- Logstash až do
- ElasticSearchu,
… kde nad ňou môžeme vykonávať všakovaké dopyty.
Zdroják projektu
Zdroják projektu sa nachádza na GitHube.
Ahoj, ak by si nad to všetko dal ešte kibanu bolo by to uno-tutti. Cez kibanu to vieš krásne prezerať :)
Kibanu som ešte neskúšal, ale verím, že je to finálna vrstva na torte (koniec-koncov, rovnaký stack). Vďaka za upozornenie.
A pri troche stastia by si to vedel nasypat priamo do ELK. Niekde som to cital a vypadalo to fajn. Tym Padom by si nepotreboval Logstash co sluzi iba na transport :)
Tohle je dobrá svatá trojice, ovšem je dobré si zodpovědet otázku co od výsledného logování očekáváme.
mnohdy tak můžeme dojít k názoru, že bue stačit pouze exceptions handler třeba Sentry https://getsentry.com/welcome/