db_client.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package oracledbreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/oracledbreceiver"
  4. import (
  5. "context"
  6. "database/sql"
  7. "fmt"
  8. "reflect"
  9. "strings"
  10. // register db driver
  11. _ "github.com/sijms/go-ora/v2"
  12. "go.uber.org/zap"
  13. )
  14. type dbClient interface {
  15. metricRows(ctx context.Context) ([]metricRow, error)
  16. }
  17. type metricRow map[string]string
  18. type dbSQLClient struct {
  19. db *sql.DB
  20. logger *zap.Logger
  21. sql string
  22. }
  23. func newDbClient(db *sql.DB, sql string, logger *zap.Logger) dbClient {
  24. return dbSQLClient{
  25. db: db,
  26. sql: sql,
  27. logger: logger,
  28. }
  29. }
  30. func (cl dbSQLClient) metricRows(ctx context.Context) ([]metricRow, error) {
  31. sqlRows, err := cl.db.QueryContext(ctx, cl.sql)
  32. if err != nil {
  33. return nil, err
  34. }
  35. var out []metricRow
  36. row := reusableRow{
  37. attrs: map[string]func() string{},
  38. }
  39. types, err := sqlRows.ColumnTypes()
  40. if err != nil {
  41. return nil, err
  42. }
  43. for _, sqlType := range types {
  44. colName := sqlType.Name()
  45. var v any
  46. row.attrs[colName] = func() string {
  47. format := "%v"
  48. if v == nil {
  49. return ""
  50. }
  51. if reflect.TypeOf(v).Kind() == reflect.Slice {
  52. // The Postgres driver returns a []uint8 (a string) for decimal and numeric types,
  53. // which we want to render as strings. e.g. "4.1" instead of "[52, 46, 49]".
  54. // Other slice types get the same treatment.
  55. format = "%s"
  56. }
  57. return fmt.Sprintf(format, v)
  58. }
  59. row.scanDest = append(row.scanDest, &v)
  60. }
  61. for sqlRows.Next() {
  62. err = sqlRows.Scan(row.scanDest...)
  63. if err != nil {
  64. return nil, err
  65. }
  66. out = append(out, row.toMetricRow())
  67. }
  68. return out, nil
  69. }
  70. type reusableRow struct {
  71. attrs map[string]func() string
  72. scanDest []any
  73. }
  74. func (row reusableRow) toMetricRow() metricRow {
  75. out := metricRow{}
  76. for k, f := range row.attrs {
  77. out[strings.ToUpper(k)] = f()
  78. }
  79. return out
  80. }