├── PostgreSQL Stats Example.json ├── README.md ├── defaults └── main.yml ├── handlers └── main.yml ├── meta └── main.yml ├── tasks └── main.yml └── templates ├── metrics.yaml.j2 ├── postgresql-exporter.service.j2 └── postgresql-prometheus_metrics.yaml.j2 /PostgreSQL Stats Example.json: -------------------------------------------------------------------------------- 1 | { 2 | "__inputs": [ 3 | { 4 | "name": "DS_PROMETHEUS", 5 | "label": "Prometheus", 6 | "description": "", 7 | "type": "datasource", 8 | "pluginId": "prometheus", 9 | "pluginName": "Prometheus" 10 | } 11 | ], 12 | "__requires": [ 13 | { 14 | "type": "grafana", 15 | "id": "grafana", 16 | "name": "Grafana", 17 | "version": "4.6.3" 18 | }, 19 | { 20 | "type": "panel", 21 | "id": "graph", 22 | "name": "Graph", 23 | "version": "" 24 | }, 25 | { 26 | "type": "datasource", 27 | "id": "prometheus", 28 | "name": "Prometheus", 29 | "version": "1.0.0" 30 | }, 31 | { 32 | "type": "panel", 33 | "id": "table", 34 | "name": "Table", 35 | "version": "" 36 | } 37 | ], 38 | "annotations": { 39 | "list": [ 40 | { 41 | "builtIn": 1, 42 | "datasource": "-- Grafana --", 43 | "enable": true, 44 | "hide": true, 45 | "iconColor": "rgba(0, 211, 255, 1)", 46 | "name": "Annotations & Alerts", 47 | "type": "dashboard" 48 | } 49 | ] 50 | }, 51 | "editable": true, 52 | "gnetId": null, 53 | "graphTooltip": 0, 54 | "hideControls": false, 55 | "id": null, 56 | "links": [], 57 | "refresh": "30s", 58 | "rows": [ 59 | { 60 | "collapse": false, 61 | "height": "250px", 62 | "panels": [ 63 | { 64 | "aliasColors": {}, 65 | "bars": false, 66 | "dashLength": 10, 67 | "dashes": false, 68 | "datasource": "${DS_PROMETHEUS}", 69 | "fill": 1, 70 | "id": 1, 71 | "legend": { 72 | "avg": false, 73 | "current": false, 74 | "max": false, 75 | "min": false, 76 | "show": true, 77 | "total": false, 78 | "values": false 79 | }, 80 | "lines": true, 81 | "linewidth": 1, 82 | "links": [], 83 | "nullPointMode": "null", 84 | "percentage": false, 85 | "pointradius": 5, 86 | "points": false, 87 | "renderer": "flot", 88 | "seriesOverrides": [], 89 | "spaceLength": 10, 90 | "span": 6, 91 | "stack": false, 92 | "steppedLine": false, 93 | "targets": [ 94 | { 95 | "expr": "sum(rate(pg_stat_statements_mean_time{datname!~\"template.*\", datname!~\"postgres\", instance=~\"$server\"}[1m])) by (instance)", 96 | "format": "time_series", 97 | "intervalFactor": 2, 98 | "legendFormat": "{{ instance }}", 99 | "refId": "A" 100 | } 101 | ], 102 | "thresholds": [], 103 | "timeFrom": null, 104 | "timeShift": null, 105 | "title": "Mean query time (by entire instance)", 106 | "tooltip": { 107 | "shared": true, 108 | "sort": 0, 109 | "value_type": "individual" 110 | }, 111 | "type": "graph", 112 | "xaxis": { 113 | "buckets": null, 114 | "mode": "time", 115 | "name": null, 116 | "show": true, 117 | "values": [] 118 | }, 119 | "yaxes": [ 120 | { 121 | "format": "ms", 122 | "label": null, 123 | "logBase": 1, 124 | "max": null, 125 | "min": null, 126 | "show": true 127 | }, 128 | { 129 | "format": "short", 130 | "label": null, 131 | "logBase": 1, 132 | "max": null, 133 | "min": null, 134 | "show": true 135 | } 136 | ] 137 | }, 138 | { 139 | "aliasColors": {}, 140 | "bars": false, 141 | "dashLength": 10, 142 | "dashes": false, 143 | "datasource": "${DS_PROMETHEUS}", 144 | "fill": 1, 145 | "id": 2, 146 | "legend": { 147 | "avg": false, 148 | "current": false, 149 | "max": false, 150 | "min": false, 151 | "show": true, 152 | "total": false, 153 | "values": false 154 | }, 155 | "lines": true, 156 | "linewidth": 1, 157 | "links": [], 158 | "nullPointMode": "null", 159 | "percentage": false, 160 | "pointradius": 5, 161 | "points": false, 162 | "renderer": "flot", 163 | "seriesOverrides": [], 164 | "spaceLength": 10, 165 | "span": 6, 166 | "stack": false, 167 | "steppedLine": false, 168 | "targets": [ 169 | { 170 | "expr": "sum(rate(pg_stat_statements_mean_time{datname!~\"template.*\", datname!~\"postgres\", instance=~\"$server\", datname=~\"$database\"}[1m])) by (datname)", 171 | "format": "time_series", 172 | "intervalFactor": 2, 173 | "legendFormat": "{{ datname }}", 174 | "refId": "A" 175 | } 176 | ], 177 | "thresholds": [], 178 | "timeFrom": null, 179 | "timeShift": null, 180 | "title": "Mean query time (by entire database)", 181 | "tooltip": { 182 | "shared": true, 183 | "sort": 0, 184 | "value_type": "individual" 185 | }, 186 | "type": "graph", 187 | "xaxis": { 188 | "buckets": null, 189 | "mode": "time", 190 | "name": null, 191 | "show": true, 192 | "values": [] 193 | }, 194 | "yaxes": [ 195 | { 196 | "format": "ms", 197 | "label": null, 198 | "logBase": 1, 199 | "max": null, 200 | "min": null, 201 | "show": true 202 | }, 203 | { 204 | "format": "short", 205 | "label": null, 206 | "logBase": 1, 207 | "max": null, 208 | "min": null, 209 | "show": true 210 | } 211 | ] 212 | } 213 | ], 214 | "repeat": null, 215 | "repeatIteration": null, 216 | "repeatRowId": null, 217 | "showTitle": true, 218 | "title": "Syntetic query time", 219 | "titleSize": "h6" 220 | }, 221 | { 222 | "collapse": false, 223 | "height": 250, 224 | "panels": [ 225 | { 226 | "aliasColors": {}, 227 | "bars": false, 228 | "dashLength": 10, 229 | "dashes": false, 230 | "datasource": "${DS_PROMETHEUS}", 231 | "fill": 1, 232 | "id": 3, 233 | "legend": { 234 | "avg": false, 235 | "current": false, 236 | "max": false, 237 | "min": false, 238 | "show": true, 239 | "total": false, 240 | "values": false 241 | }, 242 | "lines": true, 243 | "linewidth": 1, 244 | "links": [], 245 | "nullPointMode": "null", 246 | "percentage": false, 247 | "pointradius": 5, 248 | "points": false, 249 | "renderer": "flot", 250 | "seriesOverrides": [], 251 | "spaceLength": 10, 252 | "span": 6, 253 | "stack": false, 254 | "steppedLine": false, 255 | "targets": [ 256 | { 257 | "expr": "sum(increase(pg_stat_statements_calls{datname!~\"template.*\", datname!~\"postgres\", instance=~\"$server\"}[1m])) by (instance)", 258 | "format": "time_series", 259 | "intervalFactor": 2, 260 | "legendFormat": "{{instance}}", 261 | "refId": "A" 262 | } 263 | ], 264 | "thresholds": [], 265 | "timeFrom": null, 266 | "timeShift": null, 267 | "title": "Total queries count (1m rate) by entire instance", 268 | "tooltip": { 269 | "shared": true, 270 | "sort": 0, 271 | "value_type": "individual" 272 | }, 273 | "type": "graph", 274 | "xaxis": { 275 | "buckets": null, 276 | "mode": "time", 277 | "name": null, 278 | "show": true, 279 | "values": [] 280 | }, 281 | "yaxes": [ 282 | { 283 | "format": "short", 284 | "label": null, 285 | "logBase": 1, 286 | "max": null, 287 | "min": null, 288 | "show": true 289 | }, 290 | { 291 | "format": "short", 292 | "label": null, 293 | "logBase": 1, 294 | "max": null, 295 | "min": null, 296 | "show": true 297 | } 298 | ] 299 | }, 300 | { 301 | "aliasColors": {}, 302 | "bars": false, 303 | "dashLength": 10, 304 | "dashes": false, 305 | "datasource": "${DS_PROMETHEUS}", 306 | "fill": 1, 307 | "id": 4, 308 | "legend": { 309 | "avg": false, 310 | "current": false, 311 | "max": false, 312 | "min": false, 313 | "show": true, 314 | "total": false, 315 | "values": false 316 | }, 317 | "lines": true, 318 | "linewidth": 1, 319 | "links": [], 320 | "nullPointMode": "null", 321 | "percentage": false, 322 | "pointradius": 5, 323 | "points": false, 324 | "renderer": "flot", 325 | "seriesOverrides": [], 326 | "spaceLength": 10, 327 | "span": 6, 328 | "stack": false, 329 | "steppedLine": false, 330 | "targets": [ 331 | { 332 | "expr": "sum(increase(pg_stat_statements_calls{datname!~\"template.*\", datname!~\"postgres\", instance=~\"$server\", datname=~\"$database\"}[1m])) by (datname)", 333 | "format": "time_series", 334 | "intervalFactor": 2, 335 | "legendFormat": "{{ datname }}", 336 | "refId": "A" 337 | } 338 | ], 339 | "thresholds": [], 340 | "timeFrom": null, 341 | "timeShift": null, 342 | "title": "Total queries count (1m rate) by database", 343 | "tooltip": { 344 | "shared": true, 345 | "sort": 0, 346 | "value_type": "individual" 347 | }, 348 | "type": "graph", 349 | "xaxis": { 350 | "buckets": null, 351 | "mode": "time", 352 | "name": null, 353 | "show": true, 354 | "values": [] 355 | }, 356 | "yaxes": [ 357 | { 358 | "format": "short", 359 | "label": null, 360 | "logBase": 1, 361 | "max": null, 362 | "min": null, 363 | "show": true 364 | }, 365 | { 366 | "format": "short", 367 | "label": null, 368 | "logBase": 1, 369 | "max": null, 370 | "min": null, 371 | "show": true 372 | } 373 | ] 374 | } 375 | ], 376 | "repeat": null, 377 | "repeatIteration": null, 378 | "repeatRowId": null, 379 | "showTitle": true, 380 | "title": "Syntetic queries count", 381 | "titleSize": "h6" 382 | }, 383 | { 384 | "collapse": false, 385 | "height": 250, 386 | "panels": [ 387 | { 388 | "aliasColors": {}, 389 | "bars": false, 390 | "dashLength": 10, 391 | "dashes": false, 392 | "datasource": "${DS_PROMETHEUS}", 393 | "fill": 1, 394 | "id": 5, 395 | "legend": { 396 | "avg": false, 397 | "current": false, 398 | "max": false, 399 | "min": false, 400 | "show": true, 401 | "total": false, 402 | "values": false 403 | }, 404 | "lines": true, 405 | "linewidth": 1, 406 | "links": [], 407 | "nullPointMode": "null", 408 | "percentage": false, 409 | "pointradius": 5, 410 | "points": false, 411 | "renderer": "flot", 412 | "seriesOverrides": [], 413 | "spaceLength": 10, 414 | "span": 12, 415 | "stack": false, 416 | "steppedLine": false, 417 | "targets": [ 418 | { 419 | "expr": "pg_database_size{datname!~\"template.*\", datname!~\"postgres\", instance=~\"$server\", datname=~\"$database\"}/(1024*1024*1024)", 420 | "format": "time_series", 421 | "intervalFactor": 2, 422 | "legendFormat": "{{ datname }}", 423 | "refId": "A" 424 | } 425 | ], 426 | "thresholds": [], 427 | "timeFrom": null, 428 | "timeShift": null, 429 | "title": "Database size", 430 | "tooltip": { 431 | "shared": true, 432 | "sort": 0, 433 | "value_type": "individual" 434 | }, 435 | "type": "graph", 436 | "xaxis": { 437 | "buckets": null, 438 | "mode": "time", 439 | "name": null, 440 | "show": true, 441 | "values": [] 442 | }, 443 | "yaxes": [ 444 | { 445 | "format": "decgbytes", 446 | "label": null, 447 | "logBase": 1, 448 | "max": null, 449 | "min": null, 450 | "show": true 451 | }, 452 | { 453 | "format": "short", 454 | "label": null, 455 | "logBase": 1, 456 | "max": null, 457 | "min": null, 458 | "show": true 459 | } 460 | ] 461 | } 462 | ], 463 | "repeat": null, 464 | "repeatIteration": null, 465 | "repeatRowId": null, 466 | "showTitle": false, 467 | "title": "Dashboard Row", 468 | "titleSize": "h6" 469 | }, 470 | { 471 | "collapse": false, 472 | "height": 250, 473 | "panels": [ 474 | { 475 | "columns": [], 476 | "datasource": "${DS_PROMETHEUS}", 477 | "fontSize": "100%", 478 | "id": 6, 479 | "links": [], 480 | "pageSize": null, 481 | "scroll": true, 482 | "showHeader": true, 483 | "sort": { 484 | "col": 7, 485 | "desc": true 486 | }, 487 | "span": 12, 488 | "styles": [ 489 | { 490 | "alias": "Time", 491 | "dateFormat": "YYYY-MM-DD HH:mm:ss", 492 | "pattern": "Time", 493 | "type": "hidden" 494 | }, 495 | { 496 | "alias": "", 497 | "colorMode": null, 498 | "colors": [ 499 | "rgba(245, 54, 54, 0.9)", 500 | "rgba(237, 129, 40, 0.89)", 501 | "rgba(50, 172, 45, 0.97)" 502 | ], 503 | "dateFormat": "YYYY-MM-DD HH:mm:ss", 504 | "decimals": 2, 505 | "pattern": "job", 506 | "thresholds": [], 507 | "type": "hidden", 508 | "unit": "short" 509 | }, 510 | { 511 | "alias": "", 512 | "colorMode": null, 513 | "colors": [ 514 | "rgba(245, 54, 54, 0.9)", 515 | "rgba(237, 129, 40, 0.89)", 516 | "rgba(50, 172, 45, 0.97)" 517 | ], 518 | "dateFormat": "YYYY-MM-DD HH:mm:ss", 519 | "decimals": 2, 520 | "pattern": "queryid", 521 | "thresholds": [], 522 | "type": "hidden", 523 | "unit": "short" 524 | }, 525 | { 526 | "alias": "", 527 | "colorMode": null, 528 | "colors": [ 529 | "rgba(245, 54, 54, 0.9)", 530 | "rgba(237, 129, 40, 0.89)", 531 | "rgba(50, 172, 45, 0.97)" 532 | ], 533 | "dateFormat": "YYYY-MM-DD HH:mm:ss", 534 | "decimals": 2, 535 | "pattern": "team", 536 | "thresholds": [], 537 | "type": "hidden", 538 | "unit": "short" 539 | }, 540 | { 541 | "alias": "", 542 | "colorMode": null, 543 | "colors": [ 544 | "rgba(245, 54, 54, 0.9)", 545 | "rgba(237, 129, 40, 0.89)", 546 | "rgba(50, 172, 45, 0.97)" 547 | ], 548 | "decimals": 2, 549 | "pattern": "/.*/", 550 | "thresholds": [], 551 | "type": "number", 552 | "unit": "short" 553 | } 554 | ], 555 | "targets": [ 556 | { 557 | "expr": "topk(20, increase(pg_stat_statements_calls{datname!~\"template.*\", datname!~\"postgres\", instance=~\"$server\", datname=~\"$database\"}[10m]))", 558 | "format": "table", 559 | "instant": true, 560 | "intervalFactor": 2, 561 | "legendFormat": "", 562 | "refId": "A" 563 | } 564 | ], 565 | "title": "TOP-20 Most called queries (10m rate)", 566 | "transform": "table", 567 | "type": "table" 568 | } 569 | ], 570 | "repeat": null, 571 | "repeatIteration": null, 572 | "repeatRowId": null, 573 | "showTitle": false, 574 | "title": "Dashboard Row", 575 | "titleSize": "h6" 576 | }, 577 | { 578 | "collapse": false, 579 | "height": 250, 580 | "panels": [ 581 | { 582 | "columns": [], 583 | "datasource": "${DS_PROMETHEUS}", 584 | "fontSize": "100%", 585 | "id": 7, 586 | "links": [], 587 | "pageSize": null, 588 | "scroll": true, 589 | "showHeader": true, 590 | "sort": { 591 | "col": 2, 592 | "desc": false 593 | }, 594 | "span": 12, 595 | "styles": [ 596 | { 597 | "alias": "Time", 598 | "dateFormat": "YYYY-MM-DD HH:mm:ss", 599 | "pattern": "Time", 600 | "type": "hidden" 601 | }, 602 | { 603 | "alias": "", 604 | "colorMode": null, 605 | "colors": [ 606 | "rgba(245, 54, 54, 0.9)", 607 | "rgba(237, 129, 40, 0.89)", 608 | "rgba(50, 172, 45, 0.97)" 609 | ], 610 | "dateFormat": "YYYY-MM-DD HH:mm:ss", 611 | "decimals": 2, 612 | "pattern": "job", 613 | "thresholds": [], 614 | "type": "hidden", 615 | "unit": "short" 616 | }, 617 | { 618 | "alias": "", 619 | "colorMode": null, 620 | "colors": [ 621 | "rgba(245, 54, 54, 0.9)", 622 | "rgba(237, 129, 40, 0.89)", 623 | "rgba(50, 172, 45, 0.97)" 624 | ], 625 | "dateFormat": "YYYY-MM-DD HH:mm:ss", 626 | "decimals": 2, 627 | "pattern": "queryid", 628 | "thresholds": [], 629 | "type": "hidden", 630 | "unit": "short" 631 | }, 632 | { 633 | "alias": "", 634 | "colorMode": null, 635 | "colors": [ 636 | "rgba(245, 54, 54, 0.9)", 637 | "rgba(237, 129, 40, 0.89)", 638 | "rgba(50, 172, 45, 0.97)" 639 | ], 640 | "dateFormat": "YYYY-MM-DD HH:mm:ss", 641 | "decimals": 2, 642 | "pattern": "team", 643 | "thresholds": [], 644 | "type": "hidden", 645 | "unit": "short" 646 | }, 647 | { 648 | "alias": "", 649 | "colorMode": null, 650 | "colors": [ 651 | "rgba(245, 54, 54, 0.9)", 652 | "rgba(237, 129, 40, 0.89)", 653 | "rgba(50, 172, 45, 0.97)" 654 | ], 655 | "dateFormat": "YYYY-MM-DD HH:mm:ss", 656 | "decimals": 2, 657 | "pattern": "__name__", 658 | "thresholds": [], 659 | "type": "hidden", 660 | "unit": "short" 661 | }, 662 | { 663 | "alias": "", 664 | "colorMode": null, 665 | "colors": [ 666 | "rgba(245, 54, 54, 0.9)", 667 | "rgba(237, 129, 40, 0.89)", 668 | "rgba(50, 172, 45, 0.97)" 669 | ], 670 | "decimals": 2, 671 | "pattern": "/.*/", 672 | "thresholds": [], 673 | "type": "number", 674 | "unit": "short" 675 | } 676 | ], 677 | "targets": [ 678 | { 679 | "expr": "topk(20, pg_stat_statements_mean_time{datname!~\"template.*\", datname!~\"postgres\", short_query!~\"COPY.*\", instance=~\"$server\", datname=~\"$database\"})", 680 | "format": "table", 681 | "instant": true, 682 | "intervalFactor": 2, 683 | "legendFormat": "", 684 | "refId": "A" 685 | } 686 | ], 687 | "title": "TOP-20 Most long-running queries (by mean_time, except backups)", 688 | "transform": "table", 689 | "type": "table" 690 | } 691 | ], 692 | "repeat": null, 693 | "repeatIteration": null, 694 | "repeatRowId": null, 695 | "showTitle": false, 696 | "title": "Dashboard Row", 697 | "titleSize": "h6" 698 | } 699 | ], 700 | "schemaVersion": 14, 701 | "style": "dark", 702 | "tags": [], 703 | "templating": { 704 | "list": [ 705 | { 706 | "allValue": ".*", 707 | "current": {}, 708 | "datasource": "${DS_PROMETHEUS}", 709 | "hide": 0, 710 | "includeAll": true, 711 | "label": "Server", 712 | "multi": true, 713 | "name": "server", 714 | "options": [], 715 | "query": "label_values(instance)", 716 | "refresh": 1, 717 | "regex": ".*9187", 718 | "sort": 1, 719 | "tagValuesQuery": "", 720 | "tags": [], 721 | "tagsQuery": "", 722 | "type": "query", 723 | "useTags": false 724 | }, 725 | { 726 | "allValue": ".*", 727 | "current": {}, 728 | "datasource": "${DS_PROMETHEUS}", 729 | "hide": 0, 730 | "includeAll": true, 731 | "label": "Database", 732 | "multi": true, 733 | "name": "database", 734 | "options": [], 735 | "query": "label_values(datname)", 736 | "refresh": 1, 737 | "regex": "(?!^template)(?!^postgres$)(^.*$)", 738 | "sort": 1, 739 | "tagValuesQuery": "", 740 | "tags": [], 741 | "tagsQuery": "", 742 | "type": "query", 743 | "useTags": false 744 | } 745 | ] 746 | }, 747 | "time": { 748 | "from": "now-1h", 749 | "to": "now" 750 | }, 751 | "timepicker": { 752 | "refresh_intervals": [ 753 | "5s", 754 | "10s", 755 | "30s", 756 | "1m", 757 | "5m", 758 | "15m", 759 | "30m", 760 | "1h", 761 | "2h", 762 | "1d" 763 | ], 764 | "time_options": [ 765 | "5m", 766 | "15m", 767 | "1h", 768 | "6h", 769 | "12h", 770 | "24h", 771 | "2d", 772 | "7d", 773 | "30d" 774 | ] 775 | }, 776 | "timezone": "", 777 | "title": "PostgreSQL Stats Copy", 778 | "version": 1 779 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Postgresql-Exporter 2 | ========= 3 | 4 | This role installs binary postgres_exporter on Redhat-like system (any other OS with systemd should work too) from Github releases and allows access from prometheus servers 5 | 6 | Requirements 7 | ------------ 8 | 9 | Server should have working PostgreSQL server with loaded `pg_stat_statements` shared library. 10 | 11 | Example Playbook 12 | ---------------- 13 | 14 | 15 | ``` 16 | - hosts: postgresql-exporter 17 | become: true 18 | roles: 19 | - role: postgresql-exporter 20 | tags: 21 | - postgresql-exporter 22 | ``` 23 | 24 | License 25 | ------- 26 | 27 | MIT 28 | 29 | Author Information 30 | ------------------ 31 | 32 | Anton Markelov -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # defaults file for postgres_exporter 3 | pg_exporter_user: 'pg_exporter' 4 | pg_exporter_dir: '/opt/postgres_exporter' 5 | pg_exporter_connection_string: 'DATA_SOURCE_NAME="user=postgres host=/var/run/postgresql/ sslmode=disable"' 6 | pg_exporter_start_flags: "--extend.query-path={{ pg_exporter_dir }}/metrics.yaml --web.listen-address=:{{ pg_exporter_port }}" 7 | pg_exporter_version: "0.4.1" 8 | pg_exporter_port: 9187 9 | pg_exporter_team: 'dba' -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # handlers file for postgres_exporter 3 | - name: restart postgresql-exporter 4 | service: name=postgresql-exporter state=restarted 5 | 6 | - name: systemctl daemon-reload 7 | command: systemctl daemon-reload 8 | notify: restart postgresql-exporter 9 | 10 | - name: reload prometheus 11 | uri: 12 | url: http://localhost:9090/-/reload 13 | method: POST 14 | listen: "reload prometheus" 15 | delegate_to: "{{ item }}" 16 | delegate_facts: True 17 | with_items: "{{ groups.prometheus | default([]) }}" 18 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | galaxy_info: 2 | author: Anton Markelov 3 | description: role for prometheus postgresql exporter 4 | company: United Traders 5 | 6 | license: MIT 7 | 8 | min_ansible_version: 2.3 9 | 10 | platforms: 11 | - name: EL 12 | versions: 13 | - 7 14 | 15 | galaxy_tags: [] 16 | 17 | dependencies: [] -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # tasks file for postgres_exporter 3 | 4 | - name: add pg_stat_statements extention 5 | postgresql_ext: 6 | name: pg_stat_statements 7 | db: postgres 8 | 9 | - name: create user for exporter 10 | user: name='{{ pg_exporter_user }}' 11 | 12 | - name: create directory for exporter 13 | file: state=directory path={{ pg_exporter_dir }} owner={{ pg_exporter_user }} recurse=true 14 | 15 | - name: create service 16 | template: src='postgresql-exporter.service.j2' dest='/etc/systemd/system/postgresql-exporter.service' 17 | notify: systemctl daemon-reload 18 | 19 | - meta: flush_handlers 20 | 21 | - name: download and unpack exporter 22 | unarchive: 23 | src: 'https://github.com/wrouesnel/postgres_exporter/releases/download/v{{ pg_exporter_version }}/postgres_exporter_v{{ pg_exporter_version }}_linux-amd64.tar.gz' 24 | dest: '{{ pg_exporter_dir }}' 25 | remote_src: yes 26 | owner: '{{ pg_exporter_user }}' 27 | notify: restart postgresql-exporter 28 | 29 | - name: create metrics file 30 | template: src='metrics.yaml.j2' dest='{{ pg_exporter_dir }}/metrics.yaml' owner='{{ pg_exporter_user }}' 31 | notify: restart postgresql-exporter 32 | 33 | - name: create env file (because I hate systemd-escape) 34 | copy: content='{{ pg_exporter_connection_string }}' dest='{{ pg_exporter_dir }}/env' owner='{{ pg_exporter_user }}' 35 | notify: restart postgresql-exporter 36 | 37 | - name: start service 38 | service: name=postgresql-exporter state=started enabled=yes 39 | 40 | - name: Enable access to exporters 41 | firewalld: 42 | rich_rule='rule family="ipv4" source address="{{ hostvars[item]['ansible_ssh_host'] }}/32" port port="{{ pg_exporter_port }}" protocol="tcp" accept' 43 | permanent=true 44 | state=enabled 45 | zone=public 46 | immediate=true 47 | with_items: "{{ groups['prometheus'] }}" 48 | 49 | - name: create prometheus job file for metrics gathering 50 | template: src=postgresql-prometheus_metrics.yaml.j2 dest=/etc/prometheus/hosts/postgresql-{{ ansible_fqdn }}-{{ deploy_env }}.yaml 51 | delegate_to: "{{ item }}" 52 | delegate_facts: True 53 | when: has_metrics == true 54 | notify: reload prometheus 55 | with_items: "{{ groups.prometheus | default([]) }}" -------------------------------------------------------------------------------- /templates/metrics.yaml.j2: -------------------------------------------------------------------------------- 1 | replication: 2 | query: "SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))::INT as lag" 3 | metrics: 4 | - lag: 5 | usage: "GAUGE" 6 | description: "Replication lag behind master in seconds" 7 | 8 | pg_postmaster: 9 | query: "SELECT pg_postmaster_start_time as start_time_seconds from pg_postmaster_start_time()" 10 | metrics: 11 | - start_time_seconds: 12 | usage: "GAUGE" 13 | description: "Time at which postmaster started" 14 | 15 | pg_database: 16 | query: " SELECT pg_database.datname, pg_database_size(pg_database.datname) as size FROM pg_database" 17 | metrics: 18 | - datname: 19 | usage: "LABEL" 20 | description: "Name of the database" 21 | - size: 22 | usage: "GAUGE" 23 | description: "Disk space used by the database" 24 | 25 | pg_stat_statements: 26 | query: "SELECT queryid, datname, left(query, 50) as short_query, sum(calls) as calls, sum(total_time) as total_time, min(min_time) as min_time, max(max_time) as max_time, sum(mean_time*calls)/sum(calls) as mean_time FROM pg_stat_statements JOIN pg_database ON pg_stat_statements.dbid = pg_database.oid group by queryid, short_query, datname" 27 | metrics: 28 | - queryid: 29 | usage: "LABEL" 30 | description: "Query ID" 31 | - datname: 32 | usage: "LABEL" 33 | description: "Database name" 34 | - short_query: 35 | usage: "LABEL" 36 | description: "Query limited to 50 symbols" 37 | - calls: 38 | usage: "COUNTER" 39 | description: "Number of times executed" 40 | - total_time: 41 | usage: "COUNTER" 42 | description: "Total time spent in the statement, in milliseconds" 43 | - min_time: 44 | usage: "GAUGE" 45 | description: "Minimum time spent in the statement, in milliseconds" 46 | - max_time: 47 | usage: "GAUGE" 48 | description: "Maximum time spent in the statement, in milliseconds" 49 | - mean_time: 50 | usage: "GAUGE" 51 | description: "Mean time spent in the statement, in milliseconds" -------------------------------------------------------------------------------- /templates/postgresql-exporter.service.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Prometheus exporter for Postgresql (https://github.com/wrouesnel/postgres_exporter) 3 | 4 | [Service] 5 | WorkingDirectory={{ pg_exporter_dir }} 6 | EnvironmentFile={{ pg_exporter_dir }}/env 7 | ExecStart={{ pg_exporter_dir }}/postgres_exporter_v{{ pg_exporter_version }}_linux-amd64/postgres_exporter {{ pg_exporter_start_flags }} 8 | User={{ pg_exporter_user }} 9 | 10 | [Install] 11 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /templates/postgresql-prometheus_metrics.yaml.j2: -------------------------------------------------------------------------------- 1 | - targets: 2 | - '{{ ansible_fqdn }}:{{ pg_exporter_port }}' 3 | labels: 4 | job: postgresql 5 | team: {{ pg_exporter_team }} 6 | --------------------------------------------------------------------------------