using Fengling.RiskControl.Configuration; using Fengling.RiskControl.Evaluation; using Microsoft.Extensions.Logging; using System.Globalization; namespace Fengling.RiskControl.Sampling; public interface ISamplingService { bool ShouldSample(RiskEvaluationResult result); } public class SamplingService : ISamplingService { private readonly RiskControlClientOptions _options; private readonly ILogger _logger; private readonly Random _random = new(); public SamplingService( RiskControlClientOptions options, ILogger logger) { _options = options; _logger = logger; } public bool ShouldSample(RiskEvaluationResult result) { if (!_options.Sampling.Enabled) return false; foreach (var rule in _options.Sampling.Rules) { if (EvaluateCondition(rule.Condition, result)) { var sampleRate = rule.Rate; var sampled = _random.NextDouble() < sampleRate; _logger.LogDebug("Sampling check: condition={Condition}, rate={Rate}, sampled={Sampled}", rule.Condition, sampleRate, sampled); return sampled; } } var defaultSampled = _random.NextDouble() < _options.Sampling.DefaultRate; _logger.LogDebug("Default sampling: rate={Rate}, sampled={Sampled}", _options.Sampling.DefaultRate, defaultSampled); return defaultSampled; } private bool EvaluateCondition(string condition, RiskEvaluationResult result) { return condition switch { string c when c.Contains("RiskLevel == High", StringComparison.OrdinalIgnoreCase) => result.RiskLevel == RiskLevel.High, string c when c.Contains("RiskLevel == Medium", StringComparison.OrdinalIgnoreCase) => result.RiskLevel == RiskLevel.Medium, string c when c.Contains("RiskLevel == Low", StringComparison.OrdinalIgnoreCase) => result.RiskLevel == RiskLevel.Low, string c when c.Contains("IsBlocked == true", StringComparison.OrdinalIgnoreCase) => result.Blocked, string c when c.Contains("BlockedOnly", StringComparison.OrdinalIgnoreCase) => result.Blocked, _ => false }; } }