Skip to main content
This example demonstrates Oracle Database monitoring using Query Exporter to collect metrics from Oracle’s dynamic performance views.

Overview

The Oracle monitoring example collects metrics from Oracle’s v$ views to track:
  • Session statistics and states
  • Resource utilization and limits
  • ASM diskgroup space usage
  • Database activity (parses, executions, commits)
  • Wait time statistics
  • Tablespace usage

Configuration

Database Connection

Oracle uses the oracle+oracledb:// DSN format with the python-oracledb driver:
databases:
  oracle:
    dsn: !env ORACLE_DATABASE_DSN

Oracle DSN Format

Oracle requires a more complex DSN that includes the TNS connection descriptor:
export ORACLE_DATABASE_DSN="oracle+oracledb://username:password@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=hostname)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL)))"
The Oracle DSN format includes the full TNS descriptor inline. This avoids the need for a separate tnsnames.ora file.

DSN Components

  • Protocol: Typically TCP
  • Host: Oracle database server hostname
  • Port: Usually 1521 for Oracle
  • SERVICE_NAME: The Oracle service name (not SID)
  • SERVER: DEDICATED or SHARED

Complete Example

# Collection of metrics and stats for Oracle database server.
#
# Metrics and queries are inspired by https://github.com/iamseth/oracledb_exporter

databases:
  oracle:
    dsn: !env ORACLE_DATABASE_DSN

metrics:
  oracle_sessions:
    type: gauge
    description: Number of sessions
    labels: [status, type]
  oracle_resouce_current_utilization:
    type: counter
    description: Current value from v$resource_limit view
    labels: [name]
  oracle_resource_limit:
    type: counter
    description: Limit value from v$resource_limit view
    labels: [name]
  oracle_asm_diskgroup_total:
    type: counter
    description: Total size of ASM disk group
    labels: [name]
  oracle_asm_diskgroup_free:
    type: counter
    description: Free space on ASM disk group
    labels: [name]
  oracle_activity:
    type: counter
    labels: [name]
    description: Database activity from v$sysstat view
  oracle_process:
    type: gauge
    description: Process count
  oracle_wait_time:
    type: counter
    description: Wait time from v$waitclassmetric view
    labels: [wait_class]
  oracle_tablespace_bytes:
    type: counter
    description: Tablespaces size
    labels: [tablespace, type]
  oracle_tablespace_max_bytes:
    type: counter
    description: Tablespaces max size
    labels: [tablespace, type]
  oracle_tablespace_free:
    type: counter
    description: Tablespaces free size
    labels: [tablespace, type]

queries:
  session_stats:
    databases: [oracle]
    metrics:
      - oracle_sessions
    sql: |
      SELECT
        status,
        type,
        COUNT(*) AS oracle_sessions
      FROM v$session
      GROUP BY status, type

  resource_stats:
    databases: [oracle]
    metrics:
      - oracle_resouce_current_utilization
      - oracle_resource_limit
    sql: |
      SELECT
        resource_name AS name,
        current_utilization AS oracle_resouce_current_utilization,
        limit_value AS oracle_resource_limit
      FROM v$resource_limit

  activity_stats:
    databases: [oracle]
    metrics:
      - oracle_activity
    sql: |
      SELECT
        name,
        value AS oracle_activity
      FROM v$sysstat
      WHERE name IN ('parse count (total)', 'execute count', 'user commits', 'user rollbacks')

  process_stats:
    databases: [oracle]
    metrics:
      - oracle_process
    sql: |
      SELECT COUNT(*) AS oracle_process FROM v$process

  wait_time_stats:
    databases: [oracle]
    metrics:
      - oracle_wait_time
    sql: |
      SELECT
        wait_class AS wait_class,
        time_waited AS oracle_wait_time
      FROM v$waitclassmetric
      WHERE wait_class != 'Idle'

  tablespace_stats:
    databases: [oracle]
    metrics:
      - oracle_tablespace_bytes
      - oracle_tablespace_max_bytes
      - oracle_tablespace_free
    sql: |
      SELECT
        z.name AS tablespace,
        dt.contents AS type,
        z.bytes AS oracle_tablespace_bytes,
        z.max_bytes AS oracle_tablespace_max_bytes,
        z.free_bytes AS oracle_tablespace_free
      FROM
        (
          SELECT
            x.name AS name,
            SUM(nvl(x.free_bytes,0)) AS free_bytes,
            SUM(x.bytes) AS bytes,
            SUM(x.max_bytes) AS max_bytes
          FROM
            (
              SELECT
                ddf.tablespace_name AS name,
                ddf.bytes AS bytes,
                sum(coalesce(dfs.bytes, 0)) AS free_bytes,
                CASE
                  WHEN ddf.maxbytes = 0 THEN ddf.bytes
                  ELSE ddf.maxbytes
                END AS max_bytes
              FROM
                sys.dba_data_files ddf,
                sys.dba_tablespaces dt,
                sys.dba_free_space dfs
              WHERE ddf.tablespace_name = dt.tablespace_name
              AND ddf.file_id = dfs.file_id(+)
              GROUP BY ddf.tablespace_name, ddf.file_name, ddf.status, ddf.bytes, ddf.maxbytes
            ) x
          GROUP BY x.name
        ) z,
        sys.dba_tablespaces dt
      WHERE z.name = dt.tablespace_name

