1{
2 config,
3 lib,
4 pkgs,
5 options,
6 ...
7}:
8let
9 cfg = config.services.prometheus.exporters.sql;
10 inherit (lib)
11 mkOption
12 types
13 mapAttrs
14 mapAttrsToList
15 concatStringsSep
16 ;
17 cfgOptions = {
18 options = with types; {
19 jobs = mkOption {
20 type = attrsOf (submodule jobOptions);
21 default = { };
22 description = "An attrset of metrics scraping jobs to run.";
23 };
24 };
25 };
26 jobOptions = {
27 options = with types; {
28 interval = mkOption {
29 type = str;
30 description = ''
31 How often to run this job, specified in
32 [Go duration](https://golang.org/pkg/time/#ParseDuration) format.
33 '';
34 };
35 connections = mkOption {
36 type = listOf str;
37 description = "A list of connection strings of the SQL servers to scrape metrics from";
38 };
39 startupSql = mkOption {
40 type = listOf str;
41 default = [ ];
42 description = "A list of SQL statements to execute once after making a connection.";
43 };
44 queries = mkOption {
45 type = attrsOf (submodule queryOptions);
46 description = "SQL queries to run.";
47 };
48 };
49 };
50 queryOptions = {
51 options = with types; {
52 help = mkOption {
53 type = nullOr str;
54 default = null;
55 description = "A human-readable description of this metric.";
56 };
57 labels = mkOption {
58 type = listOf str;
59 default = [ ];
60 description = "A set of columns that will be used as Prometheus labels.";
61 };
62 query = mkOption {
63 type = str;
64 description = "The SQL query to run.";
65 };
66 values = mkOption {
67 type = listOf str;
68 description = "A set of columns that will be used as values of this metric.";
69 };
70 };
71 };
72
73 configFile =
74 if cfg.configFile != null then
75 cfg.configFile
76 else
77 let
78 nameInline = mapAttrsToList (k: v: v // { name = k; });
79 renameStartupSql = j: removeAttrs (j // { startup_sql = j.startupSql; }) [ "startupSql" ];
80 configuration = {
81 jobs = map renameStartupSql (
82 nameInline (mapAttrs (k: v: (v // { queries = nameInline v.queries; })) cfg.configuration.jobs)
83 );
84 };
85 in
86 builtins.toFile "config.yaml" (builtins.toJSON configuration);
87in
88{
89 extraOpts = {
90 configFile = mkOption {
91 type = with types; nullOr path;
92 default = null;
93 description = ''
94 Path to configuration file.
95 '';
96 };
97 configuration = mkOption {
98 type = with types; nullOr (submodule cfgOptions);
99 default = null;
100 description = ''
101 Exporter configuration as nix attribute set. Mutually exclusive with 'configFile' option.
102 '';
103 };
104 };
105
106 port = 9237;
107 serviceOpts = {
108 serviceConfig = {
109 ExecStart = ''
110 ${pkgs.prometheus-sql-exporter}/bin/sql_exporter \
111 -web.listen-address ${cfg.listenAddress}:${toString cfg.port} \
112 -config.file ${configFile} \
113 ${concatStringsSep " \\\n " cfg.extraFlags}
114 '';
115 RestrictAddressFamilies = [
116 # Need AF_UNIX to collect data
117 "AF_UNIX"
118 ];
119 };
120 };
121}