Statistics

The statistics are the real values netspot monitors. In the same manner as the counters, you can implement your own statistic according to your needs. In particular, they must be located in the netspot/stats subpackage.

Note

The analyzer is in charge of managing statistics. When you implement a new statistic you don't have to take care of neither load/unload operations nor Spot algorithm configuration.

Statistics are built on top of the counters. They use some counters to compute their own value. For example, the statistic R_SYN is computed as the ratio SYN/IP where SYN counts the number of SYN packets and IP counts the number of IP packets.

The general interface of a statistic (StatInterface) is quite rich but only few functions must be implemented.

// StatInterface gathers the common behavior of the statistics
type StatInterface interface {
    Name() string
    Configure() error
    Requirement() []string
    Compute(ctrvalues []uint64) float64
    Update(val float64) int
    UpProbability(quantile float64) float64
    DownProbability(quantile float64) float64
    GetThresholds() (float64, float64)
    Status() gospot.DSpotStatus
}

Actually, statistics must inherit from the the BaseStat object which already implements some functions of the StatInterface (especially all related to the Spot algorithm).

// BaseStat is the basic structure which defines a statistic. It
// embeds a string (its unique name) and a DSpot instance which monitors
// itself.
type BaseStat struct {
    name  string
    dspot *gospot.DSpot // the spot instance
}

To define a new statistic you only need to inehrit from the previous structure and code the following 3 functions:

type StatInterface interface {
    // ...
    Name() string
    Requirement() []string
    Compute(ctrvalues []uint64) float64
    // ...
}

Warning

You have to register your statistic by calling the Register(stat StatInterface) in the init() function.

Finally, your new statistic should be defined in a single file and may look like below.

// my_stat.go

package stats

func init() {
    // The statistic is registered at the very beginning
    Register(&STAT{BaseStat{name: "..."}})
}

// STAT computes something to define
type STAT struct {
    BaseStat // compose with BaseStat
    // you can add some other attributes
}

// Name returns the unique name of the stat
func (stat *STAT) Name() string {
    return "..."
}

// Requirement returns the requested counters to compute the stat.
// The order is important for the Compute() function
func (stat *STAT) Requirement() []string {

}

// Compute implements the way to compute the stat from the counters.
// Counters are given in the same order as the Requirement() function
func (stat *STAT) Compute(ctrvalues []uint64) float64 {

}