// SPDX-License-Identifier: GPL-3.0-or-later

package windows

import (
	"fmt"
	"strings"

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

const (
	prioCPUUtil = module.Priority + iota
	prioCPUCoreUtil
	prioCPUInterrupts
	prioCPUDPCs
	prioCPUCoreCState

	prioMemUtil
	prioMemPageFaults
	prioMemSwapUtil
	prioMemSwapOperations
	prioMemSwapPages
	prioMemCache
	prioMemCacheFaults
	prioMemSystemPool

	prioDiskSpaceUsage
	prioDiskBandwidth
	prioDiskOperations
	prioDiskAvgLatency

	prioNICBandwidth
	prioNICPackets
	prioNICErrors
	prioNICDiscards

	prioTCPConnsEstablished
	prioTCPConnsActive
	prioTCPConnsPassive
	prioTCPConnsFailure
	prioTCPConnsReset
	prioTCPSegmentsReceived
	prioTCPSegmentsSent
	prioTCPSegmentsRetransmitted

	prioOSProcesses
	prioOSUsers
	prioOSVisibleMemoryUsage
	prioOSPagingUsage

	prioSystemThreads
	prioSystemUptime

	prioLogonSessions

	prioThermalzoneTemperature

	prioProcessesCPUUtilization
	prioProcessesMemoryUsage
	prioProcessesIOBytes
	prioProcessesIOOperations
	prioProcessesPageFaults
	prioProcessesPageFileBytes
	prioProcessesThreads
	prioProcessesHandles

	prioIISWebsiteTraffic
	prioIISWebsiteFTPFileTransferRate
	prioIISWebsiteActiveConnectionsCount
	prioIISWebsiteRequestsRate
	prioIISWebsiteConnectionAttemptsRate
	prioIISWebsiteUsersCount
	prioIISWebsiteISAPIExtRequestsCount
	prioIISWebsiteISAPIExtRequestsRate
	prioIISWebsiteErrorsRate
	prioIISWebsiteLogonAttemptsRate
	prioIISWebsiteUptime

	// Connections
	prioMSSQLUserConnections

	// Transactions
	prioMSSQLDatabaseTransactions
	prioMSSQLDatabaseActiveTransactions
	prioMSSQLDatabaseWriteTransactions
	prioMSSQLDatabaseBackupRestoreOperations
	prioMSSQLDatabaseLogFlushes
	prioMSSQLDatabaseLogFlushed

	// Size
	prioMSSQLDatabaseDataFileSize

	// SQL activity
	prioMSSQLStatsBatchRequests
	prioMSSQLStatsCompilations
	prioMSSQLStatsRecompilations
	prioMSSQLStatsAutoParameterization
	prioMSSQLStatsSafeAutoParameterization

	// Processes
	prioMSSQLBlockedProcess

	// Buffer Cache
	prioMSSQLCacheHitRatio
	prioMSSQLBufManIOPS
	prioMSSQLBufferCheckpointPages
	prioMSSQLAccessMethodPageSplits
	prioMSSQLBufferPageLifeExpectancy

	// Memory
	prioMSSQLMemmgrConnectionMemoryBytes
	prioMSSQLMemTotalServer
	prioMSSQLMemmgrExternalBenefitOfMemory
	prioMSSQLMemmgrPendingMemoryGrants

	// Locks
	prioMSSQLLocksLockWait
	prioMSSQLLocksDeadLocks

	// Error
	prioMSSQLSqlErrorsTotal

	// NET Framework
	// Exceptions
	prioNETFrameworkCLRExceptionsThrown
	prioNETFrameworkCLRExceptionsFilters
	prioNETFrameworkCLRExceptionsFinallys
	prioNETFrameworkCLRExceptionsThrowToCatchDepth

	// InterOP
	prioNETFrameworkCLRInteropCOMCallableWrappers
	prioNETFrameworkCLRInteropMarshalling
	prioNETFrameworkCLRInteropStubsCreated
	prioNETFrameworkCLRJITMethods

	// JIT
	prioNETFrameworkCLRJITTime
	prioNETFrameworkCLRJITStandardFailures
	prioNETFrameworkCLRJITILBytes

	// Loading
	prioNETFrameworkCLRLoadingLoaderHeapSize
	prioNETFrameworkCLRLoadingAppDomainsLoaded
	prioNETFrameworkCLRLoadingAppDomainsUnloaded
	prioNETFrameworkCLRLoadingAssembliesLoaded
	prioNETFrameworkCLRLoadingClassesLoaded
	prioNETFrameworkCLRLoadingClassLoadFailure

	// Locks and threads
	prioNETFrameworkCLRLocksAndThreadsQueueLength
	prioNETFrameworkCLRLocksAndThreadsCurrentLogicalThreads
	prioNETFrameworkCLRLocksAndThreadsCurrentPhysicalThreads
	prioNETFrameworkCLRLocksAndThreadsRecognizedThreads
	prioNETFrameworkCLRLocksAndThreadsContentions

	// Memory
	prioNETFrameworkCLRMemoryAllocatedBytes
	prioNETFrameworkCLRMemoryFinalizationSurvivors
	prioNETFrameworkCLRMemoryHeapSize
	prioNETFrameworkCLRMemoryPromoted
	prioNETFrameworkCLRMemoryNumberGCHandles
	prioNETFrameworkCLRMemoryCollections
	prioNETFrameworkCLRMemoryInducedGC
	prioNETFrameworkCLRMemoryNumberPinnedObjects
	prioNETFrameworkCLRMemoryNumberSinkBlocksInUse
	prioNETFrameworkCLRMemoryCommitted
	prioNETFrameworkCLRMemoryReserved
	prioNETFrameworkCLRMemoryGCTime

	// Remoting
	prioNETFrameworkCLRRemotingChannels
	prioNETFrameworkCLRRemotingContextBoundClassesLoaded
	prioNETFrameworkCLRRemotingContextBoundObjects
	prioNETFrameworkCLRRemotingContextProxies
	prioNETFrameworkCLRRemotingContexts
	prioNETFrameworkCLRRemotingRemoteCalls

	// Security
	prioNETFrameworkCLRSecurityLinkTimeChecks
	prioNETFrameworkCLRSecurityRTChecksTime
	prioNETFrameworkCLRSecurityStackWalkDepth
	prioNETFrameworkCLRSecurityRuntimeChecks

	prioServiceState
	prioServiceStatus

	// Database
	prioADDatabaseOperations
	prioADDirectoryOperations
	prioADNameCacheLookups
	prioADCacheHits

	// Replication
	prioADDRAReplicationIntersiteCompressedTraffic
	prioADDRAReplicationIntrasiteCompressedTraffic
	prioADDRAReplicationSyncObjectsRemaining
	prioADDRAReplicationPropertiesUpdated
	prioADDRAReplicationPropertiesFiltered
	prioADDRAReplicationObjectsFiltered
	prioADReplicationPendingSyncs
	prioADDRASyncRequests
	prioADDirectoryServiceThreadsInUse

	// Bind
	prioADLDAPBindTime
	prioADBindsTotal

	// LDAP
	prioADLDAPSearchesTotal

	// Thread Queue
	prioADATQAverageRequestLatency
	prioADATQOutstandingRequests

	// Requests
	prioADCSCertTemplateRequests
	prioADCSCertTemplateRequestProcessingTime
	prioADCSCertTemplateRetrievals
	prioADCSCertTemplateFailedRequests
	prioADCSCertTemplateIssuesRequests
	prioADCSCertTemplatePendingRequests

	// Response
	prioADCSCertTemplateChallengeResponses

	// Retrieval
	prioADCSCertTemplateRetrievalProcessingTime

	// Timing
	prioADCSCertTemplateRequestCryptoSigningTime
	prioADCSCertTemplateRequestPolicyModuleProcessingTime
	prioADCSCertTemplateChallengeResponseProcessingTime
	prioADCSCertTemplateSignedCertificateTimestampLists
	prioADCSCertTemplateSignedCertificateTimestampListProcessingTime

	// ADFS
	// AD
	prioADFSADLoginConnectionFailures

	// DB Artifacts
	prioADFSDBArtifactFailures
	prioADFSDBArtifactQueryTimeSeconds

	// DB Config
	prioADFSDBConfigFailures
	prioADFSDBConfigQueryTimeSeconds

	// Auth
	prioADFSDeviceAuthentications
	prioADFSExternalAuthentications
	prioADFSOauthAuthorizationRequests
	prioADFSCertificateAuthentications
	prioADFSOauthClientAuthentications
	prioADFSPassportAuthentications
	prioADFSSSOAuthentications
	prioADFSUserPasswordAuthentications
	prioADFSWindowsIntegratedAuthentications

	// OAuth
	prioADFSOauthClientCredentials
	prioADFSOauthClientPrivkeyJwtAuthentication
	prioADFSOauthClientSecretBasicAuthentications
	prioADFSOauthClientSecretPostAuthentications
	prioADFSOauthClientWindowsAuthentications
	prioADFSOauthLogonCertificateRequests
	prioADFSOauthPasswordGrantRequests
	prioADFSOauthTokenRequestsSuccess
	prioADFSFederatedAuthentications

	// Requests
	prioADFSFederationMetadataRequests
	prioADFSPassiveRequests
	prioADFSPasswordChangeRequests
	prioADFSSAMLPTokenRequests
	prioADFSWSTrustTokenRequestsSuccess
	prioADFSTokenRequests
	prioADFSWSFedTokenRequestsSuccess

	// Exchange
	// Transport Queue
	prioExchangeTransportQueuesActiveMailboxDelivery
	prioExchangeTransportQueuesExternalActiveRemoteDelivery
	prioExchangeTransportQueuesExternalLargestDelivery
	prioExchangeTransportQueuesInternalActiveRemoteDeliery
	prioExchangeTransportQueuesInternalLargestDelivery
	prioExchangeTransportQueuesRetryMailboxDelivery
	prioExchangeTransportQueuesUnreachable
	prioExchangeTransportQueuesPoison

	// LDAP
	prioExchangeLDAPLongRunningOPS
	prioExchangeLDAPReadTime
	prioExchangeLDAPSearchTime
	prioExchangeLDAPWriteTime
	prioExchangeLDAPTimeoutErrors

	//  OWA
	prioExchangeOWACurrentUniqueUsers
	prioExchangeOWARequestsTotal

	// Sync
	prioExchangeActiveSyncPingCMDsPending
	prioExchangeActiveSyncRequests
	prioExchangeActiveSyncSyncCMDs

	// RPC
	prioExchangeRPCActiveUserCount
	prioExchangeRPCAvgLatency
	prioExchangeRPCConnectionCount
	prioExchangeRPCOperationsTotal
	prioExchangeRPCRequests
	prioExchangeRpcUserCount

	// Workload
	prioExchangeWorkloadActiveTasks
	prioExchangeWorkloadCompleteTasks
	prioExchangeWorkloadQueueTasks
	prioExchangeWorkloadYieldedTasks
	prioExchangeWorkloadActivityStatus

	// HTTP Proxy
	prioExchangeHTTPProxyAVGAuthLatency
	prioExchangeHTTPProxyAVGCASProcessingLatency
	prioExchangeHTTPProxyMailboxProxyFailureRate
	prioExchangeHTTPProxyServerLocatorAvgLatency
	prioExchangeHTTPProxyOutstandingProxyRequests
	prioExchangeHTTPProxyRequestsTotal

	// Request
	prioExchangeAutoDiscoverRequests
	prioExchangeAvailServiceRequests

	// Hyperv Health
	prioHypervVMHealth

	// Hyperv Partition
	prioHypervRootPartitionDeviceSpacePages
	prioHypervRootPartitionGPASpacePages
	prioHypervRootPartitionGPASpaceModifications
	prioHypervRootPartitionAttachedDevices
	prioHypervRootPartitionDepositedPages
	prioHypervRootPartitionSkippedInterrupts
	prioHypervRootPartitionDeviceDMAErrors
	prioHypervRootPartitionDeviceInterruptErrors
	prioHypervRootPartitionDeviceInterruptThrottleEvents
	prioHypervRootPartitionIOTlbFlush
	prioHypervRootPartitionAddressSpace
	prioHypervRootPartitionVirtualTlbFlushEntires
	prioHypervRootPartitionVirtualTlbPages

	// Hyperv VM (Memory)
	prioHypervVMCPUUsage
	prioHypervVMMemoryPhysical
	prioHypervVMMemoryPhysicalGuestVisible
	prioHypervVMMemoryPressureCurrent
	prioHypervVIDPhysicalPagesAllocated
	prioHypervVIDRemotePhysicalPages

	// Hyperv Device
	prioHypervVMDeviceBytes
	prioHypervVMDeviceOperations
	prioHypervVMDeviceErrors

	// Hyperv Interface
	prioHypervVMInterfaceBytes
	prioHypervVMInterfacePacketsDropped
	prioHypervVMInterfacePackets

	// Hyperv Vswitch
	prioHypervVswitchTrafficTotal
	prioHypervVswitchPackets
	prioHypervVswitchDirectedPackets
	prioHypervVswitchBroadcastPackets
	prioHypervVswitchMulticastPackets
	prioHypervVswitchDroppedPackets
	prioHypervVswitchExtensionsDroppedPackets
	prioHypervVswitchPacketsFlooded
	prioHypervVswitchLearnedMACAddresses
	prioHypervVswitchPurgeMACAddress

	prioCollectorDuration
	prioCollectorStatus
)

// CPU
var (
	cpuCharts = module.Charts{
		cpuUtilChart.Copy(),
	}
	cpuUtilChart = module.Chart{
		ID:       "cpu_utilization_total",
		Title:    "Total CPU Utilization (all cores)",
		Units:    "percentage",
		Fam:      "cpu",
		Ctx:      "windows.cpu_utilization_total",
		Type:     module.Stacked,
		Priority: prioCPUUtil,
		Dims: module.Dims{
			{ID: "cpu_idle_time", Name: "idle", Algo: module.PercentOfIncremental, Div: 1000, DimOpts: module.DimOpts{Hidden: true}},
			{ID: "cpu_dpc_time", Name: "dpc", Algo: module.PercentOfIncremental, Div: 1000},
			{ID: "cpu_user_time", Name: "user", Algo: module.PercentOfIncremental, Div: 1000},
			{ID: "cpu_privileged_time", Name: "privileged", Algo: module.PercentOfIncremental, Div: 1000},
			{ID: "cpu_interrupt_time", Name: "interrupt", Algo: module.PercentOfIncremental, Div: 1000},
		},
	}
)

// CPU core
var (
	cpuCoreChartsTmpl = module.Charts{
		cpuCoreUtilChartTmpl.Copy(),
		cpuCoreInterruptsChartTmpl.Copy(),
		cpuDPCsChartTmpl.Copy(),
		cpuCoreCStateChartTmpl.Copy(),
	}
	cpuCoreUtilChartTmpl = module.Chart{
		ID:       "core_%s_cpu_utilization",
		Title:    "Core CPU Utilization",
		Units:    "percentage",
		Fam:      "cpu",
		Ctx:      "windows.cpu_core_utilization",
		Type:     module.Stacked,
		Priority: prioCPUCoreUtil,
		Dims: module.Dims{
			{ID: "cpu_core_%s_idle_time", Name: "idle", Algo: module.PercentOfIncremental, Div: precision, DimOpts: module.DimOpts{Hidden: true}},
			{ID: "cpu_core_%s_dpc_time", Name: "dpc", Algo: module.PercentOfIncremental, Div: precision},
			{ID: "cpu_core_%s_user_time", Name: "user", Algo: module.PercentOfIncremental, Div: precision},
			{ID: "cpu_core_%s_privileged_time", Name: "privileged", Algo: module.PercentOfIncremental, Div: precision},
			{ID: "cpu_core_%s_interrupt_time", Name: "interrupt", Algo: module.PercentOfIncremental, Div: precision},
		},
	}
	cpuCoreInterruptsChartTmpl = module.Chart{
		ID:       "cpu_core_%s_interrupts",
		Title:    "Received and Serviced Hardware Interrupts",
		Units:    "interrupts/s",
		Fam:      "cpu",
		Ctx:      "windows.cpu_core_interrupts",
		Priority: prioCPUInterrupts,
		Dims: module.Dims{
			{ID: "cpu_core_%s_interrupts", Name: "interrupts", Algo: module.Incremental},
		},
	}
	cpuDPCsChartTmpl = module.Chart{
		ID:       "cpu_core_%s_dpcs",
		Title:    "Received and Serviced Deferred Procedure Calls (DPC)",
		Units:    "dpc/s",
		Fam:      "cpu",
		Ctx:      "windows.cpu_core_dpcs",
		Priority: prioCPUDPCs,
		Dims: module.Dims{
			{ID: "cpu_core_%s_dpcs", Name: "dpcs", Algo: module.Incremental},
		},
	}
	cpuCoreCStateChartTmpl = module.Chart{
		ID:       "cpu_core_%s_cpu_cstate",
		Title:    "Core Time Spent in Low-Power Idle State",
		Units:    "percentage",
		Fam:      "cpu",
		Ctx:      "windows.cpu_core_cstate",
		Type:     module.Stacked,
		Priority: prioCPUCoreCState,
		Dims: module.Dims{
			{ID: "cpu_core_%s_cstate_c1", Name: "c1", Algo: module.PercentOfIncremental, Div: precision},
			{ID: "cpu_core_%s_cstate_c2", Name: "c2", Algo: module.PercentOfIncremental, Div: precision},
			{ID: "cpu_core_%s_cstate_c3", Name: "c3", Algo: module.PercentOfIncremental, Div: precision},
		},
	}
)

// Memory
var (
	memCharts = module.Charts{
		memUtilChart.Copy(),
		memPageFaultsChart.Copy(),
		memSwapUtilChart.Copy(),
		memSwapOperationsChart.Copy(),
		memSwapPagesChart.Copy(),
		memCacheChart.Copy(),
		memCacheFaultsChart.Copy(),
		memSystemPoolChart.Copy(),
	}
	memUtilChart = module.Chart{
		ID:       "memory_utilization",
		Title:    "Memory Utilization",
		Units:    "bytes",
		Fam:      "mem",
		Ctx:      "windows.memory_utilization",
		Type:     module.Stacked,
		Priority: prioMemUtil,
		Dims: module.Dims{
			{ID: "memory_available_bytes", Name: "available"},
			{ID: "memory_used_bytes", Name: "used"},
		},
	}
	memPageFaultsChart = module.Chart{
		ID:       "memory_page_faults",
		Title:    "Memory Page Faults",
		Units:    "pgfaults/s",
		Fam:      "mem",
		Ctx:      "windows.memory_page_faults",
		Priority: prioMemPageFaults,
		Dims: module.Dims{
			{ID: "memory_page_faults_total", Name: "page_faults", Algo: module.Incremental},
		},
	}
	memSwapUtilChart = module.Chart{
		ID:       "memory_swap_utilization",
		Title:    "Swap Utilization",
		Units:    "bytes",
		Fam:      "mem",
		Ctx:      "windows.memory_swap_utilization",
		Type:     module.Stacked,
		Priority: prioMemSwapUtil,
		Dims: module.Dims{
			{ID: "memory_not_committed_bytes", Name: "available"},
			{ID: "memory_committed_bytes", Name: "used"},
		},
		Vars: module.Vars{
			{ID: "memory_commit_limit"},
		},
	}
	memSwapOperationsChart = module.Chart{
		ID:       "memory_swap_operations",
		Title:    "Swap Operations",
		Units:    "operations/s",
		Fam:      "mem",
		Ctx:      "windows.memory_swap_operations",
		Type:     module.Area,
		Priority: prioMemSwapOperations,
		Dims: module.Dims{
			{ID: "memory_swap_page_reads_total", Name: "read", Algo: module.Incremental},
			{ID: "memory_swap_page_writes_total", Name: "write", Algo: module.Incremental, Mul: -1},
		},
	}
	memSwapPagesChart = module.Chart{
		ID:       "memory_swap_pages",
		Title:    "Swap Pages",
		Units:    "pages/s",
		Fam:      "mem",
		Ctx:      "windows.memory_swap_pages",
		Priority: prioMemSwapPages,
		Dims: module.Dims{
			{ID: "memory_swap_pages_read_total", Name: "read", Algo: module.Incremental},
			{ID: "memory_swap_pages_written_total", Name: "written", Algo: module.Incremental, Mul: -1},
		},
	}
	memCacheChart = module.Chart{
		ID:       "memory_cached",
		Title:    "Cached",
		Units:    "bytes",
		Fam:      "mem",
		Ctx:      "windows.memory_cached",
		Type:     module.Area,
		Priority: prioMemCache,
		Dims: module.Dims{
			{ID: "memory_cache_total", Name: "cached"},
		},
	}
	memCacheFaultsChart = module.Chart{
		ID:       "memory_cache_faults",
		Title:    "Cache Faults",
		Units:    "faults/s",
		Fam:      "mem",
		Ctx:      "windows.memory_cache_faults",
		Priority: prioMemCacheFaults,
		Dims: module.Dims{
			{ID: "memory_cache_faults_total", Name: "cache_faults", Algo: module.Incremental},
		},
	}
	memSystemPoolChart = module.Chart{
		ID:       "memory_system_pool",
		Title:    "System Memory Pool",
		Units:    "bytes",
		Fam:      "mem",
		Ctx:      "windows.memory_system_pool",
		Type:     module.Stacked,
		Priority: prioMemSystemPool,
		Dims: module.Dims{
			{ID: "memory_pool_paged_bytes", Name: "paged"},
			{ID: "memory_pool_nonpaged_bytes_total", Name: "non-paged"},
		},
	}
)

// Logical Disks
var (
	diskChartsTmpl = module.Charts{
		diskSpaceUsageChartTmpl.Copy(),
		diskBandwidthChartTmpl.Copy(),
		diskOperationsChartTmpl.Copy(),
		diskAvgLatencyChartTmpl.Copy(),
	}
	diskSpaceUsageChartTmpl = module.Chart{
		ID:       "logical_disk_%s_space_usage",
		Title:    "Space usage",
		Units:    "bytes",
		Fam:      "disk",
		Ctx:      "windows.logical_disk_space_usage",
		Type:     module.Stacked,
		Priority: prioDiskSpaceUsage,
		Dims: module.Dims{
			{ID: "logical_disk_%s_free_space", Name: "free"},
			{ID: "logical_disk_%s_used_space", Name: "used"},
		},
	}
	diskBandwidthChartTmpl = module.Chart{
		ID:       "logical_disk_%s_bandwidth",
		Title:    "Bandwidth",
		Units:    "bytes/s",
		Fam:      "disk",
		Ctx:      "windows.logical_disk_bandwidth",
		Type:     module.Area,
		Priority: prioDiskBandwidth,
		Dims: module.Dims{
			{ID: "logical_disk_%s_read_bytes_total", Name: "read", Algo: module.Incremental},
			{ID: "logical_disk_%s_write_bytes_total", Name: "write", Algo: module.Incremental, Mul: -1},
		},
	}
	diskOperationsChartTmpl = module.Chart{
		ID:       "logical_disk_%s_operations",
		Title:    "Operations",
		Units:    "operations/s",
		Fam:      "disk",
		Ctx:      "windows.logical_disk_operations",
		Priority: prioDiskOperations,
		Dims: module.Dims{
			{ID: "logical_disk_%s_reads_total", Name: "reads", Algo: module.Incremental},
			{ID: "logical_disk_%s_writes_total", Name: "writes", Algo: module.Incremental, Mul: -1},
		},
	}
	diskAvgLatencyChartTmpl = module.Chart{
		ID:       "logical_disk_%s_latency",
		Title:    "Average Read/Write Latency",
		Units:    "seconds",
		Fam:      "disk",
		Ctx:      "windows.logical_disk_latency",
		Priority: prioDiskAvgLatency,
		Dims: module.Dims{
			{ID: "logical_disk_%s_read_latency", Name: "read", Algo: module.Incremental, Div: precision},
			{ID: "logical_disk_%s_write_latency", Name: "write", Algo: module.Incremental, Div: precision},
		},
	}
)

// Network interfaces
var (
	nicChartsTmpl = module.Charts{
		nicBandwidthChartTmpl.Copy(),
		nicPacketsChartTmpl.Copy(),
		nicErrorsChartTmpl.Copy(),
		nicDiscardsChartTmpl.Copy(),
	}
	nicBandwidthChartTmpl = module.Chart{
		ID:       "nic_%s_bandwidth",
		Title:    "Bandwidth",
		Units:    "kilobits/s",
		Fam:      "net",
		Ctx:      "windows.net_nic_bandwidth",
		Type:     module.Area,
		Priority: prioNICBandwidth,
		Dims: module.Dims{
			{ID: "net_nic_%s_bytes_received", Name: "received", Algo: module.Incremental, Div: 1000},
			{ID: "net_nic_%s_bytes_sent", Name: "sent", Algo: module.Incremental, Mul: -1, Div: 1000},
		},
	}
	nicPacketsChartTmpl = module.Chart{
		ID:       "nic_%s_packets",
		Title:    "Packets",
		Units:    "packets/s",
		Fam:      "net",
		Ctx:      "windows.net_nic_packets",
		Priority: prioNICPackets,
		Dims: module.Dims{
			{ID: "net_nic_%s_packets_received_total", Name: "received", Algo: module.Incremental},
			{ID: "net_nic_%s_packets_sent_total", Name: "sent", Algo: module.Incremental, Mul: -1},
		},
	}
	nicErrorsChartTmpl = module.Chart{
		ID:       "nic_%s_errors",
		Title:    "Errors",
		Units:    "errors/s",
		Fam:      "net",
		Ctx:      "windows.net_nic_errors",
		Priority: prioNICErrors,
		Dims: module.Dims{
			{ID: "net_nic_%s_packets_received_errors", Name: "inbound", Algo: module.Incremental},
			{ID: "net_nic_%s_packets_outbound_errors", Name: "outbound", Algo: module.Incremental, Mul: -1},
		},
	}
	nicDiscardsChartTmpl = module.Chart{
		ID:       "nic_%s_discarded",
		Title:    "Discards",
		Units:    "discards/s",
		Fam:      "net",
		Ctx:      "windows.net_nic_discarded",
		Priority: prioNICDiscards,
		Dims: module.Dims{
			{ID: "net_nic_%s_packets_received_discarded", Name: "inbound", Algo: module.Incremental},
			{ID: "net_nic_%s_packets_outbound_discarded", Name: "outbound", Algo: module.Incremental, Mul: -1},
		},
	}
)

// TCP
var (
	tcpCharts = module.Charts{
		tcpConnsActiveChart.Copy(),
		tcpConnsEstablishedChart.Copy(),
		tcpConnsFailuresChart.Copy(),
		tcpConnsPassiveChart.Copy(),
		tcpConnsResetsChart.Copy(),
		tcpSegmentsReceivedChart.Copy(),
		tcpSegmentsRetransmittedChart.Copy(),
		tcpSegmentsSentChart.Copy(),
	}
	tcpConnsEstablishedChart = module.Chart{
		ID:       "tcp_conns_established",
		Title:    "TCP established connections",
		Units:    "connections",
		Fam:      "tcp",
		Ctx:      "windows.tcp_conns_established",
		Priority: prioTCPConnsEstablished,
		Dims: module.Dims{
			{ID: "tcp_ipv4_conns_established", Name: "ipv4"},
			{ID: "tcp_ipv6_conns_established", Name: "ipv6"},
		},
	}
	tcpConnsActiveChart = module.Chart{
		ID:       "tcp_conns_active",
		Title:    "TCP active connections",
		Units:    "connections/s",
		Fam:      "tcp",
		Ctx:      "windows.tcp_conns_active",
		Priority: prioTCPConnsActive,
		Dims: module.Dims{
			{ID: "tcp_ipv4_conns_active", Name: "ipv4", Algo: module.Incremental},
			{ID: "tcp_ipv6_conns_active", Name: "ipv6", Algo: module.Incremental},
		},
	}
	tcpConnsPassiveChart = module.Chart{
		ID:       "tcp_conns_passive",
		Title:    "TCP passive connections",
		Units:    "connections/s",
		Fam:      "tcp",
		Ctx:      "windows.tcp_conns_passive",
		Priority: prioTCPConnsPassive,
		Dims: module.Dims{
			{ID: "tcp_ipv4_conns_passive", Name: "ipv4", Algo: module.Incremental},
			{ID: "tcp_ipv6_conns_passive", Name: "ipv6", Algo: module.Incremental},
		},
	}
	tcpConnsFailuresChart = module.Chart{
		ID:       "tcp_conns_failures",
		Title:    "TCP connection failures",
		Units:    "failures/s",
		Fam:      "tcp",
		Ctx:      "windows.tcp_conns_failures",
		Priority: prioTCPConnsFailure,
		Dims: module.Dims{
			{ID: "tcp_ipv4_conns_failures", Name: "ipv4", Algo: module.Incremental},
			{ID: "tcp_ipv6_conns_failures", Name: "ipv6", Algo: module.Incremental},
		},
	}
	tcpConnsResetsChart = module.Chart{
		ID:       "tcp_conns_resets",
		Title:    "TCP connections resets",
		Units:    "resets/s",
		Fam:      "tcp",
		Ctx:      "windows.tcp_conns_resets",
		Priority: prioTCPConnsReset,
		Dims: module.Dims{
			{ID: "tcp_ipv4_conns_resets", Name: "ipv4", Algo: module.Incremental},
			{ID: "tcp_ipv6_conns_resets", Name: "ipv6", Algo: module.Incremental},
		},
	}
	tcpSegmentsReceivedChart = module.Chart{
		ID:       "tcp_segments_received",
		Title:    "Number of TCP segments received",
		Units:    "segments/s",
		Fam:      "tcp",
		Ctx:      "windows.tcp_segments_received",
		Priority: prioTCPSegmentsReceived,
		Dims: module.Dims{
			{ID: "tcp_ipv4_segments_received", Name: "ipv4", Algo: module.Incremental},
			{ID: "tcp_ipv6_segments_received", Name: "ipv6", Algo: module.Incremental},
		},
	}
	tcpSegmentsSentChart = module.Chart{
		ID:       "tcp_segments_sent",
		Title:    "Number of TCP segments sent",
		Units:    "segments/s",
		Fam:      "tcp",
		Ctx:      "windows.tcp_segments_sent",
		Priority: prioTCPSegmentsSent,
		Dims: module.Dims{
			{ID: "tcp_ipv4_segments_sent", Name: "ipv4", Algo: module.Incremental},
			{ID: "tcp_ipv6_segments_sent", Name: "ipv6", Algo: module.Incremental},
		},
	}
	tcpSegmentsRetransmittedChart = module.Chart{
		ID:       "tcp_segments_retransmitted",
		Title:    "Number of TCP segments retransmitted",
		Units:    "segments/s",
		Fam:      "tcp",
		Ctx:      "windows.tcp_segments_retransmitted",
		Priority: prioTCPSegmentsRetransmitted,
		Dims: module.Dims{
			{ID: "tcp_ipv4_segments_retransmitted", Name: "ipv4", Algo: module.Incremental},
			{ID: "tcp_ipv6_segments_retransmitted", Name: "ipv6", Algo: module.Incremental},
		},
	}
)

// OS
var (
	osCharts = module.Charts{
		osProcessesChart.Copy(),
		osUsersChart.Copy(),
		osMemoryUsage.Copy(),
		osPagingFilesUsageChart.Copy(),
	}
	osProcessesChart = module.Chart{
		ID:       "os_processes",
		Title:    "Processes",
		Units:    "number",
		Fam:      "os",
		Ctx:      "windows.os_processes",
		Priority: prioOSProcesses,
		Dims: module.Dims{
			{ID: "os_processes", Name: "processes"},
		},
		Vars: module.Vars{
			{ID: "os_processes_limit"},
		},
	}
	osUsersChart = module.Chart{
		ID:       "os_users",
		Title:    "Number of Users",
		Units:    "users",
		Fam:      "os",
		Ctx:      "windows.os_users",
		Priority: prioOSUsers,
		Dims: module.Dims{
			{ID: "os_users", Name: "users"},
		},
	}
	osMemoryUsage = module.Chart{
		ID:       "os_visible_memory_usage",
		Title:    "Visible Memory Usage",
		Units:    "bytes",
		Fam:      "os",
		Ctx:      "windows.os_visible_memory_usage",
		Type:     module.Stacked,
		Priority: prioOSVisibleMemoryUsage,
		Dims: module.Dims{
			{ID: "os_physical_memory_free_bytes", Name: "free"},
			{ID: "os_visible_memory_used_bytes", Name: "used"},
		},
		Vars: module.Vars{
			{ID: "os_visible_memory_bytes"},
		},
	}
	osPagingFilesUsageChart = module.Chart{
		ID:       "os_paging_files_usage",
		Title:    "Paging Files Usage",
		Units:    "bytes",
		Fam:      "os",
		Ctx:      "windows.os_paging_files_usage",
		Type:     module.Stacked,
		Priority: prioOSPagingUsage,
		Dims: module.Dims{
			{ID: "os_paging_free_bytes", Name: "free"},
			{ID: "os_paging_used_bytes", Name: "used"},
		},
		Vars: module.Vars{
			{ID: "os_paging_limit_bytes"},
		},
	}
)

// System
var (
	systemCharts = module.Charts{
		systemThreadsChart.Copy(),
		systemUptimeChart.Copy(),
	}
	systemThreadsChart = module.Chart{
		ID:       "system_threads",
		Title:    "Threads",
		Units:    "number",
		Fam:      "system",
		Ctx:      "windows.system_threads",
		Priority: prioSystemThreads,
		Dims: module.Dims{
			{ID: "system_threads", Name: "threads"},
		},
	}
	systemUptimeChart = module.Chart{
		ID:       "system_uptime",
		Title:    "Uptime",
		Units:    "seconds",
		Fam:      "system",
		Ctx:      "windows.system_uptime",
		Priority: prioSystemUptime,
		Dims: module.Dims{
			{ID: "system_up_time", Name: "time"},
		},
	}
)

// IIS
var (
	iisWebsiteChartsTmpl = module.Charts{
		iisWebsiteTrafficChartTempl.Copy(),
		iisWebsiteRequestsRateChartTmpl.Copy(),
		iisWebsiteActiveConnectionsCountChartTmpl.Copy(),
		iisWebsiteUsersCountChartTmpl.Copy(),
		iisWebsiteConnectionAttemptsRate.Copy(),
		iisWebsiteISAPIExtRequestsCountChartTmpl.Copy(),
		iisWebsiteISAPIExtRequestsRateChartTmpl.Copy(),
		iisWebsiteFTPFileTransferRateChartTempl.Copy(),
		iisWebsiteLogonAttemptsRateChartTmpl.Copy(),
		iisWebsiteErrorsRateChart.Copy(),
		iisWebsiteUptimeChartTmpl.Copy(),
	}
	iisWebsiteTrafficChartTempl = module.Chart{
		OverModule: "iis",
		ID:         "iis_website_%s_traffic",
		Title:      "Website traffic",
		Units:      "bytes/s",
		Fam:        "traffic",
		Ctx:        "iis.website_traffic",
		Type:       module.Area,
		Priority:   prioIISWebsiteTraffic,
		Dims: module.Dims{
			{ID: "iis_website_%s_received_bytes_total", Name: "received", Algo: module.Incremental},
			{ID: "iis_website_%s_sent_bytes_total", Name: "sent", Algo: module.Incremental, Mul: -1},
		},
	}
	iisWebsiteFTPFileTransferRateChartTempl = module.Chart{
		OverModule: "iis",
		ID:         "iis_website_%s_ftp_file_transfer_rate",
		Title:      "Website FTP file transfer rate",
		Units:      "files/s",
		Fam:        "traffic",
		Ctx:        "iis.website_ftp_file_transfer_rate",
		Priority:   prioIISWebsiteFTPFileTransferRate,
		Dims: module.Dims{
			{ID: "iis_website_%s_files_received_total", Name: "received", Algo: module.Incremental},
			{ID: "iis_website_%s_files_sent_total", Name: "sent", Algo: module.Incremental},
		},
	}
	iisWebsiteActiveConnectionsCountChartTmpl = module.Chart{
		OverModule: "iis",
		ID:         "iis_website_%s_active_connections_count",
		Title:      "Website active connections",
		Units:      "connections",
		Fam:        "connections",
		Ctx:        "iis.website_active_connections_count",
		Priority:   prioIISWebsiteActiveConnectionsCount,
		Dims: module.Dims{
			{ID: "iis_website_%s_current_connections", Name: "active"},
		},
	}
	iisWebsiteConnectionAttemptsRate = module.Chart{
		OverModule: "iis",
		ID:         "iis_website_%s_connection_attempts_rate",
		Title:      "Website connections attempts",
		Units:      "attempts/s",
		Fam:        "connections",
		Ctx:        "iis.website_connection_attempts_rate",
		Priority:   prioIISWebsiteConnectionAttemptsRate,
		Dims: module.Dims{
			{ID: "iis_website_%s_connection_attempts_all_instances_total", Name: "connection", Algo: module.Incremental},
		},
	}
	iisWebsiteRequestsRateChartTmpl = module.Chart{
		OverModule: "iis",
		ID:         "iis_website_%s_requests_rate",
		Title:      "Website requests rate",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "iis.website_requests_rate",
		Priority:   prioIISWebsiteRequestsRate,
		Dims: module.Dims{
			{ID: "iis_website_%s_requests_total", Name: "requests", Algo: module.Incremental},
		},
	}
	iisWebsiteUsersCountChartTmpl = module.Chart{
		OverModule: "iis",
		ID:         "iis_website_%s_users_count",
		Title:      "Website users with pending requests",
		Units:      "users",
		Fam:        "requests",
		Ctx:        "iis.website_users_count",
		Type:       module.Stacked,
		Priority:   prioIISWebsiteUsersCount,
		Dims: module.Dims{
			{ID: "iis_website_%s_current_anonymous_users", Name: "anonymous"},
			{ID: "iis_website_%s_current_non_anonymous_users", Name: "non_anonymous"},
		},
	}
	iisWebsiteISAPIExtRequestsCountChartTmpl = module.Chart{
		OverModule: "iis",
		ID:         "iis_website_%s_isapi_extension_requests_count",
		Title:      "ISAPI extension requests",
		Units:      "requests",
		Fam:        "requests",
		Ctx:        "iis.website_isapi_extension_requests_count",
		Priority:   prioIISWebsiteISAPIExtRequestsCount,
		Dims: module.Dims{
			{ID: "iis_website_%s_current_isapi_extension_requests", Name: "isapi"},
		},
	}
	iisWebsiteISAPIExtRequestsRateChartTmpl = module.Chart{
		OverModule: "iis",
		ID:         "iis_website_%s_isapi_extension_requests_rate",
		Title:      "Website extensions request",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "iis.website_isapi_extension_requests_rate",
		Priority:   prioIISWebsiteISAPIExtRequestsRate,
		Dims: module.Dims{
			{ID: "iis_website_%s_isapi_extension_requests_total", Name: "isapi", Algo: module.Incremental},
		},
	}
	iisWebsiteErrorsRateChart = module.Chart{
		OverModule: "iis",
		ID:         "iis_website_%s_errors_rate",
		Title:      "Website errors",
		Units:      "errors/s",
		Fam:        "requests",
		Ctx:        "iis.website_errors_rate",
		Type:       module.Stacked,
		Priority:   prioIISWebsiteErrorsRate,
		Dims: module.Dims{
			{ID: "iis_website_%s_locked_errors_total", Name: "document_locked", Algo: module.Incremental},
			{ID: "iis_website_%s_not_found_errors_total", Name: "document_not_found", Algo: module.Incremental},
		},
	}
	iisWebsiteLogonAttemptsRateChartTmpl = module.Chart{
		OverModule: "iis",
		ID:         "iis_website_%s_logon_attempts_rate",
		Title:      "Website logon attempts",
		Units:      "attempts/s",
		Fam:        "logon",
		Ctx:        "iis.website_logon_attempts_rate",
		Priority:   prioIISWebsiteLogonAttemptsRate,
		Dims: module.Dims{
			{ID: "iis_website_%s_logon_attempts_total", Name: "logon", Algo: module.Incremental},
		},
	}
	iisWebsiteUptimeChartTmpl = module.Chart{
		OverModule: "iis",
		ID:         "iis_website_%s_uptime",
		Title:      "Website uptime",
		Units:      "seconds",
		Fam:        "uptime",
		Ctx:        "iis.website_uptime",
		Priority:   prioIISWebsiteUptime,
		Dims: module.Dims{
			{ID: "iis_website_%s_service_uptime", Name: "uptime"},
		},
	}
)

// MS-SQL
var (
	mssqlInstanceChartsTmpl = module.Charts{
		mssqlAccessMethodPageSplitsChart.Copy(),
		mssqlCacheHitRatioChart.Copy(),
		mssqlBufferCheckpointPageChart.Copy(),
		mssqlBufferPageLifeExpectancyChart.Copy(),
		mssqlBufManIOPSChart.Copy(),
		mssqlBlockedProcessChart.Copy(),
		mssqlLocksWaitChart.Copy(),
		mssqlDeadLocksChart.Copy(),
		mssqlMemmgrConnectionMemoryBytesChart.Copy(),
		mssqlMemmgrExternalBenefitOfMemoryChart.Copy(),
		mssqlMemmgrPendingMemoryChart.Copy(),
		mssqlMemmgrTotalServerChart.Copy(),
		mssqlSQLErrorsTotalChart.Copy(),
		mssqlStatsAutoParamChart.Copy(),
		mssqlStatsBatchRequestsChart.Copy(),
		mssqlStatsSafeAutoChart.Copy(),
		mssqlStatsCompilationChart.Copy(),
		mssqlStatsRecompilationChart.Copy(),
		mssqlUserConnectionChart.Copy(),
	}
	mssqlDatabaseChartsTmpl = module.Charts{
		mssqlDatabaseActiveTransactionsChart.Copy(),
		mssqlDatabaseBackupRestoreOperationsChart.Copy(),
		mssqlDatabaseSizeChart.Copy(),
		mssqlDatabaseLogFlushedChart.Copy(),
		mssqlDatabaseLogFlushesChart.Copy(),
		mssqlDatabaseTransactionsChart.Copy(),
		mssqlDatabaseWriteTransactionsChart.Copy(),
	}
	// Access Method:
	// Source: https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-access-methods-object?view=sql-server-ver16
	mssqlAccessMethodPageSplitsChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_accessmethods_page_splits",
		Title:      "Page splits",
		Units:      "splits/s",
		Fam:        "buffer cache",
		Ctx:        "mssql.instance_accessmethods_page_splits",
		Priority:   prioMSSQLAccessMethodPageSplits,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_accessmethods_page_splits", Name: "page", Algo: module.Incremental},
		},
	}
	// Buffer Management
	// Source: https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-buffer-manager-object?view=sql-server-ver16
	mssqlCacheHitRatioChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_cache_hit_ratio",
		Title:      "Buffer Cache hit ratio",
		Units:      "percentage",
		Fam:        "buffer cache",
		Ctx:        "mssql.instance_cache_hit_ratio",
		Priority:   prioMSSQLCacheHitRatio,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_cache_hit_ratio", Name: "hit_ratio"},
		},
	}
	mssqlBufferCheckpointPageChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_bufman_checkpoint_pages",
		Title:      "Flushed pages",
		Units:      "pages/s",
		Fam:        "buffer cache",
		Ctx:        "mssql.instance_bufman_checkpoint_pages",
		Priority:   prioMSSQLBufferCheckpointPages,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_bufman_checkpoint_pages", Name: "flushed", Algo: module.Incremental},
		},
	}
	mssqlBufferPageLifeExpectancyChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_bufman_page_life_expectancy",
		Title:      "Page life expectancy",
		Units:      "seconds",
		Fam:        "buffer cache",
		Ctx:        "mssql.instance_bufman_page_life_expectancy",
		Priority:   prioMSSQLBufferPageLifeExpectancy,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_bufman_page_life_expectancy_seconds", Name: "life_expectancy"},
		},
	}
	mssqlBufManIOPSChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_bufman_iops",
		Title:      "Number of pages input and output",
		Units:      "pages/s",
		Fam:        "buffer cache",
		Ctx:        "mssql.instance_bufman_iops",
		Priority:   prioMSSQLBufManIOPS,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_bufman_page_reads", Name: "read", Algo: module.Incremental},
			{ID: "mssql_instance_%s_bufman_page_writes", Name: "written", Mul: -1, Algo: module.Incremental},
		},
	}
	// General Statistic
	// Source: https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-general-statistics-object?view=sql-server-ver16
	mssqlBlockedProcessChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_blocked_process",
		Title:      "Blocked processes",
		Units:      "process",
		Fam:        "processes",
		Ctx:        "mssql.instance_blocked_processes",
		Priority:   prioMSSQLBlockedProcess,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_genstats_blocked_processes", Name: "blocked"},
		},
	}
	mssqlUserConnectionChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_user_connection",
		Title:      "User connections",
		Units:      "connections",
		Fam:        "connections",
		Ctx:        "mssql.instance_user_connection",
		Priority:   prioMSSQLUserConnections,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_genstats_user_connections", Name: "user"},
		},
	}
	// Lock Wait
	// Source: https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-locks-object?view=sql-server-ver16
	mssqlLocksWaitChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_locks_lock_wait",
		Title:      "Lock requests that required the caller to wait",
		Units:      "locks/s",
		Fam:        "locks",
		Ctx:        "mssql.instance_locks_lock_wait",
		Priority:   prioMSSQLLocksLockWait,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_resource_AllocUnit_locks_lock_wait_seconds", Name: "alloc_unit", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Application_locks_lock_wait_seconds", Name: "application", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Database_locks_lock_wait_seconds", Name: "database", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Extent_locks_lock_wait_seconds", Name: "extent", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_File_locks_lock_wait_seconds", Name: "file", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_HoBT_locks_lock_wait_seconds", Name: "hobt", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Key_locks_lock_wait_seconds", Name: "key", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Metadata_locks_lock_wait_seconds", Name: "metadata", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_OIB_locks_lock_wait_seconds", Name: "oib", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Object_locks_lock_wait_seconds", Name: "object", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Page_locks_lock_wait_seconds", Name: "page", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_RID_locks_lock_wait_seconds", Name: "rid", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_RowGroup_locks_lock_wait_seconds", Name: "row_group", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Xact_locks_lock_wait_seconds", Name: "xact", Algo: module.Incremental},
		},
	}
	mssqlDeadLocksChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_locks_deadlocks",
		Title:      "Lock requests that resulted in deadlock",
		Units:      "locks/s",
		Fam:        "locks",
		Ctx:        "mssql.instance_locks_deadlocks",
		Priority:   prioMSSQLLocksDeadLocks,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_resource_AllocUnit_locks_deadlocks", Name: "alloc_unit", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Application_locks_deadlocks", Name: "application", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Database_locks_deadlocks", Name: "database", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Extent_locks_deadlocks", Name: "extent", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_File_locks_deadlocks", Name: "file", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_HoBT_locks_deadlocks", Name: "hobt", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Key_locks_deadlocks", Name: "key", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Metadata_locks_deadlocks", Name: "metadata", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_OIB_locks_deadlocks", Name: "oib", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Object_locks_deadlocks", Name: "object", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Page_locks_deadlocks", Name: "page", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_RID_locks_deadlocks", Name: "rid", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_RowGroup_locks_deadlocks", Name: "row_group", Algo: module.Incremental},
			{ID: "mssql_instance_%s_resource_Xact_locks_deadlocks", Name: "xact", Algo: module.Incremental},
		},
	}

	// Memory Manager
	// Source: https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-memory-manager-object?view=sql-server-ver16
	mssqlMemmgrConnectionMemoryBytesChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_memmgr_connection_memory_bytes",
		Title:      "Amount of dynamic memory to maintain connections",
		Units:      "bytes",
		Fam:        "memory",
		Ctx:        "mssql.instance_memmgr_connection_memory_bytes",
		Priority:   prioMSSQLMemmgrConnectionMemoryBytes,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_memmgr_connection_memory_bytes", Name: "memory", Algo: module.Incremental},
		},
	}
	mssqlMemmgrExternalBenefitOfMemoryChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_memmgr_external_benefit_of_memory",
		Title:      "Performance benefit from adding memory to a specific cache",
		Units:      "bytes",
		Fam:        "memory",
		Ctx:        "mssql.instance_memmgr_external_benefit_of_memory",
		Priority:   prioMSSQLMemmgrExternalBenefitOfMemory,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_memmgr_external_benefit_of_memory", Name: "benefit", Algo: module.Incremental},
		},
	}
	mssqlMemmgrPendingMemoryChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_memmgr_pending_memory_grants",
		Title:      "Process waiting for memory grant",
		Units:      "process",
		Fam:        "memory",
		Ctx:        "mssql.instance_memmgr_pending_memory_grants",
		Priority:   prioMSSQLMemmgrPendingMemoryGrants,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_memmgr_pending_memory_grants", Name: "pending"},
		},
	}
	mssqlMemmgrTotalServerChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_memmgr_server_memory",
		Title:      "Memory committed",
		Units:      "bytes",
		Fam:        "memory",
		Ctx:        "mssql.instance_memmgr_server_memory",
		Priority:   prioMSSQLMemTotalServer,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_memmgr_total_server_memory_bytes", Name: "memory"},
		},
	}

	// SQL errors
	// Source: https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-errors-object?view=sql-server-ver16
	mssqlSQLErrorsTotalChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_sql_errors_total",
		Title:      "Errors",
		Units:      "errors/s",
		Fam:        "errors",
		Ctx:        "mssql.instance_sql_errors",
		Priority:   prioMSSQLSqlErrorsTotal,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_sql_errors_total_db_offline_errors", Name: "db_offline", Algo: module.Incremental},
			{ID: "mssql_instance_%s_sql_errors_total_info_errors", Name: "info", Algo: module.Incremental},
			{ID: "mssql_instance_%s_sql_errors_total_kill_connection_errors", Name: "kill_connection", Algo: module.Incremental},
			{ID: "mssql_instance_%s_sql_errors_total_user_errors", Name: "user", Algo: module.Incremental},
		},
	}

	// SQL Statistic
	// Source: https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-statistics-object?view=sql-server-ver16
	mssqlStatsAutoParamChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_sqlstats_auto_parameterization_attempts",
		Title:      "Failed auto-parameterization attempts",
		Units:      "attempts/s",
		Fam:        "sql activity",
		Ctx:        "mssql.instance_sqlstats_auto_parameterization_attempts",
		Priority:   prioMSSQLStatsAutoParameterization,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_sqlstats_auto_parameterization_attempts", Name: "failed", Algo: module.Incremental},
		},
	}
	mssqlStatsBatchRequestsChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_sqlstats_batch_requests",
		Title:      "Total of batches requests",
		Units:      "requests/s",
		Fam:        "sql activity",
		Ctx:        "mssql.instance_sqlstats_batch_requests",
		Priority:   prioMSSQLStatsBatchRequests,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_sqlstats_batch_requests", Name: "batch", Algo: module.Incremental},
		},
	}
	mssqlStatsSafeAutoChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_sqlstats_safe_auto_parameterization_attempts",
		Title:      "Safe auto-parameterization attempts",
		Units:      "attempts/s",
		Fam:        "sql activity",
		Ctx:        "mssql.instance_sqlstats_safe_auto_parameterization_attempts",
		Priority:   prioMSSQLStatsSafeAutoParameterization,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_sqlstats_safe_auto_parameterization_attempts", Name: "safe", Algo: module.Incremental},
		},
	}
	mssqlStatsCompilationChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_sqlstats_sql_compilations",
		Title:      "SQL compilations",
		Units:      "compilations/s",
		Fam:        "sql activity",
		Ctx:        "mssql.instance_sqlstats_sql_compilations",
		Priority:   prioMSSQLStatsCompilations,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_sqlstats_sql_compilations", Name: "compilations", Algo: module.Incremental},
		},
	}
	mssqlStatsRecompilationChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_instance_%s_sqlstats_sql_recompilations",
		Title:      "SQL re-compilations",
		Units:      "recompiles/s",
		Fam:        "sql activity",
		Ctx:        "mssql.instance_sqlstats_sql_recompilations",
		Priority:   prioMSSQLStatsRecompilations,
		Dims: module.Dims{
			{ID: "mssql_instance_%s_sqlstats_sql_recompilations", Name: "recompiles", Algo: module.Incremental},
		},
	}

	// Database
	// Source: https://learn.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-databases-object?view=sql-server-2017
	mssqlDatabaseActiveTransactionsChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_db_%s_instance_%s_active_transactions",
		Title:      "Active transactions per database",
		Units:      "transactions",
		Fam:        "transactions",
		Ctx:        "mssql.database_active_transactions",
		Priority:   prioMSSQLDatabaseActiveTransactions,
		Dims: module.Dims{
			{ID: "mssql_db_%s_instance_%s_active_transactions", Name: "active"},
		},
	}
	mssqlDatabaseBackupRestoreOperationsChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_db_%s_instance_%s_backup_restore_operations",
		Title:      "Backup IO per database",
		Units:      "operations/s",
		Fam:        "transactions",
		Ctx:        "mssql.database_backup_restore_operations",
		Priority:   prioMSSQLDatabaseBackupRestoreOperations,
		Dims: module.Dims{
			{ID: "mssql_db_%s_instance_%s_backup_restore_operations", Name: "backup", Algo: module.Incremental},
		},
	}
	mssqlDatabaseSizeChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_db_%s_instance_%s_data_files_size",
		Title:      "Current database size",
		Units:      "bytes",
		Fam:        "size",
		Ctx:        "mssql.database_data_files_size",
		Priority:   prioMSSQLDatabaseDataFileSize,
		Dims: module.Dims{
			{ID: "mssql_db_%s_instance_%s_data_files_size_bytes", Name: "size"},
		},
	}
	mssqlDatabaseLogFlushedChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_db_%s_instance_%s_log_flushed",
		Title:      "Log flushed",
		Units:      "bytes/s",
		Fam:        "transactions",
		Ctx:        "mssql.database_log_flushed",
		Priority:   prioMSSQLDatabaseLogFlushed,
		Dims: module.Dims{
			{ID: "mssql_db_%s_instance_%s_log_flushed_bytes", Name: "flushed", Algo: module.Incremental},
		},
	}
	mssqlDatabaseLogFlushesChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_db_%s_instance_%s_log_flushes",
		Title:      "Log flushes",
		Units:      "flushes/s",
		Fam:        "transactions",
		Ctx:        "mssql.database_log_flushes",
		Priority:   prioMSSQLDatabaseLogFlushes,
		Dims: module.Dims{
			{ID: "mssql_db_%s_instance_%s_log_flushes", Name: "log", Algo: module.Incremental},
		},
	}
	mssqlDatabaseTransactionsChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_db_%s_instance_%s_transactions",
		Title:      "Transactions",
		Units:      "transactions/s",
		Fam:        "transactions",
		Ctx:        "mssql.database_transactions",
		Priority:   prioMSSQLDatabaseTransactions,
		Dims: module.Dims{
			{ID: "mssql_db_%s_instance_%s_transactions", Name: "transactions", Algo: module.Incremental},
		},
	}
	mssqlDatabaseWriteTransactionsChart = module.Chart{
		OverModule: "mssql",
		ID:         "mssql_db_%s_instance_%s_write_transactions",
		Title:      "Write transactions",
		Units:      "transactions/s",
		Fam:        "transactions",
		Ctx:        "mssql.database_write_transactions",
		Priority:   prioMSSQLDatabaseWriteTransactions,
		Dims: module.Dims{
			{ID: "mssql_db_%s_instance_%s_write_transactions", Name: "write", Algo: module.Incremental},
		},
	}
)

// AD
var (
	adCharts = module.Charts{
		adDatabaseOperationsChart.Copy(),
		adDirectoryOperationsChart.Copy(),
		adNameCacheLookupsChart.Copy(),
		adNameCacheHitsChart.Copy(),
		adDRAReplicationIntersiteCompressedTrafficChart.Copy(),
		adDRAReplicationIntrasiteCompressedTrafficChart.Copy(),
		adDRAReplicationSyncObjectRemainingChart.Copy(),
		adDRAReplicationObjectsFilteredChart.Copy(),
		adDRAReplicationPropertiesUpdatedChart.Copy(),
		adDRAReplicationPropertiesFilteredChart.Copy(),
		adDRAReplicationPendingSyncsChart.Copy(),
		adDRAReplicationSyncRequestsChart.Copy(),
		adDirectoryServiceThreadsChart.Copy(),
		adLDAPLastBindTimeChart.Copy(),
		adBindsTotalChart.Copy(),
		adLDAPSearchesChart.Copy(),
		adATQAverageRequestLatencyChart.Copy(),
		adATQOutstandingRequestsChart.Copy(),
	}
	adDatabaseOperationsChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_database_operations",
		Title:      "AD database operations",
		Units:      "operations/s",
		Fam:        "database",
		Ctx:        "ad.database_operations",
		Priority:   prioADDatabaseOperations,
		Dims: module.Dims{
			{ID: "ad_database_operations_total_add", Name: "add", Algo: module.Incremental},
			{ID: "ad_database_operations_total_delete", Name: "delete", Algo: module.Incremental},
			{ID: "ad_database_operations_total_modify", Name: "modify", Algo: module.Incremental},
			{ID: "ad_database_operations_total_recycle", Name: "recycle", Algo: module.Incremental},
		},
	}
	adDirectoryOperationsChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_directory_operations_read",
		Title:      "AD directory operations",
		Units:      "operations/s",
		Fam:        "database",
		Ctx:        "ad.directory_operations",
		Priority:   prioADDirectoryOperations,
		Dims: module.Dims{
			{ID: "ad_directory_operations_total_read", Name: "read", Algo: module.Incremental},
			{ID: "ad_directory_operations_total_write", Name: "write", Algo: module.Incremental},
			{ID: "ad_directory_operations_total_search", Name: "search", Algo: module.Incremental},
		},
	}
	adNameCacheLookupsChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_name_cache_lookups",
		Title:      "Name cache lookups",
		Units:      "lookups/s",
		Fam:        "database",
		Ctx:        "ad.name_cache_lookups",
		Priority:   prioADNameCacheLookups,
		Dims: module.Dims{
			{ID: "ad_name_cache_lookups_total", Name: "lookups", Algo: module.Incremental},
		},
	}
	adNameCacheHitsChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_name_cache_hits",
		Title:      "Name cache hits",
		Units:      "hits/s",
		Fam:        "database",
		Ctx:        "ad.name_cache_hits",
		Priority:   prioADCacheHits,
		Dims: module.Dims{
			{ID: "ad_name_cache_hits_total", Name: "hits", Algo: module.Incremental},
		},
	}
	adDRAReplicationIntersiteCompressedTrafficChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_dra_replication_intersite_compressed_traffic",
		Title:      "DRA replication compressed traffic withing site",
		Units:      "bytes/s",
		Fam:        "replication",
		Ctx:        "ad.dra_replication_intersite_compressed_traffic",
		Priority:   prioADDRAReplicationIntersiteCompressedTraffic,
		Type:       module.Area,
		Dims: module.Dims{
			{ID: "ad_replication_data_intersite_bytes_total_inbound", Name: "inbound", Algo: module.Incremental},
			{ID: "ad_replication_data_intersite_bytes_total_outbound", Name: "outbound", Algo: module.Incremental, Mul: -1},
		},
	}
	adDRAReplicationIntrasiteCompressedTrafficChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_dra_replication_intrasite_compressed_traffic",
		Title:      "DRA replication compressed traffic between sites",
		Units:      "bytes/s",
		Fam:        "replication",
		Ctx:        "ad.dra_replication_intrasite_compressed_traffic",
		Priority:   prioADDRAReplicationIntrasiteCompressedTraffic,
		Type:       module.Area,
		Dims: module.Dims{
			{ID: "ad_replication_data_intrasite_bytes_total_inbound", Name: "inbound", Algo: module.Incremental},
			{ID: "ad_replication_data_intrasite_bytes_total_outbound", Name: "outbound", Algo: module.Incremental, Mul: -1},
		},
	}
	adDRAReplicationSyncObjectRemainingChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_dra_replication_sync_objects_remaining",
		Title:      "DRA replication full sync objects remaining",
		Units:      "objects",
		Fam:        "replication",
		Ctx:        "ad.dra_replication_sync_objects_remaining",
		Priority:   prioADDRAReplicationSyncObjectsRemaining,
		Dims: module.Dims{
			{ID: "ad_replication_inbound_sync_objects_remaining", Name: "inbound"},
		},
	}
	adDRAReplicationObjectsFilteredChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_dra_replication_objects_filtered",
		Title:      "DRA replication objects filtered",
		Units:      "objects/s",
		Fam:        "replication",
		Ctx:        "ad.dra_replication_objects_filtered",
		Priority:   prioADDRAReplicationObjectsFiltered,
		Dims: module.Dims{
			{ID: "ad_replication_inbound_objects_filtered_total", Name: "inbound", Algo: module.Incremental},
		},
	}
	adDRAReplicationPropertiesUpdatedChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_dra_replication_properties_updated",
		Title:      "DRA replication properties updated",
		Units:      "properties/s",
		Fam:        "replication",
		Ctx:        "ad.dra_replication_properties_updated",
		Priority:   prioADDRAReplicationPropertiesUpdated,
		Dims: module.Dims{
			{ID: "ad_replication_inbound_properties_updated_total", Name: "inbound", Algo: module.Incremental},
		},
	}
	adDRAReplicationPropertiesFilteredChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_dra_replication_properties_filtered",
		Title:      "DRA replication properties filtered",
		Units:      "properties/s",
		Fam:        "replication",
		Ctx:        "ad.dra_replication_properties_filtered",
		Priority:   prioADDRAReplicationPropertiesFiltered,
		Dims: module.Dims{
			{ID: "ad_replication_inbound_properties_filtered_total", Name: "inbound", Algo: module.Incremental},
		},
	}
	adDRAReplicationPendingSyncsChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_dra_replication_pending_syncs",
		Title:      "DRA replication pending syncs",
		Units:      "syncs",
		Fam:        "replication",
		Ctx:        "ad.dra_replication_pending_syncs",
		Priority:   prioADReplicationPendingSyncs,
		Dims: module.Dims{
			{ID: "ad_replication_pending_synchronizations", Name: "pending"},
		},
	}
	adDRAReplicationSyncRequestsChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_dra_replication_sync_requests",
		Title:      "DRA replication sync requests",
		Units:      "requests/s",
		Fam:        "replication",
		Ctx:        "ad.dra_replication_sync_requests",
		Priority:   prioADDRASyncRequests,
		Dims: module.Dims{
			{ID: "ad_replication_sync_requests_total", Name: "request", Algo: module.Incremental},
		},
	}
	adDirectoryServiceThreadsChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_ds_threads",
		Title:      "Directory Service threads",
		Units:      "threads",
		Fam:        "replication",
		Ctx:        "ad.ds_threads",
		Priority:   prioADDirectoryServiceThreadsInUse,
		Dims: module.Dims{
			{ID: "ad_directory_service_threads", Name: "in_use"},
		},
	}
	adLDAPLastBindTimeChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_ldap_last_bind_time",
		Title:      "LDAP last successful bind time",
		Units:      "seconds",
		Fam:        "bind",
		Ctx:        "ad.ldap_last_bind_time",
		Priority:   prioADLDAPBindTime,
		Dims: module.Dims{
			{ID: "ad_ldap_last_bind_time_seconds", Name: "last_bind"},
		},
	}
	adBindsTotalChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_binds",
		Title:      "Successful binds",
		Units:      "bind/s",
		Fam:        "bind",
		Ctx:        "ad.binds",
		Priority:   prioADBindsTotal,
		Dims: module.Dims{
			{ID: "ad_binds_total", Name: "binds", Algo: module.Incremental},
		},
	}
	adLDAPSearchesChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_ldap_searches",
		Title:      "LDAP client search operations",
		Units:      "searches/s",
		Fam:        "ldap",
		Ctx:        "ad.ldap_searches",
		Priority:   prioADLDAPSearchesTotal,
		Dims: module.Dims{
			{ID: "ad_ldap_searches_total", Name: "searches", Algo: module.Incremental},
		},
	}
	// https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/understanding-atq-performance-counters-yet-another-twist-in-the/ba-p/400293
	adATQAverageRequestLatencyChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_atq_average_request_latency",
		Title:      "Average request processing time",
		Units:      "seconds",
		Fam:        "queue",
		Ctx:        "ad.atq_average_request_latency",
		Priority:   prioADATQAverageRequestLatency,
		Dims: module.Dims{
			{ID: "ad_atq_average_request_latency", Name: "time", Div: precision},
		},
	}
	adATQOutstandingRequestsChart = module.Chart{
		OverModule: "ad",
		ID:         "ad_atq_outstanding_requests",
		Title:      "Outstanding requests",
		Units:      "requests",
		Fam:        "queue",
		Ctx:        "ad.atq_outstanding_requests",
		Priority:   prioADATQOutstandingRequests,
		Dims: module.Dims{
			{ID: "ad_atq_outstanding_requests", Name: "outstanding"},
		},
	}
)

