From 85845f4780bece61725f11bbbcdd2afeeee411da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Wed, 20 Nov 2024 02:05:31 +0100 Subject: [PATCH] exchange: Extend Transport Queue metrics (#1749) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jan-Otto Kröpke --- docs/collector.exchange.md | 102 +++++---- internal/collector/exchange/exchange.go | 61 +----- .../exchange/exchange_active_sync.go | 20 ++ .../exchange/exchange_ad_access_processes.go | 32 +++ .../exchange/exchange_autodiscover.go | 8 + .../exchange/exchange_availability_service.go | 12 +- .../collector/exchange/exchange_http_proxy.go | 38 ++++ .../exchange/exchange_mapi_http_emsmdb.go | 8 + .../exchange/exchange_outlook_web_access.go | 14 ++ .../exchange/exchange_rpc_client_access.go | 38 ++++ .../exchange/exchange_transport_queues.go | 204 ++++++++++++++++++ .../exchange/exchange_workload_management.go | 32 +++ 12 files changed, 472 insertions(+), 97 deletions(-) diff --git a/docs/collector.exchange.md b/docs/collector.exchange.md index 5da08830..603db98f 100644 --- a/docs/collector.exchange.md +++ b/docs/collector.exchange.md @@ -1,14 +1,13 @@ # exchange collector -The exchange collector collects metrics from MS Exchange hosts through perflib +The exchange collector collects metrics from MS Exchange hosts through Performance Counter ======= - -||| --|- -Metric name prefix | `exchange` -Classes | [Win32_PerfRawData_MSExchangeADAccess_MSExchangeADAccessProcesses](https://docs.microsoft.com/en-us/exchange/)
[Win32_PerfRawData_MSExchangeTransportQueues_MSExchangeTransportQueues](https://docs.microsoft.com/en-us/exchange/)
[Win32_PerfRawData_ESE_MSExchangeDatabaseInstances](https://docs.microsoft.com/en-us/exchange/)
[Win32_PerfRawData_MSExchangeHttpProxy_MSExchangeHttpProxy](https://docs.microsoft.com/en-us/exchange/)
[Win32_PerfRawData_MSExchangeActiveSync_MSExchangeActiveSync](https://docs.microsoft.com/en-us/exchange/)
[Win32_PerfRawData_MSExchangeAvailabilityService_MSExchangeAvailabilityService](https://docs.microsoft.com/en-us/exchange/)
[Win32_PerfRawData_MSExchangeOWA_MSExchangeOWA](https://docs.microsoft.com/en-us/exchange/)
[Win32_PerfRawData_MSExchangeAutodiscover_MSExchangeAutodiscover](https://docs.microsoft.com/en-us/exchange/)
[Win32_PerfRawData_MSExchangeWorkloadManagementWorkloads_MSExchangeWorkloadManagementWorkloads](https://docs.microsoft.com/en-us/exchange/)
[Win32_PerfRawData_MSExchangeRpcClientAccess_MSExchangeRpcClientAccess](https://docs.microsoft.com/en-us/exchange/)
-Enabled by default? | No +| | | +|---------------------|---------------------| +| Metric name prefix | `exchange` | +| Source | Performance Counter | +| Enabled by default? | No | ## Flags @@ -19,45 +18,56 @@ Lists the Perflib Objects that are queried for data along with the perlfib objec Comma-separated list of collectors to use, for example: `--collectors.exchange.enabled=AvailabilityService,OutlookWebAccess`. Matching is case-sensitive. Depending on the exchange installation not all performance counters are available. Use `--collectors.exchange.list` to obtain a list of supported collectors. ## Metrics -Name | Description ---------------|--------------- -`windows_exchange_rpc_avg_latency_sec` | The latency (sec), averaged for the past 1024 packets -`windows_exchange_rpc_requests` | Number of client requests currently being processed by the RPC Client Access service -`windows_exchange_rpc_active_user_count` | Number of unique users that have shown some kind of activity in the last 2 minutes -`windows_exchange_rpc_connection_count` | Total number of client connections maintained -`windows_exchange_rpc_operations_total` | The rate at which RPC operations occur -`windows_exchange_rpc_user_count` | Number of users -`windows_exchange_ldap_read_time_sec` | Time (sec) to send an LDAP read request and receive a response -`windows_exchange_ldap_search_time_sec` | Time (sec) to send an LDAP search request and receive a response -`windows_exchange_ldap_write_time_sec` | Time (sec) to send an LDAP Add/Modify/Delete request and receive a response -`windows_exchange_ldap_timeout_errors_total` | Total number of LDAP timeout errors -`windows_exchange_ldap_long_running_ops_per_sec` | Long Running LDAP operations per second -`windows_exchange_transport_queues_external_active_remote_delivery` | External Active Remote Delivery Queue length -`windows_exchange_transport_queues_internal_active_remote_delivery` | Internal Active Remote Delivery Queue length -`windows_exchange_transport_queues_active_mailbox_delivery` | Active Mailbox Delivery Queue length -`windows_exchange_transport_queues_retry_mailbox_delivery` | Retry Mailbox Delivery Queue length -`windows_exchange_transport_queues_unreachable` | Unreachable Queue length -`windows_exchange_transport_queues_external_largest_delivery` | External Largest Delivery Queue length -`windows_exchange_transport_queues_internal_largest_delivery` | Internal Largest Delivery Queue length -`windows_exchange_transport_queues_poison` | Poison Queue length -`windows_exchange_http_proxy_mailbox_server_locator_avg_latency_sec` | Average latency (sec) of MailboxServerLocator web service calls -`windows_exchange_http_proxy_avg_auth_latency` | Average time spent authenticating CAS requests over the last 200 samples -`windows_exchange_http_proxy_outstanding_proxy_requests` | Number of concurrent outstanding proxy requests -`windows_exchange_http_proxy_requests_total` | Number of proxy requests processed each second -`windows_exchange_avail_service_requests_per_sec` | Number of requests serviced per second -`windows_exchange_owa_current_unique_users` | Number of unique users currently logged on to Outlook Web App -`windows_exchange_owa_requests_total` | Number of requests handled by Outlook Web App per second -`windows_exchange_autodiscover_requests_total` | Number of autodiscover service requests processed each second -`windows_exchange_workload_active_tasks` | Number of active tasks currently running in the background for workload management -`windows_exchange_workload_completed_tasks` | Number of workload management tasks that have been completed -`windows_exchange_workload_queued_tasks` | Number of workload management tasks that are currently queued up waiting to be processed -`windows_exchange_workload_yielded_tasks` | The total number of tasks that have been yielded by a workload -`windows_exchange_workload_is_active` | Active indicates whether the workload is in an active (1) or paused (0) state -`windows_exchange_activesync_requests_total` | Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load -`windows_exchange_http_proxy_avg_cas_proccessing_latency_sec` | Average latency (sec) of CAS processing time over the last 200 reqs -`windows_exchange_http_proxy_mailbox_proxy_failure_rate` | % of failures between this CAS and MBX servers over the last 200 sample -`windows_exchange_activesync_ping_cmds_pending` | Number of ping commands currently pending in the queue -`windows_exchange_activesync_sync_cmds_total` | Number of sync commands processed per second. Clients use this command to synchronize items within a folder +| Name | Description | +|-----------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------| +| `windows_exchange_rpc_avg_latency_sec` | The latency (sec), averaged for the past 1024 packets | +| `windows_exchange_rpc_requests` | Number of client requests currently being processed by the RPC Client Access service | +| `windows_exchange_rpc_active_user_count` | Number of unique users that have shown some kind of activity in the last 2 minutes | +| `windows_exchange_rpc_connection_count` | Total number of client connections maintained | +| `windows_exchange_rpc_operations_total` | The rate at which RPC operations occur | +| `windows_exchange_rpc_user_count` | Number of users | +| `windows_exchange_ldap_read_time_sec` | Time (sec) to send an LDAP read request and receive a response | +| `windows_exchange_ldap_search_time_sec` | Time (sec) to send an LDAP search request and receive a response | +| `windows_exchange_ldap_write_time_sec` | Time (sec) to send an LDAP Add/Modify/Delete request and receive a response | +| `windows_exchange_ldap_timeout_errors_total` | Total number of LDAP timeout errors | +| `windows_exchange_ldap_long_running_ops_per_sec` | Long Running LDAP operations per second | +| `windows_exchange_transport_queues_external_active_remote_delivery` | External Active Remote Delivery Queue length | +| `windows_exchange_transport_queues_internal_active_remote_delivery` | Internal Active Remote Delivery Queue length | +| `windows_exchange_transport_queues_active_mailbox_delivery` | Active Mailbox Delivery Queue length | +| `windows_exchange_transport_queues_retry_mailbox_delivery` | Retry Mailbox Delivery Queue length | +| `windows_exchange_transport_queues_unreachable` | Unreachable Queue length | +| `windows_exchange_transport_queues_external_largest_delivery` | External Largest Delivery Queue length | +| `windows_exchange_transport_queues_internal_largest_delivery` | Internal Largest Delivery Queue length | +| `windows_exchange_transport_queues_poison` | Poison Queue length | +| `windows_exchange_transport_queues_messages_queued_for_delivery_total` | Messages Queued For Delivery Total | +| `windows_exchange_transport_queues_messages_submitted_total` | Messages Submitted Total | +| `windows_exchange_transport_queues_messages_delayed_total` | Messages Delayed Total | +| `windows_exchange_transport_queues_messages_completed_delivery_total` | Messages Completed Delivery Total | +| `windows_exchange_transport_queues_shadow_queue_length` | Shadow Queue Length | +| `windows_exchange_transport_queues_submission_queue_length` | Submission Queue Length | +| `windows_exchange_transport_queues_delay_queue_length` | Delay Queue Length | +| `windows_exchange_transport_queues_items_completed_delivery_total` | Items Completed Delivery Total | +| `windows_exchange_transport_queues_items_queued_for_delivery_expired_total` | Items Queued For Delivery Expired Total | +| `windows_exchange_transport_queues_items_queued_for_delivery_total` | Items Queued For Delivery Total | +| `windows_exchange_transport_queues_items_resubmitted_total` | Items Resubmitted Total | +| `windows_exchange_http_proxy_mailbox_server_locator_avg_latency_sec` | Average latency (sec) of MailboxServerLocator web service calls | +| `windows_exchange_http_proxy_avg_auth_latency` | Average time spent authenticating CAS requests over the last 200 samples | +| `windows_exchange_http_proxy_outstanding_proxy_requests` | Number of concurrent outstanding proxy requests | +| `windows_exchange_http_proxy_requests_total` | Number of proxy requests processed each second | +| `windows_exchange_avail_service_requests_per_sec` | Number of requests serviced per second | +| `windows_exchange_owa_current_unique_users` | Number of unique users currently logged on to Outlook Web App | +| `windows_exchange_owa_requests_total` | Number of requests handled by Outlook Web App per second | +| `windows_exchange_autodiscover_requests_total` | Number of autodiscover service requests processed each second | +| `windows_exchange_workload_active_tasks` | Number of active tasks currently running in the background for workload management | +| `windows_exchange_workload_completed_tasks` | Number of workload management tasks that have been completed | +| `windows_exchange_workload_queued_tasks` | Number of workload management tasks that are currently queued up waiting to be processed | +| `windows_exchange_workload_yielded_tasks` | The total number of tasks that have been yielded by a workload | +| `windows_exchange_workload_is_active` | Active indicates whether the workload is in an active (1) or paused (0) state | +| `windows_exchange_activesync_requests_total` | Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load | +| `windows_exchange_http_proxy_avg_cas_proccessing_latency_sec` | Average latency (sec) of CAS processing time over the last 200 reqs | +| `windows_exchange_http_proxy_mailbox_proxy_failure_rate` | % of failures between this CAS and MBX servers over the last 200 sample | +| `windows_exchange_activesync_ping_cmds_pending` | Number of ping commands currently pending in the queue | +| `windows_exchange_activesync_sync_cmds_total` | Number of sync commands processed per second. Clients use this command to synchronize items within a folder | ### Example metric _This collector does not yet have explained examples, we would appreciate your help adding them!_ diff --git a/internal/collector/exchange/exchange.go b/internal/collector/exchange/exchange.go index 85c9e1bf..3fbd7810 100644 --- a/internal/collector/exchange/exchange.go +++ b/internal/collector/exchange/exchange.go @@ -12,7 +12,6 @@ import ( "github.com/alecthomas/kingpin/v2" "github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/perfdata" - "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" ) @@ -102,6 +101,17 @@ type Collector struct { unreachableQueueLength *prometheus.Desc userCount *prometheus.Desc yieldedTasks *prometheus.Desc + messagesQueuedForDeliveryTotal *prometheus.Desc + messagesSubmittedTotal *prometheus.Desc + messagesDelayedTotal *prometheus.Desc + messagesCompletedDeliveryTotal *prometheus.Desc + shadowQueueLength *prometheus.Desc + submissionQueueLength *prometheus.Desc + delayQueueLength *prometheus.Desc + itemsCompletedDeliveryTotal *prometheus.Desc + itemsQueuedForDeliveryExpiredTotal *prometheus.Desc + itemsQueuedForDeliveryTotal *prometheus.Desc + itemsResubmittedTotal *prometheus.Desc } func New(config *Config) *Collector { @@ -207,55 +217,6 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { } } - // desc creates a new prometheus description - desc := func(metricName string, description string, labels ...string) *prometheus.Desc { - return prometheus.NewDesc( - prometheus.BuildFQName(types.Namespace, Name, metricName), - description, - labels, - nil, - ) - } - - c.rpcAveragedLatency = desc("rpc_avg_latency_sec", "The latency (sec) averaged for the past 1024 packets") - c.rpcRequests = desc("rpc_requests", "Number of client requests currently being processed by the RPC Client Access service") - c.activeUserCount = desc("rpc_active_user_count", "Number of unique users that have shown some kind of activity in the last 2 minutes") - c.connectionCount = desc("rpc_connection_count", "Total number of client connections maintained") - c.rpcOperationsPerSec = desc("rpc_operations_total", "The rate at which RPC operations occur") - c.userCount = desc("rpc_user_count", "Number of users") - c.ldapReadTime = desc("ldap_read_time_sec", "Time (sec) to send an LDAP read request and receive a response", "name") - c.ldapSearchTime = desc("ldap_search_time_sec", "Time (sec) to send an LDAP search request and receive a response", "name") - c.ldapWriteTime = desc("ldap_write_time_sec", "Time (sec) to send an LDAP Add/Modify/Delete request and receive a response", "name") - c.ldapTimeoutErrorsPerSec = desc("ldap_timeout_errors_total", "Total number of LDAP timeout errors", "name") - c.longRunningLDAPOperationsPerMin = desc("ldap_long_running_ops_per_sec", "Long Running LDAP operations per second", "name") - c.externalActiveRemoteDeliveryQueueLength = desc("transport_queues_external_active_remote_delivery", "External Active Remote Delivery Queue length", "name") - c.internalActiveRemoteDeliveryQueueLength = desc("transport_queues_internal_active_remote_delivery", "Internal Active Remote Delivery Queue length", "name") - c.activeMailboxDeliveryQueueLength = desc("transport_queues_active_mailbox_delivery", "Active Mailbox Delivery Queue length", "name") - c.retryMailboxDeliveryQueueLength = desc("transport_queues_retry_mailbox_delivery", "Retry Mailbox Delivery Queue length", "name") - c.unreachableQueueLength = desc("transport_queues_unreachable", "Unreachable Queue length", "name") - c.externalLargestDeliveryQueueLength = desc("transport_queues_external_largest_delivery", "External Largest Delivery Queue length", "name") - c.internalLargestDeliveryQueueLength = desc("transport_queues_internal_largest_delivery", "Internal Largest Delivery Queue length", "name") - c.poisonQueueLength = desc("transport_queues_poison", "Poison Queue length", "name") - c.mailboxServerLocatorAverageLatency = desc("http_proxy_mailbox_server_locator_avg_latency_sec", "Average latency (sec) of MailboxServerLocator web service calls", "name") - c.averageAuthenticationLatency = desc("http_proxy_avg_auth_latency", "Average time spent authenticating CAS requests over the last 200 samples", "name") - c.outstandingProxyRequests = desc("http_proxy_outstanding_proxy_requests", "Number of concurrent outstanding proxy requests", "name") - c.proxyRequestsPerSec = desc("http_proxy_requests_total", "Number of proxy requests processed each second", "name") - c.availabilityRequestsSec = desc("avail_service_requests_per_sec", "Number of requests serviced per second") - c.currentUniqueUsers = desc("owa_current_unique_users", "Number of unique users currently logged on to Outlook Web App") - c.owaRequestsPerSec = desc("owa_requests_total", "Number of requests handled by Outlook Web App per second") - c.autoDiscoverRequestsPerSec = desc("autodiscover_requests_total", "Number of autodiscover service requests processed each second") - c.activeTasks = desc("workload_active_tasks", "Number of active tasks currently running in the background for workload management", "name") - c.completedTasks = desc("workload_completed_tasks", "Number of workload management tasks that have been completed", "name") - c.queuedTasks = desc("workload_queued_tasks", "Number of workload management tasks that are currently queued up waiting to be processed", "name") - c.yieldedTasks = desc("workload_yielded_tasks", "The total number of tasks that have been yielded by a workload", "name") - c.isActive = desc("workload_is_active", "Active indicates whether the workload is in an active (1) or paused (0) state", "name") - c.activeSyncRequestsPerSec = desc("activesync_requests_total", "Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load") - c.averageCASProcessingLatency = desc("http_proxy_avg_cas_processing_latency_sec", "Average latency (sec) of CAS processing time over the last 200 reqs", "name") - c.mailboxServerProxyFailureRate = desc("http_proxy_mailbox_proxy_failure_rate", "% of failures between this CAS and MBX servers over the last 200 samples", "name") - c.pingCommandsPending = desc("activesync_ping_cmds_pending", "Number of ping commands currently pending in the queue") - c.syncCommandsPerSec = desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder") - c.activeUserCountMapiHttpEmsMDB = desc("mapihttp_emsmdb_active_user_count", "Number of unique outlook users that have shown some kind of activity in the last 2 minutes") - return nil } diff --git a/internal/collector/exchange/exchange_active_sync.go b/internal/collector/exchange/exchange_active_sync.go index 95df5dde..5bca8b94 100644 --- a/internal/collector/exchange/exchange_active_sync.go +++ b/internal/collector/exchange/exchange_active_sync.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" ) @@ -30,6 +31,25 @@ func (c *Collector) buildActiveSync() error { return fmt.Errorf("failed to create MSExchange ActiveSync collector: %w", err) } + c.pingCommandsPending = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "activesync_ping_cmds_pending"), + "Number of ping commands currently pending in the queue", + nil, + nil, + ) + c.syncCommandsPerSec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "activesync_sync_cmds_total"), + "Number of sync commands processed per second. Clients use this command to synchronize items within a folder", + nil, + nil, + ) + c.activeSyncRequestsPerSec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "activesync_requests_total"), + "Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load", + nil, + nil, + ) + return nil } diff --git a/internal/collector/exchange/exchange_ad_access_processes.go b/internal/collector/exchange/exchange_ad_access_processes.go index b80e1dfc..b1ad3ada 100644 --- a/internal/collector/exchange/exchange_ad_access_processes.go +++ b/internal/collector/exchange/exchange_ad_access_processes.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" ) @@ -34,6 +35,37 @@ func (c *Collector) buildADAccessProcesses() error { return fmt.Errorf("failed to create MSExchange ADAccess Processes collector: %w", err) } + c.ldapReadTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_read_time_sec"), + "Time (sec) to send an LDAP read request and receive a response", + []string{"name"}, + nil, + ) + c.ldapSearchTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_search_time_sec"), + "Time (sec) to send an LDAP search request and receive a response", + []string{"name"}, + nil, + ) + c.ldapWriteTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_write_time_sec"), + "Time (sec) to send an LDAP Add/Modify/Delete request and receive a response", + []string{"name"}, + nil, + ) + c.ldapTimeoutErrorsPerSec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_timeout_errors_total"), + "Total number of LDAP timeout errors", + []string{"name"}, + nil, + ) + c.longRunningLDAPOperationsPerMin = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_long_running_ops_per_sec"), + "Long Running LDAP operations per second", + []string{"name"}, + nil, + ) + return nil } diff --git a/internal/collector/exchange/exchange_autodiscover.go b/internal/collector/exchange/exchange_autodiscover.go index 82e60672..9dad12ea 100644 --- a/internal/collector/exchange/exchange_autodiscover.go +++ b/internal/collector/exchange/exchange_autodiscover.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" ) @@ -22,6 +23,13 @@ func (c *Collector) buildAutoDiscover() error { return fmt.Errorf("failed to create MSExchange Autodiscover collector: %w", err) } + c.autoDiscoverRequestsPerSec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "autodiscover_requests_total"), + "Number of autodiscover service requests processed each second", + nil, + nil, + ) + return nil } diff --git a/internal/collector/exchange/exchange_availability_service.go b/internal/collector/exchange/exchange_availability_service.go index b231f298..abfcdf86 100644 --- a/internal/collector/exchange/exchange_availability_service.go +++ b/internal/collector/exchange/exchange_availability_service.go @@ -7,11 +7,14 @@ import ( "fmt" "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" ) func (c *Collector) buildAvailabilityService() error { - counters := []string{} + counters := []string{ + requestsPerSec, + } var err error @@ -20,6 +23,13 @@ func (c *Collector) buildAvailabilityService() error { return fmt.Errorf("failed to create MSExchange Availability Service collector: %w", err) } + c.availabilityRequestsSec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "avail_service_requests_per_sec"), + "Number of requests serviced per second", + nil, + nil, + ) + return nil } diff --git a/internal/collector/exchange/exchange_http_proxy.go b/internal/collector/exchange/exchange_http_proxy.go index 3ced1398..d4be4830 100644 --- a/internal/collector/exchange/exchange_http_proxy.go +++ b/internal/collector/exchange/exchange_http_proxy.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" ) @@ -36,6 +37,43 @@ func (c *Collector) buildHTTPProxy() error { return fmt.Errorf("failed to create MSExchange HttpProxy collector: %w", err) } + c.mailboxServerLocatorAverageLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "http_proxy_mailbox_server_locator_avg_latency_sec"), + "Average latency (sec) of MailboxServerLocator web service calls", + []string{"name"}, + nil, + ) + c.averageAuthenticationLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "http_proxy_avg_auth_latency"), + "Average time spent authenticating CAS requests over the last 200 samples", + []string{"name"}, + nil, + ) + c.outstandingProxyRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "http_proxy_outstanding_proxy_requests"), + "Number of concurrent outstanding proxy requests", + []string{"name"}, + nil, + ) + c.proxyRequestsPerSec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "http_proxy_requests_total"), + "Number of proxy requests processed each second", + []string{"name"}, + nil, + ) + c.averageCASProcessingLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "http_proxy_avg_cas_processing_latency_sec"), + "Average latency (sec) of CAS processing time over the last 200 reqs", + []string{"name"}, + nil, + ) + c.mailboxServerProxyFailureRate = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "http_proxy_mailbox_proxy_failure_rate"), + "% of failures between this CAS and MBX servers over the last 200 samples", + []string{"name"}, + nil, + ) + return nil } diff --git a/internal/collector/exchange/exchange_mapi_http_emsmdb.go b/internal/collector/exchange/exchange_mapi_http_emsmdb.go index 67f42cf9..1c1e68d4 100644 --- a/internal/collector/exchange/exchange_mapi_http_emsmdb.go +++ b/internal/collector/exchange/exchange_mapi_http_emsmdb.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" ) @@ -26,6 +27,13 @@ func (c *Collector) buildMapiHttpEmsmdb() error { return fmt.Errorf("failed to create MSExchange MapiHttp Emsmdb: %w", err) } + c.activeUserCountMapiHttpEmsMDB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mapihttp_emsmdb_active_user_count"), + "Number of unique outlook users that have shown some kind of activity in the last 2 minutes", + nil, + nil, + ) + return nil } diff --git a/internal/collector/exchange/exchange_outlook_web_access.go b/internal/collector/exchange/exchange_outlook_web_access.go index e94aba0f..2391897f 100644 --- a/internal/collector/exchange/exchange_outlook_web_access.go +++ b/internal/collector/exchange/exchange_outlook_web_access.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" ) @@ -28,6 +29,19 @@ func (c *Collector) buildOWA() error { return fmt.Errorf("failed to create MSExchange OWA collector: %w", err) } + c.currentUniqueUsers = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "owa_current_unique_users"), + "Number of unique users currently logged on to Outlook Web App", + nil, + nil, + ) + c.owaRequestsPerSec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "owa_requests_total"), + "Number of requests handled by Outlook Web App per second", + nil, + nil, + ) + return nil } diff --git a/internal/collector/exchange/exchange_rpc_client_access.go b/internal/collector/exchange/exchange_rpc_client_access.go index 70b97374..76d3d0c7 100644 --- a/internal/collector/exchange/exchange_rpc_client_access.go +++ b/internal/collector/exchange/exchange_rpc_client_access.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" ) @@ -36,6 +37,43 @@ func (c *Collector) buildRPC() error { return fmt.Errorf("failed to create MSExchange RpcClientAccess collector: %w", err) } + c.rpcAveragedLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rpc_avg_latency_sec"), + "The latency (sec) averaged for the past 1024 packets", + nil, + nil, + ) + c.rpcRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rpc_requests"), + "Number of client requests currently being processed by the RPC Client Access service", + nil, + nil, + ) + c.activeUserCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rpc_active_user_count"), + "Number of unique users that have shown some kind of activity in the last 2 minutes", + nil, + nil, + ) + c.connectionCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rpc_connection_count"), + "Total number of client connections maintained", + nil, + nil, + ) + c.rpcOperationsPerSec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rpc_operations_total"), + "The rate at which RPC operations occur", + nil, + nil, + ) + c.userCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rpc_user_count"), + "Number of users", + nil, + nil, + ) + return nil } diff --git a/internal/collector/exchange/exchange_transport_queues.go b/internal/collector/exchange/exchange_transport_queues.go index 7ced9e1c..a42caf1f 100644 --- a/internal/collector/exchange/exchange_transport_queues.go +++ b/internal/collector/exchange/exchange_transport_queues.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" ) @@ -19,6 +20,17 @@ const ( externalLargestDeliveryQueueLength = "External Largest Delivery Queue Length" internalLargestDeliveryQueueLength = "Internal Largest Delivery Queue Length" poisonQueueLength = "Poison Queue Length" + messagesQueuedForDeliveryTotal = "Messages Queued For Delivery Total" + messagesSubmittedTotal = "Messages Submitted Total" + messagesDelayedTotal = "Messages Delayed Total" + messagesCompletedDeliveryTotal = "Messages Completed Delivery Total" + shadowQueueLength = "Shadow Queue Length" + submissionQueueLength = "Submission Queue Length" + delayQueueLength = "Delay Queue Length" + itemsCompletedDeliveryTotal = "Items Completed Delivery Total" + itemsQueuedForDeliveryExpiredTotal = "Items Queued For Delivery Expired Total" + itemsQueuedForDeliveryTotal = "Items Queued For Delivery Total" + itemsResubmittedTotal = "Items Resubmitted Total" ) func (c *Collector) buildTransportQueues() error { @@ -31,6 +43,17 @@ func (c *Collector) buildTransportQueues() error { externalLargestDeliveryQueueLength, internalLargestDeliveryQueueLength, poisonQueueLength, + messagesQueuedForDeliveryTotal, + messagesSubmittedTotal, + messagesDelayedTotal, + messagesCompletedDeliveryTotal, + shadowQueueLength, + submissionQueueLength, + delayQueueLength, + itemsCompletedDeliveryTotal, + itemsQueuedForDeliveryExpiredTotal, + itemsQueuedForDeliveryTotal, + itemsResubmittedTotal, } var err error @@ -40,6 +63,121 @@ func (c *Collector) buildTransportQueues() error { return fmt.Errorf("failed to create MSExchangeTransport Queues collector: %w", err) } + c.externalActiveRemoteDeliveryQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_external_active_remote_delivery"), + "External Active Remote Delivery Queue length", + []string{"name"}, + nil, + ) + c.internalActiveRemoteDeliveryQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_internal_active_remote_delivery"), + "Internal Active Remote Delivery Queue length", + []string{"name"}, + nil, + ) + c.activeMailboxDeliveryQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_active_mailbox_delivery"), + "Active Mailbox Delivery Queue length", + []string{"name"}, + nil, + ) + c.retryMailboxDeliveryQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_retry_mailbox_delivery"), + "Retry Mailbox Delivery Queue length", + []string{"name"}, + nil, + ) + c.unreachableQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_unreachable"), + "Unreachable Queue length", + []string{"name"}, + nil, + ) + c.externalLargestDeliveryQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_external_largest_delivery"), + "External Largest Delivery Queue length", + []string{"name"}, + nil, + ) + c.internalLargestDeliveryQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_internal_largest_delivery"), + "Internal Largest Delivery Queue length", + []string{"name"}, + nil, + ) + c.poisonQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_poison"), + "Poison Queue length", + []string{"name"}, + nil, + ) + c.messagesQueuedForDeliveryTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_messages_queued_for_delivery_total"), + "Messages Queued For Delivery Total", + []string{"name"}, + nil, + ) + c.messagesSubmittedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_messages_submitted_total"), + "Messages Submitted Total", + []string{"name"}, + nil, + ) + c.messagesDelayedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_messages_delayed_total"), + "Messages Delayed Total", + []string{"name"}, + nil, + ) + c.messagesCompletedDeliveryTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_messages_completed_delivery_total"), + "Messages Completed Delivery Total", + []string{"name"}, + nil, + ) + c.shadowQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_shadow_queue_length"), + "Shadow Queue Length", + []string{"name"}, + nil, + ) + c.submissionQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_submission_queue_length"), + "Submission Queue Length", + []string{"name"}, + nil, + ) + c.delayQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_delay_queue_length"), + "Delay Queue Length", + []string{"name"}, + nil, + ) + c.itemsCompletedDeliveryTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_items_completed_delivery_total"), + "Items Completed Delivery Total", + []string{"name"}, + nil, + ) + c.itemsQueuedForDeliveryExpiredTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_items_queued_for_delivery_expired_total"), + "Items Queued For Delivery Expired Total", + []string{"name"}, + nil, + ) + c.itemsQueuedForDeliveryTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_items_queued_for_delivery_total"), + "Items Queued For Delivery Total", + []string{"name"}, + nil, + ) + c.itemsResubmittedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transport_queues_items_resubmitted_total"), + "Items Resubmitted Total", + []string{"name"}, + nil, + ) + return nil } @@ -104,6 +242,72 @@ func (c *Collector) collectTransportQueues(ch chan<- prometheus.Metric) error { data[poisonQueueLength].FirstValue, labelName, ) + ch <- prometheus.MustNewConstMetric( + c.messagesQueuedForDeliveryTotal, + prometheus.CounterValue, + data[messagesQueuedForDeliveryTotal].FirstValue, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.messagesSubmittedTotal, + prometheus.CounterValue, + data[messagesSubmittedTotal].FirstValue, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.messagesDelayedTotal, + prometheus.CounterValue, + data[messagesDelayedTotal].FirstValue, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.messagesCompletedDeliveryTotal, + prometheus.CounterValue, + data[messagesCompletedDeliveryTotal].FirstValue, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.shadowQueueLength, + prometheus.GaugeValue, + data[shadowQueueLength].FirstValue, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.submissionQueueLength, + prometheus.GaugeValue, + data[submissionQueueLength].FirstValue, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.delayQueueLength, + prometheus.GaugeValue, + data[delayQueueLength].FirstValue, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.itemsCompletedDeliveryTotal, + prometheus.CounterValue, + data[itemsCompletedDeliveryTotal].FirstValue, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.itemsQueuedForDeliveryExpiredTotal, + prometheus.CounterValue, + data[itemsQueuedForDeliveryExpiredTotal].FirstValue, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.itemsQueuedForDeliveryTotal, + prometheus.CounterValue, + data[itemsQueuedForDeliveryTotal].FirstValue, + labelName, + ) + ch <- prometheus.MustNewConstMetric( + c.itemsResubmittedTotal, + prometheus.CounterValue, + data[itemsResubmittedTotal].FirstValue, + labelName, + ) } return nil diff --git a/internal/collector/exchange/exchange_workload_management.go b/internal/collector/exchange/exchange_workload_management.go index c5eee6a8..d9f377e5 100644 --- a/internal/collector/exchange/exchange_workload_management.go +++ b/internal/collector/exchange/exchange_workload_management.go @@ -7,6 +7,7 @@ import ( "fmt" "github.com/prometheus-community/windows_exporter/internal/perfdata" + "github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus/client_golang/prometheus" ) @@ -34,6 +35,37 @@ func (c *Collector) buildWorkloadManagementWorkloads() error { return fmt.Errorf("failed to create MSExchange WorkloadManagement Workloads collector: %w", err) } + c.activeTasks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "workload_active_tasks"), + "Number of active tasks currently running in the background for workload management", + []string{"name"}, + nil, + ) + c.completedTasks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "workload_completed_tasks"), + "Number of workload management tasks that have been completed", + []string{"name"}, + nil, + ) + c.queuedTasks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "workload_queued_tasks"), + "Number of workload management tasks that are currently queued up waiting to be processed", + []string{"name"}, + nil, + ) + c.yieldedTasks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "workload_yielded_tasks"), + "The total number of tasks that have been yielded by a workload", + []string{"name"}, + nil, + ) + c.isActive = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "workload_is_active"), + "Active indicates whether the workload is in an active (1) or paused (0) state", + []string{"name"}, + nil, + ) + return nil }