<commit_before>---
layout: base
---

%h1
  Activation Strategies

%p
  Togglz defines the concept of <i>activation strategies</i>. They are responsible to
  decide whether an enabled feature is active or not. Activation strategies can for example
  be used to activate features only for specific users, for specific client IPs or
  at a specified time.

%p
  Togglz ships with the following default strategies:

%ul
  %li
    %a(href='#username')
      Username
  %li
    %a(href='#gradual-rollout')
      Gradual rollout
  %li
    %a(href='#release-date')
      Release date
  %li
    %a(href='#client-ip')
      Client IP
  %li
    %a(href='#server-ip')
      Server IP
  %li
    %a(href='#script-engine')
      ScriptEngine

%p
  The following sections will describe each strategy in detail. The last section
  <a href="#custom">custom strategies</a> describes how to build you own strategies.

%a(name='username')
%h2
  Username

%p
  Enabling features for specific users was already supported in very early versions of Togglz, 
  even before the activation strategy concept was introduced in Togglz 2.0.0.

%p
  If you select this strategy for a feature, you can specify an comma-separated list of 
  users for which the feature should be active. Togglz will use the <code>UserProvider</code> 
  you configured for the FeatureManager to determine the current user and compare it to
  that list.

%p
  Please note that Togglz will take case into account when comparing the usernames. So the
  users <code>admin</code> and <code>Admin</code> are NOT the same.

%p
  This strategy is very useful if you want to allow a specific list of users to test a certain
  feature in production.


%a(name='gradual-rollout')
%h2
  Gradual rollout

%p
  The gradual rollout strategy allows you to activate a feature to a certain percentage of
  users. This allows you to test a feature with a very small number of users and increase the
  number over time until the feature is active for everyone.

%p
  If you select this strategy, you will be asked to enter a percentage value. If you for example 
  enter <code>25</code>, Togglz will activate the feature for every forth user.

%p
  The users are selected by calculating a hash value from the username which is then normalized
  to a value between 0 and 100. The feature will be active for a user if the hash value is smaller or
  equal to the percentage you configured. This algorithm will ensure that the feature will be
  active for a user even after you increased the percentage. Have a look at the
  <a href="https://github.com/togglz/togglz/blob/master/core/src/main/java/org/togglz/core/activation/GradualActivationStrategy.java">source code</a>
  of the strategy for more details.

%a(name='release-date')
%h2
  Release date

%p
  The release date strategy can be used to automatically activate a feature at a certain
  point in time. If you select this strategy, you have to enter a date and an optional
  time for the feature to get active. If you omit the time, the feature will be activated
  at midnight. The date must be specified in the format <code>2012-12-31</code> and the
  time in the format <code>14:15:00</code>

%a(name='client-ip')
%h2
  Client IP

%p
  The client IP strategy allows you to restrict a feature to clients connecting from a specific 
  IP address. The strategy uses <code>HttpServletRequest.getRemoteAddr()</code> to obtain the IP
  address of the client. The strategy is therefore restricted to web applications running in a 
  Servlet environment.

%p
  Please note that the strategy requires you to enter a full IP address. Specifying subnets is
  currently not supported (patches are welcome). But you can enter multiple IP addresses 
  separated by comma.

%a(name='server-ip')
%h2
  Server IP

%p
  The Server IP strategy is similar to the Client IP strategy. The only difference is that
  not the client IP but the server IP address is used. This strategy is very useful
  for canary testing where you activate a feature only on a subset of your cluster nodes
  to test for things like performance issues.

%p
  The strategy uses <a href="http://docs.oracle.com/javase/7/docs/api/java/net/NetworkInterface.html#getNetworkInterfaces()">NetworkInterface.getNetworkInterfaces()</a>
  to obtain the IP addresses of the server. All IP addresses returned by this method are compared 
  against the IP addresses configured for the strategy. The feature will be active if there is at 
  least one match. 

%a(name='script-engine')
%h2
  Script Engine

%p
  The ScriptEngine strategy is the most flexible activation strategy. It allows you to use a 
  JSR223 scripting language to implement the test that decides whether the feature is active or not.
  You can use any language supported by the 
  <a href="http://docs.oracle.com/javase/7/docs/api/javax/script/ScriptEngine.html">ScriptEngine</a> 
  of your JVM. The Oracle JVM ships with an <code>ECMAScript</code> engine that allows you
  to write JavaScript for your check out of the box.

%p
  The activation strategy has two parameters. The first one is used to specify the language to use for the
  script (for example <code>ECMAScript</code>). The second parameters is the script itself. The script must
  evaluate to a boolean result. The script context is populated with a few variables that may
  be useful for you: 

%ul
  %li
    <code>user</code>: The <code>FeatureUser</code> representing the current user.
  %li
    <code>date</code>: The current time as a <code>java.util.Date</code>

%p
  This example shows a script written in JavaScript that enables the feature
  for a user named <code>john</code> on Sundays. 

