fengling-risk-control/Fengling.RiskControl.Client/Sampling/SamplingService.cs
Sam 293209b1dc feat: add Fengling.RiskControl.Client SDK
- Implement RedisCounterService for rate limiting
- Implement RuleLoader with timer refresh
- Implement RiskEvaluator for local rule evaluation
- Implement SamplingService for CAP events
- Implement CapEventPublisher for async event publishing
- Implement FailoverStrategy for Redis failure handling
- Add configuration classes and DI extensions
- Add unit tests (9 tests)
- Add NuGet publishing script
2026-02-06 00:16:53 +08:00

68 lines
2.3 KiB
C#

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<SamplingService> _logger;
private readonly Random _random = new();
public SamplingService(
RiskControlClientOptions options,
ILogger<SamplingService> 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
};
}
}