github.com/Axway/agent-sdk@v1.1.101/pkg/config/metricreportingconfig.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strconv"
     7  	"time"
     8  
     9  	"github.com/Axway/agent-sdk/pkg/cmd/properties"
    10  	"github.com/Axway/agent-sdk/pkg/util/exception"
    11  	"github.com/Axway/agent-sdk/pkg/util/log"
    12  	"github.com/gorhill/cronexpr"
    13  )
    14  
    15  const (
    16  	// DEPRECATE remove old and new env vars as well as checks below
    17  	oldUsageReportingPublishMetricEnvVar = "CENTRAL_USAGEREPORTING_PUBLISHMETRIC"
    18  	oldUsageReportingIntervalEnvVar      = "CENTRAL_USAGEREPORTING_INTERVAL"
    19  	newMetricReportingPublishEnvVar      = "CENTRAL_METRICREPORTING_PUBLISH"
    20  	newMetricReportingScheduleEnvVar     = "CENTRAL_METRICREPORTING_SCHEDULE"
    21  
    22  	// Config paths
    23  	pathMetricReportingPublish  = "central.metricreporting.publish"
    24  	pathMetricReportingSchedule = "central.metricreporting.schedule"
    25  
    26  	qaMetricReportingScheduleEnvVar = "QA_CENTRAL_METRICREPORTING_SCHEDULE"
    27  )
    28  
    29  // MetricReportingConfig - Interface to get metric reporting config
    30  type MetricReportingConfig interface {
    31  	CanPublish() bool
    32  	GetSchedule() string
    33  	GetReportGranularity() int
    34  	UsingQAVars() bool
    35  	Validate()
    36  }
    37  
    38  // MetricReportingConfiguration - structure to hold all metric reporting settings
    39  type MetricReportingConfiguration struct {
    40  	MetricReportingConfig
    41  	Publish     bool   `config:"publish"`
    42  	Schedule    string `config:"schedule"`
    43  	granularity time.Duration
    44  	qaVars      bool
    45  }
    46  
    47  // NewMetricReporting - Creates the default metric reporting config
    48  func NewMetricReporting() MetricReportingConfig {
    49  	return &MetricReportingConfiguration{
    50  		Publish:     true,
    51  		Schedule:    "@hourly",
    52  		granularity: time.Hour,
    53  		qaVars:      false,
    54  	}
    55  }
    56  
    57  // Validate -
    58  func (m *MetricReportingConfiguration) Validate() {
    59  	m.validatePublish()
    60  	// Parse and validate interval from deprecated config for backward compatibility
    61  	m.validateInterval()
    62  	m.validateSchedule()
    63  }
    64  
    65  func (u *MetricReportingConfiguration) validateInterval() {
    66  	if val := os.Getenv(newMetricReportingScheduleEnvVar); val != "" {
    67  		return // this env var is set use what has been parsed
    68  	}
    69  
    70  	// check if the old env var had a value
    71  	if val := os.Getenv(oldUsageReportingIntervalEnvVar); val != "" {
    72  		if value, err := time.ParseDuration(val); err == nil {
    73  			log.DeprecationWarningReplace(oldUsageReportingIntervalEnvVar, newMetricReportingScheduleEnvVar)
    74  			if value < 60*time.Second {
    75  				exception.Throw(ErrBadConfig.FormatError(oldUsageReportingIntervalEnvVar))
    76  			}
    77  
    78  			intervalSchedule := fmt.Sprintf("*/%d * * * *", int(value.Minutes()))
    79  			if value > time.Hour {
    80  				intervalSchedule = fmt.Sprintf("%d %d * * *", time.Now().Minute(), int(value.Hours()))
    81  			}
    82  
    83  			_, err := cronexpr.Parse(intervalSchedule)
    84  			if err != nil {
    85  				exception.Throw(ErrBadConfig.FormatError(oldUsageReportingIntervalEnvVar))
    86  			}
    87  			u.Schedule = intervalSchedule
    88  		}
    89  	}
    90  }
    91  
    92  func (m *MetricReportingConfiguration) validatePublish() {
    93  	if val := os.Getenv(newMetricReportingPublishEnvVar); val != "" {
    94  		return // this env var is set use what has been parsed
    95  	}
    96  
    97  	// check if the old env var had a value
    98  	if val := os.Getenv(oldUsageReportingPublishMetricEnvVar); val != "" {
    99  		if value, err := strconv.ParseBool(val); err == nil {
   100  			log.DeprecationWarningReplace(oldUsageReportingPublishMetricEnvVar, newMetricReportingPublishEnvVar)
   101  			m.Publish = value
   102  		}
   103  	}
   104  }
   105  
   106  func (u *MetricReportingConfiguration) validateSchedule() {
   107  	// check if the qa env var is set
   108  	if val := os.Getenv(qaMetricReportingScheduleEnvVar); val != "" {
   109  		if _, err := cronexpr.Parse(val); err != nil {
   110  			log.Tracef("Could not use %s (%s) it is not a proper cron schedule", qaMetricReportingScheduleEnvVar, val)
   111  		} else {
   112  			log.Tracef("Using %s (%s) rather than the default (%s) for non-QA", qaMetricReportingScheduleEnvVar, val, u.Schedule)
   113  			u.Schedule = val
   114  			u.qaVars = true
   115  		}
   116  		return
   117  	}
   118  
   119  	// Check the cron expressions
   120  	cron, err := cronexpr.Parse(u.Schedule)
   121  	if err != nil {
   122  		exception.Throw(ErrBadConfig.FormatError(pathMetricReportingSchedule))
   123  	}
   124  	checks := 5
   125  	nextRuns := cron.NextN(time.Now(), uint(checks))
   126  	if len(nextRuns) != checks {
   127  		exception.Throw(ErrBadConfig.FormatError(pathMetricReportingSchedule))
   128  	}
   129  	for i := 1; i < checks-1; i++ {
   130  		u.granularity = nextRuns[i].Sub(nextRuns[i-1])
   131  		if u.granularity < time.Minute*15 {
   132  			log.Tracef("%s must be at 15 min apart", pathMetricReportingSchedule)
   133  			exception.Throw(ErrBadConfig.FormatError(pathMetricReportingSchedule))
   134  		}
   135  	}
   136  }
   137  
   138  // CanPublish - Returns the publish metric boolean
   139  func (u *MetricReportingConfiguration) CanPublish() bool {
   140  	return u.Publish
   141  }
   142  
   143  // GetSchedule - Returns the schedule string
   144  func (u *MetricReportingConfiguration) GetSchedule() string {
   145  	return u.Schedule
   146  }
   147  
   148  // GetReportGranularity - Returns the schedule string
   149  func (u *MetricReportingConfiguration) GetReportGranularity() int {
   150  	return int(u.granularity.Milliseconds())
   151  }
   152  
   153  // UsingQAVars - Returns the offline boolean
   154  func (u *MetricReportingConfiguration) UsingQAVars() bool {
   155  	return u.qaVars
   156  }
   157  
   158  // AddMetricReportingProperties - Adds the command properties needed for Metric Reporting Settings
   159  func AddMetricReportingProperties(props properties.Properties) {
   160  	props.AddBoolProperty(pathMetricReportingPublish, true, "Indicates if the agent can publish metric events to Amplify platform. Default to true")
   161  	props.AddStringProperty(pathMetricReportingSchedule, "@hourly", "The schedule at metric events are sent to the platform")
   162  }
   163  
   164  // ParseUsageReportingConfig - Parses the Usage Reporting Config values from the command line
   165  func ParseMetricReportingConfig(props properties.Properties) MetricReportingConfig {
   166  	// Start with the default config
   167  	cfg := NewMetricReporting().(*MetricReportingConfiguration)
   168  
   169  	// update the config
   170  	cfg.Publish = props.BoolPropertyValue(pathMetricReportingPublish)
   171  	cfg.Schedule = props.StringPropertyValue(pathMetricReportingSchedule)
   172  
   173  	return cfg
   174  }