[VOL-3379] Support dynamic enable/disable of Log Correlation Feature
Change-Id: I6e75bb17cc878d917c49de831fd795fc8dee247a
diff --git a/VERSION b/VERSION
index 26aaba0..538ee20 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.0
+1.2.1-dev
diff --git a/internal/pkg/commands/log.go b/internal/pkg/commands/log.go
index 036abdc..6f59b9f 100644
--- a/internal/pkg/commands/log.go
+++ b/internal/pkg/commands/log.go
@@ -36,10 +36,11 @@
)
const (
- defaultComponentName = "global"
- defaultPackageName = "default"
- logPackagesListKey = "log_package_list" // kvstore key containing list of allowed log packages
- logTracingStatusKey = "trace_publish"
+ defaultComponentName = "global"
+ defaultPackageName = "default"
+ logPackagesListKey = "log_package_list" // kvstore key containing list of allowed log packages
+ logTracingStatusKey = "trace_publish"
+ logCorrelationStatusKey = "log_correlation"
)
// Custom Option representing <component-name>#<package-name> format (package is optional)
@@ -121,6 +122,30 @@
} `positional-args:"yes" required:"yes"`
}
+// EnableLogCorrelationOpts represent the supported CLI arguments for the log correlation enable command
+type EnableLogCorrelationOpts struct {
+ OutputOptions
+ Args struct {
+ Component []ComponentName
+ } `positional-args:"yes" required:"yes"`
+}
+
+// DisableLogCorrelationOpts represent the supported CLI arguments for the log correlation disable command
+type DisableLogCorrelationOpts struct {
+ OutputOptions
+ Args struct {
+ Component []ComponentName
+ } `positional-args:"yes" required:"yes"`
+}
+
+// ListLogCorrelationOpts represents the supported CLI arguments for the log correlation list command
+type ListLogCorrelationOpts struct {
+ ListOutputOptions
+ Args struct {
+ Component []ComponentName
+ } `positional-args:"yes" required:"yes"`
+}
+
// LogPackageOpts represents the log package commands
type LogPackageOpts struct {
ListLogPackages ListLogPackagesOpts `command:"list"`
@@ -140,11 +165,19 @@
ListLogTracing ListLogTracingOpts `command:"list"`
}
+// LogCorrelationOpts represents the log correlation commands
+type LogCorrelationOpts struct {
+ EnableLogCorrelation EnableLogCorrelationOpts `command:"enable"`
+ DisableLogCorrelation DisableLogCorrelationOpts `command:"disable"`
+ ListLogCorrelation ListLogCorrelationOpts `command:"list"`
+}
+
// LogOpts represents the log commands
type LogOpts struct {
- LogLevel LogLevelOpts `command:"level"`
- LogPackage LogPackageOpts `command:"package"`
- LogTracing LogTracingOpts `command:"tracing"`
+ LogLevel LogLevelOpts `command:"level"`
+ LogPackage LogPackageOpts `command:"package"`
+ LogTracing LogTracingOpts `command:"tracing"`
+ LogCorrelation LogCorrelationOpts `command:"correlation"`
}
var logOpts = LogOpts{}
@@ -236,7 +269,6 @@
ProcessGlobalOptions()
log.SetAllLogLevel(log.FatalLevel)
-
ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.KvStoreConfig.Timeout)
defer cancel()
@@ -357,7 +389,6 @@
ProcessGlobalOptions()
log.SetAllLogLevel(log.FatalLevel)
-
ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.KvStoreConfig.Timeout)
defer cancel()
@@ -642,7 +673,6 @@
ProcessGlobalOptions()
log.SetAllLogLevel(log.FatalLevel)
-
ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.KvStoreConfig.Timeout)
defer cancel()
@@ -823,7 +853,6 @@
ProcessGlobalOptions()
log.SetAllLogLevel(log.FatalLevel)
-
ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.KvStoreConfig.Timeout)
defer cancel()
@@ -897,12 +926,6 @@
// Omitting the component name will enable trace publishing for all the components, as shown in below command.
// voltctl log tracing enable
func (options *EnableLogTracingOpts) Execute(args []string) error {
-
- var (
- componentNames []string
- err error
- )
-
ProcessGlobalOptions()
log.SetAllLogLevel(log.FatalLevel)
@@ -917,6 +940,7 @@
defer cleanupFunc()
var output []LogLevelOutput
+ var componentNames []string
if len(options.Args.Component) == 0 {
// Apply to all components if no specific component has been indicated
@@ -940,24 +964,23 @@
err := config.Save(ctx, logTracingStatusKey, "ENABLED")
if err != nil {
output = append(output, LogLevelOutput{ComponentName: component, Status: "Failure", Error: err.Error()})
- } else {
- outmsg := ""
- cvalid := false
- for _, cname := range validComponents {
- if component == cname {
- cvalid = true
- break
- }
- }
-
- // For invalid component, add * against its name to indicate possible mis-configuration
- if !cvalid {
- component = "*" + component
- outmsg = "Entered Component Name is not Currently active in Voltha"
- }
-
- output = append(output, LogLevelOutput{ComponentName: component, Status: "Success", Error: outmsg})
+ continue
}
+ outmsg := ""
+ cvalid := false
+ for _, cname := range validComponents {
+ if component == cname {
+ cvalid = true
+ break
+ }
+ }
+
+ // For invalid component, add * against its name to indicate possible mis-configuration
+ if !cvalid {
+ component = "*" + component
+ outmsg = "Entered Component Name is not Currently active in Voltha"
+ }
+ output = append(output, LogLevelOutput{ComponentName: component, Status: "Success", Error: outmsg})
}
outputFormat := CharReplacer.Replace(options.Format)
@@ -982,12 +1005,6 @@
// Omitting the component name will disable trace publishing for all the components, as shown in below command.
// voltctl log tracing disable
func (options *DisableLogTracingOpts) Execute(args []string) error {
-
- var (
- componentNames []string
- err error
- )
-
ProcessGlobalOptions()
log.SetAllLogLevel(log.FatalLevel)
@@ -1002,6 +1019,7 @@
defer cleanupFunc()
var output []LogLevelOutput
+ var componentNames []string
if len(options.Args.Component) == 0 {
// Apply to all components if no specific component has been indicated
@@ -1026,24 +1044,24 @@
if err != nil {
output = append(output, LogLevelOutput{ComponentName: component, Status: "Failure", Error: err.Error()})
- } else {
- outmsg := ""
- cvalid := false
- for _, cname := range validComponents {
- if component == cname {
- cvalid = true
- break
- }
- }
-
- // For invalid component, add * against its name to indicate possible mis-configuration
- if !cvalid {
- component = "*" + component
- outmsg = "Entered Component Name is not Currently active in Voltha"
- }
-
- output = append(output, LogLevelOutput{ComponentName: component, Status: "Success", Error: outmsg})
+ continue
}
+ outmsg := ""
+ cvalid := false
+ for _, cname := range validComponents {
+ if component == cname {
+ cvalid = true
+ break
+ }
+ }
+
+ // For invalid component, add * against its name to indicate possible mis-configuration
+ if !cvalid {
+ component = "*" + component
+ outmsg = "Entered Component Name is not Currently active in Voltha"
+ }
+
+ output = append(output, LogLevelOutput{ComponentName: component, Status: "Success", Error: outmsg})
}
outputFormat := CharReplacer.Replace(options.Format)
@@ -1068,13 +1086,6 @@
// Omitting the component name will list trace publishing for all the components, as shown in below command.
// voltctl log tracing list
func (options *ListLogTracingOpts) Execute(args []string) error {
-
- var (
- data []model.LogFeature = []model.LogFeature{}
- componentNames []string
- err error
- )
-
ProcessGlobalOptions()
log.SetAllLogLevel(log.FatalLevel)
@@ -1088,6 +1099,7 @@
}
defer cleanupFunc()
+ var componentNames []string
if len(options.Args.Component) == 0 {
// Apply to all components if no specific component has been indicated
componentNames, err = cm.RetrieveComponentList(ctx, config.ConfigTypeLogFeatures)
@@ -1102,6 +1114,7 @@
}
validComponents := getVolthaComponentNames()
+ data := []model.LogFeature{}
for _, component := range componentNames {
@@ -1151,3 +1164,231 @@
GenerateOutput(&result)
return nil
}
+
+// This method enables log correlation for components.
+// For example, using below command, log correlation can be enabled for specific component
+// voltctl log correlation enable <componentName>
+// Omitting the component name will enable log correlation for all the components, as shown in below command.
+// voltctl log correlation enable
+func (options *EnableLogCorrelationOpts) Execute(args []string) error {
+ ProcessGlobalOptions()
+
+ log.SetAllLogLevel(log.FatalLevel)
+ ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.KvStoreConfig.Timeout)
+ defer cancel()
+
+ cm, cleanupFunc, err := constructConfigManager(ctx)
+ if err != nil {
+ return fmt.Errorf("Error while constructing ConfigManager instance : %s", err)
+ }
+ defer cleanupFunc()
+
+ var output []LogLevelOutput
+ var componentNames []string
+
+ if len(options.Args.Component) == 0 {
+ // Apply to all components if no specific component has been indicated
+ componentNames, err = cm.RetrieveComponentList(ctx, config.ConfigTypeLogFeatures)
+ if err != nil {
+ return fmt.Errorf("Unable to retrieve list of voltha components : %s ", err)
+ }
+ } else {
+ for _, name := range options.Args.Component {
+ componentNames = append(componentNames, string(name))
+ }
+ }
+
+ validComponents := getVolthaComponentNames()
+
+ for _, component := range componentNames {
+ config := cm.InitComponentConfig(component, config.ConfigTypeLogFeatures)
+ err := config.Save(ctx, logCorrelationStatusKey, "ENABLED")
+
+ if err != nil {
+ output = append(output, LogLevelOutput{ComponentName: component, Status: "Failure", Error: err.Error()})
+ continue
+ }
+
+ outmsg := ""
+ cvalid := false
+ for _, cname := range validComponents {
+ if component == cname {
+ cvalid = true
+ break
+ }
+ }
+ // For invalid component, add * against its name to indicate possible mis-configuration
+ if !cvalid {
+ component = "*" + component
+ outmsg = "Entered Component Name is not Currently active in Voltha"
+ }
+ output = append(output, LogLevelOutput{ComponentName: component, Status: "Success", Error: outmsg})
+ }
+
+ outputFormat := CharReplacer.Replace(options.Format)
+ if outputFormat == "" {
+ outputFormat = GetCommandOptionWithDefault("log-correlation-enable", "format", DEFAULT_LOG_FEATURE_RESULT_FORMAT)
+ }
+
+ result := CommandResult{
+ Format: format.Format(outputFormat),
+ OutputAs: toOutputType(options.OutputAs),
+ NameLimit: options.NameLimit,
+ Data: output,
+ }
+ GenerateOutput(&result)
+ return nil
+}
+
+// This method disables log correlation for components.
+// For example, using below command, log correlation can be disabled for specific component
+// voltctl log correlation disable <componentName>
+// Omitting the component name will disable log correlation for all the components, as shown in below command.
+// voltctl log correlation disable
+func (options *DisableLogCorrelationOpts) Execute(args []string) error {
+ ProcessGlobalOptions()
+
+ log.SetAllLogLevel(log.FatalLevel)
+ ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.KvStoreConfig.Timeout)
+ defer cancel()
+
+ cm, cleanupFunc, err := constructConfigManager(ctx)
+ if err != nil {
+ return fmt.Errorf("Error while constructing ConfigManager instance : %s", err)
+ }
+ defer cleanupFunc()
+
+ var output []LogLevelOutput
+ var componentNames []string
+
+ if len(options.Args.Component) == 0 {
+ // Apply to all components if no specific component has been indicated
+ componentNames, err = cm.RetrieveComponentList(ctx, config.ConfigTypeLogFeatures)
+ if err != nil {
+ return fmt.Errorf("Unable to retrieve list of voltha components : %s ", err)
+ }
+ } else {
+ for _, name := range options.Args.Component {
+ componentNames = append(componentNames, string(name))
+ }
+ }
+
+ validComponents := getVolthaComponentNames()
+
+ for _, component := range componentNames {
+
+ config := cm.InitComponentConfig(component, config.ConfigTypeLogFeatures)
+ err := config.Save(ctx, logCorrelationStatusKey, "DISABLED")
+
+ if err != nil {
+ output = append(output, LogLevelOutput{ComponentName: component, Status: "Failure", Error: err.Error()})
+ continue
+ }
+ outmsg := ""
+ cvalid := false
+ for _, cname := range validComponents {
+ if component == cname {
+ cvalid = true
+ break
+ }
+ }
+ // For invalid component, add * against its name to indicate possible mis-configuration
+ if !cvalid {
+ component = "*" + component
+ outmsg = "Entered Component Name is not Currently active in Voltha"
+ }
+ output = append(output, LogLevelOutput{ComponentName: component, Status: "Success", Error: outmsg})
+ }
+
+ outputFormat := CharReplacer.Replace(options.Format)
+ if outputFormat == "" {
+ outputFormat = GetCommandOptionWithDefault("log-correlation-disable", "format", DEFAULT_LOG_FEATURE_RESULT_FORMAT)
+ }
+
+ result := CommandResult{
+ Format: format.Format(outputFormat),
+ OutputAs: toOutputType(options.OutputAs),
+ NameLimit: options.NameLimit,
+ Data: output,
+ }
+ GenerateOutput(&result)
+ return nil
+}
+
+// This method lists current status of log correlation for components.
+// For example, using below command, log correlation can be queried for specific component
+// voltctl log correlation list <componentName>
+// Omitting the component name will list log correlation for all the components, as shown in below command.
+// voltctl log correlation list
+func (options *ListLogCorrelationOpts) Execute(args []string) error {
+ ProcessGlobalOptions()
+ log.SetAllLogLevel(log.FatalLevel)
+ ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.KvStoreConfig.Timeout)
+ defer cancel()
+
+ cm, cleanupFunc, err := constructConfigManager(ctx)
+ if err != nil {
+ return fmt.Errorf("Error while constructing ConfigManager instance : %s", err)
+ }
+ defer cleanupFunc()
+
+ var componentNames []string
+ if len(options.Args.Component) == 0 {
+ // Apply to all components if no specific component has been indicated
+ componentNames, err = cm.RetrieveComponentList(ctx, config.ConfigTypeLogFeatures)
+ if err != nil {
+ return fmt.Errorf("Unable to retrieve list of voltha components : %s ", err)
+ }
+ } else {
+ for _, name := range options.Args.Component {
+ componentNames = append(componentNames, string(name))
+ }
+ }
+
+ validComponents := getVolthaComponentNames()
+ data := []model.LogFeature{}
+
+ for _, component := range componentNames {
+ config := cm.InitComponentConfig(component, config.ConfigTypeLogFeatures)
+ value, err := config.Retrieve(ctx, logCorrelationStatusKey)
+ if err != nil || value == "" {
+ // Ignore any error in retrieval; move to next component
+ continue
+ }
+ cvalid := false
+
+ for _, cname := range validComponents {
+ if component == cname {
+ cvalid = true
+ break
+ }
+ }
+ // For invalid component, add * against its name to indicate possible mis-configuration
+ if !cvalid {
+ component = "*" + component
+ }
+ logCorrelationStatus := model.LogFeature{}
+ logCorrelationStatus.PopulateFrom(component, value)
+ data = append(data, logCorrelationStatus)
+ }
+
+ outputFormat := CharReplacer.Replace(options.Format)
+ if outputFormat == "" {
+ outputFormat = GetCommandOptionWithDefault("log-correlation-list", "format", DEFAULT_LOG_FEATURE_STATUS_FORMAT)
+ }
+ orderBy := options.OrderBy
+ if orderBy == "" {
+ orderBy = GetCommandOptionWithDefault("log-correlation-list", "order", "ComponentName,Status")
+ }
+
+ result := CommandResult{
+ Format: format.Format(outputFormat),
+ Filter: options.Filter,
+ OrderBy: orderBy,
+ OutputAs: toOutputType(options.OutputAs),
+ NameLimit: options.NameLimit,
+ Data: data,
+ }
+ GenerateOutput(&result)
+ return nil
+}
diff --git a/voltctl_command_options.config b/voltctl_command_options.config
index fb20790..bdca081 100644
--- a/voltctl_command_options.config
+++ b/voltctl_command_options.config
@@ -32,3 +32,6 @@
log-tracing-list:
order: ComponentName,Status
+
+log-correlation-list:
+ order: ComponentName,Status