data "aws_caller_identity" "current" {
}

data "datadog_role" "datadog_admin_role" {
  filter = "Datadog Admin Role"
}

resource "datadog_monitor" "mysql_disk_space_monitor" {
  count = var.mysql_disk_space_monitor_enabled ? 1 : 0
  name  = "${var.host_name}-mysql-disk-space-monitor"
  type  = "metric alert"
  message = templatefile("${path.module}/templates/notifications.tftpl", {
    message                        = "Disk space is low on ${var.host_name}."
    notification_endpoints         = var.notification_endpoints
    alert_notification_endpoints   = var.alert_notification_endpoints
    no_data_notification_endpoints = var.no_data_notification_endpoints
  })
  escalation_message = "Disk space remains low on ${var.host_name}. Escalation to ${var.escalation_notification_endpoints}"

  query = "avg(${var.measurement_interval_disk_utilization}):max:system.disk.in_use{host:${var.host_name},!device:devtmpfs,!device:tmpfs} by {device} * 100 > ${var.critical_number_disk_utilization}"

  monitor_thresholds {
    ok                = var.ok_number_disk_utilization
    warning           = var.warning_number_disk_utilization
    warning_recovery  = var.warning_recovery_number_disk_utilization
    critical          = var.critical_number_disk_utilization
    critical_recovery = var.critical_recovery_number_disk_utilization
  }

  include_tags        = true
  notify_no_data      = true
  notify_audit        = false
  renotify_interval   = 60
  timeout_h           = 0
  require_full_window = true

  tags = local.tags
}

resource "datadog_monitor" "mysql_availability_monitor" {
  count = var.mysql_availability_monitor_enabled ? 1 : 0
  name  = "${var.host_name}-mysql-availability-monitor"
  type  = "service check"
  message = templatefile("${path.module}/templates/notifications.tftpl", {
    message                        = "MySQL is not available on ${var.host_name}. Monitor triggered."
    notification_endpoints         = var.notification_endpoints
    alert_notification_endpoints   = var.alert_notification_endpoints
    no_data_notification_endpoints = var.no_data_notification_endpoints
  })
  escalation_message = "MySQL is still not available on ${var.host_name}. Escalation to ${var.escalation_notification_endpoints}"

  query = "\"mysql.can_connect\".over(\"host:${var.host_name}\").by(\"*\").last(${max(var.ok_number_availability, var.critical_number_availability) + 1}).count_by_status()"

  monitor_thresholds {
    ok       = var.ok_number_availability
    critical = var.critical_number_availability
  }

  include_tags        = true
  notify_no_data      = true
  notify_audit        = false
  renotify_interval   = 60
  timeout_h           = 0
  require_full_window = true

  tags = local.tags
}

resource "datadog_monitor" "mysql_memory_monitor" {
  count = var.mysql_memory_monitor_enabled ? 1 : 0
  name  = "${var.host_name}-mysql-memory-monitor"
  type  = "metric alert"
  message = templatefile("${path.module}/templates/notifications.tftpl", {
    message                        = "High memory utilization on ${var.host_name}. Monitor triggered."
    notification_endpoints         = var.notification_endpoints
    alert_notification_endpoints   = var.alert_notification_endpoints
    no_data_notification_endpoints = var.no_data_notification_endpoints
  })
  escalation_message = "Memory utilization is still high on ${var.host_name}. Escalation to ${var.escalation_notification_endpoints}"

  # Usable and pct_usable do not take into consideration reserved innodb buffer pool space that may or may not be occupied at a given time
  query = "avg(${var.measurement_interval_memory}):100 * (1 - max:system.mem.pct_usable{host:${var.host_name}}) > ${var.critical_number_memory}"

  monitor_thresholds {
    ok                = var.ok_number_memory
    warning           = var.warning_number_memory
    warning_recovery  = var.warning_recovery_number_memory
    critical          = var.critical_number_memory
    critical_recovery = var.critical_recovery_number_memory
  }

  include_tags        = true
  notify_no_data      = true
  notify_audit        = false
  renotify_interval   = 60
  timeout_h           = 0
  require_full_window = true

  tags = local.tags
}