// AD CS
var (
	adcsCertTemplateChartsTmpl = module.Charts{
		adcsCertTemplateRequestsChartTmpl.Copy(),
		adcsCertTemplateFailedRequestsChartTmpl.Copy(),
		adcsCertTemplateIssuedRequestsChartTmpl.Copy(),
		adcsCertTemplatePendingRequestsChartTmpl.Copy(),
		adcsCertTemplateRequestProcessingTimeChartTmpl.Copy(),

		adcsCertTemplateRetrievalsChartTmpl.Copy(),
		adcsCertificateRetrievalsTimeChartTmpl.Copy(),
		adcsCertTemplateRequestCryptoSigningTimeChartTmpl.Copy(),
		adcsCertTemplateRequestPolicyModuleProcessingTimeChartTmpl.Copy(),
		adcsCertTemplateChallengeResponseChartTmpl.Copy(),
		adcsCertTemplateChallengeResponseProcessingTimeChartTmpl.Copy(),
		adcsCertTemplateSignedCertificateTimestampListsChartTmpl.Copy(),
		adcsCertTemplateSignedCertificateTimestampListProcessingTimeChartTmpl.Copy(),
	}
	adcsCertTemplateRequestsChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template%s_requests",
		Title:      "Certificate requests processed",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "adcs.cert_template_requests",
		Priority:   prioADCSCertTemplateRequests,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_requests_total", Name: "requests", Algo: module.Incremental},
		},
	}
	adcsCertTemplateFailedRequestsChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template_%s_failed_requests",
		Title:      "Certificate failed requests processed",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "adcs.cert_template_failed_requests",
		Priority:   prioADCSCertTemplateFailedRequests,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_failed_requests_total", Name: "failed", Algo: module.Incremental},
		},
	}
	adcsCertTemplateIssuedRequestsChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template_%s_issued_requests",
		Title:      "Certificate issued requests processed",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "adcs.cert_template_issued_requests",
		Priority:   prioADCSCertTemplateIssuesRequests,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_issued_requests_total", Name: "issued", Algo: module.Incremental},
		},
	}
	adcsCertTemplatePendingRequestsChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template_%s_pending_requests",
		Title:      "Certificate pending requests processed",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "adcs.cert_template_pending_requests",
		Priority:   prioADCSCertTemplatePendingRequests,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_pending_requests_total", Name: "pending", Algo: module.Incremental},
		},
	}
	adcsCertTemplateRequestProcessingTimeChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template_%s_request_processing_time",
		Title:      "Certificate last request processing time",
		Units:      "seconds",
		Fam:        "requests",
		Ctx:        "adcs.cert_template_request_processing_time",
		Priority:   prioADCSCertTemplateRequestProcessingTime,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_request_processing_time_seconds", Name: "processing_time", Div: precision},
		},
	}
	adcsCertTemplateChallengeResponseChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template_%s_challenge_responses",
		Title:      "Certificate challenge responses",
		Units:      "responses/s",
		Fam:        "responses",
		Ctx:        "adcs.cert_template_challenge_responses",
		Priority:   prioADCSCertTemplateChallengeResponses,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_challenge_responses_total", Name: "challenge", Algo: module.Incremental},
		},
	}
	adcsCertTemplateRetrievalsChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template_%s_retrievals",
		Title:      "Total of certificate retrievals",
		Units:      "retrievals/s",
		Fam:        "retrievals",
		Ctx:        "adcs.cert_template_retrievals",
		Priority:   prioADCSCertTemplateRetrievals,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_retrievals_total", Name: "retrievals", Algo: module.Incremental},
		},
	}
	adcsCertificateRetrievalsTimeChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template_%s_retrievals_processing_time",
		Title:      "Certificate last retrieval processing time",
		Units:      "seconds",
		Fam:        "retrievals",
		Ctx:        "adcs.cert_template_retrieval_processing_time",
		Priority:   prioADCSCertTemplateRetrievalProcessingTime,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_retrievals_processing_time_seconds", Name: "processing_time", Div: precision},
		},
	}
	adcsCertTemplateRequestCryptoSigningTimeChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template_%s_request_cryptographic_signing_time",
		Title:      "Certificate last signing operation request time",
		Units:      "seconds",
		Fam:        "timings",
		Ctx:        "adcs.cert_template_request_cryptographic_signing_time",
		Priority:   prioADCSCertTemplateRequestCryptoSigningTime,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_request_cryptographic_signing_time_seconds", Name: "singing_time", Div: precision},
		},
	}
	adcsCertTemplateRequestPolicyModuleProcessingTimeChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template_%s_request_policy_module_processing_time",
		Title:      "Certificate last policy module processing request time",
		Units:      "seconds",
		Fam:        "timings",
		Ctx:        "adcs.cert_template_request_policy_module_processing",
		Priority:   prioADCSCertTemplateRequestPolicyModuleProcessingTime,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_request_policy_module_processing_time_seconds", Name: "processing_time", Div: precision},
		},
	}
	adcsCertTemplateChallengeResponseProcessingTimeChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template_%s_challenge_response_processing_time",
		Title:      "Certificate last challenge response time",
		Units:      "seconds",
		Fam:        "timings",
		Ctx:        "adcs.cert_template_challenge_response_processing_time",
		Priority:   prioADCSCertTemplateChallengeResponseProcessingTime,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_challenge_response_processing_time_seconds", Name: "processing_time", Div: precision},
		},
	}
	adcsCertTemplateSignedCertificateTimestampListsChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template_%s_signed_certificate_timestamp_lists",
		Title:      "Certificate Signed Certificate Timestamp Lists processed",
		Units:      "lists/s",
		Fam:        "timings",
		Ctx:        "adcs.cert_template_signed_certificate_timestamp_lists",
		Priority:   prioADCSCertTemplateSignedCertificateTimestampLists,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_signed_certificate_timestamp_lists_total", Name: "processed", Algo: module.Incremental},
		},
	}
	adcsCertTemplateSignedCertificateTimestampListProcessingTimeChartTmpl = module.Chart{
		OverModule: "adcs",
		ID:         "adcs_cert_template_%s_signed_certificate_timestamp_list_processing_time",
		Title:      "Certificate last Signed Certificate Timestamp List process time",
		Units:      "seconds",
		Fam:        "timings",
		Ctx:        "adcs.cert_template_signed_certificate_timestamp_list_processing_time",
		Priority:   prioADCSCertTemplateSignedCertificateTimestampListProcessingTime,
		Dims: module.Dims{
			{ID: "adcs_cert_template_%s_signed_certificate_timestamp_list_processing_time_seconds", Name: "processing_time", Div: precision},
		},
	}
)

// AD FS
var (
	adfsCharts = module.Charts{
		adfsADLoginConnectionFailuresChart.Copy(),
		adfsCertificateAuthenticationsChart.Copy(),
		adfsDBArtifactFailuresChart.Copy(),
		adfsDBArtifactQueryTimeSecondsChart.Copy(),
		adfsDBConfigFailuresChart.Copy(),
		adfsDBConfigQueryTimeSecondsChart.Copy(),
		adfsDeviceAuthenticationsChart.Copy(),
		adfsExternalAuthenticationsChart.Copy(),
		adfsFederatedAuthenticationsChart.Copy(),
		adfsFederationMetadataRequestsChart.Copy(),

		adfsOAuthAuthorizationRequestsChart.Copy(),
		adfsOAuthClientAuthenticationsChart.Copy(),
		adfsOAuthClientCredentialRequestsChart.Copy(),
		adfsOAuthClientPrivKeyJwtAuthenticationsChart.Copy(),
		adfsOAuthClientSecretBasicAuthenticationsChart.Copy(),
		adfsOAuthClientSecretPostAuthenticationsChart.Copy(),
		adfsOAuthClientWindowsAuthenticationsChart.Copy(),
		adfsOAuthLogonCertificateRequestsChart.Copy(),
		adfsOAuthPasswordGrantRequestsChart.Copy(),
		adfsOAuthTokenRequestsChart.Copy(),

		adfsPassiveRequestsChart.Copy(),
		adfsPassportAuthenticationsChart.Copy(),
		adfsPasswordChangeChart.Copy(),
		adfsSAMLPTokenRequestsChart.Copy(),
		adfsSSOAuthenticationsChart.Copy(),
		adfsTokenRequestsChart.Copy(),
		adfsUserPasswordAuthenticationsChart.Copy(),
		adfsWindowsIntegratedAuthenticationsChart.Copy(),
		adfsWSFedTokenRequestsSuccessChart.Copy(),
		adfsWSTrustTokenRequestsSuccessChart.Copy(),
	}

	adfsADLoginConnectionFailuresChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_ad_login_connection_failures",
		Title:      "Connection failures",
		Units:      "failures/s",
		Fam:        "ad",
		Ctx:        "adfs.ad_login_connection_failures",
		Priority:   prioADFSADLoginConnectionFailures,
		Dims: module.Dims{
			{ID: "adfs_ad_login_connection_failures_total", Name: "connection", Algo: module.Incremental},
		},
	}
	adfsCertificateAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_certificate_authentications",
		Title:      "User Certificate authentications",
		Units:      "authentications/s",
		Fam:        "auth",
		Ctx:        "adfs.certificate_authentications",
		Priority:   prioADFSCertificateAuthentications,
		Dims: module.Dims{
			{ID: "adfs_certificate_authentications_total", Name: "authentications", Algo: module.Incremental},
		},
	}

	adfsDBArtifactFailuresChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_db_artifact_failures",
		Title:      "Connection failures to the artifact database",
		Units:      "failures/s",
		Fam:        "db artifact",
		Ctx:        "adfs.db_artifact_failures",
		Priority:   prioADFSDBArtifactFailures,
		Dims: module.Dims{
			{ID: "adfs_db_artifact_failure_total", Name: "connection", Algo: module.Incremental},
		},
	}
	adfsDBArtifactQueryTimeSecondsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_db_artifact_query_time_seconds",
		Title:      "Time taken for an artifact database query",
		Units:      "seconds/s",
		Fam:        "db artifact",
		Ctx:        "adfs.db_artifact_query_time_seconds",
		Priority:   prioADFSDBArtifactQueryTimeSeconds,
		Dims: module.Dims{
			{ID: "adfs_db_artifact_query_time_seconds_total", Name: "query_time", Algo: module.Incremental, Div: precision},
		},
	}
	adfsDBConfigFailuresChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_db_config_failures",
		Title:      "Connection failures to the configuration database",
		Units:      "failures/s",
		Fam:        "db config",
		Ctx:        "adfs.db_config_failures",
		Priority:   prioADFSDBConfigFailures,
		Dims: module.Dims{
			{ID: "adfs_db_config_failure_total", Name: "connection", Algo: module.Incremental},
		},
	}
	adfsDBConfigQueryTimeSecondsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_db_config_query_time_seconds",
		Title:      "Time taken for a configuration database query",
		Units:      "seconds/s",
		Fam:        "db config",
		Ctx:        "adfs.db_config_query_time_seconds",
		Priority:   prioADFSDBConfigQueryTimeSeconds,
		Dims: module.Dims{
			{ID: "adfs_db_config_query_time_seconds_total", Name: "query_time", Algo: module.Incremental, Div: precision},
		},
	}
	adfsDeviceAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_device_authentications",
		Title:      "Device authentications",
		Units:      "authentications/s",
		Fam:        "auth",
		Ctx:        "adfs.device_authentications",
		Priority:   prioADFSDeviceAuthentications,
		Dims: module.Dims{
			{ID: "adfs_device_authentications_total", Name: "authentications", Algo: module.Incremental},
		},
	}
	adfsExternalAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_external_authentications",
		Title:      "Authentications from external MFA providers",
		Units:      "authentications/s",
		Fam:        "auth",
		Ctx:        "adfs.external_authentications",
		Priority:   prioADFSExternalAuthentications,
		Dims: module.Dims{
			{ID: "adfs_external_authentications_success_total", Name: "success", Algo: module.Incremental},
			{ID: "adfs_external_authentications_failure_total", Name: "failure", Algo: module.Incremental},
		},
	}
	adfsFederatedAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_federated_authentications",
		Title:      "Authentications from Federated Sources",
		Units:      "authentications/s",
		Fam:        "auth",
		Ctx:        "adfs.federated_authentications",
		Priority:   prioADFSFederatedAuthentications,
		Dims: module.Dims{
			{ID: "adfs_federated_authentications_total", Name: "authentications", Algo: module.Incremental},
		},
	}
	adfsFederationMetadataRequestsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_federation_metadata_requests",
		Title:      "Federation Metadata requests",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "adfs.federation_metadata_requests",
		Priority:   prioADFSFederationMetadataRequests,
		Dims: module.Dims{
			{ID: "adfs_federation_metadata_requests_total", Name: "requests", Algo: module.Incremental},
		},
	}

	adfsOAuthAuthorizationRequestsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_oauth_authorization_requests",
		Title:      "Incoming requests to the OAuth Authorization endpoint",
		Units:      "requests/s",
		Fam:        "oauth",
		Ctx:        "adfs.oauth_authorization_requests",
		Priority:   prioADFSOauthAuthorizationRequests,
		Dims: module.Dims{
			{ID: "adfs_oauth_authorization_requests_total", Name: "requests", Algo: module.Incremental},
		},
	}
	adfsOAuthClientAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_oauth_client_authentications",
		Title:      "OAuth client authentications",
		Units:      "authentications/s",
		Fam:        "oauth",
		Ctx:        "adfs.oauth_client_authentications",
		Priority:   prioADFSOauthClientAuthentications,
		Dims: module.Dims{
			{ID: "adfs_oauth_client_authentication_success_total", Name: "success", Algo: module.Incremental},
			{ID: "adfs_oauth_client_authentication_failure_total", Name: "failure", Algo: module.Incremental},
		},
	}
	adfsOAuthClientCredentialRequestsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_oauth_client_credentials_requests",
		Title:      "OAuth client credentials requests",
		Units:      "requests/s",
		Fam:        "oauth",
		Ctx:        "adfs.oauth_client_credentials_requests",
		Priority:   prioADFSOauthClientCredentials,
		Dims: module.Dims{
			{ID: "adfs_oauth_client_credentials_success_total", Name: "success", Algo: module.Incremental},
			{ID: "adfs_oauth_client_credentials_failure_total", Name: "failure", Algo: module.Incremental},
		},
	}
	adfsOAuthClientPrivKeyJwtAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_oauth_client_privkey_jwt_authentications",
		Title:      "OAuth client private key JWT authentications",
		Units:      "authentications/s",
		Fam:        "oauth",
		Ctx:        "adfs.oauth_client_privkey_jwt_authentications",
		Priority:   prioADFSOauthClientPrivkeyJwtAuthentication,
		Dims: module.Dims{
			{ID: "adfs_oauth_client_privkey_jwt_authentications_success_total", Name: "success", Algo: module.Incremental},
			{ID: "adfs_oauth_client_privkey_jtw_authentication_failure_total", Name: "failure", Algo: module.Incremental},
		},
	}
	adfsOAuthClientSecretBasicAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_oauth_client_secret_basic_authentications",
		Title:      "OAuth client secret basic authentications",
		Units:      "authentications/s",
		Fam:        "oauth",
		Ctx:        "adfs.oauth_client_secret_basic_authentications",
		Priority:   prioADFSOauthClientSecretBasicAuthentications,
		Dims: module.Dims{
			{ID: "adfs_oauth_client_secret_basic_authentications_success_total", Name: "success", Algo: module.Incremental},
			{ID: "adfs_oauth_client_secret_basic_authentications_failure_total", Name: "failure", Algo: module.Incremental},
		},
	}
	adfsOAuthClientSecretPostAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_oauth_client_secret_post_authentications",
		Title:      "OAuth client secret post authentications",
		Units:      "authentications/s",
		Fam:        "oauth",
		Ctx:        "adfs.oauth_client_secret_post_authentications",
		Priority:   prioADFSOauthClientSecretPostAuthentications,
		Dims: module.Dims{
			{ID: "adfs_oauth_client_secret_post_authentications_success_total", Name: "success", Algo: module.Incremental},
			{ID: "adfs_oauth_client_secret_post_authentications_failure_total", Name: "failure", Algo: module.Incremental},
		},
	}
	adfsOAuthClientWindowsAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_oauth_client_windows_authentications",
		Title:      "OAuth client windows integrated authentications",
		Units:      "authentications/s",
		Fam:        "oauth",
		Ctx:        "adfs.oauth_client_windows_authentications",
		Priority:   prioADFSOauthClientWindowsAuthentications,
		Dims: module.Dims{
			{ID: "adfs_oauth_client_windows_authentications_success_total", Name: "success", Algo: module.Incremental},
			{ID: "adfs_oauth_client_windows_authentications_failure_total", Name: "failure", Algo: module.Incremental},
		},
	}
	adfsOAuthLogonCertificateRequestsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_oauth_logon_certificate_requests",
		Title:      "OAuth logon certificate requests",
		Units:      "requests/s",
		Fam:        "oauth",
		Ctx:        "adfs.oauth_logon_certificate_requests",
		Priority:   prioADFSOauthLogonCertificateRequests,
		Dims: module.Dims{
			{ID: "adfs_oauth_logon_certificate_token_requests_success_total", Name: "success", Algo: module.Incremental},
			{ID: "adfs_oauth_logon_certificate_requests_failure_total", Name: "failure", Algo: module.Incremental},
		},
	}
	adfsOAuthPasswordGrantRequestsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_oauth_password_grant_requests",
		Title:      "OAuth password grant requests",
		Units:      "requests/s",
		Fam:        "oauth",
		Ctx:        "adfs.oauth_password_grant_requests",
		Priority:   prioADFSOauthPasswordGrantRequests,
		Dims: module.Dims{
			{ID: "adfs_oauth_password_grant_requests_success_total", Name: "success", Algo: module.Incremental},
			{ID: "adfs_oauth_password_grant_requests_failure_total", Name: "failure", Algo: module.Incremental},
		},
	}
	adfsOAuthTokenRequestsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_oauth_token_requests_success",
		Title:      "Successful RP token requests over OAuth protocol",
		Units:      "requests/s",
		Fam:        "oauth",
		Ctx:        "adfs.oauth_token_requests_success",
		Priority:   prioADFSOauthTokenRequestsSuccess,
		Dims: module.Dims{
			{ID: "adfs_oauth_token_requests_success_total", Name: "success", Algo: module.Incremental},
		},
	}

	adfsPassiveRequestsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_passive_requests",
		Title:      "Passive requests",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "adfs.passive_requests",
		Priority:   prioADFSPassiveRequests,
		Dims: module.Dims{
			{ID: "adfs_passive_requests_total", Name: "passive", Algo: module.Incremental},
		},
	}
	adfsPassportAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_passport_authentications",
		Title:      "Microsoft Passport SSO authentications",
		Units:      "authentications/s",
		Fam:        "auth",
		Ctx:        "adfs.passport_authentications",
		Priority:   prioADFSPassportAuthentications,
		Dims: module.Dims{
			{ID: "adfs_passport_authentications_total", Name: "passport", Algo: module.Incremental},
		},
	}
	adfsPasswordChangeChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_password_change_requests",
		Title:      "Password change requests",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "adfs.password_change_requests",
		Priority:   prioADFSPasswordChangeRequests,
		Dims: module.Dims{
			{ID: "adfs_password_change_succeeded_total", Name: "success", Algo: module.Incremental},
			{ID: "adfs_password_change_failed_total", Name: "failed", Algo: module.Incremental},
		},
	}
	adfsSAMLPTokenRequestsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_samlp_token_requests_success",
		Title:      "Successful RP token requests over SAML-P protocol",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "adfs.samlp_token_requests_success",
		Priority:   prioADFSSAMLPTokenRequests,
		Dims: module.Dims{
			{ID: "adfs_samlp_token_requests_success_total", Name: "success", Algo: module.Incremental},
		},
	}
	adfsWSTrustTokenRequestsSuccessChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_wstrust_token_requests_success",
		Title:      "Successful RP token requests over WS-Trust protocol",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "adfs.wstrust_token_requests_success",
		Priority:   prioADFSWSTrustTokenRequestsSuccess,
		Dims: module.Dims{
			{ID: "adfs_wstrust_token_requests_success_total", Name: "success", Algo: module.Incremental},
		},
	}
	adfsSSOAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_sso_authentications",
		Title:      "SSO authentications",
		Units:      "authentications/s",
		Fam:        "auth",
		Ctx:        "adfs.sso_authentications",
		Priority:   prioADFSSSOAuthentications,
		Dims: module.Dims{
			{ID: "adfs_sso_authentications_success_total", Name: "success", Algo: module.Incremental},
			{ID: "adfs_sso_authentications_failure_total", Name: "failure", Algo: module.Incremental},
		},
	}
	adfsTokenRequestsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_token_requests",
		Title:      "Token access requests",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "adfs.token_requests",
		Priority:   prioADFSTokenRequests,
		Dims: module.Dims{
			{ID: "adfs_token_requests_total", Name: "requests", Algo: module.Incremental},
		},
	}
	adfsUserPasswordAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_userpassword_authentications",
		Title:      "AD U/P authentications",
		Units:      "authentications/s",
		Fam:        "auth",
		Ctx:        "adfs.userpassword_authentications",
		Priority:   prioADFSUserPasswordAuthentications,
		Dims: module.Dims{
			{ID: "adfs_sso_authentications_success_total", Name: "success", Algo: module.Incremental},
			{ID: "adfs_sso_authentications_failure_total", Name: "failure", Algo: module.Incremental},
		},
	}
	adfsWindowsIntegratedAuthenticationsChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_windows_integrated_authentications",
		Title:      "Windows integrated authentications using Kerberos or NTLM",
		Units:      "authentications/s",
		Fam:        "auth",
		Ctx:        "adfs.windows_integrated_authentications",
		Priority:   prioADFSWindowsIntegratedAuthentications,
		Dims: module.Dims{
			{ID: "adfs_windows_integrated_authentications_total", Name: "authentications", Algo: module.Incremental},
		},
	}
	adfsWSFedTokenRequestsSuccessChart = module.Chart{
		OverModule: "adfs",
		ID:         "adfs_wsfed_token_requests_success",
		Title:      "Successful RP token requests over WS-Fed protocol",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "adfs.wsfed_token_requests_success",
		Priority:   prioADFSWSFedTokenRequestsSuccess,
		Dims: module.Dims{
			{ID: "adfs_wsfed_token_requests_success_total", Name: "success", Algo: module.Incremental},
		},
	}
)

