This is documentation for the next version of Grafana Alloy Documentation. For the latest stable release, go to the latest version.

Experimental Open source

database_observability.sql_server

EXPERIMENTAL: This is an experimental component. Experimental components are subject to frequent breaking changes, and may be removed with no equivalent replacement. To enable and use an experimental component, you must set the stability.level flag to experimental.

database_observability.sql_server connects to a Microsoft SQL Server instance and collects observability data across every accessible user database on that instance. The component forwards this data as log entries to Loki receivers and exports targets for Prometheus scraping.

Usage

Alloy
database_observability.sql_server "<LABEL>" {
  data_source_name = <DATA_SOURCE_NAME>
  forward_to       = [<LOKI_RECEIVERS>]
}

Arguments

You can use the following arguments with database_observability.sql_server:

NameTypeDescriptionDefaultRequired
data_source_namesecretData Source Name for the SQL Server instance to connect to. Required when no database_instance blocks are defined.no
forward_tolist(LogsReceiver)Where to forward log entries after processing.yes
targetslist(map(string))List of external targets to scrape.no
disable_collectorslist(string)A list of collectors to disable from the default set.no
enable_collectorslist(string)A list of collectors to enable on top of the default set.no
exclude_current_userboolExclude tagged Alloy queries and query samples from sessions matching the Alloy application name or opened with the login that Alloy uses.trueno
exclude_schemaslist(string)A list of schemas to exclude from monitoring, on top of the always-excluded system schemas sys and information_schema.["alloydbadmin", "alloydbmetadata", "azure_maintenance", "azure_sys", "cloudsqladmin", "rdsadmin"]no
exclude_databaseslist(string)A list of databases to exclude from monitoring, on top of the always-excluded system databases master, model, msdb, and tempdb.["alloydbadmin", "alloydbmetadata", "azure_maintenance", "azure_sys", "cloudsqladmin", "rdsadmin"]no
exclude_userslist(string)A list of original SQL Server login names to exclude from query samples.["azuresu", "cloudsqladmin", "db-o11y", "rdsadmin"]no
query_timeoutdurationTimeout for each SQL statement."10s"no

When data_source_name doesn’t specify an application name (app name), Alloy sets it to grafana:alloy:database_observability on its SQL Server connections.

The exclude_current_user argument excludes SQL tagged by Alloy from query metrics, query details, explain plans, and query samples. Query Store doesn’t identify the login or application name that executed a query, so this exclusion can’t remove arbitrary historical queries by login or previously captured Alloy queries without the marker.

For live query samples, exclude_current_user also excludes sessions whose sys.dm_exec_sessions.program_name is grafana:alloy:database_observability or that were opened with the SQL Server login configured for Alloy. For server_metrics, exclude_current_user excludes sessions whose sys.dm_exec_sessions.program_name is grafana:alloy:database_observability from database_observability_sql_server_user_sessions. Setting it to false disables marker, application name, and automatic current-login exclusion. The exclude_users list still applies to query samples, and Alloy always excludes the request that collects the samples. Schema discovery, server configuration, and health-check results aren’t filtered by this argument.

The query_timeout applies separately to each SQL statement. The timeout includes waiting for an available connection and reading the statement results. A collection cycle can run multiple statements and can take longer than query_timeout. The server_metrics collector also runs multiple statements during a Prometheus scrape, so the total scrape duration can exceed query_timeout.

The following collectors are configurable:

NameDescriptionEnabled by default
explain_plansCollect and parse query execution plans already captured by Query Store.yes
query_detailsCollect query text and parsed table names from Query Store.yes
query_metricsCollect per-query executions, errors, and duration counters from Query Store.yes
query_samplesCollect query samples and wait events for tracked queries.yes
schema_detailsCollect schemas and tables from information_schema.yes
server_configurationCollect connection, resource-limit, and memory configuration metrics.yes
server_metricsCollect SQL Server CPU, memory, and user session metrics.yes

Blocks

You can use the following blocks with database_observability.sql_server:

cloud_provider

The cloud_provider block has no attributes. It contains zero or one of the aws, azure, or gcp blocks. You use the cloud_provider block to provide information related to the cloud provider that hosts the database under observation. This information is appended as labels to the collected metrics. The labels make it easier for you to filter and group your metrics.

