1. Genereller Aufbau

network docker compose

1.1. Ablauf

  • Demo im Homeassistant

  • Vorzeigen des Graylog UIs

  • Theorie dahinter

2. Docker Compose Files

Docker Compose File (graylog.yaml)
services:
  elasticsearch:
    image: docker.io/elastic/elasticsearch:7.10.2
    container_name: elasticsearch_7.10.2
    ports:
      - "9200:9200"
    environment:
      ES_JAVA_OPTS: "-Xms512m -Xmx512m"
      discovery.type: "single-node"
      cluster.routing.allocation.disk.threshold_enabled: false
      xpack.security.enabled: "false"
      xpack.security.transport.ssl.enabled: "false"
      TZ: "Europe/Berlin"
    volumes:
      - ./elasticsearch_7.10.2:/usr/share/elasticsearch/data
    networks:
      - graylog_network

  mongo:
    image: mongo:4.0
    container_name: mongo
    networks:
      - graylog_network
    volumes:
      - ./mongo:/data/db

  graylog:
    image: graylog/graylog:4.3.0
    container_name: graylog
    ports:
      - "9000:9000"
      - "12201:12201/udp"
      - "1514:1514"
    environment:
      GRAYLOG_HTTP_EXTERNAL_URI: "http://127.0.0.1:9000/"
      GRAYLOG_PASSWORD_SECRET: "forpasswordencryption"
      GRAYLOG_ROOT_PASSWORD_SHA2: "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918"
      GRAYLOG_TIMEZONE: "Europe/Berlin"
    networks:
      - graylog_network
    depends_on:
      - elasticsearch
      - mongo

  mqtt_logging_handler:
    image: openjdk:23-jdk-slim
    container_name: mqtt_logging_handler
    ports:
      - "8080:8080"
    volumes:
      - ../Backend/mqtt_logging_handler/target:/app
      - ./mqtt_logging_handler/logs:/app/logs
    command: java -jar /app/quarkus-app/quarkus-run.jar
    environment:
      TZ: "Europe/Berlin"
    networks:
      - graylog_network
    depends_on:
      - graylog
      - elasticsearch
      - mongo

  mqtt_for_home_assistant:
    image: eclipse-mosquitto
    container_name: mqtt_for_home_assistant
    ports:
      - "1883:1883"
    networks:
      - graylog_network
      - docker_compose_home_assistant_network
    volumes:
      - ./mosquitto/config:/mosquitto/config
      - ./mosquitto/data:/mosquitto/data
      - ./mosquitto/log:/mosquitto/log
    environment:
      TZ: "Europe/Berlin"
networks:
  graylog_network:
    driver: bridge

  docker_compose_home_assistant_network:
    external: true

2.1. Mongo

Dient als Datenbank für die Graylog Konfiguration

Bsp:

  • Users

  • Dashboard settings

~"Dient zur Haltung von Metadaten und Konfigurationen"

2.2. Graylog

Fungiert zur Visualisierung der Logs

→ Weiterleiten an Elasticsearch

2.3. Elasticsearch

Speichert die Logs aus Graylog

2.4. Home Assistent

Docker Compose File (home_assistant.yaml)
services:
  home_assistant:
    image: homeassistant/home-assistant:stable
    container_name: home_assistant
    ports:
      - "8123:8123"
    networks:
      - home_assistant_network
    volumes:
      - ./homeassistant:/config
    environment:
      - TZ=Europe/Berlin
    restart: always

networks:
  home_assistant_network:
    driver: bridge

2.5. Ausführen

Im Quarkus Logger (mqtt_logging_handler) bei Änderungen
 mvn clean package

Im Docker Compose File holt man sich automatisch die .jar File

Im Docker_Compose Verzeichnis
docker compose -f home_assistant.yml up -d
docker compose -f graylog.yml up -d

3. MQTT_Logger

application.properties
mp.messaging.incoming.mqtt.connector=smallrye-mqtt
mp.messaging.incoming.mqtt.topic=#

mp.messaging.incoming.mqtt.host=mqtt_for_home_assistant

mp.messaging.incoming.mqtt.username=nik
mp.messaging.incoming.mqtt.password=nik
mp.messaging.incoming.mqtt.port=1883
mp.messaging.incoming.mqtt.qos=0

#GreyLog Config
quarkus.log.handler.gelf.enabled=true
quarkus.log.handler.gelf.host=graylog
quarkus.log.handler.gelf.port=12201

#Log Files (Log Rotation)
quarkus.log.file.enable=true
quarkus.log.level=INFO
quarkus.log.file.path=/app/logs/quarkus.log

quarkus.log.file.rotation.max-file-size=5K
quarkus.log.file.rotation.max-backup-index=3

