netdata/netdata

View on GitHub
src/go/collectors/go.d.plugin/modules/envoy/charts.go

Summary

Maintainability
F
4 days
Test Coverage
// SPDX-License-Identifier: GPL-3.0-or-later

package envoy

import (
    "fmt"
    "strings"

    "github.com/netdata/netdata/go/go.d.plugin/agent/module"

    "github.com/prometheus/prometheus/model/labels"
)

const (
    prioServerState = module.Priority + iota
    prioServerMemoryAllocatedSize
    prioServerMemoryHeapSize
    prioServerMemoryPhysicalSize
    prioServerConnectionsCount
    prioServerParentConnectionsCount

    prioClusterManagerClustersCount
    prioClusterManagerClusterChangesRate
    prioClusterManagerClusterUpdatesRate
    prioClusterManagerClusterUpdatesVieMergeRate
    prioClusterManagerClusterUpdatesMergeCancelledRate
    prioClusterManagerClusterUpdatesOufOfMergeWindowsRate

    prioClusterMembershipEndpointsCount
    prioClusterMembershipChangesRate
    prioClusterMembershipUpdatesRate

    prioClusterUpstreamActiveConnectionsCount
    prioClusterUpstreamConnectionsRate
    prioClusterUpstreamHTTPConnectionsRate
    prioClusterUpstreamDestroyedConnectionsRate
    prioClusterUpstreamFailedConnectionsRate
    prioClusterUpstreamTimedOutConnectionsRate
    prioClusterUpstreamTrafficRate
    prioClusterUpstreamBufferedSize

    prioClusterUpstreamActiveRequestsCount
    prioClusterUpstreamRequestsRate
    prioClusterUpstreamFailedRequestsRate
    prioClusterUpstreamActivePendingRequestsCount
    prioClusterUpstreamPendingRequestsRate
    prioClusterUpstreamPendingFailedRequestsRate
    prioClusterUpstreamRequestRetriesRate
    prioClusterUpstreamRequestSuccessRetriesRate
    prioClusterUpstreamRequestBackoffRetriesRate

    prioListenerManagerListenerCount
    prioListenerManagerListenerChangesRate
    prioListenerManagerListenerObjectEventsRate

    prioListenerAdminDownstreamActiveConnectionsCount
    prioListenerAdminDownstreamConnectionsRate
    prioListenerAdminDownstreamDestroyedConnectionsRate
    prioListenerAdminDownstreamTimedOutConnectionsRate
    prioListenerAdminDownstreamRejectedConnectionsRate
    prioListenerAdminDownstreamFilterClosedByRemoteConnectionsRate
    prioListenerAdminDownstreamFilterReadErrorsRate
    prioListenerAdminDownstreamActiveSocketsCount
    prioListenerAdminDownstreamTimedOutSocketsRate

    prioListenerDownstreamActiveConnectionsCount
    prioListenerDownstreamConnectionsRate
    prioListenerDownstreamDestroyedConnectionsRate
    prioListenerDownstreamTimedOutConnectionsRate
    prioListenerDownstreamRejectedConnectionsRate
    prioListenerDownstreamFilterClosedByRemoteConnectionsRate
    prioListenerDownstreamFilterReadErrorsRate
    prioListenerDownstreamActiveSocketsCount
    prioListenerDownstreamTimedOutSocketsRate

    prioServerUptime
)