When you don’t configure a cloud_provider block, Alloy attempts to detect AWS RDS and Azure SQL hosts from the data_source_name.

aws

The aws block supplies the ARN identifier for the database being monitored.

NameTypeDescriptionDefaultRequired
arnstringThe ARN associated with the database under observation.yes

azure

The azure block supplies the identifying information for the database being monitored.

NameTypeDescriptionDefaultRequired
subscription_idstringThe Subscription ID for your Azure account.yes
resource_groupstringThe Resource Group that holds the database resource.yes
server_namestringThe database server name, for example orders-db for the host orders-db.database.windows.net.no

gcp

The gcp block supplies the identifying information for the GCP Cloud SQL database being monitored.

NameTypeDescriptionDefaultRequired
connection_namestringThe Cloud SQL instance connection name in the format project:region:instance, for example my-project:us-central1:my-db.yes

database_instance

The database_instance block defines one SQL Server instance to monitor. Repeat the block to monitor several instances with a single component. The block label must be unique across database_instance blocks and identifies the instance in the component’s metrics endpoint path. Each database_instance block must also point to a distinct server: two blocks that resolve to the same host, port or named instance, and database name are rejected.

NameTypeDescriptionDefaultRequired
data_source_namesecretData Source Name for the SQL Server instance to connect to.yes

Each database_instance block can also contain a [cloud_provider][cloud_provider] block that applies to that instance only, and [rule][rule] blocks that relabel the metrics and logs of that instance only.

When you define database_instance blocks, don’t set the top-level data_source_name, targets, and cloud_provider arguments. They’re mutually exclusive with database_instance blocks. All other arguments and blocks, such as collector settings, apply to every configured instance.

The metrics for each instance are served on a separate /db/<LABEL>/metrics path under the component’s HTTP endpoint, and the exported targets point to the corresponding path. When you don’t define database_instance blocks, the component serves metrics on its historical /metrics path. The metrics endpoints are served exactly at those paths: requests to any other path under the component’s HTTP endpoint return HTTP 404.

For example:

Alloy
database_observability.sql_server "pool" {
  forward_to = [loki.write.logs_service.receiver]

  database_instance "orders" {
    data_source_name = sys.env("ORDERS_DSN")

    cloud_provider {
      aws {
        arn = "orders-rds-db-arn"
      }
    }

    rule {
      target_label = "environment"
      replacement  = "production"
    }
  }

  database_instance "billing" {
    data_source_name = sys.env("BILLING_DSN")

    rule {
      target_label = "environment"
      replacement  = "staging"
    }
  }
}

In this example, the metrics and logs of the orders instance carry environment="production", and those of the billing instance carry environment="staging".

rule

The rule block relabels the metrics and the logs of the database_instance block that contains it. Use it to tell the data of each monitored instance apart, for example by environment, team, or tier.

The rule block defines a relabeling rule applied to the metrics and the logs of a single monitored database. If you define more than one rule block, the rules are applied in top-down order, after the labels the component sets itself, so a rule can read those labels with source_labels.

It takes the same arguments as the rule block used elsewhere in Alloy, in a restricted form: because one rule set applies to two signal paths, it supports the labelling actions only, and it can’t overwrite most of the labels the component sets. Alloy refuses to load a configuration containing a rule that breaks either restriction, so such a rule is never silently ignored.

Two further constraints are specific to a database_instance block:

  • target_label must be a literal label name: Alloy checks it against the reserved labels when it loads the configuration, so it can’t contain a capture group reference.
  • hashmod requires source_labels, and can’t target instance: hashing the empty value gives every database the same result, and hashing into instance buckets several databases onto one value even when the source is present.

Caution

A relabeling rule that computes an empty value removes its target label instead of setting it, and the default replacement of "$1" computes an empty value when a rule has no source_labels. So rule { target_label = "environment" } removes environment rather than setting it, and Alloy rejects it. Always set replacement alongside a target_label.