// Exchange
var (
	exchangeCharts = module.Charts{
		exchangeActiveSyncPingCMDsPendingChart.Copy(),
		exchangeActiveSyncRequestsChart.Copy(),
		exchangeActiveSyncCMDsChart.Copy(),
		exchangeAutoDiscoverRequestsChart.Copy(),
		exchangeAvailableServiceRequestsChart.Copy(),
		exchangeOWACurrentUniqueUsersChart.Copy(),
		exchangeOWARequestsChart.Copy(),
		exchangeRPCActiveUsersCountChart.Copy(),
		exchangeRPCAvgLatencyChart.Copy(),
		exchangeRPCConnectionChart.Copy(),
		exchangeRPCOperationsChart.Copy(),
		exchangeRPCRequestsChart.Copy(),
		exchangeRPCUserChart.Copy(),
		exchangeTransportQueuesActiveMailBoxDelivery.Copy(),
		exchangeTransportQueuesExternalActiveRemoteDelivery.Copy(),
		exchangeTransportQueuesExternalLargestDelivery.Copy(),
		exchangeTransportQueuesInternalActiveRemoteDelivery.Copy(),
		exchangeTransportQueuesInternalLargestDelivery.Copy(),
		exchangeTransportQueuesRetryMailboxDelivery.Copy(),
		exchangeTransportQueuesUnreachable.Copy(),
		exchangeTransportQueuesPoison.Copy(),
	}
	exchangeWorkloadChartsTmpl = module.Charts{
		exchangeWorkloadActiveTasks.Copy(),
		exchangeWorkloadCompletedTasks.Copy(),
		exchangeWorkloadQueuedTasks.Copy(),
		exchangeWorkloadYieldedTasks.Copy(),

		exchangeWorkloadActivityStatus.Copy(),
	}
	exchangeLDAPChartsTmpl = module.Charts{
		exchangeLDAPLongRunningOPS.Copy(),
		exchangeLDAPReadTime.Copy(),
		exchangeLDAPSearchTime.Copy(),
		exchangeLDAPTimeoutErrors.Copy(),
		exchangeLDAPWriteTime.Copy(),
	}
	exchangeHTTPProxyChartsTmpl = module.Charts{
		exchangeProxyAvgAuthLatency.Copy(),
		exchangeProxyAvgCasProcessingLatencySec.Copy(),
		exchangeProxyMailboxProxyFailureRace.Copy(),
		exchangeProxyMailboxServerLocatorAvgLatencySec.Copy(),
		exchangeProxyOutstandingProxyRequests.Copy(),
		exchangeProxyRequestsTotal.Copy(),
	}

	exchangeActiveSyncPingCMDsPendingChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_activesync_ping_cmds_pending",
		Title:      "Ping commands pending in queue",
		Units:      "commands",
		Fam:        "sync",
		Ctx:        "exchange.activesync_ping_cmds_pending",
		Priority:   prioExchangeActiveSyncPingCMDsPending,
		Dims: module.Dims{
			{ID: "exchange_activesync_ping_cmds_pending", Name: "pending"},
		},
	}
	exchangeActiveSyncRequestsChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_activesync_requests",
		Title:      "HTTP requests received from ASP.NET",
		Units:      "requests/s",
		Fam:        "sync",
		Ctx:        "exchange.activesync_requests",
		Priority:   prioExchangeActiveSyncRequests,
		Dims: module.Dims{
			{ID: "exchange_activesync_requests_total", Name: "received", Algo: module.Incremental},
		},
	}
	exchangeActiveSyncCMDsChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_activesync_sync_cmds",
		Title:      "Sync commands processed",
		Units:      "commands/s",
		Fam:        "sync",
		Ctx:        "exchange.activesync_sync_cmds",
		Priority:   prioExchangeActiveSyncSyncCMDs,
		Dims: module.Dims{
			{ID: "exchange_activesync_sync_cmds_total", Name: "processed", Algo: module.Incremental},
		},
	}
	exchangeAutoDiscoverRequestsChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_autodiscover_requests",
		Title:      "Autodiscover service requests processed",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "exchange.autodiscover_requests",
		Priority:   prioExchangeAutoDiscoverRequests,
		Dims: module.Dims{
			{ID: "exchange_autodiscover_requests_total", Name: "processed", Algo: module.Incremental},
		},
	}
	exchangeAvailableServiceRequestsChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_avail_service_requests",
		Title:      "Requests serviced",
		Units:      "requests/s",
		Fam:        "requests",
		Ctx:        "exchange.avail_service_requests",
		Priority:   prioExchangeAvailServiceRequests,
		Dims: module.Dims{
			{ID: "exchange_avail_service_requests_per_sec", Name: "serviced", Algo: module.Incremental},
		},
	}
	exchangeOWACurrentUniqueUsersChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_owa_current_unique_users",
		Title:      "Unique users currently logged on to Outlook Web App",
		Units:      "users",
		Fam:        "owa",
		Ctx:        "exchange.owa_current_unique_users",
		Priority:   prioExchangeOWACurrentUniqueUsers,
		Dims: module.Dims{
			{ID: "exchange_owa_current_unique_users", Name: "logged-in"},
		},
	}
	exchangeOWARequestsChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_owa_requests_total",
		Title:      "Requests handled by Outlook Web App",
		Units:      "requests/s",
		Fam:        "owa",
		Ctx:        "exchange.owa_requests_total",
		Priority:   prioExchangeOWARequestsTotal,
		Dims: module.Dims{
			{ID: "exchange_owa_requests_total", Name: "handled", Algo: module.Incremental},
		},
	}
	exchangeRPCActiveUsersCountChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_rpc_active_user",
		Title:      "Active unique users in the last 2 minutes",
		Units:      "users",
		Fam:        "rpc",
		Ctx:        "exchange.rpc_active_user_count",
		Priority:   prioExchangeRPCActiveUserCount,
		Dims: module.Dims{
			{ID: "exchange_rpc_active_user_count", Name: "active"},
		},
	}
	exchangeRPCAvgLatencyChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_rpc_avg_latency",
		Title:      "Average latency",
		Units:      "seconds",
		Fam:        "rpc",
		Ctx:        "exchange.rpc_avg_latency",
		Priority:   prioExchangeRPCAvgLatency,
		Dims: module.Dims{
			{ID: "exchange_rpc_avg_latency_sec", Name: "latency", Div: precision},
		},
	}
	exchangeRPCConnectionChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_rpc_connection",
		Title:      "Client connections",
		Units:      "connections",
		Fam:        "rpc",
		Ctx:        "exchange.rpc_connection_count",
		Priority:   prioExchangeRPCConnectionCount,
		Dims: module.Dims{
			{ID: "exchange_rpc_connection_count", Name: "connections"},
		},
	}
	exchangeRPCOperationsChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_rpc_operations",
		Title:      "RPC operations",
		Units:      "operations/s",
		Fam:        "rpc",
		Ctx:        "exchange.rpc_operations",
		Priority:   prioExchangeRPCOperationsTotal,
		Dims: module.Dims{
			{ID: "exchange_rpc_operations_total", Name: "operations", Algo: module.Incremental},
		},
	}
	exchangeRPCRequestsChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_rpc_requests_total",
		Title:      "Clients requests currently being processed",
		Units:      "requests",
		Fam:        "rpc",
		Ctx:        "exchange.rpc_requests",
		Priority:   prioExchangeRPCRequests,
		Dims: module.Dims{
			{ID: "exchange_rpc_requests", Name: "processed"},
		},
	}
	exchangeRPCUserChart = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_rpc_user",
		Title:      "RPC users",
		Units:      "users",
		Fam:        "rpc",
		Ctx:        "exchange.rpc_user_count",
		Priority:   prioExchangeRpcUserCount,
		Dims: module.Dims{
			{ID: "exchange_rpc_user_count", Name: "users"},
		},
	}

	// Source: https://learn.microsoft.com/en-us/exchange/mail-flow/queues/queues?view=exchserver-2019
	exchangeTransportQueuesActiveMailBoxDelivery = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_transport_queues_active_mailbox_delivery",
		Title:      "Active Mailbox Delivery Queue length",
		Units:      "messages",
		Fam:        "queue",
		Ctx:        "exchange.transport_queues_active_mail_box_delivery",
		Priority:   prioExchangeTransportQueuesActiveMailboxDelivery,
		Dims: module.Dims{
			{ID: "exchange_transport_queues_active_mailbox_delivery_low_priority", Name: "low"},
			{ID: "exchange_transport_queues_active_mailbox_delivery_high_priority", Name: "high"},
			{ID: "exchange_transport_queues_active_mailbox_delivery_none_priority", Name: "none"},
			{ID: "exchange_transport_queues_active_mailbox_delivery_normal_priority", Name: "normal"},
		},
	}
	exchangeTransportQueuesExternalActiveRemoteDelivery = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_transport_queues_external_active_remote_delivery",
		Title:      "External Active Remote Delivery Queue length",
		Units:      "messages",
		Fam:        "queue",
		Ctx:        "exchange.transport_queues_external_active_remote_delivery",
		Priority:   prioExchangeTransportQueuesExternalActiveRemoteDelivery,
		Dims: module.Dims{
			{ID: "exchange_transport_queues_external_active_remote_delivery_low_priority", Name: "low"},
			{ID: "exchange_transport_queues_external_active_remote_delivery_high_priority", Name: "high"},
			{ID: "exchange_transport_queues_external_active_remote_delivery_none_priority", Name: "none"},
			{ID: "exchange_transport_queues_external_active_remote_delivery_normal_priority", Name: "normal"},
		},
	}
	exchangeTransportQueuesExternalLargestDelivery = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_transport_queues_external_largest_delivery",
		Title:      "External Largest Delivery Queue length",
		Units:      "messages",
		Fam:        "queue",
		Ctx:        "exchange.transport_queues_external_largest_delivery",
		Priority:   prioExchangeTransportQueuesExternalLargestDelivery,
		Dims: module.Dims{
			{ID: "exchange_transport_queues_external_largest_delivery_low_priority", Name: "low"},
			{ID: "exchange_transport_queues_external_largest_delivery_high_priority", Name: "high"},
			{ID: "exchange_transport_queues_external_largest_delivery_none_priority", Name: "none"},
			{ID: "exchange_transport_queues_external_largest_delivery_normal_priority", Name: "normal"},
		},
	}
	exchangeTransportQueuesInternalActiveRemoteDelivery = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_transport_queues_internal_active_remote_delivery",
		Title:      "Internal Active Remote Delivery Queue length",
		Units:      "messages",
		Fam:        "queue",
		Ctx:        "exchange.transport_queues_internal_active_remote_delivery",
		Priority:   prioExchangeTransportQueuesInternalActiveRemoteDeliery,
		Dims: module.Dims{
			{ID: "exchange_transport_queues_internal_active_remote_delivery_low_priority", Name: "low"},
			{ID: "exchange_transport_queues_internal_active_remote_delivery_high_priority", Name: "high"},
			{ID: "exchange_transport_queues_internal_active_remote_delivery_none_priority", Name: "none"},
			{ID: "exchange_transport_queues_internal_active_remote_delivery_normal_priority", Name: "normal"},
		},
	}
	exchangeTransportQueuesInternalLargestDelivery = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_transport_queues_internal_largest_delivery",
		Title:      "Internal Largest Delivery Queue length",
		Units:      "messages",
		Fam:        "queue",
		Ctx:        "exchange.transport_queues_internal_largest_delivery",
		Priority:   prioExchangeTransportQueuesInternalLargestDelivery,
		Dims: module.Dims{
			{ID: "exchange_transport_queues_internal_largest_delivery_low_priority", Name: "low"},
			{ID: "exchange_transport_queues_internal_largest_delivery_high_priority", Name: "high"},
			{ID: "exchange_transport_queues_internal_largest_delivery_none_priority", Name: "none"},
			{ID: "exchange_transport_queues_internal_largest_delivery_normal_priority", Name: "normal"},
		},
	}
	exchangeTransportQueuesRetryMailboxDelivery = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_transport_queues_retry_mailbox_delivery",
		Title:      "Internal Active Remote Delivery Queue length",
		Units:      "messages",
		Fam:        "queue",
		Ctx:        "exchange.transport_queues_retry_mailbox_delivery",
		Priority:   prioExchangeTransportQueuesRetryMailboxDelivery,
		Dims: module.Dims{
			{ID: "exchange_transport_queues_retry_mailbox_delivery_low_priority", Name: "low"},
			{ID: "exchange_transport_queues_retry_mailbox_delivery_high_priority", Name: "high"},
			{ID: "exchange_transport_queues_retry_mailbox_delivery_none_priority", Name: "none"},
			{ID: "exchange_transport_queues_retry_mailbox_delivery_normal_priority", Name: "normal"},
		},
	}
	exchangeTransportQueuesUnreachable = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_transport_queues_unreachable",
		Title:      "Unreachable Queue length",
		Units:      "messages",
		Fam:        "queue",
		Ctx:        "exchange.transport_queues_unreachable",
		Priority:   prioExchangeTransportQueuesUnreachable,
		Dims: module.Dims{
			{ID: "exchange_transport_queues_unreachable_low_priority", Name: "low"},
			{ID: "exchange_transport_queues_unreachable_high_priority", Name: "high"},
			{ID: "exchange_transport_queues_unreachable_none_priority", Name: "none"},
			{ID: "exchange_transport_queues_unreachable_normal_priority", Name: "normal"},
		},
	}
	exchangeTransportQueuesPoison = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_transport_queues_poison",
		Title:      "Poison Queue Length",
		Units:      "messages/s",
		Fam:        "queue",
		Ctx:        "exchange.transport_queues_poison",
		Priority:   prioExchangeTransportQueuesPoison,
		Dims: module.Dims{
			{ID: "exchange_transport_queues_poison_high_priority", Name: "high"},
			{ID: "exchange_transport_queues_poison_low_priority", Name: "low"},
			{ID: "exchange_transport_queues_poison_none_priority", Name: "none"},
			{ID: "exchange_transport_queues_poison_normal_priority", Name: "normal"},
		},
	}

	exchangeWorkloadActiveTasks = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_workload_%s_tasks",
		Title:      "Workload active tasks",
		Units:      "tasks",
		Fam:        "workload",
		Ctx:        "exchange.workload_active_tasks",
		Priority:   prioExchangeWorkloadActiveTasks,
		Dims: module.Dims{
			{ID: "exchange_workload_%s_active_tasks", Name: "active"},
		},
	}
	exchangeWorkloadCompletedTasks = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_workload_%s_completed_tasks",
		Title:      "Workload completed tasks",
		Units:      "tasks/s",
		Fam:        "workload",
		Ctx:        "exchange.workload_completed_tasks",
		Priority:   prioExchangeWorkloadCompleteTasks,
		Dims: module.Dims{
			{ID: "exchange_workload_%s_completed_tasks", Name: "completed", Algo: module.Incremental},
		},
	}
	exchangeWorkloadQueuedTasks = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_workload_%s_queued_tasks",
		Title:      "Workload queued tasks",
		Units:      "tasks/s",
		Fam:        "workload",
		Ctx:        "exchange.workload_queued_tasks",
		Priority:   prioExchangeWorkloadQueueTasks,
		Dims: module.Dims{
			{ID: "exchange_workload_%s_queued_tasks", Name: "queued", Algo: module.Incremental},
		},
	}
	exchangeWorkloadYieldedTasks = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_workload_%s_yielded_tasks",
		Title:      "Workload yielded tasks",
		Units:      "tasks/s",
		Fam:        "workload",
		Ctx:        "exchange.workload_yielded_tasks",
		Priority:   prioExchangeWorkloadYieldedTasks,
		Dims: module.Dims{
			{ID: "exchange_workload_%s_yielded_tasks", Name: "yielded", Algo: module.Incremental},
		},
	}
	exchangeWorkloadActivityStatus = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_workload_%s_activity_status",
		Title:      "Workload activity status",
		Units:      "status",
		Fam:        "workload",
		Ctx:        "exchange.workload_activity_status",
		Priority:   prioExchangeWorkloadActivityStatus,
		Dims: module.Dims{
			{ID: "exchange_workload_%s_is_active", Name: "active"},
			{ID: "exchange_workload_%s_is_paused", Name: "paused"},
		},
	}

	exchangeLDAPLongRunningOPS = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_ldap_%s_long_running_ops",
		Title:      "Long Running LDAP operations",
		Units:      "operations/s",
		Fam:        "ldap",
		Ctx:        "exchange.ldap_long_running_ops_per_sec",
		Priority:   prioExchangeLDAPLongRunningOPS,
		Dims: module.Dims{
			{ID: "exchange_ldap_%s_long_running_ops_per_sec", Name: "long-running", Algo: module.Incremental},
		},
	}
	exchangeLDAPReadTime = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_ldap_%s_read_time",
		Title:      "Time to send an LDAP read request and receive a response",
		Units:      "seconds",
		Fam:        "ldap",
		Ctx:        "exchange.ldap_read_time",
		Priority:   prioExchangeLDAPReadTime,
		Dims: module.Dims{
			{ID: "exchange_ldap_%s_read_time_sec", Name: "read", Algo: module.Incremental, Div: precision},
		},
	}
	exchangeLDAPSearchTime = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_ldap_%s_search_time",
		Title:      "Time to send an LDAP search request and receive a response",
		Units:      "seconds",
		Fam:        "ldap",
		Ctx:        "exchange.ldap_search_time",
		Priority:   prioExchangeLDAPSearchTime,
		Dims: module.Dims{
			{ID: "exchange_ldap_%s_search_time_sec", Name: "search", Algo: module.Incremental, Div: precision},
		},
	}
	exchangeLDAPWriteTime = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_ldap_%s_write_time",
		Title:      "Time to send an LDAP search request and receive a response",
		Units:      "second",
		Fam:        "ldap",
		Ctx:        "exchange.ldap_write_time",
		Priority:   prioExchangeLDAPWriteTime,
		Dims: module.Dims{
			{ID: "exchange_ldap_%s_write_time_sec", Name: "write", Algo: module.Incremental, Div: precision},
		},
	}
	exchangeLDAPTimeoutErrors = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_ldap_%s_timeout_errors",
		Title:      "LDAP timeout errors",
		Units:      "errors/s",
		Fam:        "ldap",
		Ctx:        "exchange.ldap_timeout_errors",
		Priority:   prioExchangeLDAPTimeoutErrors,
		Dims: module.Dims{
			{ID: "exchange_ldap_%s_timeout_errors_total", Name: "timeout", Algo: module.Incremental},
		},
	}

	exchangeProxyAvgAuthLatency = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_proxy_%s_avg_auth_latency",
		Title:      "Average time spent authenticating CAS",
		Units:      "seconds",
		Fam:        "proxy",
		Ctx:        "exchange.http_proxy_avg_auth_latency",
		Priority:   prioExchangeHTTPProxyAVGAuthLatency,
		Dims: module.Dims{
			{ID: "exchange_http_proxy_%s_avg_auth_latency", Name: "latency"},
		},
	}
	exchangeProxyAvgCasProcessingLatencySec = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_proxy_%s_avg_cas_processing_latency_sec",
		Title:      "Average time spent authenticating CAS",
		Units:      "seconds",
		Fam:        "proxy",
		Ctx:        "exchange.http_proxy_avg_cas_processing_latency_sec",
		Priority:   prioExchangeHTTPProxyAVGCASProcessingLatency,
		Dims: module.Dims{
			{ID: "exchange_http_proxy_%s_avg_cas_proccessing_latency_sec", Name: "latency"},
		},
	}
	exchangeProxyMailboxProxyFailureRace = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_proxy_%s_mailbox_proxy_failure_rate",
		Title:      "Percentage of failures between this CAS and MBX servers",
		Units:      "percentage",
		Fam:        "proxy",
		Ctx:        "exchange.http_proxy_mailbox_proxy_failure_rate",
		Priority:   prioExchangeHTTPProxyMailboxProxyFailureRate,
		Dims: module.Dims{
			{ID: "exchange_http_proxy_%s_mailbox_proxy_failure_rate", Name: "failures", Div: precision},
		},
	}
	exchangeProxyMailboxServerLocatorAvgLatencySec = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_proxy_%s_mailbox_server_locator_avg_latency_sec",
		Title:      "Average latency of MailboxServerLocator web service calls",
		Units:      "seconds",
		Fam:        "proxy",
		Ctx:        "exchange.http_proxy_mailbox_server_locator_avg_latency_sec",
		Priority:   prioExchangeHTTPProxyServerLocatorAvgLatency,
		Dims: module.Dims{
			{ID: "exchange_http_proxy_%s_mailbox_server_locator_avg_latency_sec", Name: "latency", Div: precision},
		},
	}
	exchangeProxyOutstandingProxyRequests = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_proxy_%s_outstanding_proxy_requests",
		Title:      "Concurrent outstanding proxy requests",
		Units:      "requests",
		Fam:        "proxy",
		Ctx:        "exchange.http_proxy_outstanding_proxy_requests",
		Priority:   prioExchangeHTTPProxyOutstandingProxyRequests,
		Dims: module.Dims{
			{ID: "exchange_http_proxy_%s_outstanding_proxy_requests", Name: "outstanding"},
		},
	}
	exchangeProxyRequestsTotal = module.Chart{
		OverModule: "exchange",
		ID:         "exchange_proxy_%s_requests_total",
		Title:      "Number of proxy requests processed each second",
		Units:      "requests/s",
		Fam:        "proxy",
		Ctx:        "exchange.http_proxy_requests",
		Priority:   prioExchangeHTTPProxyRequestsTotal,
		Dims: module.Dims{
			{ID: "exchange_http_proxy_%s_requests_total", Name: "processed", Algo: module.Incremental},
		},
	}
)

// Logon
var (
	logonCharts = module.Charts{
		logonSessionsChart.Copy(),
	}
	logonSessionsChart = module.Chart{
		ID:       "logon_active_sessions_by_type",
		Title:    "Active User Logon Sessions By Type",
		Units:    "sessions",
		Fam:      "logon",
		Ctx:      "windows.logon_type_sessions",
		Type:     module.Stacked,
		Priority: prioLogonSessions,
		Dims: module.Dims{
			{ID: "logon_type_system_sessions", Name: "system"},
			{ID: "logon_type_proxy_sessions", Name: "proxy"},
			{ID: "logon_type_network_sessions", Name: "network"},
			{ID: "logon_type_interactive_sessions", Name: "interactive"},
			{ID: "logon_type_batch_sessions", Name: "batch"},
			{ID: "logon_type_service_sessions", Name: "service"},
			{ID: "logon_type_unlock_sessions", Name: "unlock"},
			{ID: "logon_type_network_clear_text_sessions", Name: "network_clear_text"},
			{ID: "logon_type_new_credentials_sessions", Name: "new_credentials"},
			{ID: "logon_type_remote_interactive_sessions", Name: "remote_interactive"},
			{ID: "logon_type_cached_interactive_sessions", Name: "cached_interactive"},
			{ID: "logon_type_cached_remote_interactive_sessions", Name: "cached_remote_interactive"},
			{ID: "logon_type_cached_unlock_sessions", Name: "cached_unlock"},
		},
	}
)

// Thermal zone
var (
	thermalzoneChartsTmpl = module.Charts{
		thermalzoneTemperatureChartTmpl.Copy(),
	}
	thermalzoneTemperatureChartTmpl = module.Chart{
		ID:       "thermalzone_%s_temperature",
		Title:    "Thermal zone temperature",
		Units:    "Celsius",
		Fam:      "thermalzone",
		Ctx:      "windows.thermalzone_temperature",
		Priority: prioThermalzoneTemperature,
		Dims: module.Dims{
			{ID: "thermalzone_%s_temperature", Name: "temperature"},
		},
	}
)

// Processes
var (
	processesCharts = module.Charts{
		processesCPUUtilizationTotalChart.Copy(),
		processesMemoryUsageChart.Copy(),
		processesHandlesChart.Copy(),
		processesIOBytesChart.Copy(),
		processesIOOperationsChart.Copy(),
		processesPageFaultsChart.Copy(),
		processesPageFileBytes.Copy(),
		processesThreads.Copy(),
	}
	processesCPUUtilizationTotalChart = module.Chart{
		ID:       "processes_cpu_utilization",
		Title:    "CPU usage (100% = 1 core)",
		Units:    "percentage",
		Fam:      "processes",
		Ctx:      "windows.processes_cpu_utilization",
		Type:     module.Stacked,
		Priority: prioProcessesCPUUtilization,
	}
	processesMemoryUsageChart = module.Chart{
		ID:       "processes_memory_usage",
		Title:    "Memory usage",
		Units:    "bytes",
		Fam:      "processes",
		Ctx:      "windows.processes_memory_usage",
		Type:     module.Stacked,
		Priority: prioProcessesMemoryUsage,
	}
	processesIOBytesChart = module.Chart{
		ID:       "processes_io_bytes",
		Title:    "Total of IO bytes (read, write, other)",
		Units:    "bytes/s",
		Fam:      "processes",
		Ctx:      "windows.processes_io_bytes",
		Type:     module.Stacked,
		Priority: prioProcessesIOBytes,
	}
	processesIOOperationsChart = module.Chart{
		ID:       "processes_io_operations",
		Title:    "Total of IO events (read, write, other)",
		Units:    "operations/s",
		Fam:      "processes",
		Ctx:      "windows.processes_io_operations",
		Type:     module.Stacked,
		Priority: prioProcessesIOOperations,
	}
	processesPageFaultsChart = module.Chart{
		ID:       "processes_page_faults",
		Title:    "Number of page faults",
		Units:    "pgfaults/s",
		Fam:      "processes",
		Ctx:      "windows.processes_page_faults",
		Type:     module.Stacked,
		Priority: prioProcessesPageFaults,
	}
	processesPageFileBytes = module.Chart{
		ID:       "processes_page_file_bytes",
		Title:    "Bytes used in page file(s)",
		Units:    "bytes",
		Fam:      "processes",
		Ctx:      "windows.processes_file_bytes",
		Type:     module.Stacked,
		Priority: prioProcessesPageFileBytes,
	}
	processesThreads = module.Chart{
		ID:       "processes_threads",
		Title:    "Active threads",
		Units:    "threads",
		Fam:      "processes",
		Ctx:      "windows.processes_threads",
		Type:     module.Stacked,
		Priority: prioProcessesThreads,
	}
	processesHandlesChart = module.Chart{
		ID:       "processes_handles",
		Title:    "Number of handles open",
		Units:    "handles",
		Fam:      "processes",
		Ctx:      "windows.processes_handles",
		Type:     module.Stacked,
		Priority: prioProcessesHandles,
	}
)

// .NET
var (
	netFrameworkCLRExceptionsChartsTmpl = module.Charts{
		netFrameworkCLRExceptionsThrown.Copy(),
		netFrameworkCLRExceptionsFilters.Copy(),
		netFrameworkCLRExceptionsFinallys.Copy(),
		netFrameworkCLRExceptionsThrowToCatchDepth.Copy(),
	}

	netFrameworkCLRInteropChartsTmpl = module.Charts{
		netFrameworkCLRInteropCOMCallableWrapper.Copy(),
		netFrameworkCLRInteropMarshalling.Copy(),
		netFrameworkCLRInteropStubsCreated.Copy(),
	}

	netFrameworkCLRJITChartsTmpl = module.Charts{
		netFrameworkCLRJITMethods.Copy(),
		netFrameworkCLRJITTime.Copy(),
		netFrameworkCLRJITStandardFailures.Copy(),
		netFrameworkCLRJITILBytes.Copy(),
	}

	netFrameworkCLRLoadingChartsTmpl = module.Charts{
		netFrameworkCLRLoadingLoaderHeapSize.Copy(),
		netFrameworkCLRLoadingAppDomainsLoaded.Copy(),
		netFrameworkCLRLoadingAppDomainsUnloaded.Copy(),
		netFrameworkCLRLoadingAssembliesLoaded.Copy(),
		netFrameworkCLRLoadingClassesLoaded.Copy(),
		netFrameworkCLRLoadingClassLoadFailure.Copy(),
	}

	netFrameworkCLRLocksAndThreadsChartsTmpl = module.Charts{
		netFrameworkCLRLockAndThreadsQueueLength.Copy(),
		netFrameworkCLRLockAndThreadsCurrentLogicalThreads.Copy(),
		netFrameworkCLRLockAndThreadsCurrentPhysicalThreads.Copy(),
		netFrameworkCLRLockAndThreadsRecognizedThreads.Copy(),
		netFrameworkCLRLockAndThreadsContentions.Copy(),
	}

	netFrameworkCLRMemoryChartsTmpl = module.Charts{
		netFrameworkCLRMemoryAllocatedBytes.Copy(),
		netFrameworkCLRMemoryFinalizationSurvivors.Copy(),
		netFrameworkCLRMemoryHeapSize.Copy(),
		netFrameworkCLRMemoryPromoted.Copy(),
		netFrameworkCLRMemoryNumberGCHandles.Copy(),
		netFrameworkCLRMemoryCollections.Copy(),
		netFrameworkCLRMemoryInducedGC.Copy(),
		netFrameworkCLRMemoryNumberPinnedObjects.Copy(),
		netFrameworkCLRMemoryNumberSinkBlocksInUse.Copy(),
		netFrameworkCLRMemoryCommitted.Copy(),
		netFrameworkCLRMemoryReserved.Copy(),
		netFrameworkCLRMemoryGCTime.Copy(),
	}

	netFrameworkCLRRemotingChartsTmpl = module.Charts{
		netFrameworkCLRRemotingChannels.Copy(),
		netFrameworkCLRRemotingContextBoundClassesLoaded.Copy(),
		netFrameworkCLRRemotingContextBoundObjects.Copy(),
		netFrameworkCLRRemotingContextProxies.Copy(),
		netFrameworkCLRRemotingContexts.Copy(),
		netFrameworkCLRRemotingCalls.Copy(),
	}

	netFrameworkCLRSecurityChartsTmpl = module.Charts{
		netFrameworkCLRSecurityLinkTimeChecks.Copy(),
		netFrameworkCLRSecurityChecksTime.Copy(),
		netFrameworkCLRSecurityStackWalkDepth.Copy(),
		netFrameworkCLRSecurityRuntimeChecks.Copy(),
	}

	// Exceptions
	netFrameworkCLRExceptionsThrown = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrexception_thrown",
		Title:      "Thrown exceptions",
		Units:      "exceptions/s",
		Fam:        "exceptions",
		Ctx:        "netframework.clrexception_thrown",
		Priority:   prioNETFrameworkCLRExceptionsThrown,
		Dims: module.Dims{
			{ID: "netframework_%s_clrexception_thrown_total", Name: "exceptions", Algo: module.Incremental},
		},
	}
	netFrameworkCLRExceptionsFilters = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrexception_filters",
		Title:      "Executed exception filters",
		Units:      "filters/s",
		Fam:        "exceptions",
		Ctx:        "netframework.clrexception_filters",
		Priority:   prioNETFrameworkCLRExceptionsFilters,
		Dims: module.Dims{
			{ID: "netframework_%s_clrexception_filters_total", Name: "filters", Algo: module.Incremental},
		},
	}
	netFrameworkCLRExceptionsFinallys = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrexception_finallys",
		Title:      "Executed finally blocks",
		Units:      "finallys/s",
		Fam:        "exceptions",
		Ctx:        "netframework.clrexception_finallys",
		Priority:   prioNETFrameworkCLRExceptionsFinallys,
		Dims: module.Dims{
			{ID: "netframework_%s_clrexception_finallys_total", Name: "finallys", Algo: module.Incremental},
		},
	}
	netFrameworkCLRExceptionsThrowToCatchDepth = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrexception_throw_to_catch_depth",
		Title:      "Traversed stack frames",
		Units:      "stack_frames/s",
		Fam:        "exceptions",
		Ctx:        "netframework.clrexception_throw_to_catch_depth",
		Priority:   prioNETFrameworkCLRExceptionsThrowToCatchDepth,
		Dims: module.Dims{
			{ID: "netframework_%s_clrexception_throw_to_catch_depth_total", Name: "traversed", Algo: module.Incremental},
		},
	}

	// Interop
	netFrameworkCLRInteropCOMCallableWrapper = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrinterop_com_callable_wrappers",
		Title:      "COM callable wrappers (CCW)",
		Units:      "ccw/s",
		Fam:        "interop",
		Ctx:        "netframework.clrinterop_com_callable_wrappers",
		Priority:   prioNETFrameworkCLRInteropCOMCallableWrappers,
		Dims: module.Dims{
			{ID: "netframework_%s_clrinterop_com_callable_wrappers_total", Name: "com_callable_wrappers", Algo: module.Incremental},
		},
	}
	netFrameworkCLRInteropMarshalling = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrinterop_interop_marshalling",
		Title:      "Arguments and return values marshallings",
		Units:      "marshalling/s",
		Fam:        "interop",
		Ctx:        "netframework.clrinterop_interop_marshallings",
		Priority:   prioNETFrameworkCLRInteropMarshalling,
		Dims: module.Dims{
			{ID: "netframework_%s_clrinterop_interop_marshalling_total", Name: "marshallings", Algo: module.Incremental},
		},
	}
	netFrameworkCLRInteropStubsCreated = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrinterop_interop_stubs_created",
		Title:      "Created stubs",
		Units:      "stubs/s",
		Fam:        "interop",
		Ctx:        "netframework.clrinterop_interop_stubs_created",
		Priority:   prioNETFrameworkCLRInteropStubsCreated,
		Dims: module.Dims{
			{ID: "netframework_%s_clrinterop_interop_stubs_created_total", Name: "created", Algo: module.Incremental},
		},
	}

	// JIT
	netFrameworkCLRJITMethods = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrjit_methods",
		Title:      "JIT-compiled methods",
		Units:      "methods/s",
		Fam:        "jit",
		Ctx:        "netframework.clrjit_methods",
		Priority:   prioNETFrameworkCLRJITMethods,
		Dims: module.Dims{
			{ID: "netframework_%s_clrjit_methods_total", Name: "jit-compiled", Algo: module.Incremental},
		},
	}
	netFrameworkCLRJITTime = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrjit_time",
		Title:      "Time spent in JIT compilation",
		Units:      "percentage",
		Fam:        "jit",
		Ctx:        "netframework.clrjit_time",
		Priority:   prioNETFrameworkCLRJITTime,
		Dims: module.Dims{
			{ID: "netframework_%s_clrjit_time_percent", Name: "time"},
		},
	}
	netFrameworkCLRJITStandardFailures = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrjit_standard_failures",
		Title:      "JIT compiler failures",
		Units:      "failures/s",
		Fam:        "jit",
		Ctx:        "netframework.clrjit_standard_failures",
		Priority:   prioNETFrameworkCLRJITStandardFailures,
		Dims: module.Dims{
			{ID: "netframework_%s_clrjit_standard_failures_total", Name: "failures", Algo: module.Incremental},
		},
	}
	netFrameworkCLRJITILBytes = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrjit_il_bytes",
		Title:      "Compiled Microsoft intermediate language (MSIL) bytes",
		Units:      "bytes/s",
		Fam:        "jit",
		Ctx:        "netframework.clrjit_il_bytes",
		Priority:   prioNETFrameworkCLRJITILBytes,
		Dims: module.Dims{
			{ID: "netframework_%s_clrjit_il_bytes_total", Name: "compiled_msil", Algo: module.Incremental},
		},
	}

	// Loading
	netFrameworkCLRLoadingLoaderHeapSize = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrloading_loader_heap_size",
		Title:      "Memory committed by class loader",
		Units:      "bytes",
		Fam:        "loading",
		Ctx:        "netframework.clrloading_loader_heap_size",
		Priority:   prioNETFrameworkCLRLoadingLoaderHeapSize,
		Dims: module.Dims{
			{ID: "netframework_%s_clrloading_loader_heap_size_bytes", Name: "committed"},
		},
	}
	netFrameworkCLRLoadingAppDomainsLoaded = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrloading_appdomains_loaded",
		Title:      "Loaded application domains",
		Units:      "domain/s",
		Fam:        "loading",
		Ctx:        "netframework.clrloading_appdomains_loaded",
		Priority:   prioNETFrameworkCLRLoadingAppDomainsLoaded,
		Dims: module.Dims{
			{ID: "netframework_%s_clrloading_appdomains_loaded_total", Name: "loaded", Algo: module.Incremental},
		},
	}
	netFrameworkCLRLoadingAppDomainsUnloaded = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrloading_appdomains_unloaded",
		Title:      "Unloaded application domains",
		Units:      "domain/s",
		Fam:        "loading",
		Ctx:        "netframework.clrloading_appdomains_unloaded",
		Priority:   prioNETFrameworkCLRLoadingAppDomainsUnloaded,
		Dims: module.Dims{
			{ID: "netframework_%s_clrloading_appdomains_unloaded_total", Name: "unloaded", Algo: module.Incremental},
		},
	}
	netFrameworkCLRLoadingAssembliesLoaded = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrloading_assemblies_loaded",
		Title:      "Loaded assemblies",
		Units:      "assemblies/s",
		Fam:        "loading",
		Ctx:        "netframework.clrloading_assemblies_loaded",
		Priority:   prioNETFrameworkCLRLoadingAssembliesLoaded,
		Dims: module.Dims{
			{ID: "netframework_%s_clrloading_assemblies_loaded_total", Name: "loaded", Algo: module.Incremental},
		},
	}
	netFrameworkCLRLoadingClassesLoaded = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrloading_classes_loaded",
		Title:      "Loaded classes in all assemblies",
		Units:      "classes/s",
		Fam:        "loading",
		Ctx:        "netframework.clrloading_classes_loaded",
		Priority:   prioNETFrameworkCLRLoadingClassesLoaded,
		Dims: module.Dims{
			{ID: "netframework_%s_clrloading_classes_loaded_total", Name: "loaded", Algo: module.Incremental},
		},
	}
	netFrameworkCLRLoadingClassLoadFailure = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrloading_class_load_failure",
		Title:      "Class load failures",
		Units:      "failures/s",
		Fam:        "loading",
		Ctx:        "netframework.clrloading_class_load_failures",
		Priority:   prioNETFrameworkCLRLoadingClassLoadFailure,
		Dims: module.Dims{
			{ID: "netframework_%s_clrloading_class_load_failures_total", Name: "class_load", Algo: module.Incremental},
		},
	}

	// Lock and Threads
	netFrameworkCLRLockAndThreadsQueueLength = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrlocksandthreads_queue_length",
		Title:      "Threads waited to acquire a managed lock",
		Units:      "threads/s",
		Fam:        "locks threads",
		Ctx:        "netframework.clrlocksandthreads_queue_length",
		Priority:   prioNETFrameworkCLRLocksAndThreadsQueueLength,
		Dims: module.Dims{
			{ID: "netframework_%s_clrlocksandthreads_queue_length_total", Name: "threads", Algo: module.Incremental},
		},
	}
	netFrameworkCLRLockAndThreadsCurrentLogicalThreads = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrlocksandthreads_current_logical_threads",
		Title:      "Logical threads",
		Units:      "threads",
		Fam:        "locks threads",
		Ctx:        "netframework.clrlocksandthreads_current_logical_threads",
		Priority:   prioNETFrameworkCLRLocksAndThreadsCurrentLogicalThreads,
		Dims: module.Dims{
			{ID: "netframework_%s_clrlocksandthreads_current_logical_threads", Name: "logical"},
		},
	}
	netFrameworkCLRLockAndThreadsCurrentPhysicalThreads = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrlocksandthreads_current_physical_threads",
		Title:      "Physical threads",
		Units:      "threads",
		Fam:        "locks threads",
		Ctx:        "netframework.clrlocksandthreads_current_physical_threads",
		Priority:   prioNETFrameworkCLRLocksAndThreadsCurrentPhysicalThreads,
		Dims: module.Dims{
			{ID: "netframework_%s_clrlocksandthreads_physical_threads_current", Name: "physical"},
		},
	}
	netFrameworkCLRLockAndThreadsRecognizedThreads = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrlocksandthreads_recognized_threads",
		Title:      "Threads recognized by the runtime",
		Units:      "threads/s",
		Fam:        "locks threads",
		Ctx:        "netframework.clrlocksandthreads_recognized_threads",
		Priority:   prioNETFrameworkCLRLocksAndThreadsRecognizedThreads,
		Dims: module.Dims{
			{ID: "netframework_%s_clrlocksandthreads_recognized_threads_total", Name: "threads", Algo: module.Incremental},
		},
	}
	netFrameworkCLRLockAndThreadsContentions = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrlocksandthreads_contentions",
		Title:      "Fails to acquire a managed lock",
		Units:      "contentions/s",
		Fam:        "locks threads",
		Ctx:        "netframework.clrlocksandthreads_contentions",
		Priority:   prioNETFrameworkCLRLocksAndThreadsContentions,
		Dims: module.Dims{
			{ID: "netframework_%s_clrlocksandthreads_contentions_total", Name: "contentions", Algo: module.Incremental},
		},
	}

	// Memory
	netFrameworkCLRMemoryAllocatedBytes = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrmemory_allocated_bytes",
		Title:      "Memory allocated on the garbage collection heap",
		Units:      "bytes/s",
		Fam:        "memory",
		Ctx:        "netframework.clrmemory_allocated_bytes",
		Priority:   prioNETFrameworkCLRMemoryAllocatedBytes,
		Dims: module.Dims{
			{ID: "netframework_%s_clrmemory_allocated_bytes_total", Name: "allocated", Algo: module.Incremental},
		},
	}
	netFrameworkCLRMemoryFinalizationSurvivors = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrmemory_finalization_survivors",
		Title:      "Objects that survived garbage-collection",
		Units:      "objects",
		Fam:        "memory",
		Ctx:        "netframework.clrmemory_finalization_survivors",
		Priority:   prioNETFrameworkCLRMemoryFinalizationSurvivors,
		Dims: module.Dims{
			{ID: "netframework_%s_clrmemory_finalization_survivors", Name: "survived"},
		},
	}
	netFrameworkCLRMemoryHeapSize = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrmemory_heap_size",
		Title:      "Maximum bytes that can be allocated",
		Units:      "bytes",
		Fam:        "memory",
		Ctx:        "netframework.clrmemory_heap_size",
		Priority:   prioNETFrameworkCLRMemoryHeapSize,
		Dims: module.Dims{
			{ID: "netframework_%s_clrmemory_heap_size_bytes", Name: "heap"},
		},
	}
	netFrameworkCLRMemoryPromoted = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrmemory_promoted",
		Title:      "Memory promoted to the next generation",
		Units:      "bytes",
		Fam:        "memory",
		Ctx:        "netframework.clrmemory_promoted",
		Priority:   prioNETFrameworkCLRMemoryPromoted,
		Dims: module.Dims{
			{ID: "netframework_%s_clrmemory_promoted_bytes", Name: "promoted"},
		},
	}
	netFrameworkCLRMemoryNumberGCHandles = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrmemory_number_gc_handles",
		Title:      "Garbage collection handles",
		Units:      "handles",
		Fam:        "memory",
		Ctx:        "netframework.clrmemory_number_gc_handles",
		Priority:   prioNETFrameworkCLRMemoryNumberGCHandles,
		Dims: module.Dims{
			{ID: "netframework_%s_clrmemory_number_gc_handles", Name: "used"},
		},
	}
	netFrameworkCLRMemoryCollections = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrmemory_collections",
		Title:      "Garbage collections",
		Units:      "gc/s",
		Fam:        "memory",
		Ctx:        "netframework.clrmemory_collections",
		Priority:   prioNETFrameworkCLRMemoryCollections,
		Dims: module.Dims{
			{ID: "netframework_%s_clrmemory_collections_total", Name: "gc", Algo: module.Incremental},
		},
	}
	netFrameworkCLRMemoryInducedGC = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrmemory_induced_gc",
		Title:      "Garbage collections induced",
		Units:      "gc/s",
		Fam:        "memory",
		Ctx:        "netframework.clrmemory_induced_gc",
		Priority:   prioNETFrameworkCLRMemoryInducedGC,
		Dims: module.Dims{
			{ID: "netframework_%s_clrmemory_induced_gc_total", Name: "gc", Algo: module.Incremental},
		},
	}
	netFrameworkCLRMemoryNumberPinnedObjects = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrmemory_number_pinned_objects",
		Title:      "Pinned objects encountered",
		Units:      "objects",
		Fam:        "memory",
		Ctx:        "netframework.clrmemory_number_pinned_objects",
		Priority:   prioNETFrameworkCLRMemoryNumberPinnedObjects,
		Dims: module.Dims{
			{ID: "netframework_%s_clrmemory_number_pinned_objects", Name: "pinned"},
		},
	}
	netFrameworkCLRMemoryNumberSinkBlocksInUse = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrmemory_number_sink_blocks_in_use",
		Title:      "Synchronization blocks in use",
		Units:      "blocks",
		Fam:        "memory",
		Ctx:        "netframework.clrmemory_number_sink_blocks_in_use",
		Priority:   prioNETFrameworkCLRMemoryNumberSinkBlocksInUse,
		Dims: module.Dims{
			{ID: "netframework_%s_clrmemory_number_sink_blocksinuse", Name: "used"},
		},
	}
	netFrameworkCLRMemoryCommitted = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrmemory_committed",
		Title:      "Virtual memory committed by GC",
		Units:      "bytes",
		Fam:        "memory",
		Ctx:        "netframework.clrmemory_committed",
		Priority:   prioNETFrameworkCLRMemoryCommitted,
		Dims: module.Dims{
			{ID: "netframework_%s_clrmemory_committed_bytes", Name: "committed"},
		},
	}
	netFrameworkCLRMemoryReserved = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrmemory_reserved",
		Title:      "Virtual memory reserved by GC",
		Units:      "bytes",
		Fam:        "memory",
		Ctx:        "netframework.clrmemory_reserved",
		Priority:   prioNETFrameworkCLRMemoryReserved,
		Dims: module.Dims{
			{ID: "netframework_%s_clrmemory_reserved_bytes", Name: "reserved"},
		},
	}
	netFrameworkCLRMemoryGCTime = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrmemory_gc_time",
		Title:      "Time spent on GC",
		Units:      "percentage",
		Fam:        "memory",
		Ctx:        "netframework.clrmemory_gc_time",
		Priority:   prioNETFrameworkCLRMemoryGCTime,
		Dims: module.Dims{
			{ID: "netframework_%s_clrmemory_gc_time_percent", Name: "time"},
		},
	}

	// Remoting
	netFrameworkCLRRemotingChannels = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrremoting_channels",
		Title:      "Registered channels",
		Units:      "channels/s",
		Fam:        "remoting",
		Ctx:        "netframework.clrremoting_channels",
		Priority:   prioNETFrameworkCLRRemotingChannels,
		Dims: module.Dims{
			{ID: "netframework_%s_clrremoting_channels_total", Name: "registered", Algo: module.Incremental},
		},
	}
	netFrameworkCLRRemotingContextBoundClassesLoaded = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrremoting_context_bound_classes_loaded",
		Title:      "Loaded context-bound classes",
		Units:      "classes",
		Fam:        "remoting",
		Ctx:        "netframework.clrremoting_context_bound_classes_loaded",
		Priority:   prioNETFrameworkCLRRemotingContextBoundClassesLoaded,
		Dims: module.Dims{
			{ID: "netframework_%s_clrremoting_context_bound_classes_loaded", Name: "loaded"},
		},
	}
	netFrameworkCLRRemotingContextBoundObjects = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrremoting_context_bound_objects",
		Title:      "Allocated context-bound objects",
		Units:      "objects/s",
		Fam:        "remoting",
		Ctx:        "netframework.clrremoting_context_bound_objects",
		Priority:   prioNETFrameworkCLRRemotingContextBoundObjects,
		Dims: module.Dims{
			{ID: "netframework_%s_clrremoting_context_bound_objects_total", Name: "allocated", Algo: module.Incremental},
		},
	}
	netFrameworkCLRRemotingContextProxies = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrremoting_context_proxies",
		Title:      "Remoting proxy objects",
		Units:      "objects/s",
		Fam:        "remoting",
		Ctx:        "netframework.clrremoting_context_proxies",
		Priority:   prioNETFrameworkCLRRemotingContextProxies,
		Dims: module.Dims{
			{ID: "netframework_%s_clrremoting_context_proxies_total", Name: "objects", Algo: module.Incremental},
		},
	}
	netFrameworkCLRRemotingContexts = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrremoting_contexts",
		Title:      "Total of remoting contexts",
		Units:      "contexts",
		Fam:        "remoting",
		Ctx:        "netframework.clrremoting_contexts",
		Priority:   prioNETFrameworkCLRRemotingContexts,
		Dims: module.Dims{
			{ID: "netframework_%s_clrremoting_contexts", Name: "contexts"},
		},
	}
	netFrameworkCLRRemotingCalls = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrremoting_calls",
		Title:      "Remote Procedure Calls (RPC) invoked",
		Units:      "calls/s",
		Fam:        "remoting",
		Ctx:        "netframework.clrremoting_remote_calls",
		Priority:   prioNETFrameworkCLRRemotingRemoteCalls,
		Dims: module.Dims{
			{ID: "netframework_%s_clrremoting_remote_calls_total", Name: "rpc", Algo: module.Incremental},
		},
	}

	// Security
	netFrameworkCLRSecurityLinkTimeChecks = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrsecurity_link_time_checks",
		Title:      "Link-time code access security checks",
		Units:      "checks/s",
		Fam:        "security",
		Ctx:        "netframework.clrsecurity_link_time_checks",
		Priority:   prioNETFrameworkCLRSecurityLinkTimeChecks,
		Dims: module.Dims{
			{ID: "netframework_%s_clrsecurity_link_time_checks_total", Name: "linktime", Algo: module.Incremental},
		},
	}
	netFrameworkCLRSecurityChecksTime = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrsecurity_checks_time",
		Title:      "Time spent performing runtime code access security checks",
		Units:      "percentage",
		Fam:        "security",
		Ctx:        "netframework.clrsecurity_checks_time",
		Priority:   prioNETFrameworkCLRSecurityRTChecksTime,
		Dims: module.Dims{
			{ID: "netframework_%s_clrsecurity_checks_time_percent", Name: "time"},
		},
	}
	netFrameworkCLRSecurityStackWalkDepth = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrsecurity_stack_walk_depth",
		Title:      "Depth of the stack",
		Units:      "depth",
		Fam:        "security",
		Ctx:        "netframework.clrsecurity_stack_walk_depth",
		Priority:   prioNETFrameworkCLRSecurityStackWalkDepth,
		Dims: module.Dims{
			{ID: "netframework_%s_clrsecurity_stack_walk_depth", Name: "stack"},
		},
	}
	netFrameworkCLRSecurityRuntimeChecks = module.Chart{
		OverModule: "netframework",
		ID:         "netframework_%s_clrsecurity_runtime_checks",
		Title:      "Runtime code access security checks performed",
		Units:      "checks/s",
		Fam:        "security",
		Ctx:        "netframework.clrsecurity_runtime_checks",
		Priority:   prioNETFrameworkCLRSecurityRuntimeChecks,
		Dims: module.Dims{
			{ID: "netframework_%s_clrsecurity_runtime_checks_total", Name: "runtime", Algo: module.Incremental},
		},
	}
)