var (
    serverChartsTmpl = module.Charts{
        serverStateChartTmpl.Copy(),

        serverMemoryAllocatedSizeChartTmpl.Copy(),
        serverMemoryHeapSizeChartTmpl.Copy(),
        serverMemoryPhysicalSizeChartTmpl.Copy(),

        serverConnectionsCountChartTmpl.Copy(),
        serverParentConnectionsCountChartTmpl.Copy(),

        serverUptimeChartTmpl.Copy(),
    }
    serverStateChartTmpl = module.Chart{
        ID:       "server_state_%s",
        Title:    "Server current state",
        Units:    "state",
        Fam:      "server",
        Ctx:      "envoy.server_state",
        Priority: prioServerState,
        Dims: module.Dims{
            {ID: "envoy_server_state_live_%s", Name: "live"},
            {ID: "envoy_server_state_draining_%s", Name: "draining"},
            {ID: "envoy_server_state_pre_initializing_%s", Name: "pre_initializing"},
            {ID: "envoy_server_state_initializing_%s", Name: "initializing"},
        },
    }
    serverConnectionsCountChartTmpl = module.Chart{
        ID:       "server_connections_%s",
        Title:    "Server current connections",
        Units:    "connections",
        Fam:      "server",
        Ctx:      "envoy.server_connections_count",
        Priority: prioServerConnectionsCount,
        Dims: module.Dims{
            {ID: "envoy_server_total_connections_%s", Name: "connections"},
        },
    }
    serverParentConnectionsCountChartTmpl = module.Chart{
        ID:       "server_parent_connections_%s",
        Title:    "Server current parent connections",
        Units:    "connections",
        Fam:      "server",
        Ctx:      "envoy.server_parent_connections_count",
        Priority: prioServerParentConnectionsCount,
        Dims: module.Dims{
            {ID: "envoy_server_parent_connections_%s", Name: "connections"},
        },
    }
    serverMemoryAllocatedSizeChartTmpl = module.Chart{
        ID:       "server_memory_allocated_size_%s",
        Title:    "Server memory allocated size",
        Units:    "bytes",
        Fam:      "server",
        Ctx:      "envoy.server_memory_allocated_size",
        Priority: prioServerMemoryAllocatedSize,
        Dims: module.Dims{
            {ID: "envoy_server_memory_allocated_%s", Name: "allocated"},
        },
    }
    serverMemoryHeapSizeChartTmpl = module.Chart{
        ID:       "server_memory_heap_size_%s",
        Title:    "Server memory heap size",
        Units:    "bytes",
        Fam:      "server",
        Ctx:      "envoy.server_memory_heap_size",
        Priority: prioServerMemoryHeapSize,
        Dims: module.Dims{
            {ID: "envoy_server_memory_heap_size_%s", Name: "heap"},
        },
    }
    serverMemoryPhysicalSizeChartTmpl = module.Chart{
        ID:       "server_memory_physical_size_%s",
        Title:    "Server memory physical size",
        Units:    "bytes",
        Fam:      "server",
        Ctx:      "envoy.server_memory_physical_size",
        Priority: prioServerMemoryPhysicalSize,
        Dims: module.Dims{
            {ID: "envoy_server_memory_physical_size_%s", Name: "physical"},
        },
    }
    serverUptimeChartTmpl = module.Chart{
        ID:       "server_uptime_%s",
        Title:    "Server uptime",
        Units:    "seconds",
        Fam:      "uptime",
        Ctx:      "envoy.server_uptime",
        Priority: prioServerUptime,
        Dims: module.Dims{
            {ID: "envoy_server_uptime_%s", Name: "uptime"},
        },
    }
)

var (
    clusterManagerChartsTmpl = module.Charts{
        clusterManagerClusterCountChartTmpl.Copy(),
        clusterManagerClusterChangesRateChartTmpl.Copy(),
        clusterManagerClusterUpdatesRateChartTmpl.Copy(),
        clusterManagerClusterUpdatesViaMergeRateChartTmpl.Copy(),
        clusterManagerClusterUpdatesMergeCancelledRateChartTmpl.Copy(),
        clusterManagerClusterUpdatesOutOfMergeWindowRateChartTmpl.Copy(),
    }
    clusterManagerClusterCountChartTmpl = module.Chart{
        ID:       "cluster_manager_cluster_count_%s",
        Title:    "Cluster manager current clusters",
        Units:    "clusters",
        Fam:      "cluster mgr",
        Ctx:      "envoy.cluster_manager_cluster_count",
        Priority: prioClusterManagerClustersCount,
        Dims: module.Dims{
            {ID: "envoy_cluster_manager_active_clusters_%s", Name: "active"},
            {ID: "envoy_cluster_manager_warming_clusters_%s", Name: "not_active"},
        },
    }
    clusterManagerClusterChangesRateChartTmpl = module.Chart{
        ID:       "cluster_manager_cluster_changes_%s",
        Title:    "Cluster manager cluster changes",
        Units:    "clusters/s",
        Fam:      "cluster mgr",
        Ctx:      "envoy.cluster_manager_cluster_changes_rate",
        Priority: prioClusterManagerClusterChangesRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_manager_cluster_added_%s", Name: "added", Algo: module.Incremental},
            {ID: "envoy_cluster_manager_cluster_modified_%s", Name: "modified", Algo: module.Incremental},
            {ID: "envoy_cluster_manager_cluster_removed_%s", Name: "removed", Algo: module.Incremental},
        },
    }
    clusterManagerClusterUpdatesRateChartTmpl = module.Chart{
        ID:       "cluster_manager_cluster_updates_%s",
        Title:    "Cluster manager updates",
        Units:    "updates/s",
        Fam:      "cluster mgr",
        Ctx:      "envoy.cluster_manager_cluster_updates_rate",
        Priority: prioClusterManagerClusterUpdatesRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_manager_cluster_updated_%s", Name: "cluster", Algo: module.Incremental},
        },
    }
    clusterManagerClusterUpdatesViaMergeRateChartTmpl = module.Chart{
        ID:       "cluster_manager_cluster_updated_via_merge_%s",
        Title:    "Cluster manager updates applied as merged updates",
        Units:    "updates/s",
        Fam:      "cluster mgr",
        Ctx:      "envoy.cluster_manager_cluster_updated_via_merge_rate",
        Priority: prioClusterManagerClusterUpdatesVieMergeRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_manager_cluster_updated_via_merge_%s", Name: "via_merge", Algo: module.Incremental},
        },
    }
    clusterManagerClusterUpdatesMergeCancelledRateChartTmpl = module.Chart{
        ID:       "cluster_manager_update_merge_cancelled_%s",
        Title:    "Cluster manager cancelled merged updates",
        Units:    "updates/s",
        Fam:      "cluster mgr",
        Ctx:      "envoy.cluster_manager_update_merge_cancelled_rate",
        Priority: prioClusterManagerClusterUpdatesMergeCancelledRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_manager_update_merge_cancelled_%s", Name: "merge_cancelled", Algo: module.Incremental},
        },
    }
    clusterManagerClusterUpdatesOutOfMergeWindowRateChartTmpl = module.Chart{
        ID:       "cluster_manager_update_out_of_merge_window_%s",
        Title:    "Cluster manager out of a merge window updates",
        Units:    "updates/s",
        Fam:      "cluster mgr",
        Ctx:      "envoy.cluster_manager_update_out_of_merge_window_rate",
        Priority: prioClusterManagerClusterUpdatesOufOfMergeWindowsRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_manager_update_out_of_merge_window_%s", Name: "out_of_merge_window", Algo: module.Incremental},
        },
    }
)

