<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Spinnaker – Using Spinnaker for Automated Canary Analysis</title>
    <link>https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/</link>
    <description>Recent content in Using Spinnaker for Automated Canary Analysis on Spinnaker</description>
    <generator>Hugo -- gohugo.io</generator>
    
	  <atom:link href="https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/index.xml" rel="self" type="application/rss+xml" />
    
    
      
        
      
    
    
    <item>
      <title>Docs: Canary Overview</title>
      <link>https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/canary-overview/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/canary-overview/</guid>
      <description>
        
        
        &lt;p&gt;Canary is a deployment process in which a change is partially rolled out, then
evaluated against the current deployment (baseline) to ensure that the new
deployment is operating at least as well as the old. This evaluation is done
using key metrics that are chosen when the canary is configured.&lt;/p&gt;
&lt;p&gt;Canaries are usually run against deployments containing changes to code,
but they can also be used for operational changes, including changes to
configuration.&lt;/p&gt;
&lt;p&gt;The canary process is not a substitute for other forms of testing.&lt;/p&gt;
&lt;h2 id=&#34;prerequisites&#34;&gt;Prerequisites&lt;/h2&gt;
&lt;h3 id=&#34;have-metrics-to-evaluate&#34;&gt;Have metrics to evaluate&lt;/h3&gt;
&lt;p&gt;Your application might send performance metrics which are published and
available by default. You can also install a monitoring agent to collect more
comprehensive metrics, and you can instrument your code to generate further
metrics for that agent. In any case, you need to have access to a set of
metrics, using some telemetry provider, which Kayenta can then use to make the
canary judgment.&lt;/p&gt;
&lt;p&gt;Support is built in for 
&lt;a href=&#34;https://cloud.google.com/stackdriver/docs/&#34; target=&#34;_blank&#34;&gt;Stackdriver&lt;/a&gt;
,

&lt;a href=&#34;https://docs.datadoghq.com/&#34; target=&#34;_blank&#34;&gt;Datadog&lt;/a&gt;
,

&lt;a href=&#34;https://prometheus.io/docs/introduction/overview/&#34; target=&#34;_blank&#34;&gt;Prometheus&lt;/a&gt;
,

&lt;a href=&#34;https://docs.signalfx.com&#34; target=&#34;_blank&#34;&gt;Signalfx&lt;/a&gt;
, and 
&lt;a href=&#34;https://docs.newrelic.com/&#34; target=&#34;_blank&#34;&gt;New Relic&lt;/a&gt;
.&lt;/p&gt;
&lt;h3 id=&#34;set-up-your-canary-environment&#34;&gt;Set up your canary environment&lt;/h3&gt;
&lt;p&gt;Before you can configure canary analysis and create canary stages for your
pipelines, your Spinnaker administrator needs to 
&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/setup/other_config/canary/&#34;&gt;enable canary for your
installation&lt;/a&gt;
.&lt;/p&gt;
&lt;h2 id=&#34;how-to-make-canary-work-in-spinnakermdashthe-high-level-process&#34;&gt;How to make Canary work in Spinnaker—the high-level process&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In Spinnaker, 
&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/config/&#34;&gt;create one or more canary
configurations&lt;/a&gt;
.&lt;/p&gt;
&lt;p&gt;The configuration provides the set of metrics for use in all pipeline
canary stages that reference it, plus default scoring thresholds and
weights—defaults that can be overridden in
a 
&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/stage/&#34;&gt;canary stage&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;You can configure each metric flexibly, to define its scope and whether it
fails when it deviates upward or down. You can also group metrics logically
and assign weights to groups to control their impact on the final score.&lt;/p&gt;
&lt;p&gt;You can think of this configuration as a templated set of queries against
your metric store.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In any deployment pipeline that will use canary, 
&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/stage/&#34;&gt;add one or more canary
stages&lt;/a&gt;
.&lt;/p&gt;
&lt;p&gt;The canary stage includes information that scopes the templated query (canary
config) to a specified set of resources and time boundaries.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;See also:&lt;br&gt;

&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/judge/&#34;&gt;The Canary Judge—how does it work?&lt;/a&gt;
&lt;br&gt;

&lt;a href=&#34;https://cloud.google.com/solutions/automated-canary-analysis-kubernetes-engine-spinnaker&#34; target=&#34;_blank&#34;&gt;Automating Canary Analysis on GKE with Spinnaker&lt;/a&gt;
&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Docs: Best practices for configuring canary</title>
      <link>https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/best-practices/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/best-practices/</guid>
      <description>
        
        
        &lt;h2 id=&#34;dont-put-too-many-metrics-in-one-group&#34;&gt;Don&amp;rsquo;t put too many metrics in one group&lt;/h2&gt;
