This may look like a crazy idea but we use it for monitoring which is not simple enough to use some standard exporter + Prometheus. We have one influxDB instance used as a datasource for Grafana. Following program uses config file (standard ini format) to run multiple queries on multiple PostgreSQL databases and inserts data into InfluxDB. Each query can be very different (with different columns) and have different target measurement in InfluxDB. Program automatically extracts number of columns and their names from PostgreSQL query.

Format of config file:

[influxdb]
URL = http://localhost:8086
#USER =
#PASSWORD =

# name of database in influxdb
DATABASE = grafana

[postgresql]
#here list of connections in form 
#instance_name=connect_string

instance1=postgres://login:password@ip_address:5432/databasename
instance2=.....

[metric1]
TASK=some name
QUERY="""
here postgresql query
taking more lines
"""

 name of measurement in influxdb
MEASUREMENT = name-of-influxdb-table

# from columns of the query mark that (those) which should be used as value(s)
# all others will be used as tags
VALUES = value

# if query contains column which should be used as timestamp
TIMESTAMP = timestamp

#...and so on metric2, metric3 part....

program (removed reference for internal library which does output messages):

package main

import (
	"database/sql"
	"fmt"
	"log"
	"os"
	"strings"
	"time"

	"flag"

	"github.com/go-ini/ini"
	"github.com/influxdata/influxdb/client/v2"
	_ "github.com/lib/pq"
)

var (
	sectionInfluxDB   = "influxdb"
	sectionPostgreSQL = "postgresql"
	sectionDefault    = "DEFAULT"
)

type configdata struct {
	influxdbURL      string
	influxdbUser     string
	influxdbPass     string
	influxdbDatabase string
	pgURI            string
	startDate        string
	endDate          string
	pgRunDate        string
	runDateUnix      int64
	taskDescription  string
	taskMeasurement  string
	taskValues       string
	taskTimestamp    string
	pgSelectQuery    string
	instanceName     string
}

func connect(driverName string, uri string) (*sql.DB, error) {
	db, err := sql.Open(driverName, uri)
	if err != nil {
		return nil, err
	}
	if err = db.Ping(); err != nil {
		return nil, err
	}
	return db, nil
}

func influxDBClient(influxuri string, influxuser string, influxpass string) client.Client {
	c, err := client.NewHTTPClient(client.HTTPConfig{
		Addr:     influxuri,
		Username: influxuser,
		Password: influxpass,
	})
	if err != nil {
		log.Fatal("InfluxDB error:", err)
	}
	return c
}