var (
    clusterUpstreamChartsTmpl = module.Charts{
        clusterUpstreamActiveConnectionsCountChartTmpl.Copy(),
        clusterUpstreamConnectionsRateChartTmpl.Copy(),
        clusterUpstreamHTTPConnectionsRateChartTmpl.Copy(),
        clusterUpstreamDestroyedConnectionsRateChartTmpl.Copy(),
        clusterUpstreamFailedConnectionsRateChartTmpl.Copy(),
        clusterUpstreamTimedOutConnectionsRateChartTmpl.Copy(),
        clusterUpstreamTrafficRateChartTmpl.Copy(),
        clusterUpstreamBufferedSizeChartTmpl.Copy(),

        clusterUpstreamActiveRequestsCountChartTmpl.Copy(),
        clusterUpstreamRequestsRateChartTmpl.Copy(),
        clusterUpstreamFailedRequestsRateChartTmpl.Copy(),
        clusterUpstreamActivePendingRequestsCountChartTmpl.Copy(),
        clusterUpstreamPendingRequestsRateChartTmpl.Copy(),
        clusterUpstreamPendingFailedRequestsRateChartTmpl.Copy(),
        clusterUpstreamRequestRetriesRateChartTmpl.Copy(),
        clusterUpstreamRequestSuccessRetriesRateChartTmpl.Copy(),
        clusterUpstreamRequestRetriesBackoffRateChartTmpl.Copy(),

        clusterMembershipEndpointsCountChartTmpl.Copy(),
        clusterMembershipChangesRateChartTmpl.Copy(),
        clusterMembershipUpdatesRateChartTmpl.Copy(),
    }

    clusterUpstreamActiveConnectionsCountChartTmpl = module.Chart{
        ID:       "cluster_upstream_cx_active_%s",
        Title:    "Cluster upstream current active connections",
        Units:    "connections",
        Fam:      "upstream conns",
        Ctx:      "envoy.cluster_upstream_cx_active_count",
        Priority: prioClusterUpstreamActiveConnectionsCount,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_cx_active_%s", Name: "active"},
        },
    }
    clusterUpstreamConnectionsRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_cx_total_%s",
        Title:    "Cluster upstream connections",
        Units:    "connections/s",
        Fam:      "upstream conns",
        Ctx:      "envoy.cluster_upstream_cx_rate",
        Priority: prioClusterUpstreamConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_cx_total_%s", Name: "created", Algo: module.Incremental},
        },
    }
    clusterUpstreamHTTPConnectionsRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_cx_http_total_%s",
        Title:    "Cluster upstream connections by HTTP version",
        Units:    "connections/s",
        Fam:      "upstream conns",
        Ctx:      "envoy.cluster_upstream_cx_http_rate",
        Priority: prioClusterUpstreamHTTPConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_cx_http1_total_%s", Name: "http1", Algo: module.Incremental},
            {ID: "envoy_cluster_upstream_cx_http2_total_%s", Name: "http2", Algo: module.Incremental},
            {ID: "envoy_cluster_upstream_cx_http3_total_%s", Name: "http3", Algo: module.Incremental},
        },
    }
    clusterUpstreamDestroyedConnectionsRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_cx_destroy_%s",
        Title:    "Cluster upstream destroyed connections",
        Units:    "connections/s",
        Fam:      "upstream conns",
        Ctx:      "envoy.cluster_upstream_cx_destroy_rate",
        Priority: prioClusterUpstreamDestroyedConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_cx_destroy_local_%s", Name: "local", Algo: module.Incremental},
            {ID: "envoy_cluster_upstream_cx_destroy_remote_%s", Name: "remote", Algo: module.Incremental},
        },
    }
    clusterUpstreamFailedConnectionsRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_cx_connect_fail_%s",
        Title:    "Cluster upstream failed connections",
        Units:    "connections/s",
        Fam:      "upstream conns",
        Ctx:      "envoy.cluster_upstream_cx_connect_fail_rate",
        Priority: prioClusterUpstreamFailedConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_cx_connect_fail_%s", Name: "failed", Algo: module.Incremental},
        },
    }
    clusterUpstreamTimedOutConnectionsRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_cx_connect_timeout_%s",
        Title:    "Cluster upstream timed out connections",
        Units:    "connections/s",
        Fam:      "upstream conns",
        Ctx:      "envoy.cluster_upstream_cx_connect_timeout_rate",
        Priority: prioClusterUpstreamTimedOutConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_cx_connect_timeout_%s", Name: "timeout", Algo: module.Incremental},
        },
    }
    clusterUpstreamTrafficRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_cx_bytes_total_%s",
        Title:    "Cluster upstream connection traffic",
        Units:    "bytes/s",
        Fam:      "upstream traffic",
        Ctx:      "envoy.cluster_upstream_cx_bytes_rate",
        Priority: prioClusterUpstreamTrafficRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_cx_rx_bytes_total_%s", Name: "received", Algo: module.Incremental},
            {ID: "envoy_cluster_upstream_cx_tx_bytes_total_%s", Name: "sent", Algo: module.Incremental},
        },
    }
    clusterUpstreamBufferedSizeChartTmpl = module.Chart{
        ID:       "cluster_upstream_cx_bytes_buffered_%s",
        Title:    "Cluster upstream current connection buffered size",
        Units:    "bytes",
        Fam:      "upstream traffic",
        Ctx:      "envoy.cluster_upstream_cx_bytes_buffered_size",
        Priority: prioClusterUpstreamBufferedSize,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_cx_rx_bytes_buffered_%s", Name: "received"},
            {ID: "envoy_cluster_upstream_cx_tx_bytes_buffered_%s", Name: "send"},
        },
    }

    clusterUpstreamActiveRequestsCountChartTmpl = module.Chart{
        ID:       "cluster_upstream_rq_active_%s",
        Title:    "Cluster upstream current active requests",
        Units:    "requests",
        Fam:      "upstream requests",
        Ctx:      "envoy.cluster_upstream_rq_active_count",
        Priority: prioClusterUpstreamActiveRequestsCount,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_rq_active_%s", Name: "active"},
        },
    }
    clusterUpstreamRequestsRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_rq_total_%s",
        Title:    "Cluster upstream requests",
        Units:    "requests/s",
        Fam:      "upstream requests",
        Ctx:      "envoy.cluster_upstream_rq_rate",
        Priority: prioClusterUpstreamRequestsRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_rq_total_%s", Name: "requests", Algo: module.Incremental},
        },
    }
    clusterUpstreamFailedRequestsRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_rq_failed_total_%s",
        Title:    "Cluster upstream failed requests",
        Units:    "requests/s",
        Fam:      "upstream requests",
        Ctx:      "envoy.cluster_upstream_rq_failed_rate",
        Priority: prioClusterUpstreamFailedRequestsRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_rq_cancelled_%s", Name: "cancelled", Algo: module.Incremental},
            {ID: "envoy_cluster_upstream_rq_maintenance_mode_%s", Name: "maintenance_mode", Algo: module.Incremental},
            {ID: "envoy_cluster_upstream_rq_timeout_%s", Name: "timeout", Algo: module.Incremental},
            {ID: "envoy_cluster_upstream_rq_max_duration_reached_%s", Name: "max_duration_reached", Algo: module.Incremental},
            {ID: "envoy_cluster_upstream_rq_per_try_timeout_%s", Name: "per_try_timeout", Algo: module.Incremental},
            {ID: "envoy_cluster_upstream_rq_rx_reset_%s", Name: "reset_local", Algo: module.Incremental},
            {ID: "envoy_cluster_upstream_rq_tx_reset_%s", Name: "reset_remote", Algo: module.Incremental},
        },
    }
    clusterUpstreamActivePendingRequestsCountChartTmpl = module.Chart{
        ID:       "cluster_upstream_rq_pending_active_%s",
        Title:    "Cluster upstream current active pending requests",
        Units:    "requests",
        Fam:      "upstream requests",
        Ctx:      "envoy.cluster_upstream_rq_pending_active_count",
        Priority: prioClusterUpstreamActivePendingRequestsCount,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_rq_pending_active_%s", Name: "active_pending"},
        },
    }
    clusterUpstreamPendingRequestsRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_rq_pending_total_%s",
        Title:    "Cluster upstream pending requests",
        Units:    "requests/s",
        Fam:      "upstream requests",
        Ctx:      "envoy.cluster_upstream_rq_pending_rate",
        Priority: prioClusterUpstreamPendingRequestsRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_rq_pending_total_%s", Name: "pending", Algo: module.Incremental},
        },
    }
    clusterUpstreamPendingFailedRequestsRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_rq_pending_failed_total_%s",
        Title:    "Cluster upstream failed pending requests",
        Units:    "requests/s",
        Fam:      "upstream requests",
        Ctx:      "envoy.cluster_upstream_rq_pending_failed_rate",
        Priority: prioClusterUpstreamPendingFailedRequestsRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_rq_pending_overflow_%s", Name: "overflow", Algo: module.Incremental},
            {ID: "envoy_cluster_upstream_rq_pending_failure_eject_%s", Name: "failure_eject", Algo: module.Incremental},
        },
    }
    clusterUpstreamRequestRetriesRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_rq_retry_%s",
        Title:    "Cluster upstream request retries",
        Units:    "retries/s",
        Fam:      "upstream requests",
        Ctx:      "envoy.cluster_upstream_rq_retry_rate",
        Priority: prioClusterUpstreamRequestRetriesRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_rq_retry_%s", Name: "request", Algo: module.Incremental},
        },
    }
    clusterUpstreamRequestSuccessRetriesRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_rq_retry_success_%s",
        Title:    "Cluster upstream request successful retries",
        Units:    "retries/s",
        Fam:      "upstream requests",
        Ctx:      "envoy.cluster_upstream_rq_retry_success_rate",
        Priority: prioClusterUpstreamRequestSuccessRetriesRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_rq_retry_success_%s", Name: "success", Algo: module.Incremental},
        },
    }
    clusterUpstreamRequestRetriesBackoffRateChartTmpl = module.Chart{
        ID:       "cluster_upstream_rq_retry_backoff_%s",
        Title:    "Cluster upstream request backoff retries",
        Units:    "retries/s",
        Fam:      "upstream requests",
        Ctx:      "envoy.cluster_upstream_rq_retry_backoff_rate",
        Priority: prioClusterUpstreamRequestBackoffRetriesRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_upstream_rq_retry_backoff_exponential_%s", Name: "exponential", Algo: module.Incremental},
            {ID: "envoy_cluster_upstream_rq_retry_backoff_ratelimited_%s", Name: "ratelimited", Algo: module.Incremental},
        },
    }

    clusterMembershipEndpointsCountChartTmpl = module.Chart{
        ID:       "cluster_membership_endpoints_count_%s",
        Title:    "Cluster membership current endpoints",
        Units:    "endpoints",
        Fam:      "cluster membership",
        Ctx:      "envoy.cluster_membership_endpoints_count",
        Priority: prioClusterMembershipEndpointsCount,
        Dims: module.Dims{
            {ID: "envoy_cluster_membership_healthy_%s", Name: "healthy"},
            {ID: "envoy_cluster_membership_degraded_%s", Name: "degraded"},
            {ID: "envoy_cluster_membership_excluded_%s", Name: "excluded"},
        },
    }
    clusterMembershipChangesRateChartTmpl = module.Chart{
        ID:       "cluster_membership_change_%s",
        Title:    "Cluster membership changes",
        Units:    "changes/s",
        Fam:      "cluster membership",
        Ctx:      "envoy.cluster_membership_changes_rate",
        Priority: prioClusterMembershipChangesRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_membership_change_%s", Name: "membership", Algo: module.Incremental},
        },
    }
    clusterMembershipUpdatesRateChartTmpl = module.Chart{
        ID:       "cluster_membership_updates_%s",
        Title:    "Cluster membership updates",
        Units:    "updates/s",
        Fam:      "cluster membership",
        Ctx:      "envoy.cluster_membership_updates_rate",
        Priority: prioClusterMembershipUpdatesRate,
        Dims: module.Dims{
            {ID: "envoy_cluster_update_success_%s", Name: "success", Algo: module.Incremental},
            {ID: "envoy_cluster_update_failure_%s", Name: "failure", Algo: module.Incremental},
            {ID: "envoy_cluster_update_empty_%s", Name: "empty", Algo: module.Incremental},
            {ID: "envoy_cluster_update_no_rebuild_%s", Name: "no_rebuild", Algo: module.Incremental},
        },
    }
)