resource "datadog_monitor" "mysql_cpu_monitor" {
  count = var.mysql_cpu_monitor_enabled ? 1 : 0
  name  = "${var.host_name}-mysql-cpu-monitor"
  type  = "metric alert"
  message = templatefile("${path.module}/templates/notifications.tftpl", {
    message                        = "High CPU utilization on ${var.host_name}. Monitor triggered."
    notification_endpoints         = var.notification_endpoints
    alert_notification_endpoints   = var.alert_notification_endpoints
    no_data_notification_endpoints = var.no_data_notification_endpoints
  })
  escalation_message = "CPU utilization is still high on ${var.host_name}. Escalation to ${var.escalation_notification_endpoints}"

  query = "avg(${var.measurement_interval_cpu}):(max:system.cpu.system{host:${var.host_name}}+max:system.cpu.iowait{host:${var.host_name}}+max:system.cpu.user{host:${var.host_name}}+max:system.cpu.stolen{host:${var.host_name}}+max:system.cpu.guest{host:${var.host_name}}) > ${var.critical_number_cpu}"

  monitor_thresholds {
    ok                = var.ok_number_cpu
    warning           = var.warning_number_cpu
    warning_recovery  = var.warning_recovery_number_cpu
    critical          = var.critical_number_cpu
    critical_recovery = var.critical_recovery_number_cpu
  }

  include_tags        = true
  notify_no_data      = true
  notify_audit        = false
  renotify_interval   = 60
  timeout_h           = 0
  require_full_window = true

  tags = local.tags
}

resource "datadog_monitor" "mysql_connection_monitor" {
  count = var.mysql_connection_monitor_enabled ? 1 : 0
  name  = "${var.host_name}-mysql-connection-monitor"
  type  = "metric alert"
  message = templatefile("${path.module}/templates/notifications.tftpl", {
    message                        = "High connection utilization on ${var.host_name}. Monitor triggered."
    notification_endpoints         = var.notification_endpoints
    alert_notification_endpoints   = var.alert_notification_endpoints
    no_data_notification_endpoints = var.no_data_notification_endpoints
  })
  escalation_message = "Connection utilization is still high on ${var.host_name}. Escalation to ${var.escalation_notification_endpoints}"

  query = "avg(${var.measurement_interval_connections}):100 * ( max:mysql.performance.threads_connected{host:${var.host_name}} / max:mysql.net.max_connections_available{host:${var.host_name}} ) > ${var.critical_number_connections}"

  monitor_thresholds {
    ok                = var.ok_number_connections
    warning           = var.warning_number_connections
    warning_recovery  = var.warning_recovery_number_connections
    critical          = var.critical_number_connections
    critical_recovery = var.critical_recovery_number_connections
  }

  include_tags        = true
  notify_no_data      = true
  notify_audit        = false
  renotify_interval   = 60
  timeout_h           = 0
  require_full_window = true

  tags = local.tags
}

resource "datadog_monitor" "mysql_slow_queries_monitor" {
  count = var.mysql_slow_queries_monitor_enabled ? 1 : 0
  name  = "${var.host_name}-mysql-slow-queries-monitor"
  type  = "metric alert"
  message = templatefile("${path.module}/templates/notifications.tftpl", {
    message                        = "High number of slow queries on ${var.host_name}. Monitor triggered."
    notification_endpoints         = var.notification_endpoints
    alert_notification_endpoints   = var.alert_notification_endpoints
    no_data_notification_endpoints = var.no_data_notification_endpoints
  })
  escalation_message = "Slow query rate is still high on ${var.host_name}. Escalation to ${var.escalation_notification_endpoints}"

  query = "avg(${var.measurement_interval_slow_queries}):mysql.performance.slow_queries{host:${var.host_name}} > ${var.critical_number_slow_queries}"

  monitor_thresholds {
    ok                = var.ok_number_slow_queries
    warning           = var.warning_number_slow_queries
    warning_recovery  = var.warning_recovery_number_slow_queries
    critical          = var.critical_number_slow_queries
    critical_recovery = var.critical_recovery_number_slow_queries
  }

  include_tags        = true
  notify_no_data      = true
  notify_audit        = false
  renotify_interval   = 60
  timeout_h           = 0
  require_full_window = true

  tags = local.tags
}

resource "datadog_monitor" "mysql_replica_lag_monitor" {
  count = var.mysql_replica_lag_monitor_enabled ? 1 : 0
  name  = "${var.host_name}-mysql-replica-lag-monitor"
  type  = "metric alert"
  message = templatefile("${path.module}/templates/notifications.tftpl", {
    message                        = "Replication lag is too high on ${var.host_name}. Monitor triggered."
    notification_endpoints         = var.notification_endpoints
    alert_notification_endpoints   = var.alert_notification_endpoints
    no_data_notification_endpoints = var.no_data_notification_endpoints
  })
  escalation_message = "Replication lag is still high on ${var.host_name}. Escalation to ${var.escalation_notification_endpoints}"

  query = "avg(${var.measurement_interval_replica_lag}):mysql.replication.seconds_behind_master{host:${var.host_name}} > ${var.critical_seconds_replica_lag}"

  monitor_thresholds {
    ok                = var.ok_seconds_replica_lag
    warning           = var.warning_seconds_replica_lag
    warning_recovery  = var.warning_recovery_seconds_replica_lag
    critical          = var.critical_seconds_replica_lag
    critical_recovery = var.critical_recovery_seconds_replica_lag
  }

  include_tags        = true
  notify_no_data      = true
  notify_audit        = false
  renotify_interval   = 60
  timeout_h           = 0
  require_full_window = true

  tags = local.tags
}

resource "datadog_dashboard" "mysql_dashboard" {
  title            = "${var.host_name} MySQL dashboard"
  description      = "${var.host_name} MySQL dashboard"
  layout_type      = "ordered"
  restricted_roles = [data.datadog_role.datadog_admin_role.id]

  widget {
    check_status_definition {
      check       = "datadog.agent.up"
      grouping    = "check"
      group       = "host:${var.host_name}"
      title       = "Datadog Agent check status"
      title_align = "left"
      title_size  = "16"
      tags        = ["*"]

    }
  }

  widget {
    check_status_definition {
      check       = "mysql.can_connect"
      grouping    = "check"
      group       = "port:3306,server:${var.mysql_socket_file},host:${var.host_name}"
      title       = "MySQL check status"
      title_align = "left"
      title_size  = "16"
      tags        = ["*"]

    }
  }

  widget {
    timeseries_definition {
      title       = "MySQL connections"
      show_legend = false

      request {
        q = "sum:mysql.net.connections{host:${var.host_name}}"
      }

      request {
        q = "sum:mysql.performance.threads_connected{host:${var.host_name}}"
      }

      request {
        q = "sum:mysql.net.max_connections_available{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "MySQL reads and writes (per sec)"
      show_legend = false

      request {
        q = "sum:mysql.innodb.data_reads{host:${var.host_name}}"
      }

      request {
        q = "sum:mysql.innodb.data_writes{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "MySQL query types"
      show_legend = false

      request {
        q = "avg:mysql.performance.com_delete{host:${var.host_name}}"
      }

      request {
        q = "avg:mysql.performance.com_load{host:${var.host_name}}"
      }

      request {
        q = "avg:mysql.performance.com_insert{host:${var.host_name}}"
      }

      request {
        q = "avg:mysql.performance.com_select{host:${var.host_name}}"
      }

      request {
        q = "avg:mysql.performance.com_update{host:${var.host_name}}"
      }

      request {
        q = "avg:mysql.performance.com_replace{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "MySQL slow queries"
      show_legend = false

      request {
        q = "sum:mysql.performance.slow_queries{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "MySQL total queries"
      show_legend = false

      request {
        q = "avg:mysql.performance.queries{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "MySQL queued queries"
      show_legend = false
      title_align = "left"
      title_size  = "16"

      request {
        q = "max:mysql.innodb.queries_queued{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "MySQL row operations"
      show_legend = false
      title_align = "left"
      title_size  = "16"

      request {
        q = "avg:mysql.innodb.rows_read{host:${var.host_name}}"
      }

      request {
        q = "avg:mysql.innodb.rows_deleted{host:${var.host_name}}"
      }

      request {
        q = "avg:mysql.innodb.rows_inserted{host:${var.host_name}}"
      }
      request {
        q = "avg:mysql.innodb.rows_updated{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "MySQL CPU time (per sec)"
      show_legend = false

      request {
        q = "avg:mysql.performance.user_time{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "MySQL table locks"
      show_legend = false

      request {
        q = "rate(sum:mysql.performance.table_locks_waited{host:${var.host_name}})"
      }

      request {
        q = "rate(sum:mysql.performance.table_locks_immediate{host:${var.host_name}})"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "Host memory"
      show_legend = false

      request {
        q = "avg:system.mem.total{host:${var.host_name}}"
      }

      request {
        q = "avg:system.mem.used{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "Innodb total memory usage"
      show_legend = false
      title_align = "left"
      title_size  = "16"

      request {
        q = "avg:mysql.innodb.mem_total{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "Host memory utilization (percent)"
      show_legend = false

      request {
        q = "100 * (1 - max:system.mem.pct_usable{host:${var.host_name}})"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "MySQL data volume disk usage"
      show_legend = false

      request {
        q = "max:system.disk.total{host:${var.host_name},device:${var.mysql_data_volume_device_name}}"
      }

      request {
        q = "max:system.disk.used{host:${var.host_name},device:${var.mysql_data_volume_device_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "System disk usage"
      show_legend = false

      request {
        q = "max:system.disk.total{host:${var.host_name},device:${var.mysql_system_disk_device_name}}"
      }

      request {
        q = "max:system.disk.used{host:${var.host_name},device:${var.mysql_system_disk_device_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "Binlog disk usage"
      show_legend = false
      title_align = "left"
      title_size  = "16"

      request {
        q = "max:mysql.binlog.disk_use{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "CPU usage (%)"
      show_legend = false

      request {
        q = "max:system.cpu.system{host:${var.host_name}}+max:system.cpu.iowait{host:${var.host_name}}+max:system.cpu.user{host:${var.host_name}}+max:system.cpu.stolen{host:${var.host_name}}+max:system.cpu.guest{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "System load"
      show_legend = false

      request {
        q = "max:system.load.1{host:${var.host_name}}"
      }

      request {
        q = "max:system.load.5{host:${var.host_name}}"
      }

      request {
        q = "max:system.load.15{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "I/O wait (%)"
      show_legend = false

      request {
        q = "max:system.cpu.iowait{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "Network traffic (per sec)"
      show_legend = false

      request {
        q = "sum:system.net.bytes_rcvd{host:${var.host_name}}"
      }

      request {
        q = "sum:system.net.bytes_sent{host:${var.host_name}}"
      }
    }
  }

  widget {
    timeseries_definition {
      title       = "Innodb buffer pool"
      show_legend = false
      title_align = "left"
      title_size  = "16"

      request {
        q = "max:mysql.innodb.buffer_pool_used{host:${var.host_name}}"
      }

      request {
        q = "max:mysql.innodb.buffer_pool_total{host:${var.host_name}}"
      }
    }
  }

  dynamic "widget" {
    for_each = var.ebs_widgets_enabled ? [1] : []
    content {
      query_table_definition {
        title = "EBS volume health"

        request {
          q          = "max:aws.ebs.status.ok{volume-name:${var.host_name}} by {volume-id}"
          aggregator = "max"
          limit      = "10"
          conditional_formats {
            comparator = ">="
            value      = "1"
            palette    = "white_on_green"
          }
          conditional_formats {
            comparator = "<"
            value      = "1"
            palette    = "white_on_red"
          }
        }
      }
    }
  }

  dynamic "widget" {
    for_each = var.ebs_widgets_enabled ? [1] : []
    content {
      timeseries_definition {
        title       = "MySQL data volume EBS operations"
        show_legend = false
        title_align = "left"
        title_size  = "16"

        request {
          q = "max:aws.ebs.volume_read_ops{host:${var.host_name},volume-id:${var.mysql_data_volume_ebs_volume_id}}.as_count()"
        }

        request {
          q = "max:aws.ebs.volume_write_ops{host:${var.host_name},volume-id:${var.mysql_data_volume_ebs_volume_id}}.as_count()"
        }
      }
    }
  }

  dynamic "widget" {
    for_each = var.ebs_widgets_enabled ? [1] : []
    content {
      timeseries_definition {
        title       = "MySQL data volume EBS queue length"
        show_legend = false
        title_align = "left"
        title_size  = "16"

        request {
          q = "max:aws.ebs.volume_queue_length{host:${var.host_name},volume-id:${var.mysql_data_volume_ebs_volume_id}}"
        }

      }
    }
  }

  dynamic "widget" {
    for_each = var.ebs_widgets_enabled ? [1] : []
    content {
      timeseries_definition {
        title       = "MySQL data volume EBS throughput"
        show_legend = false
        title_align = "left"
        title_size  = "16"

        request {
          q = "max:aws.ebs.volume_read_bytes{host:${var.host_name},volume-id:${var.mysql_data_volume_ebs_volume_id}}"
        }

        request {
          q = "max:aws.ebs.volume_write_bytes{host:${var.host_name},volume-id:${var.mysql_data_volume_ebs_volume_id}}"
        }

      }
    }
  }

  dynamic "widget" {
    for_each = var.ebs_widgets_enabled ? [1] : []
    content {
      timeseries_definition {
        title       = "MySQL data volume EBS latency"
        show_legend = false
        title_align = "left"
        title_size  = "16"

        request {
          q = "max:aws.ebs.volume_total_write_time{host:${var.host_name},volume-id:${var.mysql_data_volume_ebs_volume_id}}"
        }

        request {
          q = "max:aws.ebs.volume_total_read_time{host:${var.host_name},volume-id:${var.mysql_data_volume_ebs_volume_id}}"
        }
      }
    }
  }

  tags = local.dashboard_tags
}
