data "aws_caller_identity" "current" {
}

# Datadog Neo4j Timeboard
resource "datadog_dashboard" "neo4j_timeboard" {
  title       = "${var.environment}-${var.service_name}-timeboard"
  description = "${var.environment}-${var.service_name}-timeboard"
  layout_type = "ordered"

  template_variable {
    defaults = [var.environment]
    name     = var.service_name
    prefix   = "environment"
  }

  widget {
    group_definition {
        layout_type      = "ordered"
        show_title       = true
        title            = "Custom metrics"
        background_color = "blue"

        # Custom metrics created from: https://github.com/theorchard/irrigate-datadog/blob/master/templates/default/custom_neo4j.py.erb
        # @Todo check why we dont get these Custom metrics for neo4j_cluster:dev-neo4j-5-cluster
        widget {
          timeseries_definition {
            request {
              q            = "max:neo4j.heap.max{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
              display_type = "line"
              style {
                palette    = "classic"
                line_type  = "solid"
                line_width = "normal"
              }
            }
            request {
              q            = "max:neo4j.heap.used{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
              display_type = "line"
              style {
                palette    = "classic"
                line_type  = "solid"
                line_width = "normal"
              }
            }
            title       = "Heap memory utilization"
            title_size  = 16
            title_align = "left"
          }
        }

        widget {
          timeseries_definition {
            request {
              q            = "max:neo4j.totalmem{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
              display_type = "line"
              style {
                palette    = "classic"
                line_type  = "solid"
                line_width = "normal"
              }
            }
            title       = "Total neo4j memory (heap + non-heap + ephemeral) utilization"
            title_size  = 16
            title_align = "left"
          }
        }

        widget {
          timeseries_definition {
            request {
              q            = "max:neo4j.non_heap.init{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
              display_type = "line"
              style {
                palette    = "classic"
                line_type  = "solid"
                line_width = "normal"
              }
            }
            request {
              q            = "max:neo4j.non_heap.committed{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
              display_type = "line"
              style {
                palette    = "classic"
                line_type  = "solid"
                line_width = "normal"
              }
            }
            request {
              q            = "max:neo4j.non_heap.used{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
              display_type = "line"
              style {
                palette    = "classic"
                line_type  = "solid"
                line_width = "normal"
              }
            }
            title       = "Non-Heap memory utilization"
            title_size  = 16
            title_align = "left"
          }
        }
    } # end group_definition
  } # end widget

  widget {
    group_definition {
        layout_type      = "ordered"
        show_title       = true
        title            = "System metrics"
        background_color = "green"

      # System metrics
      widget {
        timeseries_definition {
          request {
            q            = "max:system.cpu.system{neo4j_cluster:${var.environment}-${var.service_name}} by {host}+max:system.cpu.user{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
            display_type = "line"
            style {
              palette    = "classic"
              line_type  = "solid"
              line_width = "normal"
            }
          }
          title       = "CPU utilization (percent)"
          title_size  = 16
          title_align = "left"
        }
      }

      widget {
        timeseries_definition {
          request {
            q            = "avg:system.mem.pct_usable{neo4j_cluster:${var.environment}-${var.service_name}} by {host}, 100*(1-avg:system.mem.pct_usable{neo4j_cluster:${var.environment}-${var.service_name}} by {host})"
            display_type = "line"
            style {
              palette    = "classic"
              line_type  = "solid"
              line_width = "normal"
            }
          }
          title       = "Host memory utilization (percent)"
          title_size  = 16
          title_align = "left"
        }
      }

      widget {
        timeseries_definition {
          request {
            q            = "max:system.disk.in_use{neo4j_cluster:${var.environment}-${var.service_name},!device:devtmpfs,!device:tmpfs, !device:rootfs} by {device,host}"
            display_type = "line"
            style {
              palette    = "classic"
              line_type  = "solid"
              line_width = "normal"
            }
          }
          title       = "Disk utilization (percent)"
          title_size  = 16
          title_align = "left"
        }
      }

      widget {
        timeseries_definition {
          request {
            on_right_yaxis = true
            query {
              metric_query {
                name = "iops_check"
                query = "max:aws.ebs.volume_iopsexceeded_check{neo4j_cluster:${var.environment}-${var.service_name}}"
                aggregator = "max"
              }
            }
            display_type = "bars"
            style {
              palette    = "red"
              line_type  = "solid"
              line_width = "normal"
            }

            formula {
              alias = "IOPS EXCEEDED"
              formula_expression = "cutoff_min(iops_check, 0.6)"
            }
          }

          request {
            on_right_yaxis = false
            query {
              metric_query {
                name = "avg_iops"
                query = "max:aws.ebs.volume_avg_iops{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
                aggregator = "max"
              }
            }
            query {
              metric_query {
                name = "max_avg_iops"
                query = "max:aws.ebs.volume_avg_iops.maximum{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
                aggregator = "max"
              }
            }
            display_type = "line"
            style {
              palette    = "dog_classic"
              line_type  = "solid"
              line_width = "normal"
            }

            formula {
              alias = "IOPS used"
              formula_expression = "avg_iops + max_avg_iops"
            }
          }

          title       = "EBS IOPS Utilization"
          title_size  = 16
          title_align = "left"
        }
      }
    } # end group_definition
  } # end widget

  widget {
    group_definition {
        layout_type      = "ordered"
        show_title       = true
        title            = "Neo4j metrics"
        background_color = "orange"

        # Neo4j metrics
        dynamic "widget" {
          for_each = local.metrics_widgets

          content {
            timeseries_definition {
              request {
                q            = "max:${widget.value}{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
                display_type = "line"
                style {
                  palette    = "classic"
                  line_type  = "solid"
                  line_width = "normal"
                }
              }
              title       = widget.value
              title_size  = 16
              title_align = "left"
            }
          }
        }
    } # end group_definition
  } # end widget

  # Cluster Lag metrics Widget Group
  widget {
    group_definition {
      layout_type = "ordered"
      title       = "Cluster Transaction Replication Lag metrics"

      widget {
        timeseries_definition {
          title = "Last Committed Transaction ID by Host"
          request {
            q            = "max:${local.metrics_last_commited_transaction_id}{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
            display_type = "line"
            style {
              palette    = "classic"
              line_type  = "solid"
              line_width = "normal"
            }
          }
          yaxis {
            include_zero = false
            scale        = "linear"
          }
        }
      }
      widget {
        timeseries_definition {
          title = "Transaction ID difference (max - min)"
          request {
            formula {
              formula_expression = "max_tx_id - min_tx_id"
              alias              = "tx_id difference"
            }
            query {
              metric_query {
                name       = "max_tx_id"
                query      = "max:${local.metrics_last_commited_transaction_id}{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
                aggregator = "max"
              }
            }
            query {
              metric_query {
                name       = "min_tx_id"
                query      = "min:${local.metrics_last_commited_transaction_id}{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
                aggregator = "min"
              }
            }

            display_type = "bars"
            style {
              palette = "red"
            }
          }
        }
      }
    }
  } # end widget

  widget {
    split_graph_definition {
      title = "Last Committed Transaction ID Value by Host"
      size  = "xs"
      source_widget_definition {
        query_value_definition {
          autoscale = false
          precision = 0
          request {

            query {
              metric_query {
                name       = "query1"
                query      = "max:${local.metrics_last_commited_transaction_id}{neo4j_cluster:${var.environment}-${var.service_name}}"
                aggregator = "max"
              }
            }
          }
        }
      }
      split_config {
        split_dimensions {
          one_graph_per = "host"
        }
        limit = 4
        sort {
          order = "desc"
        }
      }
    }
  } # end widget

  # Node and relationship count
  dynamic widget {
    for_each = local.show_node_rel_count_widget
    content {
      group_definition {
        layout_type = "ordered"
        title       = "Node and relationship count"

        widget {
          change_definition {
            request {
              q             = "sum:neo4j_cypher_scheduler.assert_data_quality.query_count{query_file:node-count} by {entity}"
              change_type   = "relative"
              compare_to    = "day_before"
              increase_good = true
              order_by      = "change"
              order_dir     = "desc"
              show_present  = true
            }
            title     = "Node Count"
            live_span = "1d"
          }
        }
        widget {
          change_definition {
            request {
              q             = "sum:neo4j_cypher_scheduler.assert_data_quality.query_count{query_file:relationship-count} by {entity}"
              change_type   = "relative"
              compare_to    = "day_before"
              increase_good = true
              order_by      = "change"
              order_dir     = "desc"
              show_present  = true
            }
            title     = "Relationship Count"
            live_span = "1d"
          }
        }
      }
    }
  } # end widget

  tags = local.dashboard_tags
}

# Datadog Neo4j Screenboard
resource "datadog_dashboard" "neo4j_screenboard" {
  title       = "${var.environment}-${var.service_name}-screenboard"
  description = "${var.environment}-${var.service_name}-screenboard"
  layout_type = "free"
  template_variable {
    defaults = [var.environment]
    name     = var.service_name
    prefix   = "environment"
  }

  widget {
    manage_status_definition {
      color_preference = "background"
      display_format   = "countsAndList"
      hide_zero_counts = false
      query            = "tag:(environment:${var.environment} AND service_name:${var.service_name})"
      sort             = "status,asc"
      title            = "${var.environment}-${var.service_name} monitor summary"
      title_size       = 16
      title_align      = "left"
    }
    widget_layout {
      width  = 65
      height = 30
      x      = 0
      y      = 0
    }
  }

  widget {
    hostmap_definition {
      request {
        fill {
          q = "avg:system.load.1{neo4j_cluster:${var.environment}-${var.service_name}} by {host}"
        }
      }
      node_type       = "host"
      no_group_hosts  = true
      no_metric_hosts = true
      scope = [
        "neo4j_cluster:${var.environment}-${var.service_name}"
      ]
      style {
        palette      = "green_to_orange"
        palette_flip = false
        fill_min     = "10"
        fill_max     = "20"
      }
      title = "Neo4j hosts in ${var.environment}-${var.service_name} cluster"
    }
    widget_layout {
      width  = 30
      height = 30
      x      = 70
      y      = 0
    }
  }

  widget {
    log_stream_definition {
      query = "source:neo4j neo4j_cluster:${var.environment}-${var.service_name}"
      columns = [
        "content"
      ]
      title       = "${var.environment}-${var.service_name} neo4j logs"
      title_size  = 16
      title_align = "left"


      live_span = "1h"
    }
    widget_layout {
      width  = 100
      height = 30
      x      = 0
      y      = 32
    }
  }

  tags = local.dashboard_tags
}

# Inefficient queries Dashboard
resource "datadog_dashboard" "neo4j_inefficient_queries" {
  count       = var.environment != "dev" ? 1 : 0
  title       = "${upper(var.environment)} Neo4j Inefficient queries"
  description = "Neo4j query performance: slow queries, page fault load, and DB time consumed by user."
  layout_type = "ordered"

  dynamic "widget" {
    for_each = local.timeseries_definitions

    content {
      timeseries_definition {
        title = widget.value["title"]
        yaxis {
          include_zero = true
          scale        = "linear"
        }

        legend_columns = [
          "avg",
          "max",
          "min",
          "sum",
          "value"
        ]
        legend_layout = "auto"

        request {
          display_type = "bars"
          formula {
            formula_expression = "query1"
          }
          style {
            line_type  = "solid"
            line_width = "normal"
            palette    = "dog_classic"
          }
          query {
            event_query {
              data_source = "logs"
              indexes     = ["*"]
              name        = "query1"

              search {
                query = widget.value["search_query"]
              }
              compute {
                aggregation = lookup(widget.value, "aggregation", "count")
                metric      = lookup(widget.value, "metric", null)
                interval    = 0
              }
              dynamic "group_by" {
                for_each = lookup(widget.value, "group_by", null) != null ? [widget.value["group_by"]] : []
                content {
                  facet = group_by.value
                  limit = lookup(widget.value, "limit", 10)
                  sort {
                    aggregation = lookup(widget.value, "aggregation", "count")
                    metric      = lookup(widget.value, "metric", null)
                    order       = lookup(widget.value, "sort", "desc")
                  }
                }
              }
            }
          }
        }
      }
      widget_layout {
        width  = widget.value["width"]
        height = widget.value["height"]
        x      = widget.value["pos_x"]
        y      = widget.value["pos_y"]
      }
    }
  }

  dynamic "widget" {
    for_each = local.query_table_definitions

    content {
      query_table_definition {
        title = widget.value["title"]

        request {
          dynamic "query" {
            for_each = widget.value["queries"]

            content {
              event_query {
                name        = query.value["name"]
                data_source = "logs"
                indexes     = ["*"]

                search {
                  query = query.value["search_query"]
                }

                compute {
                  aggregation = query.value["aggregation"]
                  metric      = lookup(query.value, "metric", null)
                }

                group_by {
                  facet = lookup(widget.value, "group_by_facet", "@executingUser")
                  limit = query.value["limit"]

                  sort {
                    aggregation = query.value["aggregation"]
                    order       = "desc"
                    metric      = lookup(query.value, "metric", null)
                  }
                }
              }
            }
          }

          dynamic "formula" {
            for_each = widget.value["formulas"]

            content {
              formula_expression = formula.value["expression"]
              alias              = formula.value["alias"]
              dynamic "limit" {
                for_each = lookup(formula.value, "limit_clause", false) == true ? [1] : []
                content {
                  count = formula.value["limit_count"]
                  order = formula.value["limit_order"]
                }
              }
            }
          }

        }
      }
      widget_layout {
        width  = widget.value["width"]
        height = widget.value["height"]
        x      = widget.value["pos_x"]
        y      = widget.value["pos_y"]
      }
    }

  }

  dynamic "widget" {
    for_each = local.log_stream_definitions
    content {
      log_stream_definition {
        title = widget.value["title"]
        query = widget.value["query"]
        sort {
          column = widget.value["sort_column"]
          order  = "desc"
        }
        columns = widget.value["columns"]
      }
      widget_layout {
        width  = widget.value["width"]
        height = widget.value["height"]
        x      = widget.value["pos_x"]
        y      = widget.value["pos_y"]
      }
    }
  }

  tags = local.dashboard_tags
}
