func queryNamespaceMapping(server *Server, namespace string, mapping MetricMapNamespace) ([]prometheus.Metric, []error, error) {
	// Check for a query override for this namespace
	query, found := server.queryOverrides[namespace]

	// Was this query disabled (i.e. nothing sensible can be queried on cu
	// version of PostgreSQL?
	if query == "" && found {
		// Return success (no pertinent data)
		return []prometheus.Metric{}, []error{}, nil
	}

	// Don't fail on a bad scrape of one metric
	var rows *sql.Rows
	var err error

	if !found {
		// I've no idea how to avoid this properly at the moment, but this is
		// an admin tool so you're not injecting SQL right?
		rows, err = server.db.Query(fmt.Sprintf("SELECT * FROM %s;", namespace)) // nolint: gas, safesql
	} else {
		rows, err = server.db.Query(query) // nolint: safesql
	}
	if err != nil {
		return []prometheus.Metric{}, []error{}, fmt.Errorf("Error running query on database %q: %s %v", server, namespace, err)
	}
	defer rows.Close() // nolint: errcheck

	var columnNames []string
	columnNames, err = rows.Columns()
	if err != nil {
		return []prometheus.Metric{}, []error{}, errors.New(fmt.Sprintln("Error retrieving column list for: ", namespace, err))
	}

	// Make a lookup map for the column indices
	var columnIdx = make(map[string]int, len(columnNames))
	for i, n := range columnNames {
		columnIdx[n] = i
	}

	var columnData = make([]interface{}, len(columnNames))
	var scanArgs = make([]interface{}, len(columnNames))
	for i := range columnData {
		scanArgs[i] = &columnData[i]
	}

	nonfatalErrors := []error{}

	metrics := make([]prometheus.Metric, 0)

	for rows.Next() {
		err = rows.Scan(scanArgs...)
		if err != nil {
			return []prometheus.Metric{}, []error{}, errors.New(fmt.Sprintln("Error retrieving rows:", namespace, err))
		}

		// Get the label values for this row.
		labels := make([]string, len(mapping.labels))
		for idx, label := range mapping.labels {
			labels[idx], _ = dbToString(columnData[columnIdx[label]])
		}

		// Loop over column names, and match to scan data. Unknown columns
		// will be filled with an untyped metric number *if* they can be
		// converted to float64s. NULLs are allowed and treated as NaN.
		for idx, columnName := range columnNames {
			var metric prometheus.Metric
			if metricMapping, ok := mapping.columnMappings[columnName]; ok {
				// Is this a metricy metric?
				if metricMapping.discard {
					continue
				}

				value, ok := dbToFloat64(columnData[idx])
				if !ok {
					nonfatalErrors = append(nonfatalErrors, errors.New(fmt.Sprintln("Unexpected error parsing column: ", namespace, columnName, columnData[idx])))
					continue
				}
				// Generate the metric
				metric = prometheus.MustNewConstMetric(metricMapping.desc, metricMapping.vtype, value, labels...)
			} else {
				// Unknown metric. Report as untyped if scan to float64 works, else note an error too.
				metricLabel := fmt.Sprintf("%s_%s", namespace, columnName)
				desc := prometheus.NewDesc(metricLabel, fmt.Sprintf("Unknown metric from %s", namespace), mapping.labels, server.labels)

				// Its not an error to fail here, since the values are
				// unexpected anyway.
				value, ok := dbToFloat64(columnData[idx])
				if !ok {
					nonfatalErrors = append(nonfatalErrors, errors.New(fmt.Sprintln("Unparseable column type - discarding: ", namespace, columnName, err)))
					continue
				}
				metric = prometheus.MustNewConstMetric(desc, prometheus.UntypedValue, value, labels...)
			}
			metrics = append(metrics, metric)
		}
	}
	return metrics, nonfatalErrors, nil
}
// Query within a namespace mapping and emit metrics. Returns fatal errors if
// the scrape fails, and a slice of errors if they were non-fatal.
Query within a namespace mapping and emit metrics. Returns fatal errors if
the scrape fails, and a slice of errors if they were non-fatal.
// Query within a namespace mapping and emit metrics . Returns fatal errors if // the scrape fails and a slice of errors if they were non - fatal .
func queryNamespaceMapping(server *Server, namespace string, mapping MetricMapNamespace) ([]prometheus.Metric, []error, error) {
	query, found := server.queryOverrides[namespace]
	if query == "" && found {
		return []prometheus.Metric{}, []error{}, nil
	}
	var rows *sql.Rows
	var err error
	if !found {
		rows, err = server.db.Query(fmt.Sprintf("SELECT * FROM %s;", namespace)) 
	} else {
		rows, err = server.db.Query(query) 
	}
	if err != nil {
		return []prometheus.Metric{}, []error{}, fmt.Errorf("Error running query on database %q: %s %v", server, namespace, err)
	}
	defer rows.Close() 
	var columnNames []string
	columnNames, err = rows.Columns()
	if err != nil {
		return []prometheus.Metric{}, []error{}, errors.New(fmt.Sprintln("Error retrieving column list for: ", namespace, err))
	}
	var columnIdx = make(map[string]int, len(columnNames))
	for i, n := range columnNames {
		columnIdx[n] = i
	}
	var columnData = make([]interface{}, len(columnNames))
	var scanArgs = make([]interface{}, len(columnNames))
	for i := range columnData {
		scanArgs[i] = &columnData[i]
	}
	nonfatalErrors := []error{}
	metrics := make([]prometheus.Metric, 0)
	for rows.Next() {
		err = rows.Scan(scanArgs...)
		if err != nil {
			return []prometheus.Metric{}, []error{}, errors.New(fmt.Sprintln("Error retrieving rows:", namespace, err))
		}
		labels := make([]string, len(mapping.labels))
		for idx, label := range mapping.labels {
			labels[idx], _ = dbToString(columnData[columnIdx[label]])
		}
		for idx, columnName := range columnNames {
			var metric prometheus.Metric
			if metricMapping, ok := mapping.columnMappings[columnName]; ok {
				if metricMapping.discard {
					continue
				}
				value, ok := dbToFloat64(columnData[idx])
				if !ok {
					nonfatalErrors = append(nonfatalErrors, errors.New(fmt.Sprintln("Unexpected error parsing column: ", namespace, columnName, columnData[idx])))
					continue
				}
				metric = prometheus.MustNewConstMetric(metricMapping.desc, metricMapping.vtype, value, labels...)
			} else {
				metricLabel := fmt.Sprintf("%s_%s", namespace, columnName)
				desc := prometheus.NewDesc(metricLabel, fmt.Sprintf("Unknown metric from %s", namespace), mapping.labels, server.labels)
				value, ok := dbToFloat64(columnData[idx])
				if !ok {
					nonfatalErrors = append(nonfatalErrors, errors.New(fmt.Sprintln("Unparseable column type - discarding: ", namespace, columnName, err)))
					continue
				}
				metric = prometheus.MustNewConstMetric(desc, prometheus.UntypedValue, value, labels...)
			}
			metrics = append(metrics, metric)
		}
	}
	return metrics, nonfatalErrors, nil
}
func queryNamespaceMapping ( server * Server , namespace string , mapping MetricMapNamespace ) ( [ ] prometheus . Metric , [ ] error , error ) { query , found := server . queryOverrides [ namespace ] if query == " " && found { return [ ] prometheus . Metric { } , [ ] error { } , nil } var rows * sql . Rows var err error if ! found { rows , err = server . db . Query ( fmt . Sprintf ( " " , namespace ) ) } else { rows , err = server . db . Query ( query ) } if err != nil { return [ ] prometheus . Metric { } , [ ] error { } , fmt . Errorf ( " " , server , namespace , err ) } defer rows . Close ( ) var columnNames [ ] string columnNames , err = rows . Columns ( ) if err != nil { return [ ] prometheus . Metric { } , [ ] error { } , errors . New ( fmt . Sprintln ( " " , namespace , err ) ) } var columnIdx = make ( map [ string ] int , len ( columnNames ) ) for i , n := range columnNames { columnIdx [ n ] = i } var columnData = make ( [ ] interface { } , len ( columnNames ) ) var scanArgs = make ( [ ] interface { } , len ( columnNames ) ) for i := range columnData { scanArgs [ i ] = & columnData [ i ] } nonfatalErrors := [ ] error { } metrics := make ( [ ] prometheus . Metric , 0 ) for rows . Next ( ) { err = rows . Scan ( scanArgs ... ) if err != nil { return [ ] prometheus . Metric { } , [ ] error { } , errors . New ( fmt . Sprintln ( " " , namespace , err ) ) } labels := make ( [ ] string , len ( mapping . labels ) ) for idx , label := range mapping . labels { labels [ idx ] , _ = dbToString ( columnData [ columnIdx [ label ] ] ) } for idx , columnName := range columnNames { var metric prometheus . Metric if metricMapping , ok := mapping . columnMappings [ columnName ] ; ok { if metricMapping . discard { continue } value , ok := dbToFloat64 ( columnData [ idx ] ) if ! ok { nonfatalErrors = append ( nonfatalErrors , errors . New ( fmt . Sprintln ( " " , namespace , columnName , columnData [ idx ] ) ) ) continue } metric = prometheus . MustNewConstMetric ( metricMapping . desc , metricMapping . vtype , value , labels ... ) } else { metricLabel := fmt . Sprintf ( " " , namespace , columnName ) desc := prometheus . NewDesc ( metricLabel , fmt . Sprintf ( " " , namespace ) , mapping . labels , server . labels ) value , ok := dbToFloat64 ( columnData [ idx ] ) if ! ok { nonfatalErrors = append ( nonfatalErrors , errors . New ( fmt . Sprintln ( " " , namespace , columnName , err ) ) ) continue } metric = prometheus . MustNewConstMetric ( desc , prometheus . UntypedValue , value , labels ... ) } metrics = append ( metrics , metric ) } } return metrics , nonfatalErrors , nil }
Query within a namespace mapping and emit metrics.
Query within a namespace mapping and emit metrics .
// Check for a query override for this namespace // Was this query disabled (i.e. nothing sensible can be queried on cu // version of PostgreSQL? // Return success (no pertinent data) // Don't fail on a bad scrape of one metric // I've no idea how to avoid this properly at the moment, but this is // an admin tool so you're not injecting SQL right? // nolint: gas, safesql // nolint: safesql // nolint: errcheck // Make a lookup map for the column indices // Get the label values for this row. // Loop over column names, and match to scan data. Unknown columns // will be filled with an untyped metric number *if* they can be // converted to float64s. NULLs are allowed and treated as NaN. // Is this a metricy metric? // Generate the metric // Unknown metric. Report as untyped if scan to float64 works, else note an error too. // Its not an error to fail here, since the values are // unexpected anyway.