// Service
var (
	serviceChartsTmpl = module.Charts{
		serviceStateChartTmpl.Copy(),
		serviceStatusChartTmpl.Copy(),
	}
	serviceStateChartTmpl = module.Chart{
		ID:       "service_%s_state",
		Title:    "Service state",
		Units:    "state",
		Fam:      "services",
		Ctx:      "windows.service_state",
		Priority: prioServiceState,
		Dims: module.Dims{
			{ID: "service_%s_state_running", Name: "running"},
			{ID: "service_%s_state_stopped", Name: "stopped"},
			{ID: "service_%s_state_start_pending", Name: "start_pending"},
			{ID: "service_%s_state_stop_pending", Name: "stop_pending"},
			{ID: "service_%s_state_continue_pending", Name: "continue_pending"},
			{ID: "service_%s_state_pause_pending", Name: "pause_pending"},
			{ID: "service_%s_state_paused", Name: "paused"},
			{ID: "service_%s_state_unknown", Name: "unknown"},
		},
	}
	serviceStatusChartTmpl = module.Chart{
		ID:       "service_%s_status",
		Title:    "Service status",
		Units:    "status",
		Fam:      "services",
		Ctx:      "windows.service_status",
		Priority: prioServiceStatus,
		Dims: module.Dims{
			{ID: "service_%s_status_ok", Name: "ok"},
			{ID: "service_%s_status_error", Name: "error"},
			{ID: "service_%s_status_unknown", Name: "unknown"},
			{ID: "service_%s_status_degraded", Name: "degraded"},
			{ID: "service_%s_status_pred_fail", Name: "pred_fail"},
			{ID: "service_%s_status_starting", Name: "starting"},
			{ID: "service_%s_status_stopping", Name: "stopping"},
			{ID: "service_%s_status_service", Name: "service"},
			{ID: "service_%s_status_stressed", Name: "stressed"},
			{ID: "service_%s_status_nonrecover", Name: "nonrecover"},
			{ID: "service_%s_status_no_contact", Name: "no_contact"},
			{ID: "service_%s_status_lost_comm", Name: "lost_comm"},
		},
	}
)

// HyperV
var (
	hypervChartsTmpl = module.Charts{
		hypervVirtualMachinesHealthChart.Copy(),
		hypervRootPartitionDeviceSpacePagesChart.Copy(),
		hypervRootPartitionGPASpacePagesChart.Copy(),
		hypervRootPartitionGPASpaceModificationsChart.Copy(),
		hypervRootPartitionAttachedDevicesChart.Copy(),
		hypervRootPartitionDepositedPagesChart.Copy(),
		hypervRootPartitionSkippedInterrupts.Copy(),
		hypervRootPartitionDeviceDMAErrorsChart.Copy(),
		hypervRootPartitionDeviceInterruptErrorsChart.Copy(),
		hypervRootPartitionDeviceInterruptThrottledEventsChart.Copy(),
		hypervRootPartitionIOTlbFlushChart.Copy(),
		hypervRootPartitionAddressSpaceChart.Copy(),
		hypervRootPartitionVirtualTlbFlushEntries.Copy(),
		hypervRootPartitionVirtualTlbPages.Copy(),
	}
	hypervVirtualMachinesHealthChart = module.Chart{
		OverModule: "hyperv",
		ID:         "health_vm",
		Title:      "Virtual machines health status",
		Units:      "vms",
		Fam:        "vms health",
		Ctx:        "hyperv.vms_health",
		Priority:   prioHypervVMHealth,
		Type:       module.Stacked,
		Dims: module.Dims{
			{ID: "hyperv_health_ok", Name: "ok"},
			{ID: "hyperv_health_critical", Name: "critical"},
		},
	}
	hypervRootPartitionDeviceSpacePagesChart = module.Chart{
		OverModule: "hyperv",
		ID:         "root_partition_device_space_pages",
		Title:      "Root partition pages in the device space",
		Units:      "pages",
		Fam:        "root partition",
		Ctx:        "hyperv.root_partition_device_space_pages",
		Priority:   prioHypervRootPartitionDeviceSpacePages,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_4K_device_pages", Name: "4K"},
			{ID: "hyperv_root_partition_2M_device_pages", Name: "2M"},
			{ID: "hyperv_root_partition_1G_device_pages", Name: "1G"},
		},
	}
	hypervRootPartitionGPASpacePagesChart = module.Chart{
		OverModule: "hyperv",
		ID:         "root_partition_gpa_space_pages",
		Title:      "Root partition pages in the GPA space",
		Units:      "pages",
		Fam:        "root partition",
		Ctx:        "windows.hyperv_root_partition_gpa_space_pages",
		Priority:   prioHypervRootPartitionGPASpacePages,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_4K_gpa_pages", Name: "4K"},
			{ID: "hyperv_root_partition_2M_gpa_pages", Name: "2M"},
			{ID: "hyperv_root_partition_1G_gpa_pages", Name: "1G"},
		},
	}
	hypervRootPartitionGPASpaceModificationsChart = module.Chart{
		OverModule: "hyperv",
		ID:         "root_partition_gpa_space_modifications",
		Title:      "Root partition GPA space modifications",
		Units:      "modifications/s",
		Fam:        "root partition",
		Ctx:        "hyperv.root_partition_gpa_space_modifications",
		Priority:   prioHypervRootPartitionGPASpaceModifications,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_gpa_space_modifications", Name: "gpa", Algo: module.Incremental},
		},
	}
	hypervRootPartitionAttachedDevicesChart = module.Chart{
		OverModule: "hyperv",
		ID:         "root_partition_attached_devices",
		Title:      "Root partition attached devices",
		Units:      "devices",
		Fam:        "root partition",
		Ctx:        "hyperv.root_partition_attached_devices",
		Priority:   prioHypervRootPartitionAttachedDevices,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_attached_devices", Name: "attached"},
		},
	}
	hypervRootPartitionDepositedPagesChart = module.Chart{
		OverModule: "hyperv",
		ID:         "root_partition_deposited_pages",
		Title:      "Root partition deposited pages",
		Units:      "pages",
		Fam:        "root partition",
		Ctx:        "hyperv.root_partition_deposited_pages",
		Priority:   prioHypervRootPartitionDepositedPages,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_deposited_pages", Name: "deposited"},
		},
	}
	hypervRootPartitionSkippedInterrupts = module.Chart{
		OverModule: "hyperv",
		ID:         "root_partition_skipped_interrupts",
		Title:      "Root partition skipped interrupts",
		Units:      "interrupts",
		Fam:        "root partition",
		Ctx:        "hyperv.root_partition_skipped_interrupts",
		Priority:   prioHypervRootPartitionSkippedInterrupts,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_physical_pages_allocated", Name: "skipped"},
		},
	}
	hypervRootPartitionDeviceDMAErrorsChart = module.Chart{
		OverModule: "hyperv",
		ID:         "root_partition_device_dma_errors",
		Title:      "Root partition illegal DMA requests",
		Units:      "requests",
		Fam:        "root partition",
		Ctx:        "hyperv.root_partition_device_dma_errors",
		Priority:   prioHypervRootPartitionDeviceDMAErrors,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_deposited_pages", Name: "illegal_dma"},
		},
	}
	hypervRootPartitionDeviceInterruptErrorsChart = module.Chart{
		OverModule: "hyperv",
		ID:         "partition_device_interrupt_errors",
		Title:      "Root partition illegal interrupt requests",
		Units:      "requests",
		Fam:        "root partition",
		Ctx:        "hyperv.root_partition_device_interrupt_errors",
		Priority:   prioHypervRootPartitionDeviceInterruptErrors,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_device_interrupt_errors", Name: "illegal_interrupt"},
		},
	}
	hypervRootPartitionDeviceInterruptThrottledEventsChart = module.Chart{
		OverModule: "hyperv",
		ID:         "root_partition_device_interrupt_throttle_events",
		Title:      "Root partition throttled interrupts",
		Units:      "events",
		Fam:        "root partition",
		Ctx:        "hyperv.root_partition_device_interrupt_throttle_events",
		Priority:   prioHypervRootPartitionDeviceInterruptThrottleEvents,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_device_interrupt_throttle_events", Name: "throttling"},
		},
	}
	hypervRootPartitionIOTlbFlushChart = module.Chart{
		OverModule: "hyperv",
		ID:         "root_partition_io_tbl_flush",
		Title:      "Root partition flushes of I/O TLBs",
		Units:      "flushes/s",
		Fam:        "root partition",
		Ctx:        "hyperv.root_partition_io_tlb_flush",
		Priority:   prioHypervRootPartitionIOTlbFlush,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_io_tlb_flush", Name: "flushes", Algo: module.Incremental},
		},
	}
	hypervRootPartitionAddressSpaceChart = module.Chart{
		OverModule: "hyperv",
		ID:         "root_partition_address_space",
		Title:      "Root partition address spaces in the virtual TLB",
		Units:      "address spaces",
		Fam:        "root partition",
		Ctx:        "hyperv.root_partition_address_space",
		Priority:   prioHypervRootPartitionAddressSpace,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_address_spaces", Name: "address_spaces"},
		},
	}
	hypervRootPartitionVirtualTlbFlushEntries = module.Chart{
		OverModule: "hyperv",
		ID:         "root_partition_virtual_tbl_flush_entries",
		Title:      "Root partition flushes of the entire virtual TLB",
		Units:      "flushes/s",
		Fam:        "root partition",
		Ctx:        "hyperv.root_partition_virtual_tlb_flush_entries",
		Priority:   prioHypervRootPartitionVirtualTlbFlushEntires,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_virtual_tlb_flush_entires", Name: "flushes", Algo: module.Incremental},
		},
	}
	hypervRootPartitionVirtualTlbPages = module.Chart{
		OverModule: "hyperv",
		ID:         "root_partition_virtual_tlb_pages",
		Title:      "Root partition pages used by the virtual TLB",
		Units:      "pages",
		Fam:        "root partition",
		Ctx:        "hyperv.root_partition_virtual_tlb_pages",
		Priority:   prioHypervRootPartitionVirtualTlbPages,
		Dims: module.Dims{
			{ID: "hyperv_root_partition_virtual_tlb_pages", Name: "used"},
		},
	}
)

// HyperV VM Memory
var (
	hypervVMChartsTemplate = module.Charts{
		hypervHypervVMCPUUsageChartTmpl.Copy(),
		hypervHypervVMMemoryPhysicalChartTmpl.Copy(),
		hypervHypervVMMemoryPhysicalGuestVisibleChartTmpl.Copy(),
		hypervHypervVMMemoryPressureCurrentChartTmpl.Copy(),
		hypervVIDPhysicalPagesAllocatedChartTmpl.Copy(),
		hypervVIDRemotePhysicalPagesChartTmpl.Copy(),
	}
	hypervHypervVMCPUUsageChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vm_%s_cpu_usage",
		Title:      "VM CPU usage (100% = 1 core)",
		Units:      "percentage",
		Fam:        "vm cpu",
		Ctx:        "hyperv.vm_cpu_usage",
		Priority:   prioHypervVMCPUUsage,
		Type:       module.Stacked,
		Dims: module.Dims{
			{ID: "hyperv_vm_%s_cpu_guest_run_time", Name: "guest", Div: 1e5, Algo: module.Incremental},
			{ID: "hyperv_vm_%s_cpu_hypervisor_run_time", Name: "hypervisor", Div: 1e5, Algo: module.Incremental},
			{ID: "hyperv_vm_%s_cpu_remote_run_time", Name: "remote", Div: 1e5, Algo: module.Incremental},
		},
	}
	hypervHypervVMMemoryPhysicalChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vm_%s_memory_physical",
		Title:      "VM assigned memory",
		Units:      "MiB",
		Fam:        "vm mem",
		Ctx:        "hyperv.vm_memory_physical",
		Priority:   prioHypervVMMemoryPhysical,
		Dims: module.Dims{
			{ID: "hyperv_vm_%s_memory_physical", Name: "assigned_memory"},
		},
	}
	hypervHypervVMMemoryPhysicalGuestVisibleChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vm_%s_memory_physical_guest_visible",
		Title:      "VM guest visible memory",
		Units:      "MiB",
		Fam:        "vm mem",
		Ctx:        "hyperv.vm_memory_physical_guest_visible",
		Priority:   prioHypervVMMemoryPhysicalGuestVisible,
		Dims: module.Dims{
			{ID: "hyperv_vm_%s_memory_physical_guest_visible", Name: "visible_memory"},
		},
	}
	hypervHypervVMMemoryPressureCurrentChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vm_%s_memory_pressure_current",
		Title:      "VM current pressure",
		Units:      "percentage",
		Fam:        "vm mem",
		Ctx:        "hyperv.vm_memory_pressure_current",
		Priority:   prioHypervVMMemoryPressureCurrent,
		Dims: module.Dims{
			{ID: "hyperv_vm_%s_memory_pressure_current", Name: "pressure"},
		},
	}
	hypervVIDPhysicalPagesAllocatedChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vm_%s_vid_physical_pages_allocated",
		Title:      "VM physical pages allocated",
		Units:      "pages",
		Fam:        "vm mem",
		Ctx:        "hyperv.vm_vid_physical_pages_allocated",
		Priority:   prioHypervVIDPhysicalPagesAllocated,
		Dims: module.Dims{
			{ID: "hyperv_vid_%s_physical_pages_allocated", Name: "allocated"},
		},
	}
	hypervVIDRemotePhysicalPagesChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vm_%s_remote_physical_pages",
		Title:      "VM physical pages not allocated from the preferred NUMA node",
		Units:      "pages",
		Fam:        "vm mem",
		Ctx:        "hyperv.vm_vid_remote_physical_pages",
		Priority:   prioHypervVIDRemotePhysicalPages,
		Dims: module.Dims{
			{ID: "hyperv_vid_%s_remote_physical_pages", Name: "remote_physical"},
		},
	}
)

// HyperV VM storage device
var (
	hypervVMDeviceChartsTemplate = module.Charts{
		hypervVMDeviceIOChartTmpl.Copy(),
		hypervVMDeviceIOPSChartTmpl.Copy(),
		hypervVMDeviceErrorCountChartTmpl.Copy(),
	}
	hypervVMDeviceIOChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vm_device_%s_bytes_read",
		Title:      "VM storage device IO",
		Units:      "bytes/s",
		Fam:        "vm disk",
		Ctx:        "hyperv.vm_device_bytes",
		Priority:   prioHypervVMDeviceBytes,
		Type:       module.Area,
		Dims: module.Dims{
			{ID: "hyperv_vm_device_%s_bytes_read", Name: "read", Algo: module.Incremental},
			{ID: "hyperv_vm_device_%s_bytes_written", Name: "written", Algo: module.Incremental},
		},
	}
	hypervVMDeviceIOPSChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vm_device_%s_operation_read",
		Title:      "VM storage device IOPS",
		Units:      "operations/s",
		Fam:        "vm disk",
		Ctx:        "hyperv.vm_device_operations",
		Priority:   prioHypervVMDeviceOperations,
		Dims: module.Dims{
			{ID: "hyperv_vm_device_%s_operations_read", Name: "read", Algo: module.Incremental},
			{ID: "hyperv_vm_device_%s_operations_written", Name: "write", Algo: module.Incremental},
		},
	}
	hypervVMDeviceErrorCountChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vm_device_%s_error_count",
		Title:      "VM storage device errors",
		Units:      "errors/s",
		Fam:        "vm disk",
		Ctx:        "hyperv.vm_device_errors",
		Priority:   prioHypervVMDeviceErrors,
		Dims: module.Dims{
			{ID: "hyperv_vm_device_%s_error_count", Name: "errors", Algo: module.Incremental},
		},
	}
)

// HyperV VM network interface
var (
	hypervVMInterfaceChartsTemplate = module.Charts{
		hypervVMInterfaceTrafficChartTmpl.Copy(),
		hypervVMInterfacePacketsChartTmpl.Copy(),
		hypervVMInterfacePacketsDroppedChartTmpl.Copy(),
	}

	hypervVMInterfaceTrafficChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vm_interface_%s_bytes",
		Title:      "VM interface traffic",
		Units:      "bytes/s",
		Fam:        "vm net",
		Ctx:        "hyperv.vm_interface_bytes",
		Priority:   prioHypervVMInterfaceBytes,
		Type:       module.Area,
		Dims: module.Dims{
			{ID: "hyperv_vm_interface_%s_bytes_received", Name: "received", Algo: module.Incremental},
			{ID: "hyperv_vm_interface_%s_bytes_sent", Name: "sent", Algo: module.Incremental},
		},
	}
	hypervVMInterfacePacketsChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vm_interface_%s_packets",
		Title:      "VM interface packets",
		Units:      "packets/s",
		Fam:        "vm net",
		Ctx:        "hyperv.vm_interface_packets",
		Priority:   prioHypervVMInterfacePackets,
		Dims: module.Dims{
			{ID: "hyperv_vm_interface_%s_packets_received", Name: "received", Algo: module.Incremental},
			{ID: "hyperv_vm_interface_%s_packets_sent", Name: "sent", Algo: module.Incremental},
		},
	}
	hypervVMInterfacePacketsDroppedChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vm_interface_%s_packets_dropped",
		Title:      "VM interface packets dropped",
		Units:      "drops/s",
		Fam:        "vm net",
		Ctx:        "hyperv.vm_interface_packets_dropped",
		Priority:   prioHypervVMInterfacePacketsDropped,
		Dims: module.Dims{
			{ID: "hyperv_vm_interface_%s_packets_incoming_dropped", Name: "incoming", Algo: module.Incremental},
			{ID: "hyperv_vm_interface_%s_packets_outgoing_dropped", Name: "outgoing", Algo: module.Incremental},
		},
	}
)