Alloy can only reject such a rule where the outcome is certain. A rule that reads source_labels depends on the labels present at runtime, so a missing or misspelled source label still removes the target label, except for the reserved labels and instance, which keep their previous value. Only removal is prevented: a rule that computes a non-empty value still overwrites those labels, which is why hashmod can’t target instance at all.

You can use the hashmod, labeldrop, lowercase, replace, and uppercase actions. The rest aren’t supported:

  • drop, dropequal, keep, and keepequal filter rather than label, and filtering means two different things on the two signal paths. Dropping a metrics target stops the database exporting metrics entirely, whereas dropping a log entry discards one line. To filter one database’s logs, use a loki.relabel component on the receiver named in forward_to, with a drop rule that matches that database’s instance or server_id. Every database the component monitors forwards to the same receivers, so the rule has to identify the one it applies to. To filter one database’s metrics, use a discovery.relabel component on the component’s exported targets.
  • labelmap builds label names from replacement at runtime, so Alloy can’t check them against the reserved labels when it loads the configuration.
  • labelkeep removes every label its regex doesn’t match, so a rule that preserves the reserved labels would have to match all of them. Use labeldrop to remove specific labels instead.

Because the rules run after the component’s own labels, and those are protected, a labeldrop rule can only remove a label that an earlier rule in the same block created.

Reserved labels

A rule can’t write to the following labels, and a labeldrop regular expression can’t match them:

  • Both metrics and logs: job and server_id.
  • Logs only: engine and op.
  • Metrics only: provider_name, provider_region, provider_account, __address__, __scheme__, and __metrics_path__.

This applies to rule blocks only. A downstream discovery.relabel or loki.relabel component can still overwrite any of them, but it applies to every database the component monitors rather than one.

The instance label is a special case: a rule can rewrite its value, which is a common reason to use a rule block, because a friendly name such as orders_db then applies to that database’s metrics and logs together. A rule can’t remove it, because metrics and logs are correlated on it, and because an empty instance on a metrics target makes Prometheus fill it in from __address__, which every database in one component shares, collapsing them all onto one series.

For the same reason, two database_instance blocks can’t rewrite instance to the same value. Alloy rejects that when both values are fixed in the configuration, but it can’t when the value comes from a label the databases share: source_labels = ["job"] gives every database the same instance, since they all carry the same job. Derive instance from something that differs per database, or set a literal value in each block.

Labels set on only one signal path

Some of the labels above exist on one signal path and not the other, and a rule that reads one with source_labels behaves differently on each path: where the label is absent the rule computes an empty value, which removes its target_label rather than setting it to an empty string.

A rule reading provider_region, which a database with a cloud_provider block carries on its metrics targets but not on its log entries, sets region on that database’s metrics and removes region from its logs. Reading a logs-only label such as op does the same in reverse. Only job, server_id, and instance are set on both paths, so prefer those as source_labels, or a label an earlier rule in the same block created.

clustering

NameTypeDescriptionDefaultRequired
enabledboolEnables distributing instances with other cluster nodes.falseyes

When Alloy is using clustering, and enabled is set to true, then this database_observability.sql_server component instance opts-in to distributing its configured instances between all cluster nodes.

Clustering assumes that all cluster nodes are running with the same configuration file. All component instances opting in to clustering use the instance key of each configured instance, <host>:<port>/<database>, and a consistent hashing algorithm to determine ownership of each instance between the cluster peers. Each peer then only collects from the subset of instances it’s responsible for, and only exports the targets of those instances, so prometheus.scrape components on the same node scrape exactly the instances the node owns. When a node joins or leaves the cluster, every peer recalculates ownership: expect a short gap or a brief duplicate collection for an instance while its ownership moves. While the cluster isn’t yet ready to admit traffic, for example while it’s still forming and waiting for the minimum cluster size, the component doesn’t collect from any instance.

Clustering is also useful with a single instance: when several cluster nodes run an identical configuration, exactly one node collects from the instance at a time, which gives you a highly available setup without duplicate collection.

If Alloy is not running in clustered mode, then the block is a no-op and database_observability.sql_server collects from every configured instance.

explain_plans

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to check for a changed execution plan."1m"no

