123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- package main
- import (
- "context"
- "log/slog"
- "net/http"
- "os"
- "xugu_exporter/collector"
- _ "gitee.com/XuguDB/go-xugu-driver"
- kingpin "github.com/alecthomas/kingpin/v2"
- "github.com/go-kit/log/level"
- "github.com/prometheus/client_golang/prometheus"
- "github.com/prometheus/client_golang/prometheus/collectors"
- "github.com/prometheus/client_golang/prometheus/promhttp"
- "github.com/prometheus/common/promlog"
- "github.com/prometheus/common/promlog/flag"
- "github.com/prometheus/common/version"
- "github.com/prometheus/exporter-toolkit/web"
- webflag "github.com/prometheus/exporter-toolkit/web/kingpinflag"
- // Required for debugging
- // _ "net/http/pprof"
- )
- var (
- // Version will be set at build time.
- Version = "0.0.1.dev" // 版本号,通常在构建时设置。这里初始化为一个开发版本号。
- // 使用 Kingpin 库定义命令行标志,并为每个标志提供帮助信息和默认值。
- // metricPath 定义了暴露指标的路径。默认值来自环境变量 "TELEMETRY_PATH",若未设置则默认为 "/metrics"。
- metricPath = kingpin.Flag("web.telemetry-path", "Path under which to expose metrics. (env: TELEMETRY_PATH)").Default(getEnv("TELEMETRY_PATH", "/metrics")).String()
- // dsn 定义了数据库的连接字符串。默认值来自环境变量 "DATA_SOURCE_NAME",若未设置则默认为空字符串。
- dsn = kingpin.Flag("database.dsn",
- "Connection string to a data source. (env: DATA_SOURCE_NAME)",
- ).Default(getEnv("DATA_SOURCE_NAME", "")).String()
- // dsnFile 定义了从文件读取数据库连接字符串的路径。默认值来自环境变量 "DATA_SOURCE_NAME_FILE",若未设置则默认为空字符串。
- dsnFile = kingpin.Flag("database.dsnFile",
- "File to read a string to a data source from. (env: DATA_SOURCE_NAME_FILE)",
- ).Default(getEnv("DATA_SOURCE_NAME_FILE", "")).String()
- // defaultFileMetrics 定义了存储默认指标的文件路径。该文件支持 TOML 或 YAML 格式。默认值来自环境变量 "DEFAULT_METRICS",若未设置则默认为 "default-metrics.toml"。
- defaultFileMetrics = kingpin.Flag(
- "default.metrics",
- "File with default metrics in a toml format. (env: DEFAULT_METRICS)",
- ).Default(getEnv("DEFAULT_METRICS", "default-metrics.toml")).String()
- // customMetrics 定义了包含自定义指标的文件路径。该文件支持 TOML 或 YAML 格式。默认值来自环境变量 "CUSTOM_METRICS",若未设置则默认为空字符串。
- customMetrics = kingpin.Flag(
- "custom.metrics",
- "File that may contain various custom metrics in a toml format. (env: CUSTOM_METRICS)",
- ).Default(getEnv("CUSTOM_METRICS", "")).String()
- // queryTimeout 定义了查询的超时时间,单位为秒。默认值来自环境变量 "QUERY_TIMEOUT",若未设置则默认为 5 秒。
- queryTimeout = kingpin.Flag(
- "query.timeout",
- "Query timeout (in seconds). (env: QUERY_TIMEOUT)",
- ).Default(getEnv("QUERY_TIMEOUT", "5")).Int()
- // maxIdleConns 定义了连接池中最大空闲连接数。默认值来自环境变量 "DATABASE_MAXIDLECONNS",若未设置则默认为 0。
- maxIdleConns = kingpin.Flag(
- "database.maxIdleConns",
- "Number of maximum idle connections in the connection pool. (env: DATABASE_MAXIDLECONNS)",
- ).Default(getEnv("DATABASE_MAXIDLECONNS", "0")).Int()
- // maxOpenConns 定义了连接池中最大打开连接数。默认值来自环境变量 "DATABASE_MAXOPENCONNS",若未设置则默认为 10。
- maxOpenConns = kingpin.Flag(
- "database.maxOpenConns",
- "Number of maximum open connections in the connection pool. (env: DATABASE_MAXOPENCONNS)",
- ).Default(getEnv("DATABASE_MAXOPENCONNS", "10")).Int()
- // scrapeInterval 定义了每次抓取数据的间隔时间。默认值为 0,表示在每次收集请求时进行抓取。
- scrapeInterval = kingpin.Flag(
- "scrape.interval",
- "Interval between each scrape. Default is to scrape on collect requests",
- ).Default("0s").Duration()
- // toolkitFlags 是与 Web 相关的附加标志,添加到 `kingpin.CommandLine` 上,默认端口为 ":9161"。
- toolkitFlags = webflag.AddFlags(kingpin.CommandLine, ":9161")
- )
- func main() {
- // 创建 Prometheus 日志配置对象
- promLogConfig := &promlog.Config{}
- // 添加命令行标志以配置 Prometheus 日志
- flag.AddFlags(kingpin.CommandLine, promLogConfig)
- // 设置帮助标志的快捷键
- kingpin.HelpFlag.Short('\n')
- // 设置程序版本信息
- kingpin.Version(version.Print("xugudb_exporter"))
- // 解析命令行输入的参数
- kingpin.Parse()
- // 创建新的日志记录器
- logger := promlog.New(promLogConfig)
- // 如果提供了 dsnFile 参数,读取文件中的数据库连接信息
- if dsnFile != nil && *dsnFile != "" {
- dsnFileContent, err := os.ReadFile(*dsnFile)
- if err != nil {
- // 如果文件读取失败,记录错误并退出程序
- level.Error(logger).Log("msg", "Unable to read DATA_SOURCE_NAME_FILE", "file", dsnFile, "error", err)
- os.Exit(1)
- }
- // 将文件内容作为数据库连接字符串
- *dsn = string(dsnFileContent)
- }
- // 初始化配置对象,将从命令行解析的参数赋值给配置
- config := &collector.Config{
- DSN: *dsn, // 数据库连接字符串
- MaxOpenConns: *maxOpenConns, // 最大打开连接数
- MaxIdleConns: *maxIdleConns, // 最大空闲连接数
- CustomMetrics: *customMetrics, // 自定义指标文件路径
- QueryTimeout: *queryTimeout, // 查询超时时间
- DefaultMetricsFile: *defaultFileMetrics, // 默认指标文件路径
- }
- // 创建一个新的 Exporter 实例,用于收集 xugu 数据库的指标
- exporter, err := collector.NewExporter(logger, config)
- if err != nil {
- // 如果创建 Exporter 失败,记录错误并退出程序
- level.Error(logger).Log("unable to connect to DB", err)
- }
- // 如果设置了抓取间隔(scrapeInterval),则启动定时抓取指标的任务
- if *scrapeInterval != 0 {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
- // 启动一个 goroutine,定期从数据库抓取指标
- go exporter.RunScheduledScrapes(ctx, *scrapeInterval)
- }
- // 将 Exporter 注册到 Prometheus 中,供 Prometheus 进行指标抓取
- prometheus.MustRegister(exporter)
- // 注册构建信息收集器,用于报告程序的版本信息等元数据
- prometheus.MustRegister(collectors.NewBuildInfoCollector())
- // 记录启动信息
- level.Info(logger).Log("msg", "Starting xugudb_exporter", "version", version.Info())
- level.Info(logger).Log("msg", "Build context", "build", version.BuildContext())
- level.Info(logger).Log("msg", "Collect from: ", "metricPath", *metricPath)
- // 设置 Prometheus HTTP handler 的选项
- opts := promhttp.HandlerOpts{
- ErrorHandling: promhttp.ContinueOnError, // 遇到错误时继续处理其他请求
- }
- // 配置 /metrics 路径用于暴露 Prometheus 格式的指标
- http.Handle(*metricPath, promhttp.HandlerFor(prometheus.DefaultGatherer, opts))
- // 配置根路径(/),返回一个简单的 HTML 页面,包含版本信息和指标链接
- http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("<html><head><title>xugu DB Exporter " + Version + "</title></head><body><h1>xugu DB Exporter " + Version + "</h1><p><a href='" + *metricPath + "'>Metrics</a></p></body></html>"))
- })
- // 创建一个日志处理器,输出到标准输出(os.Stdout)
- handlerS := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
- Level: slog.LevelInfo, // 设置最低日志级别为 Info
- })
- // 创建一个新的 logger
- loggerS := slog.New(handlerS)
- // 创建一个新的 logger
- //loggerS := slog.New(slog.NewTextHandler(slog.Default()))
- // 使用 logger 记录日志
- loggerS.Info("This is an info message")
- loggerS.Warn("This is a warning message")
- loggerS.Error("This is an error message")
- // 如果需要,可以添加更多的上下文信息
- loggerS.With("context", "example").Info("This is a context-aware info message")
- // 创建一个 HTTP 服务器实例
- server := &http.Server{}
- // 启动 HTTP 服务器,监听并提供 Prometheus 指标
- if err := web.ListenAndServe(server, toolkitFlags, loggerS); err != nil {
- // 如果服务器启动失败,记录错误并退出程序
- level.Error(logger).Log("msg", "Listening error", "reason", err)
- os.Exit(1)
- }
- }
- // getEnv 返回指定环境变量的值,如果环境变量未设置,则返回提供的备用值。
- func getEnv(key, fallback string) string {
- // os.LookupEnv 用于查找环境变量的值。如果环境变量存在,返回值和一个布尔值(true/false);
- // 如果环境变量不存在,返回空字符串和 false。
- if value, ok := os.LookupEnv(key); ok {
- // 如果环境变量存在,返回其值
- return value
- }
- // 如果环境变量不存在,返回备用值
- return fallback
- }
|