extensions:
health_check:
endpoint: 0.0.0.0:13133
processors:
memory_limiter:
check_interval: 1s
limit_percentage: 80
spike_limit_percentage: 25
resourcedetection:
detectors: [env, system]
timeout: 5s
override: true
system:
hostname_sources: [dns, os]
resource_attributes:
host.name: { enabled: true }
host.id: { enabled: true }
os.type: { enabled: true }
resource/postgres:
attributes:
- key: db.system
value: postgresql
action: upsert
- key: service.name
value: ${env:PG_CLUSTER_NAME}
action: upsert
- key: deployment.environment
value: ${env:OTEL_ENVIRONMENT:-production}
action: upsert
batch:
send_batch_size: 8192
send_batch_max_size: 10000
timeout: 5s
exporters:
otlp/querycomment:
endpoint: ${env:QC_ENDPOINT}
headers:
authorization: ${env:QC_INGEST_TOKEN}
compression: gzip
retry_on_failure:
enabled: true
initial_interval: 5s
max_interval: 30s
max_elapsed_time: 300s
sending_queue:
enabled: true
num_consumers: 4
queue_size: 5000
debug:
verbosity: normal
receivers:
postgresql:
endpoint: ${env:PG_HOST}:${env:PG_PORT}
transport: tcp
username: ${env:PG_USER}
password: ${env:PG_PASSWORD}
databases: []
# exclude_databases: [postgres, template0, template1] # optional
collection_interval: 15s
tls:
insecure: false
insecure_skip_verify: false
sqlquery/pg_statements_postgres_v13_16:
driver: postgres
datasource: "host=${env:PG_HOST} port=${env:PG_PORT} user=${env:PG_USER} password=${env:PG_PASSWORD} dbname=${env:PG_DBNAME} sslmode=${env:PG_SSLMODE}"
collection_interval: 15s
max_open_conn: 2
queries:
- sql: |
SELECT
pgss.queryid::text AS query_id,
LEFT(pgss.query, 500) AS query_text,
COALESCE(pg_database.datname, 'unknown') AS database_name,
COALESCE(pg_roles.rolname, 'unknown') AS role_name,
pgss.calls AS calls,
pgss.total_exec_time AS total_exec_time,
pgss.mean_exec_time AS mean_exec_time,
pgss.min_exec_time AS min_exec_time,
pgss.max_exec_time AS max_exec_time,
pgss.stddev_exec_time AS stddev_exec_time,
pgss.rows AS rows,
pgss.shared_blks_hit AS shared_blks_hit,
pgss.shared_blks_read AS shared_blks_read,
pgss.shared_blks_dirtied AS shared_blks_dirtied,
pgss.shared_blks_written AS shared_blks_written,
pgss.temp_blks_read AS temp_blks_read,
pgss.temp_blks_written AS temp_blks_written,
pgss.wal_records AS wal_records,
pgss.wal_bytes AS wal_bytes,
pgss.blk_read_time AS blk_read_time,
pgss.blk_write_time AS blk_write_time
FROM pg_stat_statements AS pgss
LEFT JOIN pg_roles ON pgss.userid = pg_roles.oid
LEFT JOIN pg_database ON pgss.dbid = pg_database.oid
WHERE pgss.queryid IS NOT NULL
AND pgss.query NOT ILIKE '%pg_stat_statements%'
AND pgss.query NOT ILIKE '%pg_catalog%'
AND pgss.query NOT ILIKE 'EXPLAIN%'
AND pgss.query NOT ILIKE 'PREPARE otel_%'
AND pgss.query NOT ILIKE 'CREATE %'
ORDER BY pgss.total_exec_time DESC
LIMIT 250
metrics: &stmt_metrics
- { metric_name: postgresql.stmt.calls, value_column: calls, attribute_columns: [query_id, database_name, role_name, query_text], value_type: int, data_type: sum, monotonic: true, aggregation: cumulative }
- { metric_name: postgresql.stmt.total_exec_time, value_column: total_exec_time, attribute_columns: [query_id, database_name, role_name, query_text], value_type: double, data_type: sum, monotonic: true, aggregation: cumulative, unit: ms }
- { metric_name: postgresql.stmt.mean_exec_time, value_column: mean_exec_time, attribute_columns: [query_id, database_name, role_name, query_text], value_type: double, data_type: gauge, unit: ms }
- { metric_name: postgresql.stmt.min_exec_time, value_column: min_exec_time, attribute_columns: [query_id, database_name, role_name, query_text], value_type: double, data_type: gauge, unit: ms }
- { metric_name: postgresql.stmt.max_exec_time, value_column: max_exec_time, attribute_columns: [query_id, database_name, role_name, query_text], value_type: double, data_type: gauge, unit: ms }
- { metric_name: postgresql.stmt.stddev_exec_time, value_column: stddev_exec_time, attribute_columns: [query_id, database_name, role_name, query_text], value_type: double, data_type: gauge, unit: ms }
- { metric_name: postgresql.stmt.rows, value_column: rows, attribute_columns: [query_id, database_name, role_name, query_text], value_type: int, data_type: sum, monotonic: true, aggregation: cumulative }
- { metric_name: postgresql.stmt.shared_blks_hit, value_column: shared_blks_hit, attribute_columns: [query_id, database_name, role_name, query_text], value_type: int, data_type: sum, monotonic: true, aggregation: cumulative }
- { metric_name: postgresql.stmt.shared_blks_read, value_column: shared_blks_read, attribute_columns: [query_id, database_name, role_name, query_text], value_type: int, data_type: sum, monotonic: true, aggregation: cumulative }
- { metric_name: postgresql.stmt.shared_blks_dirtied, value_column: shared_blks_dirtied, attribute_columns: [query_id, database_name, role_name, query_text], value_type: int, data_type: sum, monotonic: true, aggregation: cumulative }
- { metric_name: postgresql.stmt.shared_blks_written, value_column: shared_blks_written, attribute_columns: [query_id, database_name, role_name, query_text], value_type: int, data_type: sum, monotonic: true, aggregation: cumulative }
- { metric_name: postgresql.stmt.temp_blks_read, value_column: temp_blks_read, attribute_columns: [query_id, database_name, role_name, query_text], value_type: int, data_type: sum, monotonic: true, aggregation: cumulative }
- { metric_name: postgresql.stmt.temp_blks_written, value_column: temp_blks_written, attribute_columns: [query_id, database_name, role_name, query_text], value_type: int, data_type: sum, monotonic: true, aggregation: cumulative }
- { metric_name: postgresql.stmt.wal_records, value_column: wal_records, attribute_columns: [query_id, database_name, role_name, query_text], value_type: int, data_type: sum, monotonic: true, aggregation: cumulative }
- { metric_name: postgresql.stmt.wal_bytes, value_column: wal_bytes, attribute_columns: [query_id, database_name, role_name, query_text], value_type: int, data_type: sum, monotonic: true, aggregation: cumulative, unit: By }
- { metric_name: postgresql.stmt.blk_read_time, value_column: blk_read_time, attribute_columns: [query_id, database_name, role_name, query_text], value_type: double, data_type: sum, monotonic: true, aggregation: cumulative, unit: ms }
- { metric_name: postgresql.stmt.blk_write_time, value_column: blk_write_time, attribute_columns: [query_id, database_name, role_name, query_text], value_type: double, data_type: sum, monotonic: true, aggregation: cumulative, unit: ms }
sqlquery/pg_statements_postgres_v17_plus:
driver: postgres
datasource: "host=${env:PG_HOST} port=${env:PG_PORT} user=${env:PG_USER} password=${env:PG_PASSWORD} dbname=${env:PG_DBNAME} sslmode=${env:PG_SSLMODE}"
collection_interval: 15s
max_open_conn: 2
queries:
- sql: |
SELECT
pgss.queryid::text AS query_id,
LEFT(pgss.query, 500) AS query_text,
COALESCE(pg_database.datname, 'unknown') AS database_name,
COALESCE(pg_roles.rolname, 'unknown') AS role_name,
pgss.calls AS calls,
pgss.total_exec_time AS total_exec_time,
pgss.mean_exec_time AS mean_exec_time,
pgss.min_exec_time AS min_exec_time,
pgss.max_exec_time AS max_exec_time,
pgss.stddev_exec_time AS stddev_exec_time,
pgss.rows AS rows,
pgss.shared_blks_hit AS shared_blks_hit,
pgss.shared_blks_read AS shared_blks_read,
pgss.shared_blks_dirtied AS shared_blks_dirtied,
pgss.shared_blks_written AS shared_blks_written,
pgss.temp_blks_read AS temp_blks_read,
pgss.temp_blks_written AS temp_blks_written,
pgss.wal_records AS wal_records,
pgss.wal_bytes AS wal_bytes,
pgss.shared_blk_read_time AS blk_read_time,
pgss.shared_blk_write_time AS blk_write_time
FROM pg_stat_statements AS pgss
LEFT JOIN pg_roles ON pgss.userid = pg_roles.oid
LEFT JOIN pg_database ON pgss.dbid = pg_database.oid
WHERE pgss.queryid IS NOT NULL
AND pgss.query NOT ILIKE '%pg_stat_statements%'
AND pgss.query NOT ILIKE '%pg_catalog%'
AND pgss.query NOT ILIKE 'EXPLAIN%'
AND pgss.query NOT ILIKE 'PREPARE otel_%'
AND pgss.query NOT ILIKE 'CREATE %'
ORDER BY pgss.total_exec_time DESC
LIMIT 250
metrics: *stmt_metrics
sqlquery/pg_statements_postgres_v11_12:
driver: postgres
datasource: "host=${env:PG_HOST} port=${env:PG_PORT} user=${env:PG_USER} password=${env:PG_PASSWORD} dbname=${env:PG_DBNAME} sslmode=${env:PG_SSLMODE}"
collection_interval: 15s
max_open_conn: 2
queries:
- sql: |
SELECT
pgss.queryid::text AS query_id,
LEFT(pgss.query, 500) AS query_text,
COALESCE(pg_database.datname, 'unknown') AS database_name,
COALESCE(pg_roles.rolname, 'unknown') AS role_name,
pgss.calls AS calls,
pgss.total_time AS total_exec_time,
pgss.mean_time AS mean_exec_time,
pgss.min_time AS min_exec_time,
pgss.max_time AS max_exec_time,
pgss.stddev_time AS stddev_exec_time,
pgss.rows AS rows,
pgss.shared_blks_hit AS shared_blks_hit,
pgss.shared_blks_read AS shared_blks_read,
pgss.shared_blks_dirtied AS shared_blks_dirtied,
pgss.shared_blks_written AS shared_blks_written,
pgss.temp_blks_read AS temp_blks_read,
pgss.temp_blks_written AS temp_blks_written,
0::bigint AS wal_records,
0::numeric AS wal_bytes,
pgss.blk_read_time AS blk_read_time,
pgss.blk_write_time AS blk_write_time
FROM pg_stat_statements AS pgss
LEFT JOIN pg_roles ON pgss.userid = pg_roles.oid
LEFT JOIN pg_database ON pgss.dbid = pg_database.oid
WHERE pgss.queryid IS NOT NULL
AND pgss.query NOT ILIKE '%pg_stat_statements%'
AND pgss.query NOT ILIKE '%pg_catalog%'
AND pgss.query NOT ILIKE 'EXPLAIN%'
AND pgss.query NOT ILIKE 'PREPARE otel_%'
AND pgss.query NOT ILIKE 'CREATE %'
ORDER BY pgss.total_time DESC
LIMIT 250
metrics: *stmt_metrics
service:
pipelines:
metrics/postgres:
receivers: [postgresql, sqlquery/pg_statements_postgres_v13_16]
processors: [memory_limiter, resourcedetection, resource/postgres, batch]
exporters: [otlp/querycomment]