The explain_plans collector reads the execution plan Query Store already captured for each query tracked by the query_metrics collector. It doesn’t compile or run a fresh plan. Only queries that query_metrics is currently tracking are eligible. When query_metrics is disabled, explain_plans produces no output.

The collector checks for a changed plan every collect_interval. It forwards a log entry only when the plan’s shape has changed since the last entry. It also forwards a log entry when 30 minutes have passed since the last entry. This keeps log volume low and ensures a fresh entry at least every 30 minutes.

health_check

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to run health checks."1h"no

The health_check collector periodically verifies that the login has the required grants (VIEW DEFINITION, plus VIEW DATABASE STATE or its SQL Server 2022+ equivalent VIEW DATABASE PERFORMANCE STATE) and that Query Store is enabled and populated, on every database the login can access on the instance. Each check emits a log entry with op="health_status" and a check field identifying it: AlloyVersion, RequiredGrantsPresent, QueryStoreEnabled, or QueryStoreHasRows.

RequiredGrantsPresent and QueryStoreEnabled pass only when true on every database the login can access; when they fail, the log entry’s value lists the non-compliant databases. QueryStoreHasRows passes as soon as any accessible database has Query Store data, since it’s expected for a low-traffic database to have none.

query_details

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to collect query text from Query Store."1m"no

The query_details collector reads Query Store query text for the database selected in the data_source_name, not every database on the instance.

query_metrics

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to collect metrics from Query Store."1m"no
statements_limitintMaximum number of queries to track, ranked by recent duration.50no
statements_lookbackdurationOnly queries executed within this window are eligible for tracking."1h"no

The query_metrics collector reads Query Store for the database selected in the data_source_name, not every database on the instance. Configure the data_source_name to select a user database that has Query Store enabled. When the connected database is a system database such as master, or Query Store is disabled or read-only, the collector skips collection and remains healthy.

The login requires VIEW DATABASE STATE on the connected database. On SQL Server 2022 and later, VIEW DATABASE PERFORMANCE STATE is also sufficient.

query_samples

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to collect query samples."10s"no
disable_query_redactionboolCollect unredacted SQL query text (might include parameters).falseno
sample_min_durationdurationMinimum elapsed duration for a completed query sample to be emitted. Set to "0s" to disable filtering."0s"no
wait_event_min_durationdurationMinimum duration for a wait event occurrence to be emitted. Set to "0s" to disable filtering."1ms"no
max_samples_per_queryintMaximum number of completed query samples emitted per (database, query_hash) in a single collection cycle. Set to 0 for no per-query limit.5no
max_samples_per_collectintMaximum total number of completed query samples emitted across all tracked queries in a single collection cycle. Set to 0 for no per-collection limit.50no

The query_samples collector only collects requests whose query hash is tracked by the query_metrics collector.

When requests finish between polls, the collector filters out any request whose final elapsed time is shorter than sample_min_duration. Remaining completed requests are ranked by elapsed duration and then CPU time, and capped by max_samples_per_query and max_samples_per_collect. When a request is dropped by sample_min_duration, max_samples_per_query, or max_samples_per_collect, neither the query sample nor its wait event occurrences are emitted. For emitted samples, only wait event occurrences with a final duration of at least wait_event_min_duration are logged.

The collector polls live requests and can miss queries shorter than collect_interval, wait events that start and finish between collections, and a query’s first execution before Query Store admits its hash. For completed requests, the emitted resource counters contain the values from the final observation and can omit work performed after that observation.

The login requires VIEW SERVER STATE on SQL Server 2019 and earlier. On SQL Server 2022 and later, VIEW SERVER PERFORMANCE STATE is also sufficient. Azure SQL Database can restrict the dynamic management views to the current session. In that case, the collector can’t observe other sessions.

schema_details

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to collect information from database."1m"no

The collector scans every database that the login can access on the instance and collects schema details from each. Only databases where the login has CONNECT access to catalog views are collected.

server_configuration

The server_configuration block configures how often database_observability.sql_server collects connection, resource-limit, and memory configuration metrics.

NameTypeDescriptionDefaultRequired
collect_intervaldurationHow frequently to collect configuration metrics."10m"no

