//----------------------------------------------------------------------------- // // 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 Amazon.XRay.Recorder.Core.Internal.Utils; using System; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Threading; namespace Amazon.XRay.Recorder.Core.Sampling { /// /// It represents the Rules used for sampling. /// public class SamplingRule : IComparable { private static readonly Logger _logger = Logger.GetLogger(typeof(SamplingRule)); public string Host { get; set; } public string RuleName { get; set; } public int Priority { get; set; } public Reservior Reservior { get; set; } public double Rate { get; private set; } public int ReservoirSize { get; private set; } public string HTTPMethod { get; set; } public string ServiceName { get; set; } public string URLPath { get; private set; } public string ServiceType { get; private set; } public string ResourceARN { get; private set; } public Dictionary Attributes { get; private set; } public Statistics Statistics; public bool CanBorrow { get; set; } private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); public const String Default = "Default"; // Reserved keyword by X-Ray service public SamplingRule(string ruleName, int priority, double fixedRate, int reservoirSize, string host, string serviceName, string httpMethod, string urlPath, string serviceType, string resourceARN, Dictionary attributes) { RuleName = ruleName; Priority = priority; Rate = fixedRate; ReservoirSize = reservoirSize; CanBorrow = reservoirSize > 0; ServiceName = serviceName; HTTPMethod = httpMethod; URLPath = urlPath; Host = host; ServiceType = serviceType; ResourceARN = resourceARN; Attributes = attributes; Reservior = new Reservior(); Statistics = new Statistics(); } internal void IncrementRequestCount() { Statistics.IncrementRequestCount(); } internal void IncrementBorrowCount() { Statistics.IncrementBorrowCount(); } internal void IncrementSampledCount() { Statistics.IncrementSampledCount(); } /// /// Validates sampling rule. ResourceARN with "*" value is valid. SDK doesn't support Atrributes parameter with any value. /// /// Instance of /// True, if the rule is valid else false. internal static bool IsValid(Model.SamplingRuleModel rule) { if (!string.Equals(rule.ResourceARN, "*")) { return false; } if (rule.Attributes != null && rule.Attributes.Count > 0) { return false; } return true; } internal bool IsDefault() { return RuleName.Equals(Default); } /// /// Determines whether or not this sampling rule applies to the incoming /// request based on some of the request's parameters. /// /// Instance of . /// True if the rule matches. internal bool Match(SamplingInput input) { try { return StringExtension.IsMatch(input.ServiceName, ServiceName) && StringExtension.IsMatch(input.Method, HTTPMethod) && StringExtension.IsMatch(input.Url, URLPath) && StringExtension.IsMatch(input.Host, Host) && StringExtension.IsMatch(input.ServiceType, ServiceType); } catch (RegexMatchTimeoutException e) { _logger.Error(e, "Match rule timeout. Rule: serviceName = {0}, urlPath = {1}, httpMethod = {2}, host = {3}, serviceType = {4}. Input: serviceNameToMatch = {5}, urlPathToMatch = {6}, httpMethodToMatch = {7}, hostToMatch = {8}, serviceTypeToMatch = {9}.", ServiceName, URLPath, HTTPMethod, Host, ServiceType, input.ServiceName, input.Url, input.Method, input.Host, input.ServiceType); return false; } } internal void SetRate(double fixedRate) { _lock.EnterWriteLock(); try { Rate = fixedRate; } finally { _lock.ExitWriteLock(); } } internal double GetRate() { _lock.EnterReadLock(); try { return Rate; } finally { _lock.ExitReadLock(); } } internal bool ShouldReport(TimeStamp now) { if (EverMatched() && Reservior.ShouldReport(now)) { return true; } return false; } internal bool EverMatched() { return Statistics.GetRequestCount() > 0; } // Migrate all stateful attributes from the old rule internal void Merge(SamplingRule oldRule) { Statistics.CopyFrom(oldRule.Statistics); Reservior.CopyFrom(oldRule.Reservior); } /// /// Returns current state of . /// /// Instance of . internal Statistics SnapShotStatistics() { return Statistics.GetSnapShot(); } public int CompareTo(SamplingRule y) { int result = this.Priority.CompareTo(y.Priority); if (result == 0) { result = this.RuleName.CompareTo(y.RuleName); } return result; } } }