mirror of
https://codeberg.org/scip/esctl.git
synced 2026-08-24 18:04:17 +02:00
add ilm forecast show
This commit is contained in:
@@ -480,14 +480,17 @@ ilm - manage index lifecycle
|
||||
list - list index lifecycle policies
|
||||
show - show details about an index lifecycle policy
|
||||
create - create a index lifecycle policy
|
||||
forecast - calculate index phase movements
|
||||
list - list index rollover config
|
||||
show - show rollover forecast over all indices
|
||||
index - manage indicies
|
||||
list - list indicies
|
||||
show - show details about an index
|
||||
create - create a new index
|
||||
modify - modify anindex
|
||||
delete - delete an index
|
||||
close - close an index
|
||||
allocation - explain index allocation
|
||||
modify - modify an index
|
||||
fields - show info about field capabilities
|
||||
ilm - show ilm status
|
||||
alias - manage index aliases
|
||||
@@ -522,10 +525,10 @@ version - show esctl version information
|
||||
debug - developer only
|
||||
help-jsonpath - show jsonpath help
|
||||
completion - Output shell completion script for bash, zsh, fish, or Powershell
|
||||
pwsh - Output pwsh completion script
|
||||
bash - Output bash completion script
|
||||
zsh - Output zsh completion script
|
||||
fish - Output fish completion script
|
||||
pwsh - Output pwsh completion script
|
||||
```
|
||||
|
||||
# Development
|
||||
|
||||
@@ -34,6 +34,7 @@ func IlmForecast(conf *cfg.Config) *cli.Command {
|
||||
|
||||
Commands: []*cli.Command{
|
||||
IlmForecastList(conf),
|
||||
IlmForecastShow(conf),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -69,3 +70,35 @@ func IlmForecastList(conf *cfg.Config) *cli.Command {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func IlmForecastShow(conf *cfg.Config) *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "show",
|
||||
Aliases: []string{"sh"},
|
||||
Usage: "show rollover forecast over all indices",
|
||||
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "from-phase",
|
||||
Usage: "which ilm phase to forecast from",
|
||||
Destination: &conf.Ilm.FromPhase,
|
||||
Aliases: []string{"f"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "within",
|
||||
Usage: "duration withing which to forecast",
|
||||
Destination: &conf.Ilm.Within,
|
||||
Aliases: []string{"w"},
|
||||
},
|
||||
},
|
||||
|
||||
Action: func(ctx context.Context, cmd *cli.Command) error {
|
||||
valid := []string{"hot", "warm", "cold", "frozen"}
|
||||
if !slices.Contains(valid, conf.Ilm.FromPhase) {
|
||||
return errors.New("invalid from phase, allowed: hot, warm, cold, frozen")
|
||||
}
|
||||
|
||||
return es.IlmForecastShow(conf)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,83 @@ types.Lifecycle{
|
||||
|
||||
hot for 7 days or 25Gig, then Rollover => warm 14 days => frozen 60 days => delete
|
||||
*/
|
||||
|
||||
func IlmForecastList(conf *cfg.Config) error {
|
||||
phaseData, err := getIlmPhaseData(conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
table := printer.NewTable(conf, 8, 0)
|
||||
table.Addheaders("index", "current size", "current age", "virtual age", "min age", "min size", "current phase", "next phase")
|
||||
|
||||
for _, phase := range phaseData {
|
||||
virtualAge := virtualAge(&phase)
|
||||
|
||||
table.AddRow(
|
||||
phase.index,
|
||||
humanize.Bytes(uint64(phase.size)),
|
||||
fmt.Sprintf("%s", phase.age),
|
||||
|
||||
fmt.Sprintf("%s", virtualAge),
|
||||
|
||||
fmt.Sprintf("%s", phase.minage),
|
||||
humanize.Bytes(uint64(phase.minsize)),
|
||||
|
||||
phase.currentPhase,
|
||||
phase.nextPhase,
|
||||
)
|
||||
}
|
||||
|
||||
table.Sort()
|
||||
return table.Print()
|
||||
}
|
||||
|
||||
// Loop over all current index phases of the current phase
|
||||
// (conf.Ilm.FromPhase). Calculate virtualAge if phase.minsize >0. If
|
||||
// the actual age is smaller than the virtual age, use this as a base,
|
||||
// otherwise use virtual age. Then look if the rollover would happen
|
||||
// within the phase.minage window (conf.Ilm.Within + current age) and
|
||||
// add the size.
|
||||
func IlmForecastShow(conf *cfg.Config) error {
|
||||
phaseData, err := getIlmPhaseData(conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
within := parseDuration(conf.Ilm.Within)
|
||||
var toBeFreed int64 = 0
|
||||
|
||||
for _, phase := range phaseData {
|
||||
age := virtualAge(&phase)
|
||||
if age < phase.age {
|
||||
age = phase.age
|
||||
}
|
||||
|
||||
if age+within >= phase.minage {
|
||||
toBeFreed += phase.size
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("%s bytes of data will be rolled within %s\n", humanize.Bytes(uint64(toBeFreed)), within)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func virtualAge(phase *PhaseData) time.Duration {
|
||||
if phase.minsize == 0 {
|
||||
return time.Duration(0)
|
||||
}
|
||||
|
||||
oneMinAge := phase.minage.Seconds() / 100
|
||||
oneMinSize := float64(phase.minsize) / 100
|
||||
|
||||
percentSize := float64(phase.size) / oneMinSize
|
||||
virtualAge := percentSize * oneMinAge
|
||||
|
||||
return time.Duration(virtualAge) * time.Second
|
||||
}
|
||||
|
||||
func getIlmPhaseData(conf *cfg.Config) ([]PhaseData, error) {
|
||||
responses := make(chan apiResponse, 3)
|
||||
wg := &sync.WaitGroup{}
|
||||
@@ -177,33 +254,6 @@ func getIlmPhaseData(conf *cfg.Config) ([]PhaseData, error) {
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func IlmForecastList(conf *cfg.Config) error {
|
||||
phaseData, err := getIlmPhaseData(conf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
table := printer.NewTable(conf, 7, 0)
|
||||
table.Addheaders("index", "current size", "current age", "min age", "min size", "current phase", "next phase")
|
||||
|
||||
for _, phase := range phaseData {
|
||||
table.AddRow(
|
||||
phase.index,
|
||||
humanize.Bytes(uint64(phase.size)),
|
||||
fmt.Sprintf("%s", phase.age),
|
||||
|
||||
fmt.Sprintf("%s", phase.minage),
|
||||
humanize.Bytes(uint64(phase.minsize)),
|
||||
|
||||
phase.currentPhase,
|
||||
phase.nextPhase,
|
||||
)
|
||||
}
|
||||
|
||||
table.Sort()
|
||||
return table.Print()
|
||||
}
|
||||
|
||||
func findNextPhase(policy types.IlmPolicy, currentPhase string) *NextPhase {
|
||||
// phase list to determine which comes next
|
||||
order := []string{"hot", "warm", "cold", "frozen", "delete"}
|
||||
@@ -265,10 +315,7 @@ func findNextPhase(policy types.IlmPolicy, currentPhase string) *NextPhase {
|
||||
|
||||
if phase == "hot" {
|
||||
// if we're starting here, do not look for the next phase
|
||||
maxage, err := time.ParseDuration(phases[phase].Actions.Rollover.MaxAge.(string))
|
||||
if err != err {
|
||||
maxage = 0
|
||||
}
|
||||
maxage := parseDuration(phases[phase].Actions.Rollover.MaxAge.(string))
|
||||
|
||||
var maxsize int64 = 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user