&lt;p&gt;If you have many metrics in a group and one fails while the rest pass, the group
gets a passing score overall.&lt;/p&gt;
&lt;p&gt;For truly critical metrics (e.g., error rates), use the &lt;code&gt;critical: true&lt;/code&gt; flag in
the metric configuration. This causes the entire canary to fail immediately
(score = 0) if that metric is classified as High or Low, regardless of group scores.&lt;/p&gt;
&lt;p&gt;Alternatively, you can put an important metric in a group by itself to ensure
that if it fails, the whole group fails.&lt;/p&gt;
&lt;h2 id=&#34;compare-canary-against-baseline-not-against-production&#34;&gt;Compare canary against baseline, not against production&lt;/h2&gt;
&lt;p&gt;You might be tempted to compare the canary deployment against your current
production deployment. Instead always compare the canary against an equivalent
baseline, deployed at the same time.&lt;/p&gt;
&lt;p&gt;The baseline uses the same version and configuration that is currently running
in production, but is otherwise identical to the canary:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Same time of deployment&lt;/li&gt;
&lt;li&gt;Same size of deployment&lt;/li&gt;
&lt;li&gt;Same type and amount of traffic&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this way, you control for version and configuration only, and you reduce
factors that could affect the analysis, like the cache warmup time, the heap
size, and so on.&lt;/p&gt;
&lt;h2 id=&#34;run-the-canary-for-enough-time&#34;&gt;Run the canary for enough time&lt;/h2&gt;
&lt;p&gt;You need at least 50 pieces of time series data per metric for the statistical
analysis to produce accurate results. That is 50 data points per canary run,
with potentially several runs per canary analysis. In the end, you should plan
for canary analyses several hours long.&lt;/p&gt;
&lt;p&gt;You will need to tune the time parameters to your particular application. A good
starting point is to have a canary lifetime of 3 hours, an interval of 1 hour
and no warm-up period (unless you already know your application needs one).
This gives you 3 canary runs, each 1 hour long.&lt;/p&gt;
&lt;h2 id=&#34;carefully-choose-your-thresholds&#34;&gt;Carefully choose your thresholds&lt;/h2&gt;
&lt;p&gt;You need to configure two thresholds for a canary analysis:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;marginal&lt;/p&gt;
&lt;p&gt;If a canary run scores below this threshold, the whole canary fails immediately.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;pass&lt;/p&gt;
&lt;p&gt;The final canary run must score at or above this threshold for the analysis
to be considered successful. Otherwise it fails.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: Threshold comparisons are inclusive (≥). A score of exactly 95 with a
pass threshold of 95 results in a pass.&lt;/p&gt;
&lt;p&gt;These thresholds are very important for the analysis to give an accurate result.
You need to experiment with them, in the context of your own application, its
traffic and its metrics.&lt;/p&gt;
&lt;p&gt;Keep in mind that your configuration will be refined over time. Don&amp;rsquo;t think of
it as something you set up once and never think about again.&lt;/p&gt;
&lt;p&gt;Good starting points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;marginal threshold of 75&lt;/li&gt;
&lt;li&gt;pass threshold of 95&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;carefully-choose-the-metrics-to-analyze&#34;&gt;Carefully choose the metrics to analyze&lt;/h2&gt;
&lt;p&gt;You can get started with a single metric, but in the long run, your canaries
will use several.&lt;/p&gt;
&lt;p&gt;Use a variety of metrics that reflect different aspects of the health of your
application. Use these three out of the four &amp;ldquo;golden signals,&amp;rdquo; as defined in
the 
&lt;a href=&#34;https://landing.google.com/sre/book/chapters/monitoring-distributed-systems.html&#34; target=&#34;_blank&#34;&gt;SRE Book&lt;/a&gt;
:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;latency&lt;/li&gt;
&lt;li&gt;errors&lt;/li&gt;
&lt;li&gt;saturation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you consider some other specific metrics critical, place them in their own
group in the canary configuration. That allows you to fail the whole canary
analysis if there is a problem with one of those specific metrics. You can also
use the criticality flag on the individual metric.&lt;/p&gt;
&lt;h2 id=&#34;create-a-set-of-standard-reusable-canary-configs&#34;&gt;Create a set of standard, reusable canary configs&lt;/h2&gt;
&lt;p&gt;Configuring a canary is difficult, and not every developer in your organization
will be able to do so. Also, if you let all the teams in the org manage their
own configs, you will likely end up with too many configs, too many metrics,
nobody will know what is happening, and people will be afraid to change
anything.&lt;/p&gt;
&lt;p&gt;For these reasons, it&amp;rsquo;s a good idea to curate a set of configs that all the
teams can reuse.&lt;/p&gt;
&lt;h2 id=&#34;use-retrospective-analysis-to-make-debugging-faster&#34;&gt;Use retrospective analysis to make debugging faster&lt;/h2&gt;
&lt;p&gt;It takes a long time to configure a canary analysis. It can take a long time to
debug it too, partly because with 
&lt;a href=&#34;#run-the-canary-for-enough-time&#34;&gt;a long-running canary
analysis&lt;/a&gt;
 you have to wait a long time