var (
    listenerManagerChartsTmpl = module.Charts{
        listenerManagerListenersByStateCountChartTmpl.Copy(),
        listenerManagerListenerChangesRateChartTmpl.Copy(),
        listenerManagerListenerObjectEventsRateChartTmpl.Copy(),
    }
    listenerManagerListenersByStateCountChartTmpl = module.Chart{
        ID:       "listener_manager_listeners_count_%s",
        Title:    "Listener manager current listeners",
        Units:    "listeners",
        Fam:      "downstream mgr",
        Ctx:      "envoy.listener_manager_listeners_count",
        Priority: prioListenerManagerListenerCount,
        Dims: module.Dims{
            {ID: "envoy_listener_manager_total_listeners_active_%s", Name: "active"},
            {ID: "envoy_listener_manager_total_listeners_warming_%s", Name: "warming"},
            {ID: "envoy_listener_manager_total_listeners_draining_%s", Name: "draining"},
        },
    }
    listenerManagerListenerChangesRateChartTmpl = module.Chart{
        ID:       "listener_manager_listener_changes_%s",
        Title:    "Listener manager listener changes",
        Units:    "listeners/s",
        Fam:      "downstream mgr",
        Ctx:      "envoy.listener_manager_listener_changes_rate",
        Priority: prioListenerManagerListenerChangesRate,
        Dims: module.Dims{
            {ID: "envoy_listener_manager_listener_added_%s", Name: "added", Algo: module.Incremental},
            {ID: "envoy_listener_manager_listener_modified_%s", Name: "modified", Algo: module.Incremental},
            {ID: "envoy_listener_manager_listener_removed_%s", Name: "removed", Algo: module.Incremental},
            {ID: "envoy_listener_manager_listener_stopped_%s", Name: "stopped", Algo: module.Incremental},
        },
    }
    listenerManagerListenerObjectEventsRateChartTmpl = module.Chart{
        ID:       "listener_manager_listener_object_events_%s",
        Title:    "Listener manager listener object events",
        Units:    "objects/s",
        Fam:      "downstream mgr",
        Ctx:      "envoy.listener_manager_listener_object_events_rate",
        Priority: prioListenerManagerListenerObjectEventsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_manager_listener_create_success_%s", Name: "create_success", Algo: module.Incremental},
            {ID: "envoy_listener_manager_listener_create_failure_%s", Name: "create_failure", Algo: module.Incremental},
            {ID: "envoy_listener_manager_listener_in_place_updated_%s", Name: "in_place_updated", Algo: module.Incremental},
        },
    }
)

