//-----------------------------------------------------------------------------
//
// Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License").
// You may not use this file except in compliance with the License.
// A copy of the License is located at
//
// http://aws.amazon.com/apache2.0
//
// or in the "license" file accompanying this file. This file 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.
//
//-----------------------------------------------------------------------------
using Amazon.Runtime.Internal.Util;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Amazon.XRay.Recorder.Core.Sampling
{
///
/// Gets sampling rules from X-Ray service. This is a asynchronous operation.
///
public class RulePoller
{
private static readonly Logger _logger = Logger.GetLogger(typeof(RulePoller));
private RuleCache _ruleCache;
private IConnector _connector;
private const int RefreshInterval = 5 * 60 * 1000; // 5 minutes
private const int MaxJitter = 5 * 1000; // adding max jitter upto 5 seconds
private readonly Random _random;
private Timer _timer;
internal TimeStamp TimeElasped { get; set; }
internal TimeStamp TimeToWait { get; set; }
public RulePoller(RuleCache ruleCache)
{
_ruleCache = ruleCache;
_random = new Random();
}
internal void Poll(IConnector connector)
{
_connector = connector;
_timer = new Timer(Start);
_timer.Change(0, 0);
}
internal async void Start(Object state)
{
try
{
await RefreshCache();
}
catch (Exception e)
{
_logger.Error(e, "Encountered an exception while polling sampling rules.");
}
finally
{
_timer.Change(GetDelay(), 0); // Next invocation with jitter
}
}
///
/// Gets sampling rules from the X-Ray service ans populates .
///
/// Task instance.
private async Task RefreshCache()
{
TimeStamp time = TimeStamp.CurrentTime();
GetSamplingRulesResponse response = await _connector.GetSamplingRules();
if (response.IsRulePresent())
{
_ruleCache.LoadRules(response.Rules);
_ruleCache.LastUpdated = time;
_logger.InfoFormat("Successfully refreshed sampling rule cache.");
}
}
///
/// Force the rule poller to pull the sampling rules from the service
/// regardless of the polling interval.
/// This method is intended to be used by only.
///
internal void WakeUp()
{
_timer.Dispose();
// Perform out of band polling
_timer = new Timer(Start);
_timer.Change(0, 0);
}
private int GetDelay()
{
return RefreshInterval + GenerateRandomJitter();
}
///
/// A random jitter of up to 5 seconds is injected after each run
/// to ensure the calls eventually get evenly distributed over
/// the 5 minute window.
///
///
private int GenerateRandomJitter()
{
return _random.Next(1, MaxJitter);
}
}
}