for the analysis to finish before you can refine it.&lt;/p&gt;
&lt;p&gt;Fortunately, a Canary Analysis stage can be configured to use a 
&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/stage/#real-time-versus-retrospective-analysis&#34;&gt;retrospective
analysis&lt;/a&gt;

instead of a real-time analysis. This analysis is based on past monitoring data,
without having to wait for the data points to be generated. With this mode, you
can iterate more quickly on the development of the canary configuration.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: Use the copy-to-clipboard icons in the canary stage execution details
view to capture the needed timestamps.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;compare-equivalent-deployments&#34;&gt;Compare equivalent deployments&lt;/h2&gt;
&lt;p&gt;To compare the metrics between baseline and canary, Kayenta needs the exact same
metrics for both. This means that metrics should have the same labels. Problems
can arise if the metrics are labeled with their respective instance names.&lt;/p&gt;
&lt;p&gt;If you see that Kayenta is not actually comparing the metrics, confirm that the
queries that it executes against your monitoring system return metrics with the
same labels.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re using Stackdriver, you can use the Google 
&lt;a href=&#34;https://developers.google.com/apis-explorer/#search/timeseries/m/monitoring/v3/monitoring.projects.timeSeries.list&#34; target=&#34;_blank&#34;&gt;APIs Explorer&lt;/a&gt;
 to debug such problems.&lt;/p&gt;
&lt;h2 id=&#34;some-configuration-values-to-start-with&#34;&gt;Some configuration values to start with&lt;/h2&gt;
&lt;p&gt;Although these values are not necessarily &amp;ldquo;best practices,&amp;rdquo; they are reasonable
starting points for your canary configs:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;canary lifetime&lt;/td&gt;
&lt;td&gt;3 hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;successful score&lt;/td&gt;
&lt;td&gt;95&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;unhealthy score&lt;/td&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;warmup period&lt;/td&gt;
&lt;td&gt;0 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;frequency&lt;/td&gt;
&lt;td&gt;60 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;use lookback&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

      </description>
    </item>
    
    <item>
      <title>Docs: How canary judgment works</title>
      <link>https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/judge/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/judge/</guid>
      <description>
        
        
        &lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Automated canary analysis in Spinnaker is designed to support pluggable