var (
    listenerAdminDownstreamChartsTmpl = module.Charts{
        listenerAdminDownstreamActiveConnectionsCountChartTmpl.Copy(),
        listenerAdminDownstreamConnectionsRateChartTmpl.Copy(),
        listenerAdminDownstreamDestroyedConnectionsRateChartTmpl.Copy(),
        listenerAdminDownstreamTimedOutConnectionsRateChartTmpl.Copy(),
        listenerAdminDownstreamRejectedConnectionsRateChartTmpl.Copy(),
        listenerAdminDownstreamFilterClosedByRemoteConnectionsRateChartTmpl.Copy(),
        listenerAdminDownstreamFilterReadErrorsRateChartTmpl.Copy(),

        listenerAdminDownstreamActiveSocketsCountChartTmpl.Copy(),
        listenerAdminDownstreamTimedOutSocketsRateChartTmpl.Copy(),
    }

    listenerAdminDownstreamActiveConnectionsCountChartTmpl = module.Chart{
        ID:       "listener_admin_downstream_cx_active_%s",
        Title:    "Listener admin downstream current active connections",
        Units:    "connections",
        Fam:      "downstream adm conns",
        Ctx:      "envoy.listener_admin_downstream_cx_active_count",
        Priority: prioListenerAdminDownstreamActiveConnectionsCount,
        Dims: module.Dims{
            {ID: "envoy_listener_admin_downstream_cx_active_%s", Name: "active"},
        },
    }
    listenerAdminDownstreamConnectionsRateChartTmpl = module.Chart{
        ID:       "listener_admin_downstream_cx_total_%s",
        Title:    "Listener admin downstream connections",
        Units:    "connections/s",
        Fam:      "downstream adm conns",
        Ctx:      "envoy.listener_admin_downstream_cx_rate",
        Priority: prioListenerAdminDownstreamConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_admin_downstream_cx_total_%s", Name: "created", Algo: module.Incremental},
        },
    }
    listenerAdminDownstreamDestroyedConnectionsRateChartTmpl = module.Chart{
        ID:       "listener_admin_downstream_cx_destroy_%s",
        Title:    "Listener admin downstream destroyed connections",
        Units:    "connections/s",
        Fam:      "downstream adm conns",
        Ctx:      "envoy.listener_admin_downstream_cx_destroy_rate",
        Priority: prioListenerAdminDownstreamDestroyedConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_admin_downstream_cx_destroy_%s", Name: "destroyed", Algo: module.Incremental},
        },
    }
    listenerAdminDownstreamTimedOutConnectionsRateChartTmpl = module.Chart{
        ID:       "listener_admin_downstream_cx_transport_socket_connect_timeout_%s",
        Title:    "Listener admin downstream timed out connections",
        Units:    "connections/s",
        Fam:      "downstream adm conns",
        Ctx:      "envoy.listener_admin_downstream_cx_transport_socket_connect_timeout_rate",
        Priority: prioListenerAdminDownstreamTimedOutConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_admin_downstream_cx_transport_socket_connect_timeout_%s", Name: "timeout", Algo: module.Incremental},
        },
    }
    listenerAdminDownstreamRejectedConnectionsRateChartTmpl = module.Chart{
        ID:       "listener_admin_downstream_cx_rejected_%s",
        Title:    "Listener admin downstream rejected connections",
        Units:    "connections/s",
        Fam:      "downstream adm conns",
        Ctx:      "envoy.listener_admin_downstream_cx_rejected_rate",
        Priority: prioListenerAdminDownstreamRejectedConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_admin_downstream_cx_overflow_%s", Name: "overflow", Algo: module.Incremental},
            {ID: "envoy_listener_admin_downstream_cx_overload_reject_%s", Name: "overload", Algo: module.Incremental},
            {ID: "envoy_listener_admin_downstream_global_cx_overflow_%s", Name: "global_overflow", Algo: module.Incremental},
        },
    }
    listenerAdminDownstreamFilterClosedByRemoteConnectionsRateChartTmpl = module.Chart{
        ID:       "listener_admin_downstream_listener_filter_remote_close_%s",
        Title:    "Listener admin downstream connections closed by remote when peek data for listener filters",
        Units:    "connections/s",
        Fam:      "downstream adm conns",
        Ctx:      "envoy.listener_admin_downstream_listener_filter_remote_close_rate",
        Priority: prioListenerAdminDownstreamFilterClosedByRemoteConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_admin_downstream_listener_filter_remote_close_%s", Name: "closed", Algo: module.Incremental},
        },
    }
    listenerAdminDownstreamFilterReadErrorsRateChartTmpl = module.Chart{
        ID:       "listener_admin_downstream_listener_filter_error_%s",
        Title:    "Listener admin downstream read errors when peeking data for listener filters",
        Units:    "errors/s",
        Fam:      "downstream adm conns",
        Ctx:      "envoy.listener_admin_downstream_listener_filter_error_rate",
        Priority: prioListenerAdminDownstreamFilterReadErrorsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_admin_downstream_listener_filter_error_%s", Name: "read", Algo: module.Incremental},
        },
    }

    listenerAdminDownstreamActiveSocketsCountChartTmpl = module.Chart{
        ID:       "listener_admin_downstream_pre_cx_active_%s",
        Title:    "Listener admin downstream current active sockets",
        Units:    "sockets",
        Fam:      "downstream adm sockets",
        Ctx:      "envoy.listener_admin_downstream_pre_cx_active_count",
        Priority: prioListenerAdminDownstreamActiveSocketsCount,
        Dims: module.Dims{
            {ID: "envoy_listener_admin_downstream_pre_cx_active_%s", Name: "active"},
        },
    }
    listenerAdminDownstreamTimedOutSocketsRateChartTmpl = module.Chart{
        ID:       "listener_admin_downstream_pre_cx_timeout_%s",
        Title:    "Listener admin downstream timed out sockets",
        Units:    "sockets/s",
        Fam:      "downstream adm sockets",
        Ctx:      "envoy.listener_admin_downstream_pre_cx_timeout_rate",
        Priority: prioListenerAdminDownstreamTimedOutSocketsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_admin_downstream_pre_cx_timeout_%s", Name: "timeout", Algo: module.Incremental},
        },
    }
)

