Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: smart agent fluentd detector #572

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
111 changes: 111 additions & 0 deletions modules/smart-agent_fluentd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Fluentd SignalFx detectors

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
:link: **Contents**

- [How to use this module?](#how-to-use-this-module)
- [What are the available detectors in this module?](#what-are-the-available-detectors-in-this-module)
- [How to collect required metrics?](#how-to-collect-required-metrics)
- [Metrics](#metrics)
- [Related documentation](#related-documentation)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

## How to use this module?

This directory defines a [Terraform](https://www.terraform.io/)
[module](https://www.terraform.io/docs/modules/usage.html) you can use in your
existing [stack](https://github.com/claranet/terraform-signalfx-detectors/wiki/Getting-started#stack) by adding a
`module` configuration and setting its `source` parameter to URL of this folder:

```hcl
module "signalfx-detectors-smart-agent-fluentd" {
source = "github.com/claranet/terraform-signalfx-detectors.git//modules/smart-agent_fluentd?ref={revision}"

environment = var.environment
notifications = local.notifications
}
```

Note the following parameters:

* `source`: Use this parameter to specify the URL of the module. The double slash (`//`) is intentional and required.
Terraform uses it to specify subfolders within a Git repo (see [module
sources](https://www.terraform.io/docs/modules/sources.html)). The `ref` parameter specifies a specific Git tag in
this repository. It is recommended to use the latest "pinned" version in place of `{revision}`. Avoid using a branch
like `master` except for testing purpose. Note that every modules in this repository are available on the Terraform
[registry](https://registry.terraform.io/modules/claranet/detectors/signalfx) and we recommend using it as source
instead of `git` which is more flexible but less future-proof.

* `environment`: Use this parameter to specify the
[environment](https://github.com/claranet/terraform-signalfx-detectors/wiki/Getting-started#environment) used by this
instance of the module.
Its value will be added to the `prefixes` list at the start of the [detector
name](https://github.com/claranet/terraform-signalfx-detectors/wiki/Templating#example).
In general, it will also be used in the `filtering` internal sub-module to [apply
[filters](https://github.com/claranet/terraform-signalfx-detectors/wiki/Guidance#filtering) based on our default
[tagging convention](https://github.com/claranet/terraform-signalfx-detectors/wiki/Tagging-convention) by default.

* `notifications`: Use this parameter to define where alerts should be sent depending on their severity. It consists
of a Terraform [object](https://www.terraform.io/docs/configuration/types.html#object-) where each key represents an
available [detector rule severity](https://docs.signalfx.com/en/latest/detect-alert/set-up-detectors.html#severity)
and its value is a list of recipients. Every recipients must respect the [detector notification
format](https://registry.terraform.io/providers/splunk-terraform/signalfx/latest/docs/resources/detector#notification-format).
Check the [notification binding](https://github.com/claranet/terraform-signalfx-detectors/wiki/Notifications-binding)
documentation to understand the recommended role of each severity.

These 3 parameters alongs with all variables defined in [common-variables.tf](common-variables.tf) are common to all
[modules](../) in this repository. Other variables, specific to this module, are available in
[variables-gen.tf](variables-gen.tf).
In general, the default configuration "works" but all of these Terraform
[variables](https://www.terraform.io/docs/configuration/variables.html) make it possible to
customize the detectors behavior to better fit your needs.

Most of them represent usual tips and rules detailled in the
[guidance](https://github.com/claranet/terraform-signalfx-detectors/wiki/Guidance) documentation and listed in the
common [variables](https://github.com/claranet/terraform-signalfx-detectors/wiki/Variables) dedicated documentation.

Feel free to explore the [wiki](https://github.com/claranet/terraform-signalfx-detectors/wiki) for more information about
general usage of this repository.

## What are the available detectors in this module?

This module creates the following SignalFx detectors which could contain one or multiple alerting rules:

|Detector|Critical|Major|Minor|Warning|Info|
|---|---|---|---|---|---|
|Fluentd heartbeat|-|X|-|-|-|
|Fluentd buffer application|-|X|-|-|-|

## How to collect required metrics?

This module uses metrics available from
[monitors](https://docs.signalfx.com/en/latest/integrations/agent/monitors/_monitor-config.html)
available in the [SignalFx Smart
Agent](https://github.com/signalfx/signalfx-agent). Check the "Related documentation" section for more
information including the official documentation of this monitor.




### Metrics


To filter only required metrics for the detectors of this module, add the
[datapointsToExclude](https://docs.signalfx.com/en/latest/integrations/agent/filtering.html) parameter to
the corresponding monitor configuration:

```yaml
- metricNames:
- '*'
- '!fluentd_output_status_buffer_stage_length'

```



## Related documentation

* [Terraform SignalFx provider](https://registry.terraform.io/providers/splunk-terraform/signalfx/latest/docs)
* [Terraform SignalFx detector](https://registry.terraform.io/providers/splunk-terraform/signalfx/latest/docs/resources/detector)
1 change: 1 addition & 0 deletions modules/smart-agent_fluentd/common-filters.tf
1 change: 1 addition & 0 deletions modules/smart-agent_fluentd/common-locals.tf
1 change: 1 addition & 0 deletions modules/smart-agent_fluentd/common-modules.tf
1 change: 1 addition & 0 deletions modules/smart-agent_fluentd/common-variables.tf
1 change: 1 addition & 0 deletions modules/smart-agent_fluentd/common-versions.tf
42 changes: 42 additions & 0 deletions modules/smart-agent_fluentd/conf/readme.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
documentations:
- name: Smart Agent monitor
url: 'https://docs.signalfx.com/en/latest/integrations/agent/monitors/prometheus-exporter.html'

source_doc: |
### Agent

Here is the official [main
documentation](https://docs.signalfx.com/en/latest/integrations/integrations-reference/integrations.kubernetes.html) for
kubernetes including the `signalfx-agent` installation which must be installed as
[daemonset](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) on your cluster.

### Monitors

The detectors in this module are based on metrics reported by the following monitors:

* [prometheus-exporter](https://docs.signalfx.com/en/latest/integrations/agent/monitors/prometheus-exporter.html)

Detectors in this module will at least require these metric:

* `fluentd_output_status_buffer_stage_length`

This metric is enabled by default, but it is the only one used on the detectors.

### Fluentd Prometheus

For using this detector, the instance has to have an entrypoint prometheus exposing the information of fluentd.
You have to install fluent-plugin-prometheus on the server and adding the monitoring configuration to td-agent to use it.
More info on the doc [Fluentd](https://docs.fluentd.org/monitoring-fluentd/monitoring-prometheus)

notes: |
Here an example of the monitor configuration
```yaml
- type: prometheus-exporter
host: 127.0.0.1
port: 24231
- metricNames:
- '*'
- '!fluentd_output_status_buffer_stage_length'
```

You can find all the metrics on the repository [fluent-plugin-prometheus](https://github.com/fluent/fluent-plugin-prometheus/blob/master/README.md)
51 changes: 51 additions & 0 deletions modules/smart-agent_fluentd/detectors-gen.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
resource "signalfx_detector" "heartbeat" {
name = format("%s %s", local.detector_name_prefix, "Fluentd heartbeat")

authorized_writer_teams = var.authorized_writer_teams
teams = try(coalescelist(var.teams, var.authorized_writer_teams), null)
tags = compact(concat(local.common_tags, local.tags, var.extra_tags))

max_delay = 900

program_text = <<-EOF
from signalfx.detectors.not_reporting import not_reporting
signal = data('fluentd_output_status_buffer_queue_length', filter=${local.not_running_vm_filters} and ${module.filtering.signalflow})${var.heartbeat_aggregation_function}.publish('signal')
not_reporting.detector(stream=signal, resource_identifier=None, duration='${var.heartbeat_timeframe}', auto_resolve_after='${local.heartbeat_auto_resolve_after}').publish('MAJOR')
EOF

rule {
description = "is too high >= ${var.heartbeat_timeframe}"
severity = "Major"
detect_label = "MAJOR"
disabled = coalesce(var.heartbeat_disabled, var.detectors_disabled)
notifications = coalescelist(lookup(var.heartbeat_notifications, "major", []), var.notifications.major)
runbook_url = try(coalesce(var.heartbeat_runbook_url, var.runbook_url), "")
tip = var.heartbeat_tip
parameterized_subject = var.message_subject == "" ? local.rule_subject_novalue : var.message_subject
parameterized_body = var.message_body == "" ? local.rule_body : var.message_body
}
}

resource "signalfx_detector" "buffer" {
name = format("%s %s", local.detector_name_prefix, "Fluentd Buffer length")

authorized_writer_teams = var.authorized_writer_teams
teams = try(coalescelist(var.teams, var.authorized_writer_teams), null)
tags = compact(concat(local.common_tags, local.tags, var.extra_tags))

program_text = <<-EOF
signal = data('fluentd_output_status_buffer_queue_length', filter=${local.not_running_vm_filters} and ${module.filtering.signalflow})${var.buffer_aggregation_function}${var.buffer_transformation_function}.publish('signal')
detect(when(signal > ${var.buffer_threshold}, lasting="${var.buffer_lasting_seconds}s"), auto_resolve_after="${var.buffer_auto_resolve_seconds}s").publish('MAJOR')
EOF
rule {
description = "is too high > ${var.buffer_threshold}"
severity = "Major"
detect_label = "MAJOR"
disabled = coalesce(var.buffer_disabled, var.buffer_disabled, var.detectors_disabled)
notifications = coalescelist(lookup(var.buffer_notifications, "major", []), var.notifications.major)
runbook_url = try(coalesce(var.buffer_runbook_url, var.runbook_url), "")
tip = var.buffer_tip
parameterized_subject = var.message_subject == "" ? local.rule_subject : var.message_subject
parameterized_body = var.message_body == "" ? local.rule_body : var.message_body
}
}
9 changes: 9 additions & 0 deletions modules/smart-agent_fluentd/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
output "heartbeat" {
description = "Detector resource for heartbeat"
value = signalfx_detector.heartbeat
}

output "buffer" {
description = "Detector resource for buffer length"
value = signalfx_detector.buffer
}
4 changes: 4 additions & 0 deletions modules/smart-agent_fluentd/tags.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
locals {
tags = ["smart-agent", "fluentd"]
}

94 changes: 94 additions & 0 deletions modules/smart-agent_fluentd/variables-gen.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# heartbeat detector

variable "heartbeat_notifications" {
description = "Notification recipients list per severity overridden for heartbeat detector"
type = map(list(string))
default = {}
}

variable "heartbeat_aggregation_function" {
description = "Aggregation function and group by for heartbeat detector (i.e. \".mean(by=['host'])\")"
type = string
default = ".sum(by=['host'])"
}

variable "heartbeat_tip" {
description = "Suggested first course of action or any note useful for incident handling"
type = string
default = ""
}

variable "heartbeat_runbook_url" {
description = "URL like SignalFx dashboard or wiki page which can help to troubleshoot the incident cause"
type = string
default = ""
}

variable "heartbeat_disabled" {
description = "Disable all alerting rules for heartbeat detector"
type = bool
default = null
}

variable "heartbeat_timeframe" {
description = "Timeframe for heartbeat detector (i.e. \"10m\")"
type = string
default = "20m"
}

# buffer detector

variable "buffer_notifications" {
description = "Notification recipients list per severity overridden for buffer detector"
type = map(list(string))
default = {}
}

variable "buffer_aggregation_function" {
description = "Aggregation function and group by for buffer detector (i.e. \".mean(by=['host'])\")"
type = string
default = ".sum(by=['host'])"
}

variable "buffer_transformation_function" {
description = "Transformation function for buffer detector (i.e. \".mean(over='10m')\")"
type = string
default = ".min(over='10min')"
}

variable "buffer_tip" {
description = "Suggested first course of action or any note useful for incident handling"
type = string
default = ""
}

variable "buffer_disabled" {
description = "Disable all alerting rules for buffer detector"
type = bool
default = null
}

variable "buffer_runbook_url" {
description = "URL like SignalFx dashboard or wiki page which can help to troubleshoot the incident cause"
type = string
default = ""
}

variable "buffer_threshold" {
description = "Major threshold for up detector"
type = number
default = 10
}

variable "buffer_lasting_seconds" {
description = "Minimum duration that conditions must be true before raising alert (in seconds)"
type = number
default = 300
}

variable "buffer_auto_resolve_seconds" {
description = "Alert duration after NO DATA (in seconds)"
type = number
default = 60
}

Loading