Key Queries Explained

Session Statistics

Monitors active and inactive sessions by type:
SELECT
  status,
  type,
  COUNT(*) AS oracle_sessions
FROM v$session
GROUP BY status, type
Tracks sessions grouped by:
  • Status: ACTIVE, INACTIVE, KILLED, SNIPED
  • Type: USER, BACKGROUND, RECURSIVE

Resource Limits

Monitors current utilization against configured limits:
SELECT
  resource_name AS name,
  current_utilization AS oracle_resouce_current_utilization,
  limit_value AS oracle_resource_limit
FROM v$resource_limit
Key resources to monitor:
  • processes
  • sessions
  • parallel_max_servers

Database Activity

Tracks key database operations:
SELECT
  name,
  value AS oracle_activity
FROM v$sysstat
WHERE name IN ('parse count (total)', 'execute count', 'user commits', 'user rollbacks')
Monitors:
  • parse count (total): Number of SQL parses (hard and soft)
  • execute count: Total SQL executions
  • user commits: Committed transactions
  • user rollbacks: Rolled back transactions

Wait Time Statistics

Identifies database wait events by class:
SELECT
  wait_class AS wait_class,
  time_waited AS oracle_wait_time
FROM v$waitclassmetric
WHERE wait_class != 'Idle'
Common wait classes:
  • Application: Application-level waits
  • Commit: Log file sync waits
  • Concurrency: Lock contention
  • User I/O: Physical I/O waits
  • System I/O: Background I/O

Tablespace Usage

Monitors tablespace capacity and usage: The tablespace query joins multiple Oracle data dictionary views to calculate:
  • Total allocated space
  • Maximum possible space (considering autoextend)
  • Free space available
This helps identify tablespaces approaching capacity.

Oracle-Specific Considerations

Permissions Required

The monitoring user needs SELECT privileges on:
GRANT SELECT ON v_$session TO monitoring_user;
GRANT SELECT ON v_$resource_limit TO monitoring_user;
GRANT SELECT ON v_$sysstat TO monitoring_user;
GRANT SELECT ON v_$process TO monitoring_user;
GRANT SELECT ON v_$waitclassmetric TO monitoring_user;
GRANT SELECT ON sys.dba_data_files TO monitoring_user;
GRANT SELECT ON sys.dba_tablespaces TO monitoring_user;
GRANT SELECT ON sys.dba_free_space TO monitoring_user;
Access to v$ views typically requires the SELECT_CATALOG_ROLE role or explicit grants on each view.

ASM Diskgroup Monitoring

If using Oracle ASM (Automatic Storage Management), monitor diskgroup space:
queries:
  asm_diskgroup_stats:
    databases: [oracle]
    metrics:
      - oracle_asm_diskgroup_total
      - oracle_asm_diskgroup_free
    sql: |
      SELECT
        name,
        total_mb * 1024 * 1024 AS oracle_asm_diskgroup_total,
        free_mb * 1024 * 1024 AS oracle_asm_diskgroup_free
      FROM v$asm_diskgroup

Running the Example

  1. Install the Oracle driver:
    pip install oracledb
    
  2. Save the configuration as config.yaml
  3. Set your database connection:
    export ORACLE_DATABASE_DSN="oracle+oracledb://user:pass@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=dbhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL)))"
    
  4. Start Query Exporter:
    query-exporter config.yaml
    
  5. Access metrics at http://localhost:9560/metrics

Full Example Source

The complete Oracle monitoring example is available in the Query Exporter repository.

Performance Considerations

Some Oracle queries (especially tablespace calculations) can be expensive. Consider:
  • Increasing query intervals for heavy queries
  • Using materialized views for complex calculations
  • Monitoring during off-peak hours

Query Intervals

queries:
  tablespace_stats:
    databases: [oracle]
    interval: 300  # Run every 5 minutes instead of default
    metrics:
      - oracle_tablespace_bytes
      - oracle_tablespace_free
    sql: ...

Build docs developers (and LLMs) love