judges. This document describes how the default judge (NetflixACAJudge) works.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To assess the quality of a canary deployment against a baseline, metrics from
both deployments are compared in order to check for significant degradation.
This is done in two phases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Metric collection (retrieval)&lt;/p&gt;
&lt;p&gt;This phase retrieves the key metrics from the baseline and canary deployments.
These metrics are typically stored in a time-series database, and include a
set of tags or annotations that identify which deployment the data was
collected from (canary or baseline).&lt;/p&gt;
&lt;p&gt;This phase is performed by Kayenta, not by the judge. Besides the default
judge, it is possible to plug in a custom judge, and metric collection is not
the responsibility of the judge. The judge merely receives timeseries from
Kayenta and analyzes those.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Judgment&lt;/p&gt;
&lt;p&gt;In this phase Spinnaker compares those metrics and renders a decision to pass
or fail the canary (that is, was there a significant degradation in the
metrics?) The judgment can also be configured to continue on with a canary
when the result is &amp;ldquo;marginal.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The judgment consists of four main steps, and they&amp;rsquo;re described below.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;step-1-data-validation-and-nan-handling&#34;&gt;Step 1: Data validation and NaN handling&lt;/h2&gt;
&lt;p&gt;Data validation ensures there&amp;rsquo;s data for the baseline and canary metrics before
analysis begins. The behavior depends on the &lt;code&gt;nanStrategy&lt;/code&gt; configuration:&lt;/p&gt;
&lt;h3 id=&#34;nan-strategies&#34;&gt;NaN strategies&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;remove&lt;/code&gt;&lt;/strong&gt;: NaN values are filtered out of the metric arrays.
If this results in an empty array, the metric is classified based on other flags.
This is the default behavior when &lt;code&gt;nanStrategy&lt;/code&gt; is not specified or set to an unrecognized value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;replace&lt;/code&gt;&lt;/strong&gt;: NaN values are replaced with &lt;code&gt;0.0&lt;/code&gt;. The metric proceeds to
comparison even if all original values were NaN (the array will contain zeros).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;classification-when-data-is-missing&#34;&gt;Classification when data is missing&lt;/h3&gt;
&lt;p&gt;When either baseline or canary has no data after NaN handling:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;nanStrategy&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;mustHaveData&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;critical&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Classification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;remove&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Nodata&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;remove&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Nodata&lt;/code&gt; (critical)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;remove&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;NodataFailMetric&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;replace&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;any&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Pass&lt;/code&gt; (arrays have zeros)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Nodata&lt;/code&gt;&lt;/strong&gt;: Metric is excluded from group score calculations (doesn&amp;rsquo;t hurt
or help the score), but counts toward the 50% NODATA threshold.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;NodataFailMetric&lt;/code&gt;&lt;/strong&gt;: Metric counts as a failure in group score calculations.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip&lt;/strong&gt;: Use &lt;code&gt;nanStrategy: replace&lt;/code&gt; for error metrics where no data means
zero errors. Use &lt;code&gt;mustHaveData: true&lt;/code&gt; for metrics that should always have data.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;step-2-data-cleaning-outlier-removal&#34;&gt;Step 2: Data cleaning (outlier removal)&lt;/h2&gt;
&lt;p&gt;After NaN handling, the judge can optionally remove outliers from the data.&lt;/p&gt;
&lt;h3 id=&#34;outlier-detection&#34;&gt;Outlier detection&lt;/h3&gt;
&lt;p&gt;When &lt;code&gt;outliers.strategy: remove&lt;/code&gt; is configured, the judge uses an IQR-based
detector with reduced sensitivity:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Calculate Q1 (25th percentile) and Q3 (75th percentile)&lt;/li&gt;
&lt;li&gt;Calculate IQR = Q3 - Q1&lt;/li&gt;
&lt;li&gt;Calculate standard Tukey fences: &lt;code&gt;[Q1 - factor×IQR, Q3 + factor×IQR]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Also calculate 1st and 99th percentiles&lt;/li&gt;
&lt;li&gt;Final fences: &lt;code&gt;[min(P1, lower_fence), max(P99, upper_fence)]&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The default &lt;code&gt;outlierFactor&lt;/code&gt; is 3.0. Values outside the final fences are removed.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The reduced sensitivity approach makes outlier detection less
aggressive than standard Tukey&amp;rsquo;s test, keeping more data points.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;step-3-metric-comparison-classification&#34;&gt;Step 3: Metric comparison (classification)&lt;/h2&gt;
&lt;p&gt;The judge compares canary and baseline data for each metric and assigns a
classification indicating whether there&amp;rsquo;s a significant difference.&lt;/p&gt;
&lt;h3 id=&#34;classification-labels&#34;&gt;Classification labels&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Label&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Pass&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No significant difference detected&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;High&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Canary is significantly higher than baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Low&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Canary is significantly lower than baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Nodata&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Insufficient data for comparison&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NodataFailMetric&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Missing data for a metric with &lt;code&gt;mustHaveData: true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Error&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Classification failed due to an internal error&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figure&gt;&lt;img src=&#34;./metric_classifications.png&#34;/&gt;
&lt;/figure&gt;

