====== Primeros pasos con LogStash ======
Cada versión de Logstash tiene una versión de ES recomendada.
**Descargar LogStash**: [[https://www.elastic.co/downloads/logstash]]\\
**Dependencia**: Java (JDK / JRE).
Se recomienda instalar desde el repositorio oficial para que se instale los scripts de inicio, lugar donde se configuran variables del inicio para amoldarlo a las necesidades.
===== Arrancar LogStash =====
Descargar LogStash: [[https://www.elastic.co/downloads/elasticsearch]]
Con la opción "-e" se especifica la configuración desde la propia linea de comandos.
logstash -e 'input { stdin { } } output { stdout {} }'
Para modificar la salida de logstash se pueden utilizar codecs.
logstash -e 'input { stdin { } } output { stdout { codec => rubydebug } }'
Escribimos cualquier tipo de frase o palabra y obtendremos una respuesta como la siguiente.
goodnight moon
{
"message" => "XXXXX",
"@timestamp" => "2013-11-20T23:48:05.335Z",
"@version" => "1",
"host" => "XXXXX"
}
Ahora que hemos probado como funciona de forma básica, configuramos que la salida no se muestre solo en pantalla, si no que sea guardada también en el servicio ElasticSearch. Se creará por defecto un índice logstash-YYYY.MM.DD de forma automática y contendrá tantos documentos como lineas agreguemos. Se especifican múltiples salidas (ES y la pantalla).
./logstash -e 'input { stdin { } } output { elasticsearch { host => localhost cluster => esfa} stdout{} }'
NOTA: La directiva clúster es necesaria si elasticsearch corre en dicho modo.
Por defecto LogStash crea un índice para cada día de forma automática y el mismo hace la rotación a media noche (UTC).
===== Opciones de la linea de comandos logstash "--help" =====
* **-f**, **--config CONFIGFILE** Carga la configuración especificada, se pueden especificar directorios y comodines, de ser así se leeran en orden alfabético una vez se ingrese al directorio.
* **-e CONFIGSTRING** Especifica desde la linea de comandos una configuración, usa la misma sintaxis que los ficheros de configuración. Si no se especifican las directrices "input" o "output", por defecto son 'stdin { type => stdin }' y 'stdout { codec => rubydebug }}'.
* **-w**, **--filterworkers COUNT** Cuantos "workers" se arrancarán (Por defecto 1).
* **--watchdog-timeout TIMEOUT** Segundos de watchdog (por defecto 10).
* **-l, --log FILE** Permite redireccionar la salida a un fichero, por defecto lo muestra en pantalla.
* **--verbose (-v)** y **--debug (-vv)** Establece el nivel de depuración (vebosity). verbose es el más bajo y debug el más alto.
===== Estructura de un fichero de configuración en Logstash =====
# Comentarios
input {
...
}
filter {
...
}
output {
...
}
NOTA: El orden de los ficheros de entrada, filtros y salidas es importante.
===== Plugins: Input, Output, Filter y Codec =====
**Instalación / Desinstalación / Actualización de Plugins**.
# Instalación automática sin necesidad de descargar nada manualmente.
bin/plugin install logstash-output-kafka
# Usando un fichero (plugin) previamente descargado.
plugin install /path/to/logstash-output-kafka-1.0.0.gem
# Desinstalación de un Plugin.
bin/plugin uninstall logstash-output-kafka
# Actualizar todos / algunos plugins.
bin/plugin update
bin/plugin update logstash-output-kafka
# Listar todos Plugins, específicos o grupos de plugins.
bin/plugin list
bin/plugin list
bin/plugin list --group output
===== Tipos de Valores =====
Cada plugin requiere sus propios tipos de valor.
**Array**: Una cadena o varias
path => [ "/var/log/messages", "/var/log/*.log" ]
path => "/data/mysql/mysql.log"
**Booleano**: Verdadero o falso.
ssl_enable => true
**Bytes**: Define una unidad de byte, útil para definir tamaños en las opciones de los plugin. base-1000 / SI : (k M G T P E Z Y) y base-1020 / Binario : (Ki Mi Gi Ti Pi Ei Zi Yi) . Si no se especifica unidad son bytes.
my_bytes => "1113" # 1113 bytes
my_bytes => "10MiB" # 10485760 bytes
my_bytes => "100kib" # 102400 bytes
my_bytes => "180 mb" # 180000000 bytes
**Codec**: Nombre del codec de logstash encargado de representar los datos, se puede especificar en el plugin de entrada y en el de salida.
codec => "json"
**Hash**: Pares de llaves - valor (cuando se definen varios se deben separar sin comas, solo espacios en blanco).
match => {
"field1" => "value1"
"field2" => "value2"
...
}
**Números** (entero o coma flotante).
port => 33
**Cadenas** (siempre debe estar entre comillas).
name => "Hello world"
**Password**: Cadena que no es logueada o mostrada
my_password => "password"
**Path**: Cadena que muestra una ruta valida del sistema.
my_path => "/tmp/logstash"
===== Referenciar campos / Formato sprint =====
NOTA: Esto no es válido para el bloque del plugin input, solo para filter y output.
Todos los eventos (una entrada de un log) tienen propiedades que logstash califica como campos (fields). Ej, "status code 200", "request path /", "IP", etc...
Referenciar un campo en concreto se hace mediante corchetes y si es anidado se debe especificar también con corchetes como se ve a continuación.
{
"agent": "Mozilla/5.0 (compatible; MSIE 9.0)",
"ip": "192.168.24.44",
"request": "/index.html"
"response": {
"status": 200,
"bytes": 52353
},
"ua": {
"os": "Windows 10"
}
}
Para referirnos al campo del sistema operativo "Windows 10" la referencia es //[ua][os]//.
**Formato sprint**: Permite referenciar un campo desde dentro de una cadena.
output {
statsd {
increment => "apache.%{[response][status]}"
}
}
En vez de usar un campo se puede especificar un formato de fecha, que junto con el campo type crea el nombre del fichero de salida.
output {
file {
path => "/var/log/%{type}.%{+yyyy.MM.dd.HH}"
}
}
===== Condiciones en LogStash =====
Es posible hacer pilas de condiciones complejas y combinar unas dentro de otras.
if EXPRESSION {
...
} else if EXPRESSION {
...
} else {
...
}
** Operadores de comparación**.
* Igualdad: //==, !=, <, >, <=, >=//
* regexp: //=~, !~//
* inclusion: //in, not in//
** Operadores booleanos**: //and, or, nand, xor//
**Operador binario para negar:** !
**Operador para realizar agrupaciones**: //(...)//
Ejemplos
filter {
if [action] == "login" and [host] == "dominio.com" {
mutate { remove => "secret" }
}
}
filter {
if [foo] in [foobar] {
mutate { add_tag => "field in field" }
}
if [foo] in "foo" {
mutate { add_tag => "field in string" }
}
if "hello" in [greeting] {
mutate { add_tag => "string in field" }
}
if [foo] in ["hello", "world", "foo"] {
mutate { add_tag => "field in list" }
}
if [missing] in [alsomissing] {
mutate { add_tag => "shouldnotexist" }
}
if !("foo" in ["hello", "world"]) {
mutate { add_tag => "shouldexist" }
}
}
===== El campo metadata =====
Este campo está solo disponible a partir de LogStash >= 1.5.
Este campo es útil para usarlo en algún momento cuando temporalmente sea necesario un campo que no deba incluirse en las salidas.
./logstash -e 'input { stdin { } }
filter {
mutate { add_field => { "show" => "This data will be in the output" } }
mutate { add_field => { "[@metadata][test]" => "Hello" } }
mutate { add_field => { "[@metadata][no_show]" => "This data will not be in the output" } }
}
output {
if [@metadata][test] == "Hello" {
stdout { codec => rubydebug }
}
}'
Logstash startup completed
Insertamos la cadena: HOLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
{
"message" => "HOLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"@version" => "1",
"@timestamp" => "2015-06-08T14:13:14.271Z",
"host" => "es1",
"show" => "This data will be in the output"
}
Si se quieren ver el campo @metada y sus subcampos, se debe activar dentro de las propiedades del codec rubydebug (único codec que puede hacerlo).
stdout { codec => rubydebug { metadata => true } }
Ejemplo de uso para sobreescribir el @timestamp por el proporcionado en el mensaje.
./logstash -e 'input { stdin { } }
filter {
grok { match => [ "message", "%{HTTPDATE:[@metadata][timestamp]}" ] }
date { match => [ "[@metadata][timestamp]", "dd/MMM/yyyy:HH:mm:ss Z" ] }
}
output {
stdout { codec => rubydebug }
}'
De esta manera no tenemos dos campos con el mismo valor (timestamp y @timestamp) y evitamos tener que borrar posteriormente el campo timestamp. Este uso es algo más avanzado y se entederá posteriormente después de haber practicado un poco con LogStash.
===== Pipeline (Input / Filter / Output) =====
**__Input__** ([[https://www.elastic.co/guide/en/logstash/current/input-plugins.html]])
* **file**: Lee de un fichero (equivalente a tail -0a).
* **syslog**: Escucha en el puerto 514 para syslog y parsea en base a RFC3164.
* **lumberjack**: procesa eventos usando logstash-forwarder (lumberjack protocol).
* **redis**: Lee desde un servidor redis, es utilizado habitualmente como intermediario (broker) para encolar mensajes y enviarlo a los servidores logstash que procesan dichos eventos (shippers).
**__Filtros__** ([[https://www.elastic.co/guide/en/logstash/current/filter-plugins.html]])
Se pueden combinar con condiciones para realizar alguna acción o filtrar por algún criterio.
* **grok**: Parsea estructuras de texto arbitrario, tiene más de 120 patrones disponibles y es el recomendado cuando se debe trabajar con logs orientados a humanos y no a máquinas.
* **mutate**: Transforma los campos de los eventos, puede renombrar, eliminar, remplazar y modificar
* **drop**: Borra eventos completamente, por ejemplo eventos debug.
* **clone**: Hace una copia de un eventos, normalmente agregando o quitando campos.
* **geoip**: Agrega información geográfica para después visualizarla en kibana.
**__Output__** ([[https://www.elastic.co/guide/en/logstash/current/output-plugins.html]])
Los eventos una vez filtrados pueden tener múltiples salidas.
* **elasticsearch**: Servidor elasticsearch si los eventos deben ser analizados.
* **file**: Fichero en disco.
* **graphite**: guarda los eventos y muestra gráficas.
* **statsd**: Envía la salida a statsd.
**__Codecs__** ([[https://www.elastic.co/guide/en/logstash/current/codec-plugins.html]])
Tiene la propiedad de filrar una entrada o salida, solo se usan en los plugins "Input" y "Output".
* **json**: Codifica o decodifica en formato JSON.
* **multiline**: Filtra varias lineas, útil pore ejemplo para eventos de java.
===== Colas e hilos en LogStash =====
**Colas en LogStash**.
Los eventos se van procesando parte por parte usando unas colas mediante "SizedQueue", cuyo máximo es 20 y no puede ser modificado. Si se exceden esos 20 las entradas en la cola son bloqueadas.
Hay una cola por cada miembro de la tubería (pipeline), es decir, input, filter y output. Si el hilo que maneja output no puede escribir en disco, este espera a poder hacerlo y deja de leer de su cola, cuando esta esta se llena, el hilo perteneciente al filtro no puede seguir escribiendo en esa cola y deja de leer su cola saturando también la cola del input. Esto produce una pérdida de todos los eventos que no pueden ser encolados. Por ello se suele recomendar el uso de aplicaciones como [[https://www.rabbitmq.com/|RabbitMQ]].
**Hilos en LogStash**.
Los hilos siguen la siguiente estructura (el filtro es opcional).
input threads | filter worker threads | output worker
input threads | output worker
* **Input**: Cada entrada usa su propio hilo, de esa forma si una entrada es más lenta no afecta a las demás.
* **Filter**: Se usa el modelo de "worker", donde cada worker recibe un evento y aplica todos los filtros en el orden establecido para enviarlo a la cola de salida, esto permite escalabilidad ya que algunos filtros consumen mucha CPU. Por defecto es solo uno, pero con "-w" se pueden especificar más
* **Output**: Por defecto usa un solo hilo y puede ser que almacene eventos en un buffer antes de escribirlos, esto pasa al utilizar ElasticSearch como salida. En el caso de utilizar ES, se almacenan eventos en el buffer y luego un hilo extra lo limpia volcando todos los eventos en ElasticSearch, esto mejora el rendimiento ya que evita saturar las colas frente a una posible respuesta tardía de ElasticSearch.
Si se hace un debug de los hilos java en funcionamiento se debe prestar atención a las siguientes etiquetas para poder detectar donde se encuentra el problema / cuello de botella.
* **input**: "//outputworker//"
===== Configuracion Logrotate para Logstash =====
Algunos paquetes (rpm, deb,..) de Logstash ya traen incorporada dicha configuración para logrotate de forma automática.
Fichero: /etc/logrotate.d/logstash
/var/log/logstash/*.log {
daily
rotate 7
copytruncate
compress
delaycompress
missingok
notifempty
}
Ejemplo.
ls -lt /var/log/logstash/
total 63612
-rw-r--r-- 1 logstash logstash 35586668 Nov 24 16:14 logstash.log
-rw-r--r-- 1 logstash logstash 29522368 Nov 24 03:14 logstash.log-20151124
-rw-r--r-- 1 logstash logstash 327 Nov 24 03:14 logstash.log-20151123.gz
-rw-r--r-- 1 logstash logstash 5790 Nov 23 03:43 logstash.log-20151122.gz
-rw-r--r-- 1 logstash logstash 5065 Nov 22 03:40 logstash.log-20151121.gz
-rw-r--r-- 1 root root 57 Nov 20 16:48 logstash.stdout
-rw-r--r-- 1 root root 0 Nov 20 16:48 logstash.err