var (
    listenerDownstreamChartsTmpl = module.Charts{
        listenerDownstreamActiveConnectionsCountChartTmpl.Copy(),
        listenerDownstreamConnectionsRateChartTmpl.Copy(),
        listenerDownstreamDestroyedConnectionsRateChartTmpl.Copy(),
        listenerDownstreamTimedOutConnectionsRateChartTmpl.Copy(),
        listenerDownstreamRejectedConnectionsRateChartTmpl.Copy(),
        listenerDownstreamFilterClosedByRemoteConnectionsRateChartTmpl.Copy(),
        listenerDownstreamFilterReadErrorsRateChartTmpl.Copy(),

        listenerDownstreamActiveSocketsCountChartTmpl.Copy(),
        listenerDownstreamTimedOutSocketsRateChartTmpl.Copy(),
    }

    listenerDownstreamActiveConnectionsCountChartTmpl = module.Chart{
        ID:       "listener_downstream_cx_active_%s",
        Title:    "Listener downstream current active connections",
        Units:    "connections",
        Fam:      "downstream conns",
        Ctx:      "envoy.listener_downstream_cx_active_count",
        Priority: prioListenerDownstreamActiveConnectionsCount,
        Dims: module.Dims{
            {ID: "envoy_listener_downstream_cx_active_%s", Name: "active"},
        },
    }
    listenerDownstreamConnectionsRateChartTmpl = module.Chart{
        ID:       "listener_downstream_cx_total_%s",
        Title:    "Listener downstream connections",
        Units:    "connections/s",
        Fam:      "downstream conns",
        Ctx:      "envoy.listener_downstream_cx_rate",
        Priority: prioListenerDownstreamConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_downstream_cx_total_%s", Name: "created", Algo: module.Incremental},
        },
    }
    listenerDownstreamDestroyedConnectionsRateChartTmpl = module.Chart{
        ID:       "listener_downstream_cx_destroy_%s",
        Title:    "Listener downstream destroyed connections",
        Units:    "connections/s",
        Fam:      "downstream conns",
        Ctx:      "envoy.listener_downstream_cx_destroy_rate",
        Priority: prioListenerDownstreamDestroyedConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_downstream_cx_destroy_%s", Name: "destroyed", Algo: module.Incremental},
        },
    }
    listenerDownstreamTimedOutConnectionsRateChartTmpl = module.Chart{
        ID:       "listener_downstream_cx_transport_socket_connect_timeout_%s",
        Title:    "Listener downstream timed out connections",
        Units:    "connections/s",
        Fam:      "downstream conns",
        Ctx:      "envoy.listener_downstream_cx_transport_socket_connect_timeout_rate",
        Priority: prioListenerDownstreamTimedOutConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_downstream_cx_transport_socket_connect_timeout_%s", Name: "timeout", Algo: module.Incremental},
        },
    }
    listenerDownstreamRejectedConnectionsRateChartTmpl = module.Chart{
        ID:       "listener_downstream_cx_rejected_%s",
        Title:    "Listener downstream rejected connections",
        Units:    "connections/s",
        Fam:      "downstream conns",
        Ctx:      "envoy.listener_downstream_cx_rejected_rate",
        Priority: prioListenerDownstreamRejectedConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_downstream_cx_overflow_%s", Name: "overflow", Algo: module.Incremental},
            {ID: "envoy_listener_downstream_cx_overload_reject_%s", Name: "overload", Algo: module.Incremental},
            {ID: "envoy_listener_downstream_global_cx_overflow_%s", Name: "global_overflow", Algo: module.Incremental},
        },
    }
    listenerDownstreamFilterClosedByRemoteConnectionsRateChartTmpl = module.Chart{
        ID:       "listener_downstream_listener_filter_remote_close_%s",
        Title:    "Listener downstream connections closed by remote when peek data for listener filters",
        Units:    "connections/s",
        Fam:      "downstream conns",
        Ctx:      "envoy.listener_downstream_listener_filter_remote_close_rate",
        Priority: prioListenerDownstreamFilterClosedByRemoteConnectionsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_downstream_listener_filter_remote_close_%s", Name: "closed", Algo: module.Incremental},
        },
    }
    listenerDownstreamFilterReadErrorsRateChartTmpl = module.Chart{
        ID:       "listener_downstream_listener_filter_error_%s",
        Title:    "Listener downstream read errors when peeking data for listener filters",
        Units:    "errors/s",
        Fam:      "downstream conns",
        Ctx:      "envoy.listener_downstream_listener_filter_error_rate",
        Priority: prioListenerDownstreamFilterReadErrorsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_downstream_listener_filter_error_%s", Name: "read", Algo: module.Incremental},
        },
    }

    listenerDownstreamActiveSocketsCountChartTmpl = module.Chart{
        ID:       "listener_downstream_pre_cx_active_%s",
        Title:    "Listener downstream current active sockets",
        Units:    "sockets",
        Fam:      "downstream sockets",
        Ctx:      "envoy.listener_downstream_pre_cx_active_count",
        Priority: prioListenerDownstreamActiveSocketsCount,
        Dims: module.Dims{
            {ID: "envoy_listener_downstream_pre_cx_active_%s", Name: "active"},
        },
    }
    listenerDownstreamTimedOutSocketsRateChartTmpl = module.Chart{
        ID:       "listener_downstream_pre_cx_timeout_%s",
        Title:    "Listener downstream timed out sockets",
        Units:    "sockets/s",
        Fam:      "downstream sockets",
        Ctx:      "envoy.listener_downstream_pre_cx_timeout_rate",
        Priority: prioListenerDownstreamTimedOutSocketsRate,
        Dims: module.Dims{
            {ID: "envoy_listener_downstream_pre_cx_timeout_%s", Name: "timeout", Algo: module.Incremental},
        },
    }
)