&lt;h3 id=&#34;mann-whitney-u-test&#34;&gt;Mann-Whitney U test&lt;/h3&gt;
&lt;p&gt;The judge compares the canary and baseline metric values to determine if there&amp;rsquo;s
a real difference or just random noise. It uses a statistical test that answers:
&amp;ldquo;Are these two sets of numbers meaningfully different?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In plain terms:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The judge needs to be &lt;strong&gt;98% confident&lt;/strong&gt; there&amp;rsquo;s a real difference before flagging a metric&lt;/li&gt;
&lt;li&gt;Small differences that could be random noise are ignored&lt;/li&gt;
&lt;li&gt;The test doesn&amp;rsquo;t assume your data follows any particular pattern (like a bell curve)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Technical details:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The Mann-Whitney U test is a nonparametric test that compares two distributions.
A metric is classified as High or Low only when:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The 98% confidence interval falls entirely outside a tolerance band&lt;/li&gt;
&lt;li&gt;The effect size exceeds the configured threshold (&lt;code&gt;allowedIncrease&lt;/code&gt;/&lt;code&gt;allowedDecrease&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The metric&amp;rsquo;s &lt;code&gt;direction&lt;/code&gt; allows that classification&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The tolerance band is ±(0.25 × |Hodges-Lehmann estimate|), which creates a
&amp;ldquo;dead zone&amp;rdquo; around zero where small differences are ignored.&lt;/p&gt;
&lt;h3 id=&#34;effect-size-and-thresholds&#34;&gt;Effect size and thresholds&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;effectSize&lt;/code&gt; configuration controls classification sensitivity:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;allowedIncrease&lt;/code&gt;&lt;/strong&gt;: Minimum ratio for a High classification (default: 1.0)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;allowedDecrease&lt;/code&gt;&lt;/strong&gt;: Maximum ratio for a Low classification (default: 1.0)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;criticalIncrease&lt;/code&gt;/&lt;code&gt;criticalDecrease&lt;/code&gt;&lt;/strong&gt;: Thresholds for critical failures&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Effect size thresholds are secondary gates. A metric must first
show statistical significance before the effect size is checked. This means a
metric with a 20% increase might still pass if the confidence interval is wide.
If the effect size is NaN (e.g., when a mean is zero), the threshold check is
skipped and only statistical significance determines the classification.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;critical-metrics&#34;&gt;Critical metrics&lt;/h3&gt;
&lt;p&gt;When a metric has &lt;code&gt;critical: true&lt;/code&gt; and is classified as High or Low with an
effect size exceeding &lt;code&gt;criticalIncrease&lt;/code&gt;/&lt;code&gt;criticalDecrease&lt;/code&gt;, it becomes a
&lt;strong&gt;critical failure&lt;/strong&gt;. This immediately sets the canary score to 0.&lt;/p&gt;
&lt;h2 id=&#34;step-4-score-computation&#34;&gt;Step 4: Score computation&lt;/h2&gt;
&lt;p&gt;After classification, the judge computes group scores and a summary score.&lt;/p&gt;
&lt;h3 id=&#34;group-scores&#34;&gt;Group scores&lt;/h3&gt;
&lt;p&gt;For each metric group:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Group Score = (Pass count / Total count) × 100
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Where &lt;strong&gt;Total count&lt;/strong&gt; includes &lt;code&gt;Pass&lt;/code&gt;, &lt;code&gt;High&lt;/code&gt;, &lt;code&gt;Low&lt;/code&gt;, and &lt;code&gt;NodataFailMetric&lt;/code&gt;
classifications. Metrics classified as &lt;code&gt;Nodata&lt;/code&gt; are &lt;strong&gt;excluded&lt;/strong&gt; from the count.&lt;/p&gt;
&lt;p&gt;If all metrics in a group are &lt;code&gt;Nodata&lt;/code&gt;, the group gets an effective score of 100
(it doesn&amp;rsquo;t penalize the canary).&lt;/p&gt;
&lt;h3 id=&#34;summary-score&#34;&gt;Summary score&lt;/h3&gt;
&lt;p&gt;The summary score is a weighted average of group scores:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Groups with configured weights use those weights&lt;/li&gt;
&lt;li&gt;Unweighted groups share the remaining weight equally:
&lt;code&gt;(100 - sum_of_configured_weights) / number_of_unweighted_groups&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Caution&lt;/strong&gt;: If configured weights sum to 100 or more, unweighted groups
receive no positive remaining weight (they may effectively have zero or even
negative influence). Avoid having group weights sum to 100 or more.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;automatic-failures&#34;&gt;Automatic failures&lt;/h3&gt;
&lt;p&gt;The canary automatically fails (score = 0) in these cases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Critical metric failure&lt;/strong&gt;: Any metric with &lt;code&gt;critical: true&lt;/code&gt; that is
classified as High or Low and exceeds the critical effect size threshold
(or has a NaN effect size, in which case the threshold check is skipped)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;50% NODATA rule&lt;/strong&gt;: If 50% or more of all metrics are classified as &lt;code&gt;Nodata&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;muted-metrics&#34;&gt;Muted metrics&lt;/h3&gt;
&lt;p&gt;Metrics with &lt;code&gt;muted: true&lt;/code&gt; are excluded from all scoring calculations but still
appear in results for visibility.&lt;/p&gt;
&lt;h3 id=&#34;final-classification&#34;&gt;Final classification&lt;/h3&gt;
&lt;p&gt;The summary score is compared against thresholds (comparisons are inclusive):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Score ≥ &lt;code&gt;passThreshold&lt;/code&gt; → &lt;strong&gt;Pass&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Score ≥ &lt;code&gt;marginalThreshold&lt;/code&gt; → &lt;strong&gt;Marginal&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Otherwise → &lt;strong&gt;Fail&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;reference&#34;&gt;Reference&lt;/h2&gt;
&lt;h3 id=&#34;effect-size-measures&#34;&gt;Effect size measures&lt;/h3&gt;
&lt;p&gt;The judge supports two effect size measures:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Measure&lt;/th&gt;
&lt;th&gt;Formula&lt;/th&gt;
&lt;th&gt;Range&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;meanRatio&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;canary_mean / baseline_mean&lt;/td&gt;
&lt;td&gt;0 to ∞&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;Latency, throughput metrics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Proportion of pairs where canary &amp;gt; baseline&lt;/td&gt;
&lt;td&gt;0 to 1&lt;/td&gt;
&lt;td&gt;0.5&lt;/td&gt;
&lt;td&gt;When means can be zero&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;code&gt;meanRatio&lt;/code&gt; returns NaN if either mean is zero. Use &lt;code&gt;cles&lt;/code&gt; for
metrics like error counts where zero values are common.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;result-metadata&#34;&gt;Result metadata&lt;/h3&gt;
&lt;p&gt;Each metric result includes statistics for debugging:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;controlMetadata.stats&lt;/code&gt;: &lt;code&gt;{min, max, mean, std, count}&lt;/code&gt; for baseline&lt;/li&gt;
&lt;li&gt;&lt;code&gt;experimentMetadata.stats&lt;/code&gt;: &lt;code&gt;{min, max, mean, std, count}&lt;/code&gt; for canary&lt;/li&gt;
&lt;li&gt;&lt;code&gt;resultMetadata.ratio&lt;/code&gt;: The mean ratio (may be NaN)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These statistics are calculated &lt;strong&gt;after&lt;/strong&gt; NaN handling and outlier removal.&lt;/p&gt;
&lt;h3 id=&#34;hard-coded-constants&#34;&gt;Hard-coded constants&lt;/h3&gt;
&lt;p&gt;These values are built into NetflixACAJudge and cannot be configured:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Constant&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Confidence level&lt;/td&gt;
&lt;td&gt;98%&lt;/td&gt;
&lt;td&gt;Mann-Whitney U test confidence interval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tolerance&lt;/td&gt;
&lt;td&gt;0.25&lt;/td&gt;
&lt;td&gt;Tolerance band = ±(0.25 × estimate)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NODATA threshold&lt;/td&gt;
&lt;td&gt;50%&lt;/td&gt;
&lt;td&gt;Canary fails if ≥50% metrics are Nodata&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reduce sensitivity&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;Outlier detection uses permissive fences&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;special-cases&#34;&gt;Special cases&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Identical data&lt;/strong&gt;: If baseline and canary arrays are identical after
transformation, the metric is classified as &lt;code&gt;Pass&lt;/code&gt; with ratio &lt;code&gt;1.0&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Degenerate distributions&lt;/strong&gt;: If both arrays have only one unique value,
tiny Gaussian noise is added to enable the Mann-Whitney test.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;worked-examples&#34;&gt;Worked examples&lt;/h2&gt;
&lt;h3 id=&#34;example-a-error-spike-with-nan-baseline&#34;&gt;Example A: Error spike with NaN baseline&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: An error count metric where the baseline has no errors (all NaN)
but the canary has errors.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nanStrategy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;replace&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;direction&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;increase&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;critical&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;What happens&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Baseline: all NaN → replaced with zeros, mean = 0&lt;/li&gt;
&lt;li&gt;Canary: positive values, mean &amp;gt; 0&lt;/li&gt;
&lt;li&gt;Classification: &lt;strong&gt;High&lt;/strong&gt; (canary significantly higher)&lt;/li&gt;
&lt;li&gt;Ratio: &lt;strong&gt;NaN&lt;/strong&gt; (because baseline mean is 0)&lt;/li&gt;
&lt;li&gt;Result: Canary &lt;strong&gt;fails with score 0&lt;/strong&gt; (critical metric classified High)&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key insight&lt;/strong&gt;: A metric can be classified &lt;code&gt;High&lt;/code&gt; even when the ratio is NaN.
The statistical test compares distributions, not just means.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;example-b-no-errors-on-either-side&#34;&gt;Example B: No errors on either side&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: Both baseline and canary have no errors (all NaN values).&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nanStrategy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;replace&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;What happens&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Both arrays: all NaN → replaced with zeros&lt;/li&gt;
&lt;li&gt;Arrays are identical after transformation&lt;/li&gt;
&lt;li&gt;Classification: &lt;strong&gt;Pass&lt;/strong&gt; with reason &amp;ldquo;data are identical&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Ratio: &lt;strong&gt;1.0&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;example-c-latency-increase-within-tolerance&#34;&gt;Example C: Latency increase within tolerance&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: Latency increased by 23%, but the canary passes.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;direction&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;increase&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;allowedIncrease&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1.2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observed ratio&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1.23&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;What happens&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The ratio (1.23) exceeds &lt;code&gt;allowedIncrease&lt;/code&gt; (1.2)&lt;/li&gt;
&lt;li&gt;However, the 98% confidence interval is wide due to variance&lt;/li&gt;
&lt;li&gt;The lower bound of the CI doesn&amp;rsquo;t exceed the tolerance band&lt;/li&gt;
&lt;li&gt;Classification: &lt;strong&gt;Pass&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key insight&lt;/strong&gt;: Effect size thresholds are secondary gates. Statistical
significance must be established first. Noisy data can cause metrics to pass
even when the observed ratio exceeds the threshold.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;example-d-critical-latency-failure&#34;&gt;Example D: Critical latency failure&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: Latency increased by 60% on a critical metric.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;direction&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;increase&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;critical&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;criticalIncrease&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1.5&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observed ratio&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1.6&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;What happens&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Statistical test shows significant increase (CI outside tolerance)&lt;/li&gt;
&lt;li&gt;Ratio (1.6) exceeds &lt;code&gt;criticalIncrease&lt;/code&gt; (1.5)&lt;/li&gt;
&lt;li&gt;Metric is &lt;code&gt;critical: true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Classification: &lt;strong&gt;High (Critical)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Result: Canary &lt;strong&gt;fails with score 0&lt;/strong&gt; regardless of other metrics&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;faq&#34;&gt;FAQ&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Why is my metric High but its ratio is NaN?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The ratio is calculated as &lt;code&gt;canary_mean / baseline_mean&lt;/code&gt;. If either mean is
zero, the ratio is undefined (NaN). However, the Mann-Whitney test compares
the full distributions, not just means, so it can still detect a significant
difference.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why did my canary Pass even though the ratio exceeds allowedIncrease?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The effect size threshold is a secondary check. The metric must first show
statistical significance (98% CI outside the tolerance band). If the data is
noisy, the confidence interval may be too wide to establish significance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why did my canary get a score of 0 when only one metric failed?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The metric likely has &lt;code&gt;critical: true&lt;/code&gt; configured. Critical metrics that are
classified as High or Low immediately set the canary score to 0.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What&amp;rsquo;s the difference between Nodata and NodataFailMetric?&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Nodata&lt;/code&gt;: Metric had no data but wasn&amp;rsquo;t required. It&amp;rsquo;s excluded from scoring
but counts toward the 50% NODATA threshold.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NodataFailMetric&lt;/code&gt;: Metric had &lt;code&gt;mustHaveData: true&lt;/code&gt; but no data. It counts
as a failure in group score calculations.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;other-classifiers&#34;&gt;Other classifiers&lt;/h2&gt;
&lt;p&gt;NetflixACAJudge uses the Mann-Whitney classifier by default. Kayenta also
includes two other classifiers that are &lt;strong&gt;not recommended for production&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MeanInequalityClassifier&lt;/strong&gt;: Compares means directly without statistical
testing. Primarily used for benchmarking.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RandomClassifier&lt;/strong&gt;: Assigns random Pass/High/Low classifications. Intended
for testing only.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These classifiers are not exposed in the standard configuration UI.&lt;/p&gt;

      </description>
    </item>
    
    <item>
      <title>Docs: Configure a canary</title>
      <link>https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/config/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/config/</guid>
      <description>
        
        
        
      </description>
    </item>
    
    <item>
      <title>Docs: Add a canary stage to a pipeline</title>
      <link>https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/stage/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/stage/</guid>
      <description>
        
        
        &lt;p&gt;If you have 
&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/setup/other_config/canary/&#34;&gt;enabled canary for your application&lt;/a&gt;
 and have one
or more 
&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/config/&#34;&gt;canary configs prepared&lt;/a&gt;
, you can now add
a canary stage to your pipeline and configure it to perform canary analysis for
your deployment.&lt;/p&gt;
&lt;p&gt;This stage type is for the canary &lt;em&gt;analysis&lt;/em&gt; only. The canary stage doesn&amp;rsquo;t
perform any provisioning or cleanup operations for you. Those must be configured
elsewhere in your pipeline.&lt;/p&gt;
&lt;h2 id=&#34;about-the-canary-stage&#34;&gt;About the canary stage&lt;/h2&gt;
&lt;p&gt;The canary analysis can be performed over data points collected beginning from
the moment of execution and into the future, or it can be performed over a
specified time interval.&lt;/p&gt;
&lt;h3 id=&#34;real-time-versus-retrospective-analysis&#34;&gt;Real-time versus retrospective analysis&lt;/h3&gt;
&lt;p&gt;A real-time analysis means that the canary analysis is performed over a time
interval beginning at the moment of execution. In a retrospective analysis the
canary analysis is performed over an explicitly specified time interval (likely
in the past).&lt;/p&gt;
&lt;h3 id=&#34;metric-scope&#34;&gt;Metric scope&lt;/h3&gt;
&lt;p&gt;Metric scope defines where, when, and on what the canary analysis occurs.
It describes the specific baseline and canary server groups, the start and end
times and interval, and the cloud resource on which the baseline and canary are running.&lt;/p&gt;
&lt;p&gt;You can also refine the scope using 
&lt;a href=&#34;#extended-params&#34;&gt;extended params&lt;/a&gt;
.&lt;/p&gt;
&lt;h2 id=&#34;define-the-canary-stage&#34;&gt;Define the canary stage&lt;/h2&gt;
&lt;!-- something here about where in the pipeline you&#39;d put the canary stage, and
other permutations, like multiple stages? --&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In the pipeline in which you will run the canary, click &lt;strong&gt;Add stage&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This pipeline needs to be in an application that has access to the 
&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/config/&#34;&gt;canary
configuration&lt;/a&gt;
 you want to use.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For &lt;strong&gt;Type&lt;/strong&gt; select &lt;strong&gt;Canary&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Give the stage a name, and use the &lt;strong&gt;Depends On&lt;/strong&gt; field to position the stage
downstream of its dependencies.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/stage/canary_stage_top.png&#34; alt=&#34;Canary stage declaration&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select the &lt;strong&gt;Analysis Type&lt;/strong&gt;—either &lt;strong&gt;Real Time&lt;/strong&gt; or &lt;strong&gt;Retrospective&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Real Time&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The analysis happens for a specified time period, beginning when the stage
executes (or after a specified &lt;strong&gt;Delay&lt;/strong&gt;).&lt;/p&gt;
&lt;p&gt;For &lt;strong&gt;Real Time&lt;/strong&gt;, also specify the number of hours to run (&lt;strong&gt;Lifetime&lt;/strong&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Retrospective&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Analysis occurs over some specified period. Typically, this is done
for a time period in the past, against a baseline deployment and a canary
deployment which have already been running before this canary analysis
stage starts.&lt;/p&gt;
&lt;p&gt;Note that this analysis might analyze data for resources which no longer
exist, for which there are still published time series.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Specify the analysis configuration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Choose the &lt;strong&gt;Config Name&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This is the canary config you created 
&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/config&#34;&gt;here&lt;/a&gt;
.
That configuration must be visible to this application. By default, all
configs are visible to all applications, but your canary might be 
&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/setup/other_config/canary/#specify-the-scope-of-canary-configs&#34;&gt;set up
so that each config is limited&lt;/a&gt;
 to the application in which it is created.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set a &lt;strong&gt;Delay&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For real-time analyses, how many minutes to wait before starting the
analysis. The gives both the baseline and canary a chance to get &amp;ldquo;warmed
up&amp;rdquo; before they&amp;rsquo;re expected to provide meaningful metrics. Leave blank for
a delay of zero minutes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Set the &lt;strong&gt;Interval&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This is how frequently (in minutes) to capture and score the metrics.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For &lt;strong&gt;Lookback Type&lt;/strong&gt;, select &lt;strong&gt;Growing&lt;/strong&gt; or &lt;strong&gt;Sliding&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;In a growing analysis, a judgment is taken every [interval] minutes, but
each judgment goes all the way back to the beginning of the &lt;strong&gt;Lifetime&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A sliding Lookback also makes a judgment every [interval], but each
judgment only looks at the data from the most recent lookback duration.
It would not be unusual for the &lt;strong&gt;Interval&lt;/strong&gt; and the &lt;strong&gt;look-back&lt;/strong&gt;
duration to be the same, but they don&amp;rsquo;t have to be.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/stage/stage_config_analysis.png&#34; alt=&#34;Canary stage declaration&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Describe the metric scope.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can enter server groups and regions by name, but you can also click the
magic wand here to automatically populate the fields with expressions that
resolve to available resources. Those resources are a starting point, which
you can edit to match the specific resources you need.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Baseline&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The server group to treat as the &amp;ldquo;control&amp;rdquo; in the canary
analysis—that is, the deployment against which to compare the canary
deployment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Baseline Region&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The region in which the baseline server group is deployed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Canary&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The server group to treat as the experiment in the analysis.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Canary Region&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The region in which that canary server group is deployed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Step&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The interval, in seconds, for the metric time series.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Start Time&lt;/strong&gt; and &lt;strong&gt;End Time&lt;/strong&gt; (for retrospective)&lt;/p&gt;
&lt;p&gt;For a retrospective analysis, the specific time span over which to conduct
the analysis.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a name=&#34;extended-params&#34; /&gt;&lt;strong&gt;Extended Params&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Add any additional parameters, which are specific to the metric sources and
which can be used to refine the scope of the analysis. These parameters can
provide variable bindings for use in the expansion of custom filter
templates 
&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/config/filter-templates/&#34;&gt;specified in the canary
config&lt;/a&gt;
.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/stage/metric_scope.png&#34; alt=&#34;Canary stage declaration&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Adjust the &lt;strong&gt;Scoring Thresholds&lt;/strong&gt;, if needed.&lt;/p&gt;
&lt;p&gt;The thresholds are pre-populated based on those configured in the main

&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/config/&#34;&gt;canary config&lt;/a&gt;
, but you can override them here.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Specify the accounts you&amp;rsquo;re using for metrics and storage.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;Metrics Account&lt;/strong&gt; points to the telemetry service provider account
you configured 
&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/setup/other_config/canary/&#34;&gt;here&lt;/a&gt;
.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;strong&gt;Storage Account&lt;/strong&gt; points to the GCS or S3 account you configured

&lt;a href=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/setup/install/storage/&#34;&gt;here&lt;/a&gt;
.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://deploy-preview-629--spinnaker-io.netlify.app/docs/guides/user/canary/stage/advanced_settings.png&#34; alt=&#34;Canary stage declaration&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;!--   ## Time scope in the canary stage

   When you define your canary stage, you have a lot of choices about how to
   manage the analysis over time, beginning with the analysis type:

   * real time

   * retrospective

   So let&#39;s think about it in those two categories...

   ### Real-time analysis


   ### Retrospective analysis
--&gt;

      </description>
    </item>
    
  </channel>
</rss>