The collector queries configuration immediately after it starts and then every collect_interval. Prometheus scrapes read the latest successful result from memory and don’t query SQL Server. If a query fails, the collector retains the last successful result and tries again at the next interval. The top-level query_timeout applies to each configuration query.

For SQL Server, Amazon RDS for SQL Server, Google Cloud SQL for SQL Server, and Azure SQL Managed Instance, the collector reads the settings available in sys.configurations. Managed database services can omit settings or manage their values. The collector skips unavailable settings without failing the collection.

The collector exports the following metrics:

MetricTypeSource settingDescription
database_observability_sql_server_config_backup_compression_defaultgaugebackup compression defaultWhether backup compression is enabled by default.
database_observability_sql_server_config_cost_threshold_for_parallelismgaugecost threshold for parallelismThreshold at which SQL Server creates and runs parallel plans.
database_observability_sql_server_config_database_max_degree_of_parallelismgaugesys.database_scoped_configurations.MAXDOPMaximum degree of parallelism for the current Azure SQL Database.
database_observability_sql_server_config_index_create_memory_bytesgaugeindex create memory (KB)Minimum memory for index creation.
database_observability_sql_server_config_max_degree_of_parallelismgaugemax degree of parallelismMaximum processors used for a parallel plan.
database_observability_sql_server_config_max_server_memory_bytesgaugemax server memory (MB)Maximum memory available to the SQL Server memory manager.
database_observability_sql_server_config_max_worker_threadsgaugemax worker threadsMaximum worker threads.
database_observability_sql_server_config_min_memory_per_query_bytesgaugemin memory per query (KB)Minimum memory for query execution.
database_observability_sql_server_config_min_server_memory_bytesgaugemin server memory (MB)Minimum memory retained by the SQL Server memory manager.
database_observability_sql_server_config_network_packet_size_bytesgaugenetwork packet size (B)Default network packet size.
database_observability_sql_server_config_optimize_for_ad_hoc_workloadsgaugeoptimize for ad hoc workloadsWhether plan cache efficiency for single-use ad hoc batches is enabled.
database_observability_sql_server_config_remote_admin_connectionsgaugeremote admin connectionsWhether remote dedicated administrator connections are enabled.
database_observability_sql_server_config_remote_login_timeout_secondsgaugeremote login timeout (s)Timeout for outgoing remote login attempts.
database_observability_sql_server_config_user_connectionsgaugeuser connectionsConfigured user connection limit.

Except for database_observability_sql_server_config_database_max_degree_of_parallelism, each metric has a state label. The configured state reports the requested value from sys.configurations.value. The in_use state reports the running value from sys.configurations.value_in_use. The values can differ when an administrator hasn’t run RECONFIGURE or when a setting change requires a restart. SQL Server can also represent automatic defaults differently for max server memory (MB) and min server memory (MB).

server_metrics collector

The server_metrics collector queries SQL Server when Prometheus scrapes the component. It has no configuration block; enable or disable it with the enable_collectors and disable_collectors arguments. It supports SQL Server 2019 and later, including SQL Server on Amazon RDS, Google Cloud SQL, Azure SQL Database, and Azure SQL Managed Instance.

The collector exports the following metrics:

MetricTypeSourceDescription
database_observability_sql_server_batch_requests_totalcountersys.dm_os_performance_countersTotal Transact-SQL command batches received by SQL Server.
database_observability_sql_server_database_cpu_utilization_ratiogaugesys.dm_db_resource_statsAverage Azure SQL Database CPU utilization relative to the service-tier limit.
database_observability_sql_server_database_data_io_utilization_ratiogaugesys.dm_db_resource_statsAverage Azure SQL Database data I/O utilization relative to the service-tier limit.
database_observability_sql_server_database_dtu_limitgaugesys.dm_user_db_resource_governanceDTU limit of an Azure SQL Database that uses the DTU purchasing model.
database_observability_sql_server_database_log_write_utilization_ratiogaugesys.dm_db_resource_statsAverage Azure SQL Database log-write utilization relative to the service-tier limit.
database_observability_sql_server_database_memory_grant_limit_ratiogaugesys.dm_user_db_resource_governanceMaximum memory grant for a single Azure SQL Database request as a ratio of user workload group memory.
database_observability_sql_server_database_memory_utilization_ratiogaugesys.dm_db_resource_statsAverage Azure SQL Database memory utilization relative to the service-tier limit.
database_observability_sql_server_database_resource_stats_timestamp_secondsgaugesys.dm_db_resource_statsUnix timestamp of the latest Azure SQL Database resource statistics interval.
database_observability_sql_server_database_resource_governor_max_degree_of_parallelismgaugesys.dm_user_db_resource_governanceMaximum degree of parallelism enforced by the Azure SQL Database user workload group.
database_observability_sql_server_database_session_utilization_ratiogaugesys.dm_db_resource_statsMaximum Azure SQL Database session utilization during the latest reporting interval.
database_observability_sql_server_database_storage_allocated_bytesgaugesys.database_filesSpace allocated to the connected database files, labeled by file_type.
database_observability_sql_server_database_storage_limit_bytesgaugeDATABASEPROPERTYEXMaximum configured storage capacity of the connected database.
database_observability_sql_server_database_storage_used_bytesgaugesys.database_filesSpace used within the connected database files, labeled by file_type.
database_observability_sql_server_database_vcore_limitgaugesys.dm_user_db_resource_governancevCore limit of an Azure SQL Database that uses the vCore purchasing model.
database_observability_sql_server_database_worker_limitgaugesys.dm_user_db_resource_governanceWorker thread limit of the Azure SQL Database user workload group.
database_observability_sql_server_database_worker_utilization_ratiogaugesys.dm_db_resource_statsMaximum Azure SQL Database worker utilization during the latest reporting interval.
database_observability_sql_server_deadlocks_totalcountersys.dm_os_performance_countersTotal lock requests that resulted in a deadlock.
database_observability_sql_server_host_commit_available_bytesgaugesys.dm_os_sys_memoryAvailable operating system commit visible to the SQL Server host.
database_observability_sql_server_host_commit_limit_bytesgaugesys.dm_os_sys_memoryOperating system commit limit visible to the SQL Server host.
database_observability_sql_server_host_high_memory_signalgaugesys.dm_os_sys_memoryWhether the host high-memory resource notification is set.
database_observability_sql_server_host_logical_cpu_countgaugesys.dm_os_sys_infoNumber of logical CPUs visible to the SQL Server host.
database_observability_sql_server_host_low_memory_signalgaugesys.dm_os_sys_memoryWhether the host low-memory resource notification is set.
database_observability_sql_server_host_physical_memory_available_bytesgaugesys.dm_os_sys_memoryAvailable physical memory visible to the SQL Server host.
database_observability_sql_server_host_physical_memory_total_bytesgaugesys.dm_os_sys_memoryTotal physical memory visible to the SQL Server host.
database_observability_sql_server_infogaugeSERVERPROPERTY, sys.databasesSQL Server engine edition and product version metadata, labeled by engine_edition, edition_name, product_version, product_level, product_build, and compatibility_level.
database_observability_sql_server_instance_cpu_utilization_ratiogaugesys.dm_db_resource_stats, master.sys.server_resource_statsAverage CPU utilization relative to the Azure SQL service-tier limit.
database_observability_sql_server_instance_io_operations_per_secondgaugemaster.sys.server_resource_statsAverage physical I/O operations per second during the latest Azure SQL Managed Instance reporting interval.
database_observability_sql_server_instance_io_read_bytes_per_secondgaugemaster.sys.server_resource_statsAverage physical bytes read per second during the latest Azure SQL Managed Instance reporting interval.
database_observability_sql_server_instance_io_written_bytes_per_secondgaugemaster.sys.server_resource_statsAverage physical bytes written per second during the latest Azure SQL Managed Instance reporting interval.
database_observability_sql_server_instance_memory_utilization_ratiogaugesys.dm_db_resource_statsAverage memory utilization of the database engine instance hosting an Azure SQL Database.
database_observability_sql_server_instance_resource_stats_timestamp_secondsgaugemaster.sys.server_resource_statsUnix timestamp of the latest Azure SQL Managed Instance resource statistics interval.
database_observability_sql_server_instance_storage_allocated_bytesgaugesys.dm_io_virtual_file_statsTotal space allocated to database files on the SQL Server instance.
database_observability_sql_server_instance_storage_available_bytesgaugesys.dm_os_volume_statsAvailable storage capacity on operating system volumes hosting SQL Server files.
database_observability_sql_server_instance_storage_limit_bytesgaugemaster.sys.server_resource_stats, sys.dm_os_volume_statsReserved storage capacity of an Azure SQL Managed Instance or total operating system volume capacity.
database_observability_sql_server_instance_storage_used_bytesgaugemaster.sys.server_resource_stats, sys.dm_os_volume_statsStorage used by an Azure SQL Managed Instance or across operating system volumes hosting SQL Server files.
database_observability_sql_server_instance_vcore_limitgaugemaster.sys.server_resource_statsvCore limit of an Azure SQL Managed Instance.
database_observability_sql_server_io_read_bytes_totalcountersys.dm_io_virtual_file_statsTotal bytes read from SQL Server database and log files.
database_observability_sql_server_io_read_stall_seconds_totalcountersys.dm_io_virtual_file_statsTotal time spent waiting for read operations on SQL Server files.
database_observability_sql_server_io_reads_totalcountersys.dm_io_virtual_file_statsTotal physical read operations issued on SQL Server database and log files.
database_observability_sql_server_io_write_stall_seconds_totalcountersys.dm_io_virtual_file_statsTotal time spent waiting for write operations on SQL Server files.
database_observability_sql_server_io_writes_totalcountersys.dm_io_virtual_file_statsTotal physical write operations issued on SQL Server database and log files.
database_observability_sql_server_io_written_bytes_totalcountersys.dm_io_virtual_file_statsTotal bytes written to SQL Server database and log files.
database_observability_sql_server_lock_waits_totalcountersys.dm_os_performance_countersTotal lock requests that required the caller to wait.
database_observability_sql_server_memory_grants_pendinggaugesys.dm_os_performance_countersCurrent number of processes waiting for a workspace memory grant.
database_observability_sql_server_memory_manager_committed_bytesgaugesys.dm_os_sys_infoMemory committed by the SQL Server memory manager.
database_observability_sql_server_memory_manager_target_bytesgaugesys.dm_os_sys_infoMemory the SQL Server memory manager can consume.
database_observability_sql_server_page_life_expectancy_secondsgaugesys.dm_os_performance_countersDuration in seconds that a data page stays in the buffer pool without references.
database_observability_sql_server_process_available_commit_memory_bytesgaugesys.dm_os_process_memoryMemory available to be committed by the SQL Server process.
database_observability_sql_server_process_committed_memory_resident_ratiogaugesys.dm_os_process_memoryRatio of committed process memory resident in the working set.
database_observability_sql_server_process_cpu_limitgaugesys.dm_os_job_objectLogical CPU capacity available to Azure SQL Managed Instance.
database_observability_sql_server_process_cpu_seconds_totalcountersys.dm_os_sys_infoCPU time consumed by SQL Server threads, labeled by mode.
database_observability_sql_server_process_memory_limit_bytesgaugesys.dm_os_job_objectMaximum committed memory available to Azure SQL Managed Instance.
database_observability_sql_server_process_page_faults_totalcountersys.dm_os_process_memoryPage faults incurred by the SQL Server process.
database_observability_sql_server_process_physical_memory_lowgaugesys.dm_os_process_memoryWhether the process is responding to a low physical-memory notification.
database_observability_sql_server_process_resident_memory_bytesgaugesys.dm_os_process_memorySQL Server process working set.
database_observability_sql_server_process_virtual_memory_bytesgaugesys.dm_os_process_memoryVirtual address space committed by the SQL Server process.
database_observability_sql_server_process_virtual_memory_lowgaugesys.dm_os_process_memoryWhether the process has detected a low virtual-memory condition.
database_observability_sql_server_sos_memory_target_bytesgaugesys.dm_os_job_objectMemory available to the Azure SQL Managed Instance SQL operating system.
database_observability_sql_server_sql_compilations_totalcountersys.dm_os_performance_countersTotal SQL compilations performed by SQL Server.
database_observability_sql_server_sql_recompilations_totalcountersys.dm_os_performance_countersTotal SQL statement recompilations performed by SQL Server.
database_observability_sql_server_tempdb_space_unallocated_bytesgaugetempdb.sys.dm_db_file_space_usageUnallocated space in tempdb data files.
database_observability_sql_server_tempdb_space_used_bytesgaugetempdb.sys.dm_db_file_space_usageSpace used in tempdb data files, labeled by category.
database_observability_sql_server_uptime_secondsgaugesys.dm_os_sys_infoTime since the SQL Server process started.
database_observability_sql_server_user_session_limitgaugesys.configurationsMaximum user sessions allowed by the active configuration and service limit.
database_observability_sql_server_user_sessionsgaugesys.dm_exec_sessionsAuthenticated user sessions, labeled by status.