func (e *Envoy) addServerCharts(id string, labels labels.Labels) {
    e.addCharts(serverChartsTmpl.Copy(), id, labels)
}

func (e *Envoy) addClusterManagerCharts(id string, labels labels.Labels) {
    e.addCharts(clusterManagerChartsTmpl.Copy(), id, labels)
}

func (e *Envoy) addClusterUpstreamCharts(id string, labels labels.Labels) {
    e.addCharts(clusterUpstreamChartsTmpl.Copy(), id, labels)
}

func (e *Envoy) addListenerManagerCharts(id string, labels labels.Labels) {
    e.addCharts(listenerManagerChartsTmpl.Copy(), id, labels)
}

func (e *Envoy) addListenerAdminDownstreamCharts(id string, labels labels.Labels) {
    e.addCharts(listenerAdminDownstreamChartsTmpl.Copy(), id, labels)
}

func (e *Envoy) addListenerDownstreamCharts(id string, labels labels.Labels) {
    e.addCharts(listenerDownstreamChartsTmpl.Copy(), id, labels)
}

func (e *Envoy) addCharts(charts *module.Charts, id string, labels labels.Labels) {
    charts = charts.Copy()

    for _, chart := range *charts {
        if id == "" {
            chart.ID = strings.Replace(chart.ID, "_%s", "", 1)
            for _, dim := range chart.Dims {
                dim.ID = strings.Replace(dim.ID, "_%s", "", 1)
            }
        } else {
            chart.ID = fmt.Sprintf(chart.ID, dotReplacer.Replace(id))
            for _, dim := range chart.Dims {
                dim.ID = fmt.Sprintf(dim.ID, id)
            }
        }

        for _, lbl := range labels {
            chart.Labels = append(chart.Labels, module.Label{Key: lbl.Name, Value: lbl.Value})
        }
    }

    if err := e.Charts().Add(*charts...); err != nil {
        e.Warning(err)
    }
}

func (e *Envoy) removeCharts(id string) {
    if id == "" {
        return
    }

    id = dotReplacer.Replace(id)
    for _, chart := range *e.Charts() {
        if strings.HasSuffix(chart.ID, id) {
            chart.MarkRemove()
            chart.MarkNotCreated()
        }
    }
}

var dotReplacer = strings.NewReplacer(".", "_")