func (opts Options) getCPU() int {
	var (
		numCPU      int
		availCPU    = runtime.NumCPU()
		invalCPUErr = "the CPU percentage is invalid: it should be between 1-100"
		numCPUErr   = "the CPU number should be greater than zero!"
	)
	if strings.Contains(opts.CPUCap, "%") {
		pctStr := strings.Trim(opts.CPUCap, "%")
		pctInt, err := strconv.Atoi(pctStr)
		if err != nil {
			opts.Logger.Fatalf("invalid CPU cap")
		}
		if pctInt < 1 || pctInt > 100 {
			opts.Logger.Fatalf(invalCPUErr)
		}
		numCPU = int(float32(availCPU) * (float32(pctInt) / 100))
	} else {
		numInt, err := strconv.Atoi(opts.CPUCap)
		if err != nil {
			opts.Logger.Fatalf("invalid CPU cap")
		}
		if numInt < 1 {
			opts.Logger.Fatalf(numCPUErr)
		}
		numCPU = numInt
	}
	if numCPU > availCPU {
		numCPU = availCPU
	}
	return numCPU
}
getCPU returns the number of the CPU
package main
import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path"
	"reflect"
	"runtime"
	"strconv"
	"strings"
	"gopkg.in/yaml.v2"
)
var (
	version    string
	maxWorkers = runtime.NumCPU() * 1e4
)
type arrUInt32Flags []uint32
type Options struct {
	Verbose    bool   `yaml:"verbose"`
	LogFile    string `yaml:"log-file"`
	PIDFile    string `yaml:"pid-file"`
	CPUCap     string `yaml:"cpu-cap"`
	DynWorkers bool   `yaml:"dynamic-workers"`
	Logger     *log.Logger
	version    bool
	StatsEnabled  bool   `yaml:"stats-enabled"`
	StatsFormat   string `yaml:"stats-format"`
	StatsHTTPAddr string `yaml:"stats-http-addr"`
	StatsHTTPPort string `yaml:"stats-http-port"`
	SFlowEnabled       bool           `yaml:"sflow-enabled"`
	SFlowPort          int            `yaml:"sflow-port"`
	SFlowAddr          string         `yaml:"sflow-addr"`
	SFlowUDPSize       int            `yaml:"sflow-udp-size"`
	SFlowWorkers       int            `yaml:"sflow-workers"`
	SFlowTopic         string         `yaml:"sflow-topic"`
	SFlowMirrorAddr    string         `yaml:"sflow-mirror-addr"`
	SFlowMirrorPort    int            `yaml:"sflow-mirror-port"`
	SFlowMirrorWorkers int            `yaml:"sflow-mirror-workers"`
	SFlowTypeFilter    arrUInt32Flags `yaml:"sflow-type-filter"`
	IPFIXEnabled       bool   `yaml:"ipfix-enabled"`
	IPFIXRPCEnabled    bool   `yaml:"ipfix-rpc-enabled"`
	IPFIXPort          int    `yaml:"ipfix-port"`
	IPFIXAddr          string `yaml:"ipfix-addr"`
	IPFIXUDPSize       int    `yaml:"ipfix-udp-size"`
	IPFIXWorkers       int    `yaml:"ipfix-workers"`
	IPFIXTopic         string `yaml:"ipfix-topic"`
	IPFIXMirrorAddr    string `yaml:"ipfix-mirror-addr"`
	IPFIXMirrorPort    int    `yaml:"ipfix-mirror-port"`
	IPFIXMirrorWorkers int    `yaml:"ipfix-mirror-workers"`
	IPFIXTplCacheFile  string `yaml:"ipfix-tpl-cache-file"`
	NetflowV5Enabled bool   `yaml:"netflow5-enabled"`
	NetflowV5Port    int    `yaml:"netflow5-port"`
	NetflowV5Addr    string `yaml:"netflow5-addr"`
	NetflowV5UDPSize int    `yaml:"netflow5-udp-size"`
	NetflowV5Workers int    `yaml:"netflow5-workers"`
	NetflowV5Topic   string `yaml:"netflow5-topic"`
	NetflowV9Enabled      bool   `yaml:"netflow9-enabled"`
	NetflowV9Port         int    `yaml:"netflow9-port"`
	NetflowV9Addr         string `yaml:"netflow9-addr"`
	NetflowV9UDPSize      int    `yaml:"netflow9-udp-size"`
	NetflowV9Workers      int    `yaml:"netflow9-workers"`
	NetflowV9Topic        string `yaml:"netflow9-topic"`
	NetflowV9TplCacheFile string `yaml:"netflow9-tpl-cache-file"`
	ProducerEnabled bool   `yaml:"producer-enabled"`
	MQName          string `yaml:"mq-name"`
	MQConfigFile    string `yaml:"mq-config-file"`
	VFlowConfigPath string
}
func init() {
	if version == "" {
		version = "unknown"
	}
}
func (a *arrUInt32Flags) String() string {
	return "SFlow Type string"
}
func (a *arrUInt32Flags) Set(value string) error {
	arr := strings.Split(value, ",")
	for _, v := range arr {
		v64, err := strconv.ParseUint(v, 10, 32)
		if err != nil {
			return err
		}
		*a = append(*a, uint32(v64))
	}
	return nil
}
func NewOptions() *Options {
	return &Options{
		Verbose:    false,
		version:    false,
		DynWorkers: true,
		PIDFile:    "/var/run/vflow.pid",
		CPUCap:     "100%",
		Logger:     log.New(os.Stderr, "[vflow] ", log.Ldate|log.Ltime),
		StatsEnabled:  true,
		StatsFormat:   "prometheus",
		StatsHTTPPort: "8081",
		StatsHTTPAddr: "",
		SFlowEnabled:       true,
		SFlowPort:          6343,
		SFlowUDPSize:       1500,
		SFlowWorkers:       200,
		SFlowTopic:         "vflow.sflow",
		SFlowMirrorAddr:    "",
		SFlowMirrorPort:    4171,
		SFlowMirrorWorkers: 5,
		SFlowTypeFilter:    []uint32{},
		IPFIXEnabled:       true,
		IPFIXRPCEnabled:    true,
		IPFIXPort:          4739,
		IPFIXUDPSize:       1500,
		IPFIXWorkers:       200,
		IPFIXTopic:         "vflow.ipfix",
		IPFIXMirrorAddr:    "",
		IPFIXMirrorPort:    4172,
		IPFIXMirrorWorkers: 5,
		IPFIXTplCacheFile:  "/tmp/vflow.templates",
		NetflowV5Enabled: true,
		NetflowV5Port:    9996,
		NetflowV5UDPSize: 1500,
		NetflowV5Workers: 200,
		NetflowV5Topic:   "vflow.netflow5",
		NetflowV9Enabled:      true,
		NetflowV9Port:         4729,
		NetflowV9UDPSize:      1500,
		NetflowV9Workers:      200,
		NetflowV9Topic:        "vflow.netflow9",
		NetflowV9TplCacheFile: "/tmp/netflowv9.templates",
		ProducerEnabled: true,
		MQName:          "kafka",
		MQConfigFile:    "mq.conf",
		VFlowConfigPath: "/etc/vflow",
	}
}
func GetOptions() *Options {
	opts := NewOptions()
	opts.flagSet()
	opts.printVersion()
	if opts.Verbose {
		opts.Logger.Printf("the full logging enabled")
		opts.Logger.SetFlags(log.LstdFlags | log.Lshortfile)
	}
	if opts.LogFile != "" {
		f, err := os.OpenFile(opts.LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		if err != nil {
			opts.Logger.Println(err)
		} else {
			opts.Logger.SetOutput(f)
		}
	}
	if ok := opts.vFlowIsRunning(); ok {
		opts.Logger.Fatal("the vFlow already is running!")
	}
	opts.vFlowPIDWrite()
	opts.Logger.Printf("Welcome to vFlow v.%s Apache License 2.0", version)
	opts.Logger.Printf("Copyright (C) 2018 Verizon. github.com/EdgeCast/vflow")
	return opts
}
func (opts Options) vFlowPIDWrite() {
	f, err := os.OpenFile(opts.PIDFile, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666)
	if err != nil {
		opts.Logger.Println(err)
		return
	}
	_, err = fmt.Fprintf(f, "%d", os.Getpid())
	if err != nil {
		opts.Logger.Println(err)
	}
}
func (opts Options) vFlowIsRunning() bool {
	b, err := ioutil.ReadFile(opts.PIDFile)
	if err != nil {
		return false
	}
	cmd := exec.Command("kill", "-0", string(b))
	_, err = cmd.Output()
	return err == nil
}
func (opts Options) printVersion() {
	if opts.version {
		fmt.Printf("vFlow version: %s\n", version)
		os.Exit(0)
	}
}