| /* |
| * Copyright 2018-present Open Networking Foundation |
| |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package config |
| |
| import ( |
| "context" |
| "errors" |
| "github.com/opencord/voltha-lib-go/v3/pkg/log" |
| "os" |
| "strings" |
| ) |
| |
| const ( |
| defaultTracingStatusKey = "trace_publish" // kvstore key containing tracing configuration status |
| defaultLogCorrelationStatusKey = "log_correlation" // kvstore key containing log correlation configuration status |
| ) |
| |
| // ComponentLogFeatureController represents Configuration for Logging related features of Tracing and Log |
| // Correlation of specific Voltha component. |
| type ComponentLogFeaturesController struct { |
| ComponentName string |
| componentNameConfig *ComponentConfig |
| configManager *ConfigManager |
| initialTracingStatus bool // Initial default tracing status set by helm chart |
| initialLogCorrelationStatus bool // Initial default log correlation status set by helm chart |
| } |
| |
| func NewComponentLogFeaturesController(ctx context.Context, cm *ConfigManager) (*ComponentLogFeaturesController, error) { |
| logger.Debug(ctx, "creating-new-component-log-features-controller") |
| componentName := os.Getenv("COMPONENT_NAME") |
| if componentName == "" { |
| return nil, errors.New("Unable to retrieve PoD Component Name from Runtime env") |
| } |
| |
| tracingStatus := log.GetGlobalLFM().GetTracePublishingStatus() |
| logCorrelationStatus := log.GetGlobalLFM().GetLogCorrelationStatus() |
| |
| return &ComponentLogFeaturesController{ |
| ComponentName: componentName, |
| componentNameConfig: nil, |
| configManager: cm, |
| initialTracingStatus: tracingStatus, |
| initialLogCorrelationStatus: logCorrelationStatus, |
| }, nil |
| |
| } |
| |
| // StartLogFeaturesConfigProcessing persists initial config of Log Features into Config Store before |
| // starting the loading and processing of Configuration updates |
| func StartLogFeaturesConfigProcessing(cm *ConfigManager, ctx context.Context) { |
| cc, err := NewComponentLogFeaturesController(ctx, cm) |
| if err != nil { |
| logger.Errorw(ctx, "unable-to-construct-component-log-features-controller-instance-for-monitoring", log.Fields{"error": err}) |
| return |
| } |
| |
| cc.componentNameConfig = cm.InitComponentConfig(cc.ComponentName, ConfigTypeLogFeatures) |
| logger.Debugw(ctx, "component-log-features-config", log.Fields{"cc-component-name-config": cc.componentNameConfig}) |
| |
| cc.persistInitialLogFeaturesConfigs(ctx) |
| |
| cc.processLogFeaturesConfig(ctx) |
| } |
| |
| // Method to persist Initial status of Log Correlation and Tracing features (as set from command line) |
| // into config store (etcd kvstore), if not set yet |
| func (cc *ComponentLogFeaturesController) persistInitialLogFeaturesConfigs(ctx context.Context) { |
| |
| _, err := cc.componentNameConfig.Retrieve(ctx, defaultTracingStatusKey) |
| if err != nil { |
| statusString := "DISABLED" |
| if cc.initialTracingStatus { |
| statusString = "ENABLED" |
| } |
| err = cc.componentNameConfig.Save(ctx, defaultTracingStatusKey, statusString) |
| if err != nil { |
| logger.Errorw(ctx, "failed-to-persist-component-initial-tracing-status-at-startup", log.Fields{"error": err, "tracingstatus": statusString}) |
| } |
| } |
| |
| _, err = cc.componentNameConfig.Retrieve(ctx, defaultLogCorrelationStatusKey) |
| if err != nil { |
| statusString := "DISABLED" |
| if cc.initialLogCorrelationStatus { |
| statusString = "ENABLED" |
| } |
| err = cc.componentNameConfig.Save(ctx, defaultLogCorrelationStatusKey, statusString) |
| if err != nil { |
| logger.Errorw(ctx, "failed-to-persist-component-initial-log-correlation-status-at-startup", log.Fields{"error": err, "logcorrelationstatus": statusString}) |
| } |
| } |
| } |
| |
| // processLogFeaturesConfig will first load and apply configuration of log features. Then it will start waiting for any changes |
| // made to configuration in config store (etcd) and apply the same |
| func (cc *ComponentLogFeaturesController) processLogFeaturesConfig(ctx context.Context) { |
| |
| // Load and apply Tracing Status and log correlation status for first time |
| cc.loadAndApplyTracingStatusUpdate(ctx) |
| cc.loadAndApplyLogCorrelationStatusUpdate(ctx) |
| |
| componentConfigEventChan := cc.componentNameConfig.MonitorForConfigChange(ctx) |
| |
| // process the change events received on the channel |
| var configEvent *ConfigChangeEvent |
| for { |
| select { |
| case <-ctx.Done(): |
| return |
| |
| case configEvent = <-componentConfigEventChan: |
| logger.Debugw(ctx, "processing-log-features-config-change", log.Fields{"ChangeType": configEvent.ChangeType, "Package": configEvent.ConfigAttribute}) |
| |
| if strings.HasSuffix(configEvent.ConfigAttribute, defaultTracingStatusKey) { |
| cc.loadAndApplyTracingStatusUpdate(ctx) |
| } else if strings.HasSuffix(configEvent.ConfigAttribute, defaultLogCorrelationStatusKey) { |
| cc.loadAndApplyLogCorrelationStatusUpdate(ctx) |
| } |
| } |
| } |
| |
| } |
| |
| func (cc *ComponentLogFeaturesController) loadAndApplyTracingStatusUpdate(ctx context.Context) { |
| |
| desiredTracingStatus, err := cc.componentNameConfig.Retrieve(ctx, defaultTracingStatusKey) |
| if err != nil || desiredTracingStatus == "" { |
| logger.Warn(ctx, "unable-to-retrieve-tracing-status-from-config-store") |
| return |
| } |
| |
| if desiredTracingStatus != "ENABLED" && desiredTracingStatus != "DISABLED" { |
| logger.Warnw(ctx, "unsupported-tracing-status-configured-in-config-store", log.Fields{"failed-tracing-status": desiredTracingStatus, "tracing-status": log.GetGlobalLFM().GetTracePublishingStatus()}) |
| return |
| } |
| |
| logger.Debugw(ctx, "retrieved-tracing-status", log.Fields{"tracing-status": desiredTracingStatus}) |
| |
| log.GetGlobalLFM().SetTracePublishingStatus(desiredTracingStatus == "ENABLED") |
| } |
| |
| func (cc *ComponentLogFeaturesController) loadAndApplyLogCorrelationStatusUpdate(ctx context.Context) { |
| |
| desiredLogCorrelationStatus, err := cc.componentNameConfig.Retrieve(ctx, defaultLogCorrelationStatusKey) |
| if err != nil || desiredLogCorrelationStatus == "" { |
| logger.Warn(ctx, "unable-to-retrieve-log-correlation-status-from-config-store") |
| return |
| } |
| |
| if desiredLogCorrelationStatus != "ENABLED" && desiredLogCorrelationStatus != "DISABLED" { |
| logger.Warnw(ctx, "unsupported-log-correlation-status-configured-in-config-store", log.Fields{"failed-log-correlation-status": desiredLogCorrelationStatus, "log-correlation-status": log.GetGlobalLFM().GetLogCorrelationStatus()}) |
| return |
| } |
| |
| logger.Debugw(ctx, "retrieved-log-correlation-status", log.Fields{"log-correlation-status": desiredLogCorrelationStatus}) |
| |
| log.GetGlobalLFM().SetLogCorrelationStatus(desiredLogCorrelationStatus == "ENABLED") |
| } |