3.1. REST-Get Logger

@Path("/hello")
public class HelloResource {
    private static final Logger LOG = Logger.getLogger(MqttMessageLogger.class);

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        LOG.info("/hello was called");
        return "Hello";
    }
}

3.2. MQTT Logger

@ApplicationScoped
public class MqttMessageLogger {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yy HH:mm:ss");

    private static final Logger LOG = Logger.getLogger(MqttMessageLogger.class);

    @Incoming("mqtt")
    public CompletionStage<Void> onMqttMessage(Message<String> message) {

        String payload = message.getPayload();

        System.out.println("\n" + LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()), ZoneId.systemDefault()).format(formatter));

        System.out.println("Received message: " + payload);

        Optional<String> topicNameOpt = message.getMetadata()
                .get(ReceivingMqttMessageMetadata.class)
                .map(metadata -> metadata.getMessage().topicName());

        topicNameOpt.ifPresent(topicName -> {
            String logMessage = topicName + " " + payload;
            System.out.println("Sent to topic: " + topicName);

            if (topicName.contains("/debug")) {
                LOG.debug(logMessage);
            } else if (payload.contains("offline") || payload.contains("online")) {
                LOG.warn(logMessage);
            } else if (payload.contains("error") || payload.contains("failure")) {
                LOG.error(logMessage);
            } else {
                LOG.info(logMessage);
            }
        });

        return CompletableFuture.completedFuture(null);
    }
}

4. Graylog

4.1. Inject Logger (Input)

4.2. Logging Levels

log level
Figure 1. edgedata

4.2.1. Im Graylog:

  • 0 - Emergency

  • 1 - Alert

  • 2 - Critical

  • 3 - Error

  • 4 - Warning

  • 5 - Notice

  • 6 - Informational

  • 7 - Debug

5. Alternativen zu Graylog

5.1. ELK Stack (Elasticsearch, Logstash, Kibana)

Vorteile:

  • bekannte und weit verbreitete Lösung

  • Suchleistung ist überragend (Pfeilschnell)

  • viele Plugins

Nachteile:

  • Komplex aufzusetzen

  • ressourcenintensiv

5.2. EFK Stack (Elasticsearch, Fluentd, Kibana)

Vorteile:

  • Ressourcenschonend

  • Simpel aufzusetzen

Nachteile:

  • Weniger Möglichkeiten / Funktionen für komplexe Abfragen und Transformationen

  • Weniger verbreitet

5.3. Graylog vs Fluentd vs Logstash

Funktion Graylog Fluentd Logstash

Hauptanwendung

Zentralisiertes Logging und Analysefähigkeiten

Datensammlung und -aggregation

Datenverarbeitung und -aggregation

Benutzerfreundlichkeit

Benutzerfreundliche Oberfläche und eigene Dashboards

Konfiguration über YAML-Dateien

Erfordert benutzerdefinierte Pipelines und Konfigurationen

Integrationen

Eingebaute Unterstützung für ElasticSearch, MongoDB

Breites Plugin-Ökosystem, schnelle Integration mit Kafka, o.ä.

Umfangreiche Plugin-Bibliothek

aggregation: Beschreibt das Sammeln und Zusammenfassen von Daten.

5.4. für Grafana enthusiasten: Loki

6. GELF + Alternativen (Graylog Extended Log Format)

{
  "version": "1.1",
  "host": "example.org",
  "short_message": "A short message that helps you identify what is going on",
  "full_message": "Backtrace here\n\nmore stuff",
  "timestamp": 1385053862.3072,
  "level": 1,
  "_user_id": 9001,
  "_some_info": "foo",
  "_some_env_var": "bar"
}

6.1. JSON

6.2. ECS (Elastic Common Schema) format

{
"@timestamp": "2023-01-01T12:00:00Z",
"event.action": "authentication",
"user.name": "jeeva_s",
"source.ip": "172.1.1.1",
"outcome": "success"
}

7. Centralized / Decentralized Logging

7.1. Centralized Logging

Logs aus verschiedenen Quellen werden in einem Platz zusammengesammelt. Das bietet eine vereinte Suche und Analyse.

Bsp:

  • Graylog

  • ELK / EFK Stack

Vorteile:

  • leichteres Management / Monitoring

  • Real-time Analysen

Nachteile:

  • Kostenintensiv

  • braucht eine starke Netzwerk-Infrastruktur

7.2. Decentralized Logging

Logs werden lokal gespeichert, was unabhängig vom Netzwerk funktioniert

Bsp:

  • rsyslog

  • lokale .log files

Vorteile:

  • Simples Setup

  • Netzwerk unabhängig

Nachteile:

  • schwer zu analysieren / auszuwerten

  • Fehlersuche ist zeitintensiv