Add reauth feature, remove errors library.
This commit is contained in:
		
							parent
							
								
									5b838948d8
								
							
						
					
					
						commit
						10d17b4a31
					
				|  | @ -21,14 +21,6 @@ | ||||||
|   pruneopts = "UT" |   pruneopts = "UT" | ||||||
|   revision = "fc22c7df067eefd070157f157893fbce961d6359" |   revision = "fc22c7df067eefd070157f157893fbce961d6359" | ||||||
| 
 | 
 | ||||||
| [[projects]] |  | ||||||
|   digest = "1:cf31692c14422fa27c83a05292eb5cbe0fb2775972e8f1f8446a71549bd8980b" |  | ||||||
|   name = "github.com/pkg/errors" |  | ||||||
|   packages = ["."] |  | ||||||
|   pruneopts = "UT" |  | ||||||
|   revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4" |  | ||||||
|   version = "v0.8.1" |  | ||||||
| 
 |  | ||||||
| [[projects]] | [[projects]] | ||||||
|   digest = "1:c1b1102241e7f645bc8e0c22ae352e8f0dc6484b6cb4d132fa9f24174e0119e2" |   digest = "1:c1b1102241e7f645bc8e0c22ae352e8f0dc6484b6cb4d132fa9f24174e0119e2" | ||||||
|   name = "github.com/spf13/pflag" |   name = "github.com/spf13/pflag" | ||||||
|  | @ -59,7 +51,6 @@ | ||||||
|   input-imports = [ |   input-imports = [ | ||||||
|     "github.com/BurntSushi/toml", |     "github.com/BurntSushi/toml", | ||||||
|     "github.com/influxdata/influxdb1-client/v2", |     "github.com/influxdata/influxdb1-client/v2", | ||||||
|     "github.com/pkg/errors", |  | ||||||
|     "github.com/spf13/pflag", |     "github.com/spf13/pflag", | ||||||
|     "golift.io/unifi", |     "golift.io/unifi", | ||||||
|     "gopkg.in/yaml.v2", |     "gopkg.in/yaml.v2", | ||||||
|  |  | ||||||
|  | @ -65,7 +65,7 @@ is provided so the application can be easily adapted to any environment. | ||||||
| 
 | 
 | ||||||
| `Config File Parameters` | `Config File Parameters` | ||||||
| 
 | 
 | ||||||
|     sites          default: ["all"] |     sites           default: ["all"] | ||||||
|         This list of strings should represent the names of sites on the UniFi |         This list of strings should represent the names of sites on the UniFi | ||||||
|         controller that will be polled for data. Pass `all` in the list to |         controller that will be polled for data. Pass `all` in the list to | ||||||
|         poll all sites. On startup, the application prints out all site names |         poll all sites. On startup, the application prints out all site names | ||||||
|  | @ -73,20 +73,20 @@ is provided so the application can be easily adapted to any environment. | ||||||
|         next to them. The cryptic names go into the config file `sites` list. |         next to them. The cryptic names go into the config file `sites` list. | ||||||
|         The controller's first site is not cryptic and is named `default`. |         The controller's first site is not cryptic and is named `default`. | ||||||
| 
 | 
 | ||||||
|     interval       default: 30s |     interval        default: 30s | ||||||
|         How often to poll the controller for updated client and device data. |         How often to poll the controller for updated client and device data. | ||||||
|         The UniFi Controller only updates traffic stats about every 30 seconds. |         The UniFi Controller only updates traffic stats about every 30 seconds. | ||||||
| 
 | 
 | ||||||
|     debug          default: false |     debug           default: false | ||||||
|         This turns on time stamps and line numbers in logs, outputs a few extra |         This turns on time stamps and line numbers in logs, outputs a few extra | ||||||
|         lines of information while processing. |         lines of information while processing. | ||||||
| 
 | 
 | ||||||
|     quiet          default: false   |     quiet           default: false | ||||||
|         Setting this to true will turn off per-device and per-interval logs. Only |         Setting this to true will turn off per-device and per-interval logs. Only | ||||||
|         errors will be logged. Using this with debug=true adds line numbers to |         errors will be logged. Using this with debug=true adds line numbers to | ||||||
|         any error logs. |         any error logs. | ||||||
| 
 | 
 | ||||||
|     mode           default: "influx" |     mode            default: "influx" | ||||||
|         * Value: influx |         * Value: influx | ||||||
|         This default mode runs this application as a daemon. It will poll |         This default mode runs this application as a daemon. It will poll | ||||||
|         the controller at the configured interval. Providing an invalid value |         the controller at the configured interval. Providing an invalid value | ||||||
|  | @ -101,7 +101,7 @@ is provided so the application can be easily adapted to any environment. | ||||||
|         This mode can also be combined with a "test database" in InfluxDB to |         This mode can also be combined with a "test database" in InfluxDB to | ||||||
|         give yourself a "test config file" you may run ad-hoc to test changes. |         give yourself a "test config file" you may run ad-hoc to test changes. | ||||||
| 
 | 
 | ||||||
|     max_errors     default: 0 |     max_errors      default: 0 | ||||||
|         If you restart the UniFI controller, the poller will lose access until |         If you restart the UniFI controller, the poller will lose access until | ||||||
|         it is restarted. Specifying a number greater than -1 for max_errors will |         it is restarted. Specifying a number greater than -1 for max_errors will | ||||||
|         cause the poller to exit when it reaches the error count specified. |         cause the poller to exit when it reaches the error count specified. | ||||||
|  | @ -113,16 +113,16 @@ is provided so the application can be easily adapted to any environment. | ||||||
|         docker or launchd. The default setting of 0 will cause an exit after |         docker or launchd. The default setting of 0 will cause an exit after | ||||||
|         just 1 error. Recommended values are 0-5. |         just 1 error. Recommended values are 0-5. | ||||||
| 
 | 
 | ||||||
|     influx_url     default: http://127.0.0.1:8086 |     influx_url      default: http://127.0.0.1:8086 | ||||||
|         This is the URL where the Influx web server is available. |         This is the URL where the Influx web server is available. | ||||||
| 
 | 
 | ||||||
|     influx_user    default: unifi |     influx_user     default: unifi | ||||||
|         Username used to authenticate with InfluxDB. |         Username used to authenticate with InfluxDB. | ||||||
| 
 | 
 | ||||||
|     influx_pass    default: unifi |     influx_pass     default: unifi | ||||||
|         Password used to authenticate with InfluxDB. |         Password used to authenticate with InfluxDB. | ||||||
| 
 | 
 | ||||||
|     influx_db      default: unifi |     influx_db       default: unifi | ||||||
|         Custom database created in InfluxDB to use with this application. |         Custom database created in InfluxDB to use with this application. | ||||||
|         On first setup, log into InfluxDB and create access: |         On first setup, log into InfluxDB and create access: | ||||||
|         $ influx -host localhost -port 8086 |         $ influx -host localhost -port 8086 | ||||||
|  | @ -130,24 +130,30 @@ is provided so the application can be easily adapted to any environment. | ||||||
|         CREATE USER unifi WITH PASSWORD 'unifi' WITH ALL PRIVILEGES |         CREATE USER unifi WITH PASSWORD 'unifi' WITH ALL PRIVILEGES | ||||||
|         GRANT ALL ON unifi TO unifi |         GRANT ALL ON unifi TO unifi | ||||||
| 
 | 
 | ||||||
|     unifi_url      default: https://127.0.0.1:8443 |     unifi_url       default: https://127.0.0.1:8443 | ||||||
|         This is the URL where the UniFi Controller is available. |         This is the URL where the UniFi Controller is available. | ||||||
| 
 | 
 | ||||||
|     unifi_user     default: influxdb |     unifi_user      default: influxdb | ||||||
|         Username used to authenticate with UniFi controller. This should be a |         Username used to authenticate with UniFi controller. This should be a | ||||||
|         special service account created on the control with read-only access. |         special service account created on the control with read-only access. | ||||||
| 
 | 
 | ||||||
|     unifi_user     no default   ENV: UNIFI_PASSWORD |     unifi_user      no default   ENV: UNIFI_PASSWORD | ||||||
|         Password used to authenticate with UniFi controller. This can also be |         Password used to authenticate with UniFi controller. This can also be | ||||||
|         set in an environment variable instead of a configuration file. |         set in an environment variable instead of a configuration file. | ||||||
| 
 | 
 | ||||||
|     collect_ids    default: false |     collect_ids     default: false | ||||||
|         Setting this parameter to true will enable collection of Intrusion |         Setting this parameter to true will enable collection of Intrusion | ||||||
|         Detection System data. IDS and IPS are the same data set. This is off |         Detection System data. IDS and IPS are the same data set. This is off | ||||||
|         by default because most controllers do not have this enabled. It also |         by default because most controllers do not have this enabled. It also | ||||||
|         creates a lot of new metrics from controllers with a lot of IDS entries. |         creates a lot of new metrics from controllers with a lot of IDS entries. | ||||||
| 
 | 
 | ||||||
|     verify_ssl     default: false |     reauthenticate  default: false | ||||||
|  |         Setting this parameter to true will make UniFi Poller send a new login | ||||||
|  |         request on every interval. This generates a new cookie. Some controller | ||||||
|  |         or reverse proxy configurations require this. Do not enable it unless | ||||||
|  |         your configuration causes the poller to be logged out after some time. | ||||||
|  | 
 | ||||||
|  |     verify_ssl      default: false | ||||||
|         If your UniFi controller has a valid SSL certificate, you can enable |         If your UniFi controller has a valid SSL certificate, you can enable | ||||||
|         this option to validate it. Otherwise, any SSL certificate is valid. |         this option to validate it. Otherwise, any SSL certificate is valid. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -54,7 +54,14 @@ unifi_pass = "4BB9345C-2341-48D7-99F5-E01B583FF77F" | ||||||
| # Only useful if IDS or IPS are enabled on one of the sites. | # Only useful if IDS or IPS are enabled on one of the sites. | ||||||
| #collect_ids = false | #collect_ids = false | ||||||
| 
 | 
 | ||||||
| # If your UniFi controller has a valid SSL certificate, you can enable | # Some controllers or reverse proxy configurations do not allow cookies to be | ||||||
| # this option to validate it. Otherwise, any SSL certificate is valid. | # re-user on every request (every interval). This setting provides a workaround | ||||||
| # If you don't know if you have a valid SSL cert, then you don't have one. | # That causes the poller to re-auth (login) to the controller on every interval. | ||||||
|  | # Only enable this if you get login errors after 30 seconds. This will generate | ||||||
|  | # a few more requests to your controller every interval. | ||||||
|  | #reauthenticate = false | ||||||
|  | 
 | ||||||
|  | # If your UniFi controller has a valid SSL certificate (like lets encrypt), | ||||||
|  | # you can enable this option to validate it. Otherwise, any SSL certificate is | ||||||
|  | # valid. If you don't know if you have a valid SSL cert, then you don't have one. | ||||||
| #verify_ssl = false | #verify_ssl = false | ||||||
|  |  | ||||||
|  | @ -13,5 +13,6 @@ | ||||||
|  "unifi_pass": "", |  "unifi_pass": "", | ||||||
|  "unifi_url": "https://127.0.0.1:8443", |  "unifi_url": "https://127.0.0.1:8443", | ||||||
|  "collect_ids": false, |  "collect_ids": false, | ||||||
|  |  "reauthenticate": false, | ||||||
|  "verify_ssl": false |  "verify_ssl": false | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -77,6 +77,14 @@ | ||||||
|   --> |   --> | ||||||
|   <collect_ids>false</collect_ids> |   <collect_ids>false</collect_ids> | ||||||
|   <!-- |   <!-- | ||||||
|  |   # Some controllers or reverse proxy configurations do not allow cookies to be | ||||||
|  |   # re-user on every request (every interval). This setting provides a workaround | ||||||
|  |   # That causes the poller to re-auth (login) to the controller on every interval. | ||||||
|  |   # Only enable this if you get login errors after 30 seconds. This will generate | ||||||
|  |   # a few more requests to your controller every interval. | ||||||
|  |   --> | ||||||
|  |   <reauthenticate>false</reauthenticate> | ||||||
|  |   <!-- | ||||||
|   # If your UniFi controller has a valid SSL certificate, you can enable |   # If your UniFi controller has a valid SSL certificate, you can enable | ||||||
|   # this option to validate it. Otherwise, any SSL certificate is valid. |   # this option to validate it. Otherwise, any SSL certificate is valid. | ||||||
|   --> |   --> | ||||||
|  |  | ||||||
|  | @ -54,6 +54,13 @@ unifi_url: "https://127.0.0.1:8443" | ||||||
| # Only useful if IDS or IPS are enabled on one of the sites. | # Only useful if IDS or IPS are enabled on one of the sites. | ||||||
| collect_ids: false | collect_ids: false | ||||||
| 
 | 
 | ||||||
|  | # Some controllers or reverse proxy configurations do not allow cookies to be | ||||||
|  | # re-user on every request (every interval). This setting provides a workaround | ||||||
|  | # That causes the poller to re-auth (login) to the controller on every interval. | ||||||
|  | # Only enable this if you get login errors after 30 seconds. This will generate | ||||||
|  | # a few more requests to your controller every interval. | ||||||
|  | reauthenticate: false | ||||||
|  | 
 | ||||||
| # If your UniFi controller has a valid SSL certificate, you can enable | # If your UniFi controller has a valid SSL certificate, you can enable | ||||||
| # this option to validate it. Otherwise, any SSL certificate is valid. | # this option to validate it. Otherwise, any SSL certificate is valid. | ||||||
| verify_ssl: false | verify_ssl: false | ||||||
|  |  | ||||||
|  | @ -60,6 +60,7 @@ type Config struct { | ||||||
| 	Quiet      bool     `json:"quiet,_omitempty" toml:"quiet,_omitempty" xml:"quiet" yaml:"quiet"` | 	Quiet      bool     `json:"quiet,_omitempty" toml:"quiet,_omitempty" xml:"quiet" yaml:"quiet"` | ||||||
| 	VerifySSL  bool     `json:"verify_ssl" toml:"verify_ssl" xml:"verify_ssl" yaml:"verify_ssl"` | 	VerifySSL  bool     `json:"verify_ssl" toml:"verify_ssl" xml:"verify_ssl" yaml:"verify_ssl"` | ||||||
| 	CollectIDS bool     `json:"collect_ids" toml:"collect_ids" xml:"collect_ids" yaml:"collect_ids"` | 	CollectIDS bool     `json:"collect_ids" toml:"collect_ids" xml:"collect_ids" yaml:"collect_ids"` | ||||||
|  | 	ReAuth     bool     `json:"reauthenticate" toml:"reauthenticate" xml:"reauthenticate" yaml:"reauthenticate"` | ||||||
| 	Mode       string   `json:"mode" toml:"mode" xml:"mode" yaml:"mode"` | 	Mode       string   `json:"mode" toml:"mode" xml:"mode" yaml:"mode"` | ||||||
| 	InfluxURL  string   `json:"influx_url,_omitempty" toml:"influx_url,_omitempty" xml:"influx_url" yaml:"influx_url"` | 	InfluxURL  string   `json:"influx_url,_omitempty" toml:"influx_url,_omitempty" xml:"influx_url" yaml:"influx_url"` | ||||||
| 	InfluxUser string   `json:"influx_user,_omitempty" toml:"influx_user,_omitempty" xml:"influx_user" yaml:"influx_user"` | 	InfluxUser string   `json:"influx_user,_omitempty" toml:"influx_user,_omitempty" xml:"influx_user" yaml:"influx_user"` | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ import ( | ||||||
| 	"os" | 	"os" | ||||||
| 	"strings" | 	"strings" | ||||||
| 
 | 
 | ||||||
| 	"github.com/pkg/errors" |  | ||||||
| 	"golift.io/unifi" | 	"golift.io/unifi" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -35,7 +34,7 @@ func (u *UnifiPoller) DumpJSONPayload() (err error) { | ||||||
| 		_, _ = fmt.Fprintf(os.Stderr, "[INFO] Dumping Path '%s':\n", apiPath) | 		_, _ = fmt.Fprintf(os.Stderr, "[INFO] Dumping Path '%s':\n", apiPath) | ||||||
| 		return u.PrintRawAPIJSON(apiPath) | 		return u.PrintRawAPIJSON(apiPath) | ||||||
| 	default: | 	default: | ||||||
| 		return errors.New("must provide filter: devices, clients, other") | 		return fmt.Errorf("must provide filter: devices, clients, other") | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,10 +12,9 @@ import ( | ||||||
| 
 | 
 | ||||||
| 	"github.com/BurntSushi/toml" | 	"github.com/BurntSushi/toml" | ||||||
| 	influx "github.com/influxdata/influxdb1-client/v2" | 	influx "github.com/influxdata/influxdb1-client/v2" | ||||||
| 	"github.com/pkg/errors" | 	"github.com/spf13/pflag" | ||||||
| 	flag "github.com/spf13/pflag" |  | ||||||
| 	"golift.io/unifi" | 	"golift.io/unifi" | ||||||
| 	yaml "gopkg.in/yaml.v2" | 	"gopkg.in/yaml.v2" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // Start begins the application from a CLI.
 | // Start begins the application from a CLI.
 | ||||||
|  | @ -36,7 +35,7 @@ func Start() error { | ||||||
| 
 | 
 | ||||||
| // ParseFlags runs the parser.
 | // ParseFlags runs the parser.
 | ||||||
| func (u *UnifiPoller) ParseFlags(args []string) { | func (u *UnifiPoller) ParseFlags(args []string) { | ||||||
| 	u.Flag = flag.NewFlagSet("unifi-poller", flag.ExitOnError) | 	u.Flag = pflag.NewFlagSet("unifi-poller", pflag.ExitOnError) | ||||||
| 	u.Flag.Usage = func() { | 	u.Flag.Usage = func() { | ||||||
| 		fmt.Println("Usage: unifi-poller [--config=filepath] [--version]") | 		fmt.Println("Usage: unifi-poller [--config=filepath] [--version]") | ||||||
| 		u.Flag.PrintDefaults() | 		u.Flag.PrintDefaults() | ||||||
|  | @ -91,9 +90,11 @@ func (u *UnifiPoller) Run() (err error) { | ||||||
| 	if err = u.GetUnifi(); err != nil { | 	if err = u.GetUnifi(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | 	u.Logf("Polling UniFi Controller at %s v%s as user %s. Sites: %v", u.UnifiBase, u.ServerVersion, u.UnifiUser, u.Sites) | ||||||
| 	if err = u.GetInfluxDB(); err != nil { | 	if err = u.GetInfluxDB(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  | 	u.Logf("Logging Measurements to InfluxDB at %s as user %s", u.InfluxURL, u.InfluxUser) | ||||||
| 	switch strings.ToLower(u.Mode) { | 	switch strings.ToLower(u.Mode) { | ||||||
| 	case "influxlambda", "lambdainflux", "lambda_influx", "influx_lambda": | 	case "influxlambda", "lambdainflux", "lambda_influx", "influx_lambda": | ||||||
| 		u.LogDebugf("Lambda Mode Enabled") | 		u.LogDebugf("Lambda Mode Enabled") | ||||||
|  | @ -112,9 +113,8 @@ func (u *UnifiPoller) GetInfluxDB() (err error) { | ||||||
| 		Password: u.InfluxPass, | 		Password: u.InfluxPass, | ||||||
| 	}) | 	}) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return errors.Wrap(err, "influxdb") | 		return fmt.Errorf("influxdb: %v", err) | ||||||
| 	} | 	} | ||||||
| 	u.Logf("Logging Measurements to InfluxDB at %s as user %s", u.InfluxURL, u.InfluxUser) |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -123,14 +123,12 @@ func (u *UnifiPoller) GetUnifi() (err error) { | ||||||
| 	// Create an authenticated session to the Unifi Controller.
 | 	// Create an authenticated session to the Unifi Controller.
 | ||||||
| 	u.Unifi, err = unifi.NewUnifi(u.UnifiUser, u.UnifiPass, u.UnifiBase, u.VerifySSL) | 	u.Unifi, err = unifi.NewUnifi(u.UnifiUser, u.UnifiPass, u.UnifiBase, u.VerifySSL) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return errors.Wrap(err, "unifi controller") | 		return fmt.Errorf("unifi controller: %v", err) | ||||||
| 	} | 	} | ||||||
| 	u.Unifi.ErrorLog = u.LogErrorf // Log all errors.
 | 	u.Unifi.ErrorLog = u.LogErrorf // Log all errors.
 | ||||||
| 	u.Unifi.DebugLog = u.LogDebugf // Log debug messages.
 | 	u.Unifi.DebugLog = u.LogDebugf // Log debug messages.
 | ||||||
| 	u.Logf("Authenticated to UniFi Controller at %s version %s as user %s", u.UnifiBase, u.ServerVersion, u.UnifiUser) |  | ||||||
| 	if err := u.CheckSites(); err != nil { | 	if err := u.CheckSites(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	u.Logf("Polling UniFi Controller Sites: %v", u.Sites) |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -7,7 +7,6 @@ import ( | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	influx "github.com/influxdata/influxdb1-client/v2" | 	influx "github.com/influxdata/influxdb1-client/v2" | ||||||
| 	"github.com/pkg/errors" |  | ||||||
| 	"golift.io/unifi" | 	"golift.io/unifi" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -49,9 +48,19 @@ func (u *UnifiPoller) PollController() error { | ||||||
| 	log.Println("[INFO] Everything checks out! Poller started, interval:", u.Interval.Round(time.Second)) | 	log.Println("[INFO] Everything checks out! Poller started, interval:", u.Interval.Round(time.Second)) | ||||||
| 	ticker := time.NewTicker(u.Interval.Round(time.Second)) | 	ticker := time.NewTicker(u.Interval.Round(time.Second)) | ||||||
| 	for u.LastCheck = range ticker.C { | 	for u.LastCheck = range ticker.C { | ||||||
| 		_ = u.CollectAndReport() | 		var err error | ||||||
|  | 		if u.ReAuth { | ||||||
|  | 			// Some users need to re-auth every interval because the cookie times out.
 | ||||||
|  | 			if err = u.GetUnifi(); err != nil { | ||||||
|  | 				u.LogError(err, "re-authenticating") | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if err == nil { | ||||||
|  | 			// Only run this if the authentication procedure didn't return error.
 | ||||||
|  | 			_ = u.CollectAndReport() | ||||||
|  | 		} | ||||||
| 		if u.MaxErrors >= 0 && u.errorCount > u.MaxErrors { | 		if u.MaxErrors >= 0 && u.errorCount > u.MaxErrors { | ||||||
| 			return errors.Errorf("reached maximum error count, stopping poller (%d > %d)", u.errorCount, u.MaxErrors) | 			return fmt.Errorf("reached maximum error count, stopping poller (%d > %d)", u.errorCount, u.MaxErrors) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
|  | @ -131,7 +140,7 @@ func (u *UnifiPoller) ReportMetrics(metrics *Metrics) error { | ||||||
| 	} | 	} | ||||||
| 	err := u.Write(metrics.BatchPoints) | 	err := u.Write(metrics.BatchPoints) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return errors.Wrap(err, "influxdb.Write(points)") | 		return fmt.Errorf("influxdb.Write(points): %v", err) | ||||||
| 	} | 	} | ||||||
| 	var fields, points int | 	var fields, points int | ||||||
| 	for _, p := range metrics.Points() { | 	for _, p := range metrics.Points() { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue