blob: 8f4131e867a190bd5ac0c0193067ba3202fd7d1d [file] [log] [blame]
/*
* Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
* 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"
"os"
"strings"
"github.com/opencord/voltha-lib-go/v7/pkg/log"
)
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")
}