Skip to content

Commit 6c87b8d

Browse files
authored
Add output of Mermaid syntax overview to Logstash (#377)
This feature was born out of an Elastic Stack workshop I did with customers. We used [Mermaid](https://mermaid.js.org/) to visualize how pipelines are interconnected. So the idea was born that it might be very helpful if the collection could create Mermaid code automatically. I tried the following to test this code. Added the following variable to `group_vars/logstash.yml`. ``` logstash_pipelines: - name: sorter exclusive: true input: - name: input key: input output: - name: syslog key: syslog-input condition: '[log][file][path] == "/var/log/syslog"' congestion: 5000 - name: apache key: apache condition: '[log][file][path] =~ /\/var\/log\/apache2\/.*access.*log$/' congestion: 5000 - name: apache-error key: apache-error condition: '[log][file][path] =~ /\/var\/log\/apache2\/.*error.*log$/' congestion: 5000 - name: haproxy key: syslog-input condition: '[log][file][path] == "/var/log/haproxy.log"' congestion: 5000 - name: mysql-error key: mysql-error condition: '[log][file][path] == "/var/log/mysql/error.log" or [log][file][path] == "/var/log/mysql/mysql.err"' congestion: 5000 - name: mysql-slow key: mysql-slow condition: '[log][file][path] =~ /\/var\/log\/mysql\/.*-slow.log/' congestion: 5000 - name: haproxy key: syslog-input condition: '[log][file][path] =~ /^\/var\/log\/mail/' congestion: 5000 - name: forwarder key: forwarder congestion: 5000 - name: syslog source: https://github.com/NETWAYS/syslog-logstash-pipeline.git version: master exclusive: true input: - name: syslog-input key: syslog-input output: - name: postfix condition: '[program] =~ /^postfix/ or [log][file][path] =~ /^\/var\/log\/mail/' key: postfix congestion: 5000 - name: haproxy key: haproxy condition: '[program] == "haproxy"' congestion: 5000 - name: forwarder key: forwarder congestion: 5000 - name: postfix source: https://github.com/NETWAYS/postfix-logstash-pipeline.git version: master exclusive: false input: - name: postfix key: postfix output: - name: forwarder key: forwarder congestion: 5000 - name: apache source: https://github.com/widhalmt/apache-access-logstash-pipeline.git version: master exclusive: false input: - name: apache key: apache output: - name: forwarder key: forwarder congestion: 5000 - name: apache-error #source: https://github.com/widhalmt/apache-error-logstash-pipeline.git #version: main exclusive: false input: - name: apache-error key: apache-error output: - name: forwarder key: forwarder congestion: 5000 - name: haproxy source: https://github.com/widhalmt/haproxy-logstash-pipeline.git version: master exclusive: false input: - name: haproxy key: haproxy output: - name: forwarder key: forwarder congestion: 5000 - name: mysql-error source: https://github.com/widhalmt/mysql-error-logstash-pipeline.git version: main exclusive: false input: - name: mysql-error key: mysql-error output: - name: forwarder key: forwarder congestion: 5000 - name: mysql-slow source: https://github.com/widhalmt/mysql-slowlog-logstash-pipeline.git version: main exclusive: false input: - name: mysql-slow key: mysql-slow output: - name: forwarder key: forwarder congestion: 1000 ``` This resulted in the following contents in `/etc/logstash/pipelines.mermaid`. ``` # Managed via Ansible role # https://github.com/netways/ansible-role-logstash # Use the following code with your favorite Mermaid editor # Or paste into: https://mermaid.live/ # To get a graphical overview of your Logstash pipelines flowchart TD p_ansible-input[ansible-input] --> k_input{input} k_forwarder{forwarder} --> p_ansible-forwarder[ansible-forwarder] k_input{input} --> p_sorter[sorter] p_sorter[sorter] --> |if log.file.path == /var/log/syslog|k_syslog-input{syslog-input} p_sorter[sorter] --> |if log.file.path =~ /\/var\/log\/apache2\/.*access.*log$/|k_apache{apache} p_sorter[sorter] --> |if log.file.path =~ /\/var\/log\/apache2\/.*error.*log$/|k_apache-error{apache-error} p_sorter[sorter] --> |if log.file.path == /var/log/haproxy.log|k_syslog-input{syslog-input} p_sorter[sorter] --> |if log.file.path == /var/log/mysql/error.log or log.file.path == /var/log/mysql/mysql.err|k_mysql-error{mysql-error} p_sorter[sorter] --> |if log.file.path =~ /\/var\/log\/mysql\/.*-slow.log/|k_mysql-slow{mysql-slow} p_sorter[sorter] --> |if log.file.path =~ /^\/var\/log\/mail/|k_syslog-input{syslog-input} p_sorter[sorter] --> k_forwarder{forwarder} k_syslog-input{syslog-input} --> p_syslog[syslog] p_syslog[syslog] --> |if program =~ /^postfix/ or log.file.path =~ /^\/var\/log\/mail/|k_postfix{postfix} p_syslog[syslog] --> |if program == haproxy|k_haproxy{haproxy} p_syslog[syslog] --> k_forwarder{forwarder} k_postfix{postfix} --> p_postfix[postfix] p_postfix[postfix] --> k_forwarder{forwarder} k_apache{apache} --> p_apache[apache] p_apache[apache] --> k_forwarder{forwarder} k_apache-error{apache-error} --> p_apache-error[apache-error] p_apache-error[apache-error] --> k_forwarder{forwarder} k_haproxy{haproxy} --> p_haproxy[haproxy] p_haproxy[haproxy] --> k_forwarder{forwarder} k_mysql-error{mysql-error} --> p_mysql-error[mysql-error] p_mysql-error[mysql-error] --> k_forwarder{forwarder} k_mysql-slow{mysql-slow} --> p_mysql-slow[mysql-slow] p_mysql-slow[mysql-slow] --> k_forwarder{forwarder} ``` When I post it into an [online Merm ![mermaid-diagram-2025-03-14-115941](https://github.com/user-attachments/assets/fbbd9d25-8bc3-4035-95ca-81ba03034a40) aid Editor](https://mermaid.live/), then I get the following:
1 parent 14adca4 commit 6c87b8d

File tree

6 files changed

+91
-0
lines changed

6 files changed

+91
-0
lines changed

docs/logstash-pipelines.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Pipelines #
22

3+
## Keeping an overview ##
4+
5+
It can be quite difficult to stay on top of your pipeline configuration because they tend to become very complex.
6+
7+
This collection will leave some comments about how pipelines are interconnected within the `/etc/logstash/pipelines.yml` configuration file.
8+
9+
If you set `logstash_mermaid` to `true` (which is the default), then you will also get a new file in `/etc/logstash/pipelines.mermaid`. You can paste it into a Mermaid editor in your documentation tool or in an [online Mermaid editor](https://mermaid.live/). The same content will be available on your control node in a temporary file. You can even add arbitrary code to reflect manually managed pipelines by using `logstash_mermaid_extra`.
10+
311
## Git managed ##
412

513
If you have pipeline code managed in (and available via) Git repositories, you can use this role to check them out and integrate them into `pipelines.yml`.

docs/role-logstash.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ Aside from `logstash.yml` we can manage Logstashs pipelines.
8989
* *logstash_legacy_monitoring*: Enables legacy monitoring - ignored when `elasticstack_full_stack` is not set. (default: `true`)
9090
* *logstash_redis_password*: If set this will use this password when connecting our simple inputs and outputs to Redis. (default: not set)
9191

92+
* *logstash_mermaid*: Print overview over Logstash pipelines in Mermaid syntax. (default: `true`)
93+
* *logstash_mermaid_logstash*: Place Mermaid syntax into `/etc/logstash/pipelines.mermaid` on Logstash hosts. (default: `true`)
94+
* *logstash_mermaid_local*: Place Mermaid syntax into temporary file on control node. (default: `false`)
95+
* *logstash_mermaid_extra*: You can add extra Mermaid syntax to the output by adding it to this variable. YAML-multiline is supported. (default: none)
96+
9297
The following variables configure Log4j for Logstash. All default to `true` as this is the default after the installation.
9398

9499
* *logstash_logging_console*: Log to console - syslog when run via systemd

roles/logstash/defaults/main.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ logstash_pipeline_identifier: true
8888
logstash_pipeline_identifier_field_name: "[netways][pipeline]"
8989
logstash_pipeline_identifier_defaults: false
9090

91+
logstash_mermaid: true
92+
logstash_mermaid_local: false
93+
logstash_mermaid_logstash: true
94+
9195
# Only for internal use
9296

9397
logstash_freshstart:
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
3+
- name: Print Logstash pipelines in Mermaid syntax on Logstash hosts
4+
ansible.builtin.template:
5+
src: pipelines.mermaid.j2
6+
dest: /etc/logstash/pipelines.mermaid
7+
owner: root
8+
group: root
9+
mode: 0655
10+
when:
11+
- logstash_mermaid_logstash | bool
12+
13+
- name: Provide Logstash pipelines in Mermaid syntax on control node
14+
when:
15+
- logstash_mermaid_local | bool
16+
block:
17+
18+
- name: Create temporary directory on control node
19+
ansible.builtin.tempfile:
20+
prefix: logstash_mermaid
21+
register: mermaid_path
22+
delegate_to: localhost
23+
24+
- name: Print Logstash pipelines in Mermaid syntax on control node
25+
ansible.builtin.template:
26+
src: pipelines.mermaid.j2
27+
dest: "{{ mermaid_path.path }}"
28+
owner: root
29+
group: root
30+
mode: 0655
31+
delegate_to: localhost
32+
33+
- name: Send user to Mermaid file
34+
ansible.builtin.debug:
35+
msg:
36+
- "You can find an overview of your pipeline configuration in Mermaid syntax at {{ mermaid_path.path }}"

roles/logstash/tasks/main.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,13 @@
251251
- configuration
252252
- logstash_configuration
253253

254+
- name: Print Logstash pipelines in Mermaid syntax
255+
ansible.builtin.import_tasks: logstash-mermaid.yml
256+
when:
257+
- logstash_mermaid | bool
258+
tags:
259+
- mermaid
260+
254261
- name: Install Logstash plugins
255262
community.general.logstash_plugin:
256263
state: present
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Managed via Ansible role
2+
# https://github.com/netways/ansible-role-logstash
3+
4+
# Use the following code with your favorite Mermaid editor
5+
# Or paste into: https://mermaid.live/
6+
# To get a graphical overview of your Logstash pipelines
7+
8+
flowchart TD
9+
{% if logstash_beats_input | bool %}
10+
p_ansible-input[ansible-input] --> k_input{input}
11+
{% endif %}
12+
{% if logstash_elasticsearch_output | bool %}
13+
k_forwarder{forwarder} --> p_ansible-forwarder[ansible-forwarder]
14+
{% endif %}
15+
{% if logstash_pipelines is defined %}
16+
{% for item in logstash_pipelines %}
17+
{% if item.input is defined %}
18+
{% for input in item.input %}
19+
k_{{ input.key }}{{ '{' }}{{ input.key }}{{ '}' }} --> p_{{ item.name }}{{ '[' }}{{item.name}}{{ ']' }}
20+
{% endfor %}
21+
{% endif %}
22+
{% if item.output is defined %}
23+
{% for output in item.output %}
24+
p_{{ item.name }}{{ '[' }}{{ item.name }}{{ ']' }} --> {% if output.condition is defined %}{{ '|' }}if {{ output.condition | replace("][", ".") | replace("[","") | replace("]","") | replace('"', '')}}{{ '|' }}{% endif %}k_{{ output.key }}{{ '{' }}{{ output.key }}}
25+
{% endfor %}
26+
{% endif %}
27+
{% endfor %}
28+
{% endif %}
29+
{% if logstash_mermaid_extra is defined %}
30+
{{ logstash_mermaid_extra }}
31+
{% endif %}

0 commit comments

Comments
 (0)