// HyperV Virtual Switch
var (
	hypervVswitchChartsTemplate = module.Charts{
		hypervVswitchTrafficChartTmpl.Copy(),
		hypervVswitchPacketsChartTmpl.Copy(),
		hypervVswitchDirectedPacketsChartTmpl.Copy(),
		hypervVswitchBroadcastPacketsChartTmpl.Copy(),
		hypervVswitchMulticastPacketsChartTmpl.Copy(),
		hypervVswitchDroppedPacketsChartTmpl.Copy(),
		hypervVswitchExtensionDroppedPacketsChartTmpl.Copy(),
		hypervVswitchPacketsFloodedTotalChartTmpl.Copy(),
		hypervVswitchLearnedMACAddressChartTmpl.Copy(),
		hypervVswitchPurgedMACAddressChartTmpl.Copy(),
	}

	hypervVswitchTrafficChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vswitch_%s_traffic",
		Title:      "Virtual switch traffic",
		Units:      "bytes/s",
		Fam:        "vswitch traffic",
		Ctx:        "hyperv.vswitch_bytes",
		Priority:   prioHypervVswitchTrafficTotal,
		Type:       module.Area,
		Dims: module.Dims{
			{ID: "hyperv_vswitch_%s_bytes_received_total", Name: "received", Algo: module.Incremental},
			{ID: "hyperv_vswitch_%s_bytes_sent_total", Name: "sent", Algo: module.Incremental},
		},
	}
	hypervVswitchPacketsChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vswitch_%s_packets",
		Title:      "Virtual switch packets",
		Units:      "packets/s",
		Fam:        "vswitch packets",
		Ctx:        "hyperv.vswitch_packets",
		Priority:   prioHypervVswitchPackets,
		Dims: module.Dims{
			{ID: "hyperv_vswitch_%s_packets_received_total", Name: "received", Algo: module.Incremental},
			// FIXME: https://github.com/prometheus-community/windows_exporter/pull/1201
			//{ID: "hyperv_vswitch_%s_packets_sent_total", Name: "sent", Algo: module.Incremental},
		},
	}
	hypervVswitchDirectedPacketsChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vswitch_%s_directed_packets",
		Title:      "Virtual switch directed packets",
		Units:      "packets/s",
		Fam:        "vswitch packets",
		Ctx:        "hyperv.vswitch_directed_packets",
		Priority:   prioHypervVswitchDirectedPackets,
		Dims: module.Dims{
			{ID: "hyperv_vswitch_%s_directed_packets_received_total", Name: "received", Algo: module.Incremental},
			{ID: "hyperv_vswitch_%s_directed_packets_send_total", Name: "sent", Algo: module.Incremental},
		},
	}
	hypervVswitchBroadcastPacketsChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vswitch_%s_broadcast_packets",
		Title:      "Virtual switch broadcast packets",
		Units:      "packets/s",
		Fam:        "vswitch packets",
		Ctx:        "hyperv.vswitch_broadcast_packets",
		Priority:   prioHypervVswitchBroadcastPackets,
		Dims: module.Dims{
			{ID: "hyperv_vswitch_%s_broadcast_packets_received_total", Name: "received", Algo: module.Incremental},
			{ID: "hyperv_vswitch_%s_broadcast_packets_sent_total", Name: "sent", Algo: module.Incremental},
		},
	}
	hypervVswitchMulticastPacketsChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vswitch_%s_multicast_packets",
		Title:      "Virtual switch multicast packets",
		Units:      "packets/s",
		Fam:        "vswitch packets",
		Ctx:        "hyperv.vswitch_multicast_packets",
		Priority:   prioHypervVswitchMulticastPackets,
		Dims: module.Dims{
			{ID: "hyperv_vswitch_%s_multicast_packets_received_total", Name: "received", Algo: module.Incremental},
			{ID: "hyperv_vswitch_%s_multicast_packets_sent_total", Name: "sent", Algo: module.Incremental},
		},
	}
	hypervVswitchDroppedPacketsChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vswitch_%s_dropped_packets",
		Title:      "Virtual switch dropped packets",
		Units:      "drops/s",
		Fam:        "vswitch drops",
		Ctx:        "hyperv.vswitch_dropped_packets",
		Priority:   prioHypervVswitchDroppedPackets,
		Dims: module.Dims{
			{ID: "hyperv_vswitch_%s_dropped_packets_incoming_total", Name: "incoming", Algo: module.Incremental},
			{ID: "hyperv_vswitch_%s_dropped_packets_outcoming_total", Name: "outgoing", Algo: module.Incremental},
		},
	}
	hypervVswitchExtensionDroppedPacketsChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vswitch_%s_extensions_dropped_packets_incoming",
		Title:      "Virtual switch extensions dropped packets",
		Units:      "drops/s",
		Fam:        "vswitch drops",
		Ctx:        "hyperv.vswitch_extensions_dropped_packets",
		Priority:   prioHypervVswitchExtensionsDroppedPackets,
		Dims: module.Dims{
			{ID: "hyperv_vswitch_%s_extensions_dropped_packets_incoming_total", Name: "incoming", Algo: module.Incremental},
			{ID: "hyperv_vswitch_%s_extensions_dropped_packets_outcoming_total", Name: "outgoing", Algo: module.Incremental},
		},
	}
	hypervVswitchPacketsFloodedTotalChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vswitch_%s_packets_flooded",
		Title:      "Virtual switch flooded packets",
		Units:      "packets/s",
		Fam:        "vswitch flood",
		Ctx:        "hyperv.vswitch_packets_flooded",
		Priority:   prioHypervVswitchPacketsFlooded,
		Dims: module.Dims{
			{ID: "hyperv_vswitch_%s_packets_flooded_total", Name: "flooded", Algo: module.Incremental},
		},
	}
	hypervVswitchLearnedMACAddressChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vswitch_%s_learned_mac_addresses",
		Title:      "Virtual switch learned MAC addresses",
		Units:      "mac addresses/s",
		Fam:        "vswitch mac addresses",
		Ctx:        "hyperv.vswitch_learned_mac_addresses",
		Priority:   prioHypervVswitchLearnedMACAddresses,
		Dims: module.Dims{
			{ID: "hyperv_vswitch_%s_learned_mac_addresses_total", Name: "learned", Algo: module.Incremental},
		},
	}
	hypervVswitchPurgedMACAddressChartTmpl = module.Chart{
		OverModule: "hyperv",
		ID:         "vswitch_%s_purged_mac_addresses",
		Title:      "Virtual switch purged MAC addresses",
		Units:      "mac addresses/s",
		Fam:        "vswitch mac addresses",
		Ctx:        "hyperv.vswitch_purged_mac_addresses",
		Priority:   prioHypervVswitchPurgeMACAddress,
		Dims: module.Dims{
			{ID: "hyperv_vswitch_%s_purged_mac_addresses_total", Name: "purged", Algo: module.Incremental},
		},
	}
)

// Collectors
var (
	collectorChartsTmpl = module.Charts{
		collectorDurationChartTmpl.Copy(),
		collectorStatusChartTmpl.Copy(),
	}
	collectorDurationChartTmpl = module.Chart{
		ID:       "collector_%s_duration",
		Title:    "Duration of a data collection",
		Units:    "seconds",
		Fam:      "collection",
		Ctx:      "windows.collector_duration",
		Priority: prioCollectorDuration,
		Dims: module.Dims{
			{ID: "collector_%s_duration", Name: "duration", Div: precision},
		},
	}
	collectorStatusChartTmpl = module.Chart{
		ID:       "collector_%s_status",
		Title:    "Status of a data collection",
		Units:    "status",
		Fam:      "collection",
		Ctx:      "windows.collector_status",
		Priority: prioCollectorStatus,
		Dims: module.Dims{
			{ID: "collector_%s_status_success", Name: "success"},
			{ID: "collector_%s_status_fail", Name: "fail"},
		},
	}
)

func (w *Windows) addCPUCharts() {
	charts := cpuCharts.Copy()

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

func (w *Windows) addCPUCoreCharts(core string) {
	charts := cpuCoreChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, core)
		chart.Labels = []module.Label{
			{Key: "core", Value: core},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, core)
		}
	}

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

func (w *Windows) removeCPUCoreCharts(core string) {
	px := fmt.Sprintf("cpu_core_%s", core)
	w.removeCharts(px)
}

func (w *Windows) addMemoryCharts() {
	charts := memCharts.Copy()

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

func (w *Windows) addDiskCharts(disk string) {
	charts := diskChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, disk)
		chart.Labels = []module.Label{
			{Key: "disk", Value: disk},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, disk)
		}
	}

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

func (w *Windows) removeDiskCharts(disk string) {
	px := fmt.Sprintf("logical_disk_%s", disk)
	w.removeCharts(px)
}

func (w *Windows) addNICCharts(nic string) {
	charts := nicChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, nic)
		chart.Labels = []module.Label{
			{Key: "nic", Value: nic},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, nic)
		}
	}

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

func (w *Windows) removeNICCharts(nic string) {
	px := fmt.Sprintf("nic_%s", nic)
	w.removeCharts(px)
}

func (w *Windows) addTCPCharts() {
	charts := tcpCharts.Copy()

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

func (w *Windows) addOSCharts() {
	charts := osCharts.Copy()

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

func (w *Windows) addSystemCharts() {
	charts := systemCharts.Copy()

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

func (w *Windows) addLogonCharts() {
	charts := logonCharts.Copy()

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

func (w *Windows) addADFSCharts() {
	charts := adfsCharts.Copy()

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

func (w *Windows) addExchangeCharts() {
	charts := exchangeCharts.Copy()

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

func (w *Windows) addExchangeWorkloadCharts(name string) {
	charts := exchangeWorkloadChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, name)
		chart.Labels = []module.Label{
			{Key: "workload", Value: name},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, name)
		}
	}

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

func (w *Windows) removeExchangeWorkloadCharts(name string) {
	px := fmt.Sprintf("exchange_workload_%s", name)
	w.removeCharts(px)
}

func (w *Windows) addExchangeLDAPCharts(name string) {
	charts := exchangeLDAPChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, name)
		chart.Labels = []module.Label{
			{Key: "ldap_process", Value: name},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, name)
		}
	}

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

func (w *Windows) removeExchangeLDAPCharts(name string) {
	px := fmt.Sprintf("exchange_ldap_%s", name)
	w.removeCharts(px)
}

func (w *Windows) addExchangeHTTPProxyCharts(name string) {
	charts := exchangeHTTPProxyChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, name)
		chart.Labels = []module.Label{
			{Key: "http_proxy", Value: name},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, name)
		}
	}

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

func (w *Windows) removeExchangeHTTPProxyCharts(name string) {
	px := fmt.Sprintf("exchange_http_proxy_%s", name)
	w.removeCharts(px)
}

func (w *Windows) addThermalZoneCharts(zone string) {
	charts := thermalzoneChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, zone)
		chart.Labels = []module.Label{
			{Key: "thermalzone", Value: zone},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, zone)
		}
	}

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

func (w *Windows) removeThermalZoneCharts(zone string) {
	px := fmt.Sprintf("thermalzone_%s", zone)
	w.removeCharts(px)
}

func (w *Windows) addIISWebsiteCharts(website string) {
	charts := iisWebsiteChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, website)
		chart.Labels = []module.Label{
			{Key: "website", Value: website},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, website)
		}
	}

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

func (w *Windows) removeIIWebsiteSCharts(website string) {
	px := fmt.Sprintf("iis_website_%s", website)
	w.removeCharts(px)
}

func (w *Windows) addMSSQLDBCharts(instance string, dbname string) {
	charts := mssqlDatabaseChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, dbname, instance)
		chart.Labels = []module.Label{
			{Key: "mssql_instance", Value: instance},
			{Key: "database", Value: dbname},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, dbname, instance)
		}
	}

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

func (w *Windows) removeMSSQLDBCharts(instance string, dbname string) {
	px := fmt.Sprintf("mssql_db_%s_instance_%s", dbname, instance)
	w.removeCharts(px)
}

func (w *Windows) addMSSQLInstanceCharts(instance string) {
	charts := mssqlInstanceChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, instance)
		chart.Labels = []module.Label{
			{Key: "mssql_instance", Value: instance},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, instance)
		}
	}

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

func (w *Windows) removeMSSQLInstanceCharts(instance string) {
	px := fmt.Sprintf("mssql_instance_%s", instance)
	w.removeCharts(px)
}

func (w *Windows) addProcessesCharts() {
	charts := processesCharts.Copy()

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

func (w *Windows) addADCharts() {
	charts := adCharts.Copy()

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

func (w *Windows) addCertificateTemplateCharts(template string) {
	charts := adcsCertTemplateChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, template)
		chart.Labels = []module.Label{
			{Key: "cert_template", Value: template},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, template)
		}
	}

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

func (w *Windows) removeCertificateTemplateCharts(template string) {
	px := fmt.Sprintf("adcs_cert_template_%s", template)
	w.removeCharts(px)
}

func (w *Windows) addProcessToCharts(procID string) {
	for _, chart := range *w.Charts() {
		var dim *module.Dim
		switch chart.ID {
		case processesCPUUtilizationTotalChart.ID:
			id := fmt.Sprintf("process_%s_cpu_time", procID)
			dim = &module.Dim{ID: id, Name: procID, Algo: module.Incremental, Div: 1000, Mul: 100}
			if procID == "Idle" {
				dim.Hidden = true
			}
		case processesMemoryUsageChart.ID:
			id := fmt.Sprintf("process_%s_working_set_private_bytes", procID)
			dim = &module.Dim{ID: id, Name: procID}
		case processesIOBytesChart.ID:
			id := fmt.Sprintf("process_%s_io_bytes", procID)
			dim = &module.Dim{ID: id, Name: procID, Algo: module.Incremental}
		case processesIOOperationsChart.ID:
			id := fmt.Sprintf("process_%s_io_operations", procID)
			dim = &module.Dim{ID: id, Name: procID, Algo: module.Incremental}
		case processesPageFaultsChart.ID:
			id := fmt.Sprintf("process_%s_page_faults", procID)
			dim = &module.Dim{ID: id, Name: procID, Algo: module.Incremental}
		case processesPageFileBytes.ID:
			id := fmt.Sprintf("process_%s_page_file_bytes", procID)
			dim = &module.Dim{ID: id, Name: procID}
		case processesThreads.ID:
			id := fmt.Sprintf("process_%s_threads", procID)
			dim = &module.Dim{ID: id, Name: procID}
		case processesHandlesChart.ID:
			id := fmt.Sprintf("process_%s_handles", procID)
			dim = &module.Dim{ID: id, Name: procID}
		default:
			continue
		}

		if err := chart.AddDim(dim); err != nil {
			w.Warning(err)
			continue
		}
		chart.MarkNotCreated()
	}
}

func (w *Windows) removeProcessFromCharts(procID string) {
	for _, chart := range *w.Charts() {
		var id string
		switch chart.ID {
		case processesCPUUtilizationTotalChart.ID:
			id = fmt.Sprintf("process_%s_cpu_time", procID)
		case processesMemoryUsageChart.ID:
			id = fmt.Sprintf("process_%s_working_set_private_bytes", procID)
		case processesIOBytesChart.ID:
			id = fmt.Sprintf("process_%s_io_bytes", procID)
		case processesIOOperationsChart.ID:
			id = fmt.Sprintf("process_%s_io_operations", procID)
		case processesPageFaultsChart.ID:
			id = fmt.Sprintf("process_%s_page_faults", procID)
		case processesPageFileBytes.ID:
			id = fmt.Sprintf("process_%s_page_file_bytes", procID)
		case processesThreads.ID:
			id = fmt.Sprintf("process_%s_threads", procID)
		case processesHandlesChart.ID:
			id = fmt.Sprintf("process_%s_handles", procID)
		default:
			continue
		}

		if err := chart.MarkDimRemove(id, false); err != nil {
			w.Warning(err)
			continue
		}
		chart.MarkNotCreated()
	}
}

func (w *Windows) addProcessNetFrameworkExceptionsCharts(procName string) {
	charts := netFrameworkCLRExceptionsChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, strings.ToLower(procName))
		chart.Labels = []module.Label{
			{Key: "process", Value: procName},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, procName)
		}
	}

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

func (w *Windows) removeProcessFromNetFrameworkExceptionsCharts(procName string) {
	px := fmt.Sprintf("netframework_%s_clrexception", strings.ToLower(procName))
	w.removeCharts(px)
}

func (w *Windows) addProcessNetFrameworkInteropCharts(procName string) {
	charts := netFrameworkCLRInteropChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, strings.ToLower(procName))
		chart.Labels = []module.Label{
			{Key: "process", Value: procName},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, procName)
		}
	}

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

func (w *Windows) removeProcessNetFrameworkInteropCharts(procName string) {
	px := fmt.Sprintf("netframework_%s_clrinterop", strings.ToLower(procName))
	w.removeCharts(px)
}

func (w *Windows) addProcessNetFrameworkJITCharts(procName string) {
	charts := netFrameworkCLRJITChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, strings.ToLower(procName))
		chart.Labels = []module.Label{
			{Key: "process", Value: procName},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, procName)
		}
	}

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

func (w *Windows) removeProcessNetFrameworkJITCharts(procName string) {
	px := fmt.Sprintf("netframework_%s_clrjit", strings.ToLower(procName))
	w.removeCharts(px)
}

func (w *Windows) addProcessNetFrameworkLoadingCharts(procName string) {
	charts := netFrameworkCLRLoadingChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, strings.ToLower(procName))
		chart.Labels = []module.Label{
			{Key: "process", Value: procName},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, procName)
		}
	}

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

func (w *Windows) removeProcessNetFrameworkLoadingCharts(procName string) {
	px := fmt.Sprintf("netframework_%s_clrloading", strings.ToLower(procName))
	w.removeCharts(px)
}

func (w *Windows) addProcessNetFrameworkLocksAndThreadsCharts(procName string) {
	charts := netFrameworkCLRLocksAndThreadsChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, strings.ToLower(procName))
		chart.Labels = []module.Label{
			{Key: "process", Value: procName},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, procName)
		}
	}

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

func (w *Windows) removeProcessNetFrameworkLocksAndThreadsCharts(procName string) {
	px := fmt.Sprintf("netframework_%s_clrlocksandthreads", strings.ToLower(procName))
	w.removeCharts(px)
}

func (w *Windows) addProcessNetFrameworkMemoryCharts(procName string) {
	charts := netFrameworkCLRMemoryChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, strings.ToLower(procName))
		chart.Labels = []module.Label{
			{Key: "process", Value: procName},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, procName)
		}
	}

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

func (w *Windows) removeProcessNetFrameworkMemoryCharts(procName string) {
	px := fmt.Sprintf("netframework_%s_clrmemory", strings.ToLower(procName))
	w.removeCharts(px)
}

func (w *Windows) addProcessNetFrameworkRemotingCharts(procName string) {
	charts := netFrameworkCLRRemotingChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, strings.ToLower(procName))
		chart.Labels = []module.Label{
			{Key: "process", Value: procName},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, procName)
		}
	}

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

func (w *Windows) removeProcessNetFrameworkRemotingCharts(procName string) {
	px := fmt.Sprintf("netframework_%s_clrremoting", strings.ToLower(procName))
	w.removeCharts(px)
}

func (w *Windows) addProcessNetFrameworkSecurityCharts(procName string) {
	charts := netFrameworkCLRSecurityChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, strings.ToLower(procName))
		chart.Labels = []module.Label{
			{Key: "process", Value: procName},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, procName)
		}
	}

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

func (w *Windows) removeProcessNetFrameworkSecurityCharts(procName string) {
	px := fmt.Sprintf("netframework_%s_clrsecurity", strings.ToLower(procName))
	w.removeCharts(px)
}

func (w *Windows) addServiceCharts(svc string) {
	charts := serviceChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, svc)
		chart.Labels = []module.Label{
			{Key: "service", Value: svc},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, svc)
		}
	}

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

func (w *Windows) removeServiceCharts(svc string) {
	px := fmt.Sprintf("service_%s", svc)
	w.removeCharts(px)
}

func (w *Windows) addCollectorCharts(name string) {
	charts := collectorChartsTmpl.Copy()

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, name)
		chart.Labels = []module.Label{
			{Key: "collector", Value: name},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, name)
		}
	}

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

func (w *Windows) addHypervCharts() {
	charts := hypervChartsTmpl.Copy()

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

func (w *Windows) addHypervVMCharts(vm string) {
	charts := hypervVMChartsTemplate.Copy()
	n := hypervCleanName(vm)

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, n)
		chart.Labels = []module.Label{
			{Key: "vm_name", Value: vm},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, n)
		}
	}

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

func (w *Windows) removeHypervVMCharts(vm string) {
	px := fmt.Sprintf("vm_%s", hypervCleanName(vm))
	w.removeCharts(px)
}

func (w *Windows) addHypervVMDeviceCharts(device string) {
	charts := hypervVMDeviceChartsTemplate.Copy()
	n := hypervCleanName(device)

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, n)
		chart.Labels = []module.Label{
			{Key: "vm_device", Value: device},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, n)
		}
	}

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

func (w *Windows) removeHypervVMDeviceCharts(device string) {
	px := fmt.Sprintf("vm_device_%s", hypervCleanName(device))
	w.removeCharts(px)
}

func (w *Windows) addHypervVMInterfaceCharts(iface string) {
	charts := hypervVMInterfaceChartsTemplate.Copy()
	n := hypervCleanName(iface)

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, n)
		chart.Labels = []module.Label{
			{Key: "vm_interface", Value: iface},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, n)
		}
	}

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

func (w *Windows) removeHypervVMInterfaceCharts(iface string) {
	px := fmt.Sprintf("vm_interface_%s", hypervCleanName(iface))
	w.removeCharts(px)
}

func (w *Windows) addHypervVSwitchCharts(vswitch string) {
	charts := hypervVswitchChartsTemplate.Copy()
	n := hypervCleanName(vswitch)

	for _, chart := range *charts {
		chart.ID = fmt.Sprintf(chart.ID, n)
		chart.Labels = []module.Label{
			{Key: "vswitch", Value: vswitch},
		}
		for _, dim := range chart.Dims {
			dim.ID = fmt.Sprintf(dim.ID, n)
		}
	}

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

func (w *Windows) removeHypervVSwitchCharts(vswitch string) {
	px := fmt.Sprintf("vswitch_%s", hypervCleanName(vswitch))
	w.removeCharts(px)
}

func (w *Windows) removeCollectorCharts(name string) {
	px := fmt.Sprintf("collector_%s", name)
	w.removeCharts(px)
}

func (w *Windows) removeCharts(prefix string) {
	for _, chart := range *w.Charts() {
		if strings.HasPrefix(chart.ID, prefix) {
			chart.MarkRemove()
			chart.MarkNotCreated()
		}
	}
}