%ul
  %li
    <strong>Language:</strong><br/><code>ECMAScript</code>
  %li
    <strong>Script:</strong><br/><code>user.name == 'john' && date.day == 0</code>

%p
  Please double check your script before using it for a feature. If the script evaluation
  fails due to some error, the feature will be inactive.
  
  
%a(name='custom')
%h2
  Custom Strategies

%p
  TODO

<commit_msg>Documentation on how to build custom activation strategies<commit_after>---
layout: base
---

%h1
  Activation Strategies

%p
  Togglz defines the concept of <i>activation strategies</i>. They are responsible to
  decide whether an enabled feature is active or not. Activation strategies can for example
  be used to activate features only for specific users, for specific client IPs or
  at a specified time.

%p
  Togglz ships with the following default strategies:

%ul
  %li
    %a(href='#username')
      Username
  %li
    %a(href='#gradual-rollout')
      Gradual rollout
  %li
    %a(href='#release-date')
      Release date
  %li
    %a(href='#client-ip')
      Client IP
  %li
    %a(href='#server-ip')
      Server IP
  %li
    %a(href='#script-engine')
      ScriptEngine

%p
  The following sections will describe each strategy in detail. The last section
  <a href="#custom">custom strategies</a> describes how to build you own strategies.

%a(name='username')
%h2
  Username

%p
  Enabling features for specific users was already supported in very early versions of Togglz, 
  even before the activation strategy concept was introduced in Togglz 2.0.0.

%p
  If you select this strategy for a feature, you can specify an comma-separated list of 
  users for which the feature should be active. Togglz will use the <code>UserProvider</code> 
  you configured for the FeatureManager to determine the current user and compare it to
  that list.

%p
  Please note that Togglz will take case into account when comparing the usernames. So the
  users <code>admin</code> and <code>Admin</code> are NOT the same.

%p
  This strategy is very useful if you want to allow a specific list of users to test a certain
  feature in production.


%a(name='gradual-rollout')
%h2
  Gradual rollout

%p
  The gradual rollout strategy allows you to activate a feature to a certain percentage of
  users. This allows you to test a feature with a very small number of users and increase the
  number over time until the feature is active for everyone.

%p
  If you select this strategy, you will be asked to enter a percentage value. If you for example 
  enter <code>25</code>, Togglz will activate the feature for every forth user.

%p
  The users are selected by calculating a hash value from the username which is then normalized
  to a value between 0 and 100. The feature will be active for a user if the hash value is smaller or
  equal to the percentage you configured. This algorithm will ensure that the feature will be
  active for a user even after you increased the percentage. Have a look at the
  <a href="https://github.com/togglz/togglz/blob/master/core/src/main/java/org/togglz/core/activation/GradualActivationStrategy.java">source code</a>
  of the strategy for more details.

%a(name='release-date')
%h2
  Release date

%p
  The release date strategy can be used to automatically activate a feature at a certain
  point in time. If you select this strategy, you have to enter a date and an optional
  time for the feature to get active. If you omit the time, the feature will be activated
  at midnight. The date must be specified in the format <code>2012-12-31</code> and the
  time in the format <code>14:15:00</code>

%a(name='client-ip')
%h2
  Client IP

%p
  The client IP strategy allows you to restrict a feature to clients connecting from a specific 
  IP address. The strategy uses <code>HttpServletRequest.getRemoteAddr()</code> to obtain the IP
  address of the client. The strategy is therefore restricted to web applications running in a 
  Servlet environment.

%p
  Please note that the strategy requires you to enter a full IP address. Specifying subnets is
  currently not supported (patches are welcome). But you can enter multiple IP addresses 
  separated by comma.

%a(name='server-ip')
%h2
  Server IP

%p
  The Server IP strategy is similar to the Client IP strategy. The only difference is that
  not the client IP but the server IP address is used. This strategy is very useful
  for canary testing where you activate a feature only on a subset of your cluster nodes
  to test for things like performance issues.

%p
  The strategy uses <a href="http://docs.oracle.com/javase/7/docs/api/java/net/NetworkInterface.html#getNetworkInterfaces()">NetworkInterface.getNetworkInterfaces()</a>
  to obtain the IP addresses of the server. All IP addresses returned by this method are compared 
  against the IP addresses configured for the strategy. The feature will be active if there is at 
  least one match. 

%a(name='script-engine')
%h2
  Script Engine

%p
  The ScriptEngine strategy is the most flexible activation strategy. It allows you to use a 
  JSR223 scripting language to implement the test that decides whether the feature is active or not.
  You can use any language supported by the 
  <a href="http://docs.oracle.com/javase/7/docs/api/javax/script/ScriptEngine.html">ScriptEngine</a> 
  of your JVM. The Oracle JVM ships with an <code>ECMAScript</code> engine that allows you
  to write JavaScript for your check out of the box.

%p
  The activation strategy has two parameters. The first one is used to specify the language to use for the
  script (for example <code>ECMAScript</code>). The second parameters is the script itself. The script must
  evaluate to a boolean result. The script context is populated with a few variables that may
  be useful for you: 

