diff --git a/README.md b/README.md index 351a166..8e2871e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Build Status](https://jenkins.confdroid.com/buildStatus/icon?job=confdroid_alloy&style=plastic)](https://jenkins.confdroid.com/job/confdroid_alloy/) [![Security Hotspots](https://sonarqube.confdroid.com/api/project_badges/measure?project=confdroid_alloy&metric=security_hotspots&token=sqb_05c3bd9116b3d2585b1f06dd7b6d0d5a6433fe8b)](https://sonarqube.confdroid.com/dashboard?id=confdroid_alloy) -[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/grizzlycoda/puppet_collection) +[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/grizzlycoda/puppet_collection) - [Readme](#readme) - [Synopsis](#synopsis) @@ -55,6 +55,7 @@ See the full Puppet documentation including parameters in `docs/index.html` All dependencies must be included in the catalogue. - [confdroid_nagios](https://sourcecode.confdroid.com/confdroid/confdroid_nagios) if nagios monitoring is desired +- [puppetlabs/concat](https://forge.puppet.com/modules/puppetlabs/concat) for composing the Alloy configuration ## Deployment @@ -68,6 +69,15 @@ node 'example.example.net' { } ``` +External modules can add log files to Alloy's `path_targets` list with the +`confdroid_alloy::log_targets` defined type: + +```puppet +confdroid_alloy::log_targets { 'my_application': + targets => ['/var/log/my_application/*.log', '/var/log/my_application/audit.log'], +} +``` + - through Foreman: In order to apply parameters through Foreman, the params.pp must be added to the host or host group in question. diff --git a/manifests/log_targets.pp b/manifests/log_targets.pp new file mode 100644 index 0000000..68e9172 --- /dev/null +++ b/manifests/log_targets.pp @@ -0,0 +1,20 @@ +## confdroid_alloy::log_targets.pp +# Module name: confdroid_alloy +# @summary Adds log file targets to the Alloy configuration. +# @param [Array[String]] targets Paths to log files to scrape. +############################################################################### +define confdroid_alloy::log_targets ( + + Array[String] $targets = [], + +) { + if $confdroid_alloy::params::ay_manage_loki == true and $targets != [] { + $log_targets_array = $targets + + concat::fragment { "log_targets_${name}": + target => $confdroid_alloy::params::ay_main_file, + content => template('confdroid_alloy/log_targets.alloy.erb'), + order => '020', + } + } +} diff --git a/manifests/main/files.pp b/manifests/main/files.pp index 2e07f3c..983d188 100644 --- a/manifests/main/files.pp +++ b/manifests/main/files.pp @@ -7,12 +7,12 @@ class confdroid_alloy::main::files ( ) inherits confdroid_alloy::params { require confdroid_alloy::main::dirs + include concat - # Ensure log_targets is always an array $log_targets_array = Array($confdroid_alloy::params::ay_log_targets, true) - file { $ay_main_file: - ensure => file, + concat { $ay_main_file: + ensure => present, owner => 'root', group => 'root', mode => '0644', @@ -20,10 +20,29 @@ class confdroid_alloy::main::files ( selrole => object_r, seltype => etc_t, seluser => system_u, - content => template('confdroid_alloy/config.alloy.erb'), notify => Service[$ay_service], } + concat::fragment { 'confdroid_alloy_config_header': + target => $ay_main_file, + content => template('confdroid_alloy/config.alloy.erb'), + order => '001', + } + + if $ay_manage_loki == true { + concat::fragment { 'confdroid_alloy_log_targets_default': + target => $ay_main_file, + content => template('confdroid_alloy/log_targets.alloy.erb'), + order => '010', + } + } + + concat::fragment { 'confdroid_alloy_config_tail': + target => $ay_main_file, + content => template('confdroid_alloy/config.alloy.tail.erb'), + order => '999', + } + # manage logrotate for rsyslog to allow adm group membership file { '/etc/logrotate.d/rsyslog': ensure => file, diff --git a/templates/config.alloy.erb b/templates/config.alloy.erb index 31e72d7..ce50749 100644 --- a/templates/config.alloy.erb +++ b/templates/config.alloy.erb @@ -18,87 +18,4 @@ loki.process "alloy" { // Define file discovery for your logs local.file_match "system_logs" { path_targets = [ -<% @log_targets_array.each do |target| -%> - {__path__ = "<%= target %>"}, <% end -%> - ] - sync_period = "5s" -} - -// Scrape the logs from the matched files -loki.source.file "system_logs" { - targets = local.file_match.system_logs.targets - forward_to = [loki.process.syslog.receiver] -} - -loki.process "syslog" { - - stage.static_labels { - values = { - fqdn = constants.hostname, - service = "linux_logs", - } - } - forward_to = [loki.write.loki.receiver] -} - -loki.write "loki" { - endpoint { - url = "<%= @ay_loki_url %>" - basic_auth { - username = "<%= @ay_loki_username %>" - password = "<%= @ay_loki_userpass %>" - } - } -} -<% end -%> -<% if @ay_manage_prom == true -%> -// 1. Exporter (or keep your existing node_exporter binary) -prometheus.exporter.unix "node" { - // optional: disable unused collectors - // disable_collectors = ["ipvs", "btrfs", ...] -} - -// 2. Relabel the targets so instance = real hostname -discovery.relabel "node_exporter" { - targets = prometheus.exporter.unix.node.targets - - rule { - target_label = "instance" - replacement = constants.hostname - } - - rule { - target_label = "job" - replacement = "integrations/node_exporter" - } -} - -// 3. Scrape the properly labeled targets -prometheus.scrape "node_exporter" { - targets = discovery.relabel.node_exporter.output - forward_to = [prometheus.remote_write.prometheus.receiver] - scrape_interval = "15s" - honor_timestamps = <%= @ay_prom_honor_timestamps %> - track_timestamps_staleness = <%= @ay_prom_track_timestamps_staleness %> -} - -prometheus.remote_write "prometheus" { - external_labels = { - // makes every series from this Alloy unmistakably unique - alloy_instance = constants.hostname, - } - endpoint { - url = "<%= @ay_prom_url %>" - basic_auth { - username = "<%= @ay_loki_username %>" - password = "<%= @ay_loki_userpass %>" - } - queue_config { - max_shards = <%= @ay_prom_max_shards %> - max_samples_per_send = <%= @ay_prom_max_samples_per_send %> - batch_send_deadline = "<%= @ay_prom_batch_send_deadline %>" - } - } -} -<% end %> \ No newline at end of file diff --git a/templates/config.alloy.tail.erb b/templates/config.alloy.tail.erb new file mode 100644 index 0000000..b0545cc --- /dev/null +++ b/templates/config.alloy.tail.erb @@ -0,0 +1,82 @@ +<% if @ay_manage_loki == true -%> + ] + sync_period = "5s" +} + +// Scrape the logs from the matched files +loki.source.file "system_logs" { + targets = local.file_match.system_logs.targets + forward_to = [loki.process.syslog.receiver] +} + +loki.process "syslog" { + + stage.static_labels { + values = { + fqdn = constants.hostname, + service = "linux_logs", + } + } + forward_to = [loki.write.loki.receiver] +} + +loki.write "loki" { + endpoint { + url = "<%= @ay_loki_url %>" + basic_auth { + username = "<%= @ay_loki_username %>" + password = "<%= @ay_loki_userpass %>" + } + } +} +<% end -%> +<% if @ay_manage_prom == true -%> +// 1. Exporter (or keep your existing node_exporter binary) +prometheus.exporter.unix "node" { + // optional: disable unused collectors + // disable_collectors = ["ipvs", "btrfs", ...] +} + +// 2. Relabel the targets so instance = real hostname +discovery.relabel "node_exporter" { + targets = prometheus.exporter.unix.node.targets + + rule { + target_label = "instance" + replacement = constants.hostname + } + + rule { + target_label = "job" + replacement = "integrations/node_exporter" + } +} + +// 3. Scrape the properly labeled targets +prometheus.scrape "node_exporter" { + targets = discovery.relabel.node_exporter.output + forward_to = [prometheus.remote_write.prometheus.receiver] + scrape_interval = "15s" + honor_timestamps = <%= @ay_prom_honor_timestamps %> + track_timestamps_staleness = <%= @ay_prom_track_timestamps_staleness %> +} + +prometheus.remote_write "prometheus" { + external_labels = { + // makes every series from this Alloy unmistakably unique + alloy_instance = constants.hostname, + } + endpoint { + url = "<%= @ay_prom_url %>" + basic_auth { + username = "<%= @ay_loki_username %>" + password = "<%= @ay_loki_userpass %>" + } + queue_config { + max_shards = <%= @ay_prom_max_shards %> + max_samples_per_send = <%= @ay_prom_max_samples_per_send %> + batch_send_deadline = "<%= @ay_prom_batch_send_deadline %>" + } + } +} +<% end -%> diff --git a/templates/log_targets.alloy.erb b/templates/log_targets.alloy.erb new file mode 100644 index 0000000..23d5a24 --- /dev/null +++ b/templates/log_targets.alloy.erb @@ -0,0 +1,3 @@ +<% @log_targets_array.each do |target| -%> + {__path__ = "<%= target %>"}, +<% end -%>