Skip to content

Commit

Permalink
Propagate orchestrator score thresholds to canary judge. (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Duftler authored Aug 4, 2017
1 parent e843144 commit 3c93d77
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,3 @@ public class CanaryClassifierConfig {
@Getter
private CanaryClassifierThresholdsConfig scoreThresholds;
}

@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
class CanaryClassifierThresholdsConfig {

@NotNull
@Getter
private Double pass;

@NotNull
@Getter
private Double marginal;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2017 Google, Inc.
*
* 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 com.netflix.kayenta.canary;

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

import javax.validation.constraints.NotNull;

@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CanaryClassifierThresholdsConfig {

@NotNull
@Getter
private Double pass;

@NotNull
@Getter
private Double marginal;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,7 @@

public interface CanaryJudge {
String getName();
CanaryJudgeResult judge(CanaryConfig canaryConfig, List<MetricSetPair> metricSetPairList);
CanaryJudgeResult judge(CanaryConfig canaryConfig,
CanaryClassifierThresholdsConfig orchestratorScoreThresholds,
List<MetricSetPair> metricSetPairList);
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ public String getName() {
}

@Override
public CanaryJudgeResult judge(CanaryConfig canaryConfig, List<MetricSetPair> metricSetPairList) {
public CanaryJudgeResult judge(CanaryConfig canaryConfig,
CanaryClassifierThresholdsConfig orchestratorScoreThresholds,
List<MetricSetPair> metricSetPairList) {
// TODO: "You're the judge; so judge!"

CanaryJudgeScore score = CanaryJudgeScore.builder().score(random.nextDouble() * 100).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.netflix.kayenta.canary.orca;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.kayenta.canary.CanaryClassifierThresholdsConfig;
import com.netflix.kayenta.canary.CanaryConfig;
import com.netflix.kayenta.canary.CanaryJudge;
import com.netflix.kayenta.canary.CanaryMetricConfig;
Expand Down Expand Up @@ -51,6 +53,9 @@ public class CanaryJudgeTask implements RetryableTask {
@Autowired
List<CanaryJudge> canaryJudges;

@Autowired
ObjectMapper objectMapper;

@Override
public long getBackoffPeriod() {
// TODO(duftler): Externalize this configuration.
Expand All @@ -72,6 +77,9 @@ public TaskResult execute(Stage stage) {
accountCredentialsRepository);
String canaryConfigId = (String)context.get("canaryConfigId");
String metricSetPairListId = (String)context.get("metricSetPairListId");
Map<String, String> orchestratorScoreThresholdsMap = (Map<String, String>)context.get("orchestratorScoreThresholds");
CanaryClassifierThresholdsConfig orchestratorScoreThresholds = objectMapper.convertValue(orchestratorScoreThresholdsMap,
CanaryClassifierThresholdsConfig.class);
StorageService storageService =
storageServiceRepository
.getOne(resolvedAccountName)
Expand Down Expand Up @@ -106,7 +114,7 @@ public TaskResult execute(Stage stage) {
canaryJudge = canaryJudges.get(0);
}

CanaryJudgeResult result = canaryJudge.judge(canaryConfig, metricSetPairList);
CanaryJudgeResult result = canaryJudge.judge(canaryConfig, orchestratorScoreThresholds, metricSetPairList);
Map<String, CanaryJudgeResult> outputs = Collections.singletonMap("result", result);

return new TaskResult(ExecutionStatus.SUCCEEDED, outputs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ package com.netflix.kayenta.judge.netflix
import java.util

import com.netflix.kayenta.canary.results.CanaryJudgeResult
import com.netflix.kayenta.canary.{CanaryConfig, CanaryJudge}
import com.netflix.kayenta.canary.{CanaryClassifierThresholdsConfig, CanaryConfig, CanaryJudge}
import com.netflix.kayenta.metrics.MetricSetPair

class NetflixJudge extends CanaryJudge {
override def getName(): String = {
"netflixJudge-v1.0"
}

override def judge(canaryConfig: CanaryConfig, metricSetPairList: util.List[MetricSetPair]): CanaryJudgeResult = {
override def judge(canaryConfig: CanaryConfig, orchestratorScoreThresholds: CanaryClassifierThresholdsConfig, metricSetPairList: util.List[MetricSetPair]): CanaryJudgeResult = {
val result = CanaryJudgeResult.builder().build()
result
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.netflix.kayenta.canary.CanaryClassifierThresholdsConfig;
import com.netflix.kayenta.canary.CanaryConfig;
import com.netflix.kayenta.canary.CanaryScope;
import com.netflix.kayenta.canary.CanaryScopeFactory;
Expand Down Expand Up @@ -95,7 +96,9 @@ public String initiateCanary(@RequestParam(required = false) final String metric
@ApiParam(defaultValue = "2017-07-02T15:27:00Z") @RequestParam String endTimeIso,
// TODO(duftler): Normalize this somehow. Stackdriver expects a number in seconds and Atlas expects a duration like PT10S.
@ApiParam(value = "Stackdriver expects a number in seconds and Atlas expects a duration like PT10S.", defaultValue = "3600") @RequestParam String step,
@ApiParam(value = "Atlas requires \"type\" to be set to application, cluster or node.") @RequestBody(required = false) Map<String, String> extendedScopeParams) {
@ApiParam(value = "Atlas requires \"type\" to be set to application, cluster or node.") @RequestBody(required = false) Map<String, String> extendedScopeParams,
@RequestParam(required = false) String scoreThresholdPass,
@RequestParam(required = false) String scoreThresholdMarginal) {
String resolvedMetricsAccountName = CredentialsHelper.resolveAccountByNameOrType(metricsAccountName,
AccountCredentials.Type.METRICS_STORE,
accountCredentialsRepository);
Expand Down Expand Up @@ -168,6 +171,20 @@ public String initiateCanary(@RequestParam(required = false) final String metric
.put("experimentMetricSetListIds", "${ #stage('Fetch Experiment from " + serviceType + "')['context']['metricSetListIds']}")
.build());

CanaryClassifierThresholdsConfig orchestratorScoreThresholds;

if (scoreThresholdPass != null && scoreThresholdMarginal != null) {
orchestratorScoreThresholds =
CanaryClassifierThresholdsConfig
.builder()
.pass(Double.parseDouble(scoreThresholdPass))
.marginal(Double.parseDouble(scoreThresholdMarginal))
.build();
} else {
// The score thresholds were not explicitly passed in from the orchestrator (i.e. Spinnaker), so just use the canary config values.
orchestratorScoreThresholds = canaryConfig.getClassifier().getScoreThresholds();
}

Map<String, Object> canaryJudgeContext =
Maps.newHashMap(
new ImmutableMap.Builder<String, Object>()
Expand All @@ -176,6 +193,7 @@ public String initiateCanary(@RequestParam(required = false) final String metric
.put("user", "[anonymous]")
.put("canaryConfigId", canaryConfigId)
.put("metricSetPairListId", "${ #stage('Mix Control and Experiment Results')['context']['metricSetPairListId']}")
.put("orchestratorScoreThresholds", orchestratorScoreThresholds)
.build());

Pipeline pipeline =
Expand Down

0 comments on commit 3c93d77

Please sign in to comment.