%ul
  %li
    <code>user</code>: The <code>FeatureUser</code> representing the current user.
  %li
    <code>date</code>: The current time as a <code>java.util.Date</code>

%p
  This example shows a script written in JavaScript that enables the feature
  for a user named <code>john</code> on Sundays. 

%ul
  %li
    <strong>Language:</strong><br/><code>ECMAScript</code>
  %li
    <strong>Script:</strong><br/><code>user.name == 'john' && date.day == 0</code>

%p
  Please double check your script before using it for a feature. If the script evaluation
  fails due to some error, the feature will be inactive.
  
  
%a(name='custom')
%h2
  Custom Strategies

%p
  The great thing about activation strategies is that it is very easy to add your
  own strategies. Togglz offers an extension point that allows you to implement a new
  strategy with only a single class.

%p
  All activation strategies have to implement the interface
  <a href="http://www.togglz.org/apidocs/#{site.stableVersion}/org/togglz/core/spi/ActivationStrategy.html">ActivationStrategy</a>.
  Togglz looks up the implementations using the standard Java
  <a href="http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html">ServiceLoader</a>
  mechanism. 

%p
  To register an custom activation strategy implementation, you have to create a file called
  <code>META-INF/services/org.togglz.core.spi.ActivationStrategy</code> on your classpath 
  and add single line containing the fully-qualified class name of your implementation class.

%p
  The <code>ActivationStrategy</code> interface defines the following methods:

%h3
  getId()

%p
  This method has to return a unique id for the strategy. This id is used to identify the strategy
  when the feature state is persisted by a <code>StateRepository</code>.

%h3
  getName()

%p
  This method returns the human readable name of the activation strategy. This name will for example be
  displayed in the Togglz Admin Console.

%h3
  getParameters()

%p
  The <code>getParameters()</code> method can be used by the activation strategy to tell Togglz about
  the strategy parameters it supports. The method returns an array of
  <a href="http://www.togglz.org/apidocs/#{site.stableVersion}/org/togglz/core/activation/Parameter.html">Parameter</a>
  instances. Each element in this array represents a specification for a single parameter.

%p
  The simplest way to create <code>Parameter</code> instances is to use 
  <a href="http://www.togglz.org/apidocs/#{site.stableVersion}/org/togglz/core/activation/ParameterBuilder.html">ParameterBuilder</a>.
  The builder offers a fluent API for defining a parameter. However you can also create your own
  <code>Parameter</code> implementation. This can be useful especially if you need to implement custom
  validation for a parameter.

%h3
  isActive()

%p
  This method is responsible for the evaluation of the strategy. It is called every time a feature
  state is checked for a feature which uses the strategy. The method has two arguments, the 
  current user as a <code>FeatureUser</code> and the <code>FeatureState</code> representing
  the configuration of the feature. The implementation of the method can obtain the values of the
  strategy parameters by calling <code>FeatureState.getParameter()</code>.

%h3
  Example

%p
  Enough theory for now. The easiest way to understand how to build a custom strategy is to see
  an example.

%p
  The following strategy allows you to activate a feature only for specific days of the week. 
  So it can for example be configured so that the feature is only active on Mondays.
  The strategy defines a single parameter identified by the id <code>day</code>. This value of
  this parameter is then compared against the current weekday. 

%pre(class="prettyprint lang-java")
  :escaped
    public class WeekdayActivationStrategy implements ActivationStrategy {
    
        private static final String[] SHORT_WEEKDAYS = 
            DateFormatSymbols.getInstance().getShortWeekdays();
    
        @Override
        public String getId() {
            return "weekday";
        }
    
        @Override
        public String getName() {
            return "Weekday strategy";
        }
    
        @Override
        public Parameter[] getParameters() {
            return new Parameter[] {
                    ParameterBuilder.create("day").label("Day of week")
            };
        }
    
        @Override
        public boolean isActive(FeatureState featureState, FeatureUser user) {
    
            // the weekday name configured for the strategy
            String selectedWeekday = featureState.getParameter("day");
    
            // get the weekday name for today
            Calendar now = GregorianCalendar.getInstance();
            int currentWeekday = now.get(Calendar.DAY_OF_WEEK);
            String currentWeekdayName = SHORT_WEEKDAYS[currentWeekday];
    
            // the feature is active if the weekday matches
            return selectedWeekday.equals(currentWeekdayName);
    
        }
    
    }

%p
  Easy, isn't it? :)

{'fraction_non_alphanumeric': 0.06910519951632406, 'fraction_numerical': 0.0048367593712212815, 'mean_word_length': 3.5870770937326677, 'pattern_counts': {'":': 0, '<': 127, '<?xml version=': 0, '>': 127, 'https://': 2, 'lorem ipsum': 0, 'www.': 3, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1075609', 'n_tokens_mistral': 4640, 'n_tokens_neox': 4507, 'n_words': 2155}