func main() {

	var iniFile string
	var cd configdata

	paramQueryfile := flag.String("queryfile", "", "config file with query")
	paramDate := flag.String("date", "", "particular day for check")
	paramStartDate := flag.String("startdate", "", "start date of the interval for which data will be checked")
	paramEndDate := flag.String("enddate", "", "end date of the interval for which data will be checked")
	paramTable := flag.String("table", "", "parent table to ")
	paramHelp := flag.Bool("help", false, "print help")
	paramDebug := flag.Bool("debug", false, "print debug messages")
	paramDebugLevel := flag.Int("debug_level", 0, "level of debug messages: 0 = default, common messages from run / 1 = show variables, queries etc. / 2 = deep debug, shows inserted data etc.")
	flag.Parse()

	iniFile = *paramQueryfile
	calcDate := *paramDate
	startDate := *paramStartDate
	endDate := *paramEndDate
	printHelp := *paramHelp
	pcg.PrintDebugMsg = *paramDebug
	pcg.DebugLevel = *paramDebugLevel
	parentTable := *paramTable

	pcg.DebugMsg(1, fmt.Sprintf("pcg.PrintDebugMsg: %v", pcg.PrintDebugMsg))
	pcg.DebugMsg(1, fmt.Sprintf("pcg.DebugLevel: %v", pcg.DebugLevel))

	pcg.DebugMsg(1, fmt.Sprintf("calcDate: %s", calcDate))
	pcg.DebugMsg(1, fmt.Sprintf("startDate: %s", startDate))
	pcg.DebugMsg(1, fmt.Sprintf("endDate: %s", endDate))
	pcg.DebugMsg(1, fmt.Sprintf("iniFile: %s", iniFile))
	pcg.DebugMsg(1, fmt.Sprintf("printHelp: %v", printHelp))
	pcg.DebugMsg(1, fmt.Sprintf("printDebugMsg: %v", pcg.PrintDebugMsg))
	pcg.DebugMsg(1, fmt.Sprintf("parentTable: %v", parentTable))

	if printHelp == true || iniFile == "" {
		if iniFile == "" {
			pcg.PrintMsg("you must specify query file")
		}
		flag.PrintDefaults()
		log.Fatal()
	}

	if calcDate != "" {
		startDate = calcDate
		endDate = calcDate
	} else if startDate == "" {
		t := time.Now().UTC().AddDate(0, 0, -1)
		startDate = fmt.Sprintf("%d-%02d-%02d", t.Year(), t.Month(), t.Day())
	}

	if endDate == "" {
		endDate = startDate
	}

	_, err := pcg.CheckDataBoundariesStr(startDate, endDate)
	if err != nil {
		log.Fatal("ERROR: in check of dates: ", err)
	}

	if _, err := os.Stat(iniFile); os.IsNotExist(err) {
		log.Fatal("ERROR: Cannot find ini file", iniFile, "message:", err)
	}

	cfg, err := ini.LoadSources(ini.LoadOptions{Loose: false}, iniFile)
	if err != nil {
		log.Fatal("ERROR: cannot read ini file:", iniFile, "message:", err)
	}

	cd.influxdbURL = cfg.Section(sectionInfluxDB).Key("URL").String()
	pcg.CheckValue("influxDB URL", cd.influxdbURL, true, pcg.PrintDebugMsg)

	cd.influxdbUser = cfg.Section(sectionInfluxDB).Key("USER").String()
	pcg.CheckValue("influxDB User", cd.influxdbUser, false, pcg.PrintDebugMsg)

	cd.influxdbPass = cfg.Section(sectionInfluxDB).Key("PASSWORD").String()
	pcg.CheckValue("influxDB PASSWORD", cd.influxdbPass, false, pcg.PrintDebugMsg)

	cd.influxdbDatabase = cfg.Section(sectionInfluxDB).Key("DATABASE").String()
	pcg.CheckValue("influxDB DATABASE", cd.influxdbDatabase, true, pcg.PrintDebugMsg)

	influxdb := influxDBClient(cd.influxdbURL, cd.influxdbUser, cd.influxdbPass)

	pgInstances := cfg.Section(sectionPostgreSQL).KeyStrings()
	for k := 0; k < len(pgInstances); k++ {
		cd.instanceName = pgInstances[k]
		pcg.CheckValue("instanceName", cd.instanceName, true, pcg.PrintDebugMsg)

		cd.pgURI = cfg.Section(sectionPostgreSQL).Key(cd.instanceName).String()
		pcg.CheckValue("pgURI", cd.pgURI, true, pcg.PrintDebugMsg)

		pgDB, err := connect("postgres", cd.pgURI)
		if err != nil {
			log.Fatal("cannot connect to postgresql:", err)
		}
		defer func() {
			if errClose := pgDB.Close(); err != nil {
				pcg.PrintMsg("closing database:", errClose.Error())
			}
		}()

		sections := cfg.SectionStrings()
		for i := 0; i < len(sections); i++ {
			section := sections[i]
			if section != sectionInfluxDB && section != sectionPostgreSQL && section != sectionDefault {
				pcg.CheckValue("Section", section, false, true)

				cd.taskDescription = cfg.Section(section).Key("TASK").String()
				pcg.CheckValue("task Description", cd.taskDescription, false, true)

				cd.pgSelectQuery = cfg.Section(section).Key("QUERY").String()
				cd.pgSelectQuery = strings.Replace(cd.pgSelectQuery, "${YYYY-MM-DD}", cd.pgRunDate, -1)
				cd.pgSelectQuery = strings.Replace(cd.pgSelectQuery, "${YYYYMMDD}", cd.pgRunDate, -1)
				cd.pgSelectQuery = strings.Replace(cd.pgSelectQuery, "${INSTANCE}", cd.instanceName, -1)
				pcg.CheckValue("bigquery QUERY", cd.pgSelectQuery, false, false)

				cd.taskMeasurement = cfg.Section(section).Key("MEASUREMENT").String()
				pcg.CheckValue("task MEASUREMENT", cd.taskMeasurement, true, pcg.PrintDebugMsg)

				//pgTaskColumns = cfg.Section(section).Key("COLUMNS").String()
				//pcg.CheckValue("task COLUMNS", pgTaskColumns, true, pcg.PrintDebugMsg)

				cd.taskValues = cfg.Section(section).Key("VALUES").String()
				pcg.CheckValue("task VALUES", cd.taskValues, true, pcg.PrintDebugMsg)

				cd.taskTimestamp = cfg.Section(section).Key("TIMESTAMP").String()
				pcg.CheckValue("task TIMESTAMP", cd.taskValues, false, pcg.PrintDebugMsg)

				pcg.DebugMsg(1, "Starting BQ query")
				pgRows, err := pgDB.Query(cd.pgSelectQuery)
				if err != nil {
					log.Fatalln("Cannot read data from PG: ", err)
				}

				pgTaskColumns, err := pgRows.Columns()
				if err != nil {
					log.Fatal("cannot read source columns:", err)
				}

				pcg.DebugMsg(1, "pgColumns: ", pgTaskColumns)
				numOfPgColumns := len(pgTaskColumns)
				pgColumnPointers := make([]interface{}, numOfPgColumns)
				pgTaskColumns2 := make([]interface{}, numOfPgColumns)

				for i := 0; i < len(pgTaskColumns); i++ {
					pgColumnPointers[i] = &pgTaskColumns2[i]
				}

				pcg.DebugMsg(1, "Starting InfluxDB inserts")
				rowCount := 0
				if pgRows != nil {
					for pgRows.Next() {
						if err = pgRows.Scan(pgColumnPointers...); err != nil {
							log.Fatal("cannot parse pg data:", err)
						}

						pcg.DebugMsg(3, "PG values: ", fmt.Sprint(pgColumnPointers))
						if rowCount%1000 == 0 {
							pcg.PrintMsg(rowCount, " rows inserted")
						}
						insertGrafanaDashboards(influxdb, pgTaskColumns, cd, pgTaskColumns2) //pgColumnPointers)
						rowCount++
					}
				}
				pcg.PrintMsg("Rows processed: ", rowCount)
			}
		}
	}
}