The process_cpu_seconds_total counter has the mode label values user and kernel. The user_sessions gauge has the status label values running, sleeping, dormant, and preconnect. Process-lifetime counters reset when SQL Server restarts or fails over.

The user_session_limit metric resolves the default user connections setting of 0 to 32767. For Azure SQL Managed Instance, it reports the lower of the configured limit and the service limit of 30000. Other resources, such as workers and memory, can become saturated before the session limit. For Azure SQL Database, user_sessions is a current count from the connected database. The separate database_session_utilization_ratio metric is the maximum session utilization during the latest 15-second resource statistics interval. CPU, memory, data I/O, and log-write ratios are averages over that interval. Worker and session ratios are maxima. For databases in an elastic pool, these ratios are relative to the per-database limits configured by the pool.

The Azure SQL Database resource metrics require VIEW DATABASE STATE. For Basic, S0, and S1 service objectives and databases in elastic pools, the monitoring login must be a server administrator, a Microsoft Entra administrator, or a member of the ##MS_ServerStateReader## server role.

The host CPU and memory metrics are available for self-hosted SQL Server, Amazon RDS, and Google Cloud SQL. They describe the operating system visible to SQL Server and can include managed-service overhead. Use provider metrics as the authoritative source for cloud service entitlement.

The host metrics aren’t emitted for Azure SQL Managed Instance because its host values don’t represent the resources allocated to the managed instance. The collector instead uses sys.dm_os_job_object to export the governed CPU and memory limits. It uses master.sys.server_resource_stats for direct CPU, vCore, storage, and I/O metrics. The I/O metrics are average rates calculated from the totals and actual duration of the latest source interval. This view is refreshed independently of the Prometheus scrape interval.

The login requires VIEW SERVER STATE on SQL Server 2019 and earlier. On SQL Server 2022 and later, VIEW SERVER PERFORMANCE STATE is also sufficient. Azure SQL Managed Instance requires VIEW SERVER PERFORMANCE STATE for process, job-object, and complete session metrics. Without that permission, user_sessions can include only the monitoring login’s own session.

Example

Alloy
database_observability.sql_server "orders_db" {
  data_source_name = "sqlserver://user:pass@server:1433"
  forward_to       = [loki.write.logs_service.receiver]
}

loki.write "logs_service" {
  endpoint {
    url = sys.env("<GRAFANA_CLOUD_HOSTED_LOGS_URL>")
    basic_auth {
      username = sys.env("<GRAFANA_CLOUD_HOSTED_LOGS_ID>")
      password = sys.env("<GRAFANA_CLOUD_RW_API_KEY>")
    }
  }
}

Replace the following:

  • <GRAFANA_CLOUD_HOSTED_LOGS_URL>: The URL for your Grafana Cloud hosted logs.
  • <GRAFANA_CLOUD_HOSTED_LOGS_ID>: The user ID for your Grafana Cloud hosted logs.
  • <GRAFANA_CLOUD_RW_API_KEY>: Your Grafana Cloud API key.

Compatible components

database_observability.sql_server can accept arguments from the following components:

database_observability.sql_server has exports that can be consumed by the following components:

Note

Connecting some components may not be sensible or components may require further configuration to make the connection work correctly. Refer to the linked documentation for more details.