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 }