func insertGrafanaDashboards(c client.Client, columns []string, cd configdata, data []interface{}) {
	bp, err := client.NewBatchPoints(client.BatchPointsConfig{
		Database:  cd.influxdbDatabase,
		Precision: "s",
	})
	if err != nil {
		log.Fatal("InfluxDB NewBatchPoints Error:", err)
	}

	tags := make(map[string]string)
	fields := make(map[string]interface{})

	var itimestamp int64
	for i := range columns {
		col := columns[i]
		dataval := data[i]
		colIsValue := isInList(cd.taskValues, col)
		colIsTimestamp := isInList(cd.taskTimestamp, col)
		switch {
		case colIsValue == true:
			// values
			pcg.DebugMsg(2, fmt.Sprint(i, " : ", col, " : ", dataval, " - value"))
			fields[col] = fmt.Sprintf("%v", dataval)
		case colIsTimestamp == true:
			// timestamp
			pcg.DebugMsg(2, fmt.Sprint(i, " : ", col, " : ", dataval, " - timestamp"))
			itimestamp = int64(dataval.(float64))
		default:
			//tags
			pcg.DebugMsg(2, fmt.Sprint(i, " : ", col, " : ", dataval, " - tag"))
			tags[col] = fmt.Sprint(dataval)
		}
	}

	pcg.DebugMsg(2, "creating influxdb new point")
	point, err := client.NewPoint(
		cd.taskMeasurement,
		tags,
		fields,
		time.Unix(itimestamp, 0),
	)
	if err != nil {
		log.Fatal("NewPoint Error:", err)
	}

	bp.AddPoint(point)
	if err != nil {
		log.Fatal("addpoint error:", err)
	}

	pcg.DebugMsg(2, "writing into influxdb")
	err = c.Write(bp)
	if err != nil {
		log.Fatal("influx write error:", err)
	}
}

func isInList(sList string, val string) (isIn bool) {
	listArray := strings.Split(sList, ",")
	for i := range listArray {
		if isIn = (strings.Compare(listArray[i], val) == 0); isIn == true {
			return
		}
	}
	return
}