diff --git a/sdk/src/Core/AWSXRayRecorder.Core.csproj b/sdk/src/Core/AWSXRayRecorder.Core.csproj
index 760a603d..105d7ded 100644
--- a/sdk/src/Core/AWSXRayRecorder.Core.csproj
+++ b/sdk/src/Core/AWSXRayRecorder.Core.csproj
@@ -39,7 +39,6 @@
-
diff --git a/sdk/src/Core/Sampling/DefaultSamplingStrategy.cs b/sdk/src/Core/Sampling/DefaultSamplingStrategy.cs
index ea9e02e5..7fecca1b 100644
--- a/sdk/src/Core/Sampling/DefaultSamplingStrategy.cs
+++ b/sdk/src/Core/Sampling/DefaultSamplingStrategy.cs
@@ -43,9 +43,9 @@ public class DefaultSamplingStrategy : ISamplingStrategy
public DaemonConfig DaemonCfg { get; private set; }
///
- /// Instance of .
+ /// Instance of .
///
- public AmazonXRayClient XRayClient = null;
+ public XRayConfig XRayConfig = null;
///
/// Instance of .
@@ -81,7 +81,7 @@ private void Start()
{
if (!_isPollerStarted)
{
- _connector = new ServiceConnector(DaemonCfg, XRayClient);
+ _connector = new ServiceConnector(DaemonCfg, XRayConfig);
_rulePoller.Poll(_connector);
_targetPoller.Poll(_connector);
_isPollerStarted = true;
diff --git a/sdk/src/Core/Sampling/GetSamplingRulesResponse.cs b/sdk/src/Core/Sampling/GetSamplingRulesResponse.cs
index 624f6475..a9576622 100644
--- a/sdk/src/Core/Sampling/GetSamplingRulesResponse.cs
+++ b/sdk/src/Core/Sampling/GetSamplingRulesResponse.cs
@@ -19,7 +19,7 @@
namespace Amazon.XRay.Recorder.Core.Sampling
{
///
- /// Wrapper to API call response.
+ /// Class for keep list of sampling rules from x-ray backend.
///
public class GetSamplingRulesResponse
{
diff --git a/sdk/src/Core/Sampling/GetSamplingTargetsResponse.cs b/sdk/src/Core/Sampling/GetSamplingTargetsResponse.cs
index bf69a3f4..9fbba06a 100644
--- a/sdk/src/Core/Sampling/GetSamplingTargetsResponse.cs
+++ b/sdk/src/Core/Sampling/GetSamplingTargetsResponse.cs
@@ -19,7 +19,7 @@
namespace Amazon.XRay.Recorder.Core.Sampling
{
///
- /// Wrapper for API call response.
+ /// Class for keep last rule modification timestamp and list of sampling targets from x-ray backend.
///
public class GetSamplingTargetsResponse
{
diff --git a/sdk/src/Core/Sampling/Model/SamplingRuleModel.cs b/sdk/src/Core/Sampling/Model/SamplingRuleModel.cs
new file mode 100644
index 00000000..65ee367f
--- /dev/null
+++ b/sdk/src/Core/Sampling/Model/SamplingRuleModel.cs
@@ -0,0 +1,53 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright 2020 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 System.Collections.Generic;
+
+namespace Amazon.XRay.Recorder.Core.Sampling.Model
+{
+ ///
+ /// Class model for unmarshalling sampling rule from sampling rule response json.
+ ///
+ public class SamplingRuleModel
+ {
+ public string RuleName;
+
+ public int? Priority;
+
+ public double? FixedRate;
+
+ public int? ReservoirSize;
+
+ public string Host;
+
+ public string ServiceName;
+
+ public string HTTPMethod;
+
+ public string URLPath;
+
+ public string ServiceType;
+
+ public string ResourceARN;
+
+ public string RuleARN;
+
+ public int? Version;
+
+ public Dictionary Attributes;
+ }
+}
diff --git a/sdk/src/Core/Sampling/Model/SamplingRuleRecordsModel.cs b/sdk/src/Core/Sampling/Model/SamplingRuleRecordsModel.cs
new file mode 100644
index 00000000..25f030df
--- /dev/null
+++ b/sdk/src/Core/Sampling/Model/SamplingRuleRecordsModel.cs
@@ -0,0 +1,31 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright 2020 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.
+//
+//-----------------------------------------------------------------------------
+
+namespace Amazon.XRay.Recorder.Core.Sampling.Model
+{
+ ///
+ /// Class model for unmarshalling sampling rule record from sampling rule response json.
+ ///
+ public class SamplingRuleRecordsModel
+ {
+ public double? CreatedAt;
+
+ public double? ModifiedAt;
+
+ public SamplingRuleModel SamplingRule;
+ }
+}
diff --git a/sdk/src/Core/Sampling/Model/SamplingRuleResponseModel.cs b/sdk/src/Core/Sampling/Model/SamplingRuleResponseModel.cs
new file mode 100644
index 00000000..f805ad1e
--- /dev/null
+++ b/sdk/src/Core/Sampling/Model/SamplingRuleResponseModel.cs
@@ -0,0 +1,31 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright 2020 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 System.Collections.Generic;
+
+namespace Amazon.XRay.Recorder.Core.Sampling.Model
+{
+ ///
+ /// Class model for unmarshalling sampling rule response json.
+ ///
+ public class SamplingRuleResponseModel
+ {
+ public string NextToken;
+
+ public List SamplingRuleRecords = new List();
+ }
+}
diff --git a/sdk/src/Core/Sampling/Model/SamplingStatisticsDocumentModel.cs b/sdk/src/Core/Sampling/Model/SamplingStatisticsDocumentModel.cs
new file mode 100644
index 00000000..3182db0b
--- /dev/null
+++ b/sdk/src/Core/Sampling/Model/SamplingStatisticsDocumentModel.cs
@@ -0,0 +1,37 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright 2020 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.
+//
+//-----------------------------------------------------------------------------
+
+namespace Amazon.XRay.Recorder.Core.Sampling.Model
+{
+ ///
+ /// Class for marshalling sampling statistics document json.
+ ///
+ public class SamplingStatisticsDocumentModel
+ {
+ public string ClientID { get; set; }
+
+ public string RuleName { get; set; }
+
+ public int? RequestCount { get; set; }
+
+ public int? SampledCount { get; set; }
+
+ public int? BorrowCount { get; set; }
+
+ public double? Timestamp { get; set; }
+ }
+}
diff --git a/sdk/src/Core/Sampling/Model/SamplingStatisticsModel.cs b/sdk/src/Core/Sampling/Model/SamplingStatisticsModel.cs
new file mode 100644
index 00000000..69f5917c
--- /dev/null
+++ b/sdk/src/Core/Sampling/Model/SamplingStatisticsModel.cs
@@ -0,0 +1,29 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright 2020 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 System.Collections.Generic;
+
+namespace Amazon.XRay.Recorder.Core.Sampling.Model
+{
+ ///
+ /// Class for marshalling sampling statistics document json.
+ ///
+ public class SamplingStatisticsModel
+ {
+ public List SamplingStatisticsDocuments { get; set; } = new List();
+ }
+}
diff --git a/sdk/src/Core/Sampling/Model/SamplingTargetModel.cs b/sdk/src/Core/Sampling/Model/SamplingTargetModel.cs
new file mode 100644
index 00000000..56c59c39
--- /dev/null
+++ b/sdk/src/Core/Sampling/Model/SamplingTargetModel.cs
@@ -0,0 +1,35 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright 2020 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.
+//
+//-----------------------------------------------------------------------------
+
+namespace Amazon.XRay.Recorder.Core.Sampling.Model
+{
+ ///
+ /// Class model for unmarshalling sampling target from sampling target response json.
+ ///
+ public class SamplingTargetModel
+ {
+ public double? FixedRate;
+
+ public int? ReservoirQuota;
+
+ public double? ReservoirQuotaTTL;
+
+ public string RuleName;
+
+ public int? Interval;
+ }
+}
diff --git a/sdk/src/Core/Sampling/Model/SamplingTargetResponseModel.cs b/sdk/src/Core/Sampling/Model/SamplingTargetResponseModel.cs
new file mode 100644
index 00000000..bc5e395d
--- /dev/null
+++ b/sdk/src/Core/Sampling/Model/SamplingTargetResponseModel.cs
@@ -0,0 +1,33 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright 2020 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 System.Collections.Generic;
+
+namespace Amazon.XRay.Recorder.Core.Sampling.Model
+{
+ ///
+ /// Class model for unmarshalling sampling target response json.
+ ///
+ public class SamplingTargetResponseModel
+ {
+ public double? LastRuleModification;
+
+ public List SamplingTargetDocuments = new List();
+
+ public List UnprocessedStatistics = new List();
+ }
+}
diff --git a/sdk/src/Core/Sampling/Model/UnprocessedStatisticsModel.cs b/sdk/src/Core/Sampling/Model/UnprocessedStatisticsModel.cs
new file mode 100644
index 00000000..ec0ee8f6
--- /dev/null
+++ b/sdk/src/Core/Sampling/Model/UnprocessedStatisticsModel.cs
@@ -0,0 +1,31 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright 2020 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.
+//
+//-----------------------------------------------------------------------------
+
+namespace Amazon.XRay.Recorder.Core.Sampling.Model
+{
+ ///
+ /// Class for unmarshalling unprocessed statistics from sampling target response json.
+ ///
+ public class UnprocessedStatisticsModel
+ {
+ public string RuleName;
+
+ public string ErrorCode;
+
+ public string Message;
+ }
+}
diff --git a/sdk/src/Core/Sampling/SamplingRule.cs b/sdk/src/Core/Sampling/SamplingRule.cs
index 2f8843e6..02e0b15c 100644
--- a/sdk/src/Core/Sampling/SamplingRule.cs
+++ b/sdk/src/Core/Sampling/SamplingRule.cs
@@ -85,9 +85,9 @@ internal void IncrementSampledCount()
///
/// Validates sampling rule. ResourceARN with "*" value is valid. SDK doesn't support Atrributes parameter with any value.
///
- /// Instance of
+ /// Instance of
/// True, if the rule is valid else false.
- internal static bool IsValid(Model.SamplingRule rule)
+ internal static bool IsValid(Model.SamplingRuleModel rule)
{
if (!string.Equals(rule.ResourceARN, "*"))
{
diff --git a/sdk/src/Core/Sampling/ServiceConnector.cs b/sdk/src/Core/Sampling/ServiceConnector.cs
index de783568..5ca4ebf9 100644
--- a/sdk/src/Core/Sampling/ServiceConnector.cs
+++ b/sdk/src/Core/Sampling/ServiceConnector.cs
@@ -14,13 +14,16 @@
// permissions and limitations under the License.
//
//-----------------------------------------------------------------------------
+
using System.Collections.Generic;
-using Amazon.XRay.Model;
using System.Threading.Tasks;
using System;
-using Amazon.Runtime;
using Amazon.XRay.Recorder.Core.Internal.Utils;
using Amazon.Runtime.Internal.Util;
+using Amazon.XRay.Recorder.Core.Sampling.Model;
+using ThirdParty.LitJson;
+using System.Text;
+using System.Net.Http;
namespace Amazon.XRay.Recorder.Core.Sampling
{
@@ -32,19 +35,19 @@ namespace Amazon.XRay.Recorder.Core.Sampling
class ServiceConnector : IConnector
{
private static readonly Logger _logger = Logger.GetLogger(typeof(ServiceConnector));
- private AmazonXRayClient _xrayClient;
+ private XRayConfig _xrayConfig;
private readonly object _xrayClientLock = new object();
private const int Version = 1;
- private readonly AmazonXRayConfig _config = new AmazonXRayConfig();
- private readonly AWSCredentials _credentials = new AnonymousAWSCredentials(); // sends unsigned requests to daemon endpoint
private readonly DaemonConfig _daemonConfig;
+ private readonly DateTime EpochStart = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ private static readonly HttpClient _httpClient = new HttpClient();
///
/// Client id for the instance. Its 24 digit hex number.
///
public string ClientID;
- public ServiceConnector(DaemonConfig daemonConfig, AmazonXRayClient xrayClient)
+ public ServiceConnector(DaemonConfig daemonConfig, XRayConfig xrayConfig)
{
ClientID = ThreadSafeRandom.GenerateHexNumber(24);
if (daemonConfig == null)
@@ -53,61 +56,96 @@ public ServiceConnector(DaemonConfig daemonConfig, AmazonXRayClient xrayClient)
}
_daemonConfig = daemonConfig;
- if (xrayClient == null)
+ if (xrayConfig == null)
{
- xrayClient = CreateXRayClient();
+ xrayConfig = CreateXRayConfig();
}
- _xrayClient = xrayClient;
+ _xrayConfig = xrayConfig;
}
- private AmazonXRayClient CreateXRayClient()
+ private XRayConfig CreateXRayConfig()
{
- _config.ServiceURL = $"http://{_daemonConfig.TCPEndpoint.Address}:{_daemonConfig.TCPEndpoint.Port}";
- return new AmazonXRayClient(_credentials,_config);
+ var config = new XRayConfig();
+ config.ServiceURL = $"http://{_daemonConfig.TCPEndpoint.Address}:{_daemonConfig.TCPEndpoint.Port}";
+ return config;
}
private void RefreshEndPoint()
{
var serviceUrlCandidate = $"http://{_daemonConfig.TCPEndpoint.Address}:{_daemonConfig.TCPEndpoint.Port}";
-
- if (serviceUrlCandidate.Equals(_xrayClient.Config.ServiceURL)) return; // endpoint do not need refreshing
- _config.ServiceURL = serviceUrlCandidate;
- _xrayClient = new AmazonXRayClient(_credentials, _config);
- _logger.DebugFormat($"ServiceConnector Endpoint refreshed to: {_xrayClient.Config.ServiceURL}");
+ if (serviceUrlCandidate.Equals(_xrayConfig.ServiceURL)) return; // endpoint do not need refreshing
+
+ _xrayConfig.ServiceURL = serviceUrlCandidate;
+ _logger.DebugFormat($"ServiceConnector Endpoint refreshed to: {_xrayConfig.ServiceURL}");
}
///
- /// Use X-Ray client to get the sampling rules
- /// from X-Ray service.The call is proxied and signed by X-Ray Daemon.
+ /// Get the sampling rules from X-Ray service.The call is proxied and signed by X-Ray Daemon.
///
///
- public async Task GetSamplingRules()
+ public async Task GetSamplingRules()
{
- List newRules = new List();
- GetSamplingRulesRequest request = new GetSamplingRulesRequest();
-
- Task responseTask;
+ Task responseTask;
lock (_xrayClientLock)
{
RefreshEndPoint();
- responseTask = _xrayClient.GetSamplingRulesAsync(request);
+ responseTask = GetSamplingInfoAsync(_xrayConfig.ServiceURL + "/GetSamplingRules", string.Empty);
}
- var response = await responseTask;
+ var responseContent = await responseTask;
+
+ List samplingRules = UnmarshallSamplingRuleResponse(responseContent);
+
+ GetSamplingRulesResponse result = new GetSamplingRulesResponse(samplingRules);
+ return result;
+ }
- foreach(var record in response.SamplingRuleRecords)
+ private async Task GetSamplingInfoAsync(string url, string content)
+ {
+ using (var stringContent = new StringContent(content, Encoding.UTF8, "application/json"))
{
- var rule = record.SamplingRule;
- if (rule.Version == Version && SamplingRule.IsValid(rule)) // We currently only handle v1 sampling rules.
+ // Need to set header "ExpectContinue" as false for Daemon to sign properly.
+ // https://github.com/aws/aws-sdk-net/blob/master/sdk/src/Core/Amazon.Runtime/Internal/AmazonWebServiceRequest.cs#L41
+ _httpClient.DefaultRequestHeaders.ExpectContinue = false;
+ using (var response = await _httpClient.PostAsync(url, stringContent))
{
- var sampleRule = new SamplingRule(rule.RuleName, rule.Priority, rule.FixedRate, rule.ReservoirSize, rule.Host, rule.ServiceName, rule.HTTPMethod, rule.URLPath, rule.ServiceType, rule.ResourceARN, rule.Attributes);
- newRules.Add(sampleRule);
+ response.EnsureSuccessStatusCode();
+ return await response.Content.ReadAsStringAsync();
}
}
+ }
- GetSamplingRulesResponse result = new GetSamplingRulesResponse(newRules);
- return result;
+ private List UnmarshallSamplingRuleResponse(string responseContent)
+ {
+ List samplingRules = new List();
+
+ var samplingRuleResponse = JsonMapper.ToObject(responseContent);
+
+ foreach (var samplingRuleRecord in samplingRuleResponse.SamplingRuleRecords)
+ {
+ var samplingRuleModel = samplingRuleRecord.SamplingRule;
+ if (samplingRuleModel.Version.GetValueOrDefault() == Version && SamplingRule.IsValid(samplingRuleModel))
+ {
+ var samplingRule = new SamplingRule
+ (
+ samplingRuleModel.RuleName,
+ samplingRuleModel.Priority.GetValueOrDefault(),
+ samplingRuleModel.FixedRate.GetValueOrDefault(),
+ samplingRuleModel.ReservoirSize.GetValueOrDefault(),
+ samplingRuleModel.Host,
+ samplingRuleModel.ServiceName,
+ samplingRuleModel.HTTPMethod,
+ samplingRuleModel.URLPath,
+ samplingRuleModel.ServiceType,
+ samplingRuleModel.ResourceARN,
+ samplingRuleModel.Attributes
+ );
+ samplingRules.Add(samplingRule);
+ }
+ }
+
+ return samplingRules;
}
///
@@ -119,47 +157,83 @@ public async Task GetSamplingRules()
/// Instance of .
public async Task GetSamplingTargets(List rules)
{
- GetSamplingTargetsRequest request = new GetSamplingTargetsRequest();
- IList newTargets = new List();
DateTime currentTime = TimeStamp.CurrentDateTime();
- List samplingStatisticsDocuments = GetSamplingStatisticsDocuments(rules, currentTime);
- request.SamplingStatisticsDocuments = samplingStatisticsDocuments;
- Task responseTask;
+ List samplingStatisticsDocumentModels = GetSamplingStatisticsDocuments(rules, currentTime);
+ var samplingStatisticsModel = new SamplingStatisticsModel();
+ samplingStatisticsModel.SamplingStatisticsDocuments = samplingStatisticsDocumentModels;
+
+ string requestContent = JsonMapper.ToJson(samplingStatisticsModel); // Marshall SamplingStatisticsDocument to json
+
+ Task responseTask;
lock (_xrayClientLock)
{
RefreshEndPoint();
- responseTask = _xrayClient.GetSamplingTargetsAsync(request);
+ responseTask = GetSamplingInfoAsync(_xrayConfig.ServiceURL + "/SamplingTargets", requestContent);
}
- var response = await responseTask;
- foreach (var record in response.SamplingTargetDocuments)
+ var responseContent = await responseTask;
+
+ var samplingTargetResponse = UnmarshallSamplingTargetResponse(responseContent);
+
+ var targetList = ConvertTargetList(samplingTargetResponse.SamplingTargetDocuments);
+
+ GetSamplingTargetsResponse result = new GetSamplingTargetsResponse(targetList);
+ result.RuleFreshness = new TimeStamp(ConvertDoubleToDateTime(samplingTargetResponse.LastRuleModification));
+ return result;
+ }
+
+ private List ConvertTargetList(List targetModels)
+ {
+ List result = new List();
+ foreach (var targetModel in targetModels)
{
- Target t = new Target(record.RuleName, record.FixedRate, record.ReservoirQuota, record.ReservoirQuotaTTL, record.Interval);
- newTargets.Add(t);
+ Target t = new Target
+ (
+ targetModel.RuleName,
+ targetModel.FixedRate.GetValueOrDefault(),
+ targetModel.ReservoirQuota.GetValueOrDefault(),
+ ConvertDoubleToDateTime(targetModel.ReservoirQuotaTTL),
+ targetModel.Interval.GetValueOrDefault()
+ );
+ result.Add(t);
}
-
- GetSamplingTargetsResponse result = new GetSamplingTargetsResponse(newTargets);
- result.RuleFreshness = new TimeStamp(response.LastRuleModification);
return result;
}
- private List GetSamplingStatisticsDocuments(List rules, DateTime currentTime)
+ private SamplingTargetResponseModel UnmarshallSamplingTargetResponse(string responseContent)
{
- List samplingStatisticsDocuments = new List();
+ var samplingTargetResponse = JsonMapper.ToObject(responseContent);
+
+ return samplingTargetResponse;
+ }
+
+ private List GetSamplingStatisticsDocuments(List rules, DateTime currentTime)
+ {
+ List samplingStatisticsDocumentModels = new List();
foreach (var rule in rules)
{
Statistics statistics = rule.SnapShotStatistics();
- SamplingStatisticsDocument doc = new SamplingStatisticsDocument();
- doc.ClientID = ClientID;
- doc.RuleName = rule.RuleName;
- doc.RequestCount = statistics.RequestCount;
- doc.SampledCount = statistics.SampledCount;
- doc.BorrowCount = statistics.BorrowCount;
- doc.Timestamp = currentTime;
- samplingStatisticsDocuments.Add(doc);
+ SamplingStatisticsDocumentModel item = new SamplingStatisticsDocumentModel();
+ item.ClientID = ClientID;
+ item.RuleName = rule.RuleName;
+ item.RequestCount = statistics.RequestCount;
+ item.SampledCount = statistics.SampledCount;
+ item.BorrowCount = statistics.BorrowCount;
+ item.Timestamp = ConvertDateTimeToDouble(currentTime);
+ samplingStatisticsDocumentModels.Add(item);
}
- return samplingStatisticsDocuments;
+ return samplingStatisticsDocumentModels;
+ }
+
+ private double ConvertDateTimeToDouble(DateTime currentTime)
+ {
+ var current = new TimeSpan(currentTime.ToUniversalTime().Ticks - EpochStart.Ticks);
+ return Math.Round(current.TotalMilliseconds, 0) / 1000.0;
+ }
+
+ private DateTime ConvertDoubleToDateTime(double? seconds)
+ {
+ return seconds == null ? default(DateTime) : EpochStart.AddSeconds(seconds.GetValueOrDefault());
}
}
}
-
diff --git a/sdk/src/Core/Sampling/XRayConfig.cs b/sdk/src/Core/Sampling/XRayConfig.cs
new file mode 100644
index 00000000..35795dde
--- /dev/null
+++ b/sdk/src/Core/Sampling/XRayConfig.cs
@@ -0,0 +1,37 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright 2020 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.
+//
+//-----------------------------------------------------------------------------
+
+namespace Amazon.XRay.Recorder.Core.Sampling
+{
+ ///
+ /// Class for xray configuration for getting sampling rules and sampling targets.
+ ///
+ public class XRayConfig
+ {
+ ///
+ /// Gets and sets of the ServiceURL property.
+ ///
+ public string ServiceURL { get; set; }
+
+ ///
+ /// Default constructor.
+ ///
+ public XRayConfig()
+ {
+ }
+ }
+}
diff --git a/sdk/test/UnitTests/AWSXRayRecorder.UnitTests.csproj b/sdk/test/UnitTests/AWSXRayRecorder.UnitTests.csproj
index 70129ece..c2e116cc 100644
--- a/sdk/test/UnitTests/AWSXRayRecorder.UnitTests.csproj
+++ b/sdk/test/UnitTests/AWSXRayRecorder.UnitTests.csproj
@@ -40,7 +40,6 @@
-
diff --git a/sdk/test/UnitTests/JsonMapperTest.cs b/sdk/test/UnitTests/JsonMapperTest.cs
new file mode 100644
index 00000000..65c16807
--- /dev/null
+++ b/sdk/test/UnitTests/JsonMapperTest.cs
@@ -0,0 +1,275 @@
+//-----------------------------------------------------------------------------
+//
+// Copyright 2020 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.XRay.Recorder.Core.Sampling.Model;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using ThirdParty.LitJson;
+
+namespace Amazon.XRay.Recorder.UnitTests
+{
+ [TestClass]
+ public class JsonMapperTest
+ {
+ [TestMethod]
+ public void TestMarshallSamplingStatisticsDocuments()
+ {
+ var samplingStatisticsModel = new SamplingStatisticsModel();
+ var samplingStatisticsDocumentModel = new SamplingStatisticsDocumentModel
+ {
+ ClientID = "07492221d7fd13a86e750de2",
+ RuleName = "Test",
+ RequestCount = 108,
+ SampledCount = 4,
+ BorrowCount = 6,
+ Timestamp = 1604297926.362
+ };
+
+ samplingStatisticsModel.SamplingStatisticsDocuments.Add(samplingStatisticsDocumentModel);
+
+ var expected = "{\"SamplingStatisticsDocuments\":[{\"ClientID\":\"07492221d7fd13a86e750de2\",\"RuleName\":\"Test\",\"RequestCount\":108,\"SampledCount\":4,\"BorrowCount\":6,\"Timestamp\":1604297926.362}]}";
+ var actual = JsonMapper.ToJson(samplingStatisticsModel);
+
+ Assert.AreEqual(expected, actual);
+ }
+
+ [TestMethod]
+ public void TestMarshallSamplingStatisticsDocumentsWithEmptyValues()
+ {
+ var samplingStatisticsModel = new SamplingStatisticsModel();
+ var samplingStatisticsDocumentModel = new SamplingStatisticsDocumentModel();
+
+ samplingStatisticsModel.SamplingStatisticsDocuments.Add(samplingStatisticsDocumentModel);
+
+ var expected = "{\"SamplingStatisticsDocuments\":[{\"ClientID\":null,\"RuleName\":null,\"RequestCount\":null,\"SampledCount\":null,\"BorrowCount\":null,\"Timestamp\":null}]}";
+ var actual = JsonMapper.ToJson(samplingStatisticsModel);
+
+ Assert.AreEqual(expected, actual);
+ }
+
+ [TestMethod]
+ public void TestMarshallSamplingStatisticsDocumentsWithEmptyItems()
+ {
+ var samplingStatisticsModel = new SamplingStatisticsModel();
+
+ var expected = "{\"SamplingStatisticsDocuments\":[]}";
+ var actual = JsonMapper.ToJson(samplingStatisticsModel);
+
+ Assert.AreEqual(expected, actual);
+ }
+
+ [TestMethod]
+ public void TestUnmarshallSamplingRuleResponse()
+ {
+ var samplingRuleResponseJson = "{\"NextToken\":null,\"SamplingRuleRecords\":[{\"CreatedAt\":0.0,\"ModifiedAt\":1.602621583E9,\"SamplingRule\":{\"Attributes\":{},\"FixedRate\":0.05,\"HTTPMethod\":\"*\",\"Host\":\"*\",\"Priority\":10000,\"ReservoirSize\":1,\"ResourceARN\":\"*\",\"RuleARN\":\"arn:aws:xray:us-east-1:1234567:sampling-rule/Default\",\"RuleName\":\"Default\",\"ServiceName\":\"*\",\"ServiceType\":\"*\",\"URLPath\":\"*\",\"Version\":1}}]}";
+
+ var samplingRuleResponseModel = JsonMapper.ToObject(samplingRuleResponseJson);
+
+ Assert.IsNull(samplingRuleResponseModel.NextToken);
+ Assert.IsTrue(samplingRuleResponseModel.SamplingRuleRecords.Count > 0);
+
+ foreach (var samplingRuleRecord in samplingRuleResponseModel.SamplingRuleRecords)
+ {
+ Assert.AreEqual(0.0, samplingRuleRecord.CreatedAt.GetValueOrDefault());
+ Assert.AreEqual(1.602621583E9, samplingRuleRecord.ModifiedAt.GetValueOrDefault());
+ Assert.IsNotNull(samplingRuleRecord.SamplingRule);
+ Assert.IsTrue(samplingRuleRecord.SamplingRule.Attributes.Count == 0);
+ Assert.AreEqual(0.05, samplingRuleRecord.SamplingRule.FixedRate.GetValueOrDefault());
+ Assert.AreEqual("*", samplingRuleRecord.SamplingRule.HTTPMethod);
+ Assert.AreEqual("*", samplingRuleRecord.SamplingRule.Host);
+ Assert.AreEqual(10000, samplingRuleRecord.SamplingRule.Priority.GetValueOrDefault());
+ Assert.AreEqual(1, samplingRuleRecord.SamplingRule.ReservoirSize.GetValueOrDefault());
+ Assert.AreEqual("*", samplingRuleRecord.SamplingRule.ResourceARN);
+ Assert.AreEqual("arn:aws:xray:us-east-1:1234567:sampling-rule/Default", samplingRuleRecord.SamplingRule.RuleARN);
+ Assert.AreEqual("Default", samplingRuleRecord.SamplingRule.RuleName);
+ Assert.AreEqual("*", samplingRuleRecord.SamplingRule.ServiceName);
+ Assert.AreEqual("*", samplingRuleRecord.SamplingRule.ServiceType);
+ Assert.AreEqual("*", samplingRuleRecord.SamplingRule.URLPath);
+ Assert.AreEqual(1, samplingRuleRecord.SamplingRule.Version.GetValueOrDefault());
+ }
+ }
+
+ [TestMethod]
+ public void TestUnmarshallSamplingRuleResponseWithEmptyValues()
+ {
+ var samplingRuleResponseJson = "{\"NextToken\":null,\"SamplingRuleRecords\":[{\"CreatedAt\":null,\"ModifiedAt\":null,\"SamplingRule\":{\"Attributes\":{},\"FixedRate\":null,\"HTTPMethod\":null,\"Host\":null,\"Priority\":null,\"ReservoirSize\":null,\"ResourceARN\":null,\"RuleARN\":null,\"RuleName\":null,\"ServiceName\":null,\"ServiceType\":null,\"URLPath\":null,\"Version\":null}}]}";
+
+ var samplingRuleResponseModel = JsonMapper.ToObject(samplingRuleResponseJson);
+
+ Assert.IsNull(samplingRuleResponseModel.NextToken);
+ Assert.IsTrue(samplingRuleResponseModel.SamplingRuleRecords.Count > 0);
+
+ foreach (var samplingRuleRecord in samplingRuleResponseModel.SamplingRuleRecords)
+ {
+ Assert.AreEqual(0, samplingRuleRecord.CreatedAt.GetValueOrDefault());
+ Assert.AreEqual(0, samplingRuleRecord.ModifiedAt.GetValueOrDefault());
+ Assert.IsNotNull(samplingRuleRecord.SamplingRule);
+ Assert.IsTrue(samplingRuleRecord.SamplingRule.Attributes.Count == 0);
+ Assert.AreEqual(0, samplingRuleRecord.SamplingRule.FixedRate.GetValueOrDefault());
+ Assert.AreEqual(null, samplingRuleRecord.SamplingRule.HTTPMethod);
+ Assert.AreEqual(null, samplingRuleRecord.SamplingRule.Host);
+ Assert.AreEqual(0, samplingRuleRecord.SamplingRule.Priority.GetValueOrDefault());
+ Assert.AreEqual(0, samplingRuleRecord.SamplingRule.ReservoirSize.GetValueOrDefault());
+ Assert.AreEqual(null, samplingRuleRecord.SamplingRule.ResourceARN);
+ Assert.AreEqual(null, samplingRuleRecord.SamplingRule.RuleARN);
+ Assert.AreEqual(null, samplingRuleRecord.SamplingRule.RuleName);
+ Assert.AreEqual(null, samplingRuleRecord.SamplingRule.ServiceName);
+ Assert.AreEqual(null, samplingRuleRecord.SamplingRule.ServiceType);
+ Assert.AreEqual(null, samplingRuleRecord.SamplingRule.URLPath);
+ Assert.AreEqual(0, samplingRuleRecord.SamplingRule.Version.GetValueOrDefault());
+ }
+ }
+
+ [TestMethod]
+ public void TestUnmarshallSamplingRuleResponseWithInvalidFormat()
+ {
+ var samplingRuleResponseJson = "{\"a\":null,\"b\":[{\"c\":0.0,\"d\":1.602621583E9,\"e\":{\"f\":{},\"g\":0.05,\"h\":\"*\",\"i\":\"*\",\"j\":10000,\"k\":1,\"l\":\"*\",\"m\":\"arn:aws:xray:us-east-1:1234567:sampling-rule/Default\",\"n\":\"Default\",\"o\":\"*\",\"p\":\"*\",\"q\":\"*\",\"r\":1}}]}";
+
+ var samplingRuleResponseModel = JsonMapper.ToObject(samplingRuleResponseJson);
+
+ Assert.IsNull(samplingRuleResponseModel.NextToken);
+ Assert.IsTrue(samplingRuleResponseModel.SamplingRuleRecords.Count == 0);
+ }
+
+ [TestMethod]
+ public void TestUnmarshallSamplingRuleResponseWithNull()
+ {
+ string samplingRuleResponseJson = "";
+
+ var samplingRuleResponseModel = JsonMapper.ToObject(samplingRuleResponseJson);
+
+ Assert.IsNull(samplingRuleResponseModel);
+ }
+
+ [TestMethod]
+ public void TestUnmarshallSamplingTargetResponse()
+ {
+ string samplingTargetResponseJson = "{\"LastRuleModification\":1.603923208E9,\"SamplingTargetDocuments\":[{\"FixedRate\":0.05,\"Interval\":2,\"ReservoirQuota\":1,\"ReservoirQuotaTTL\":1.5,\"RuleName\":\"Test\"}],\"UnprocessedStatistics\":[{\"ErrorCode\":\"400\",\"Message\":\"Unknown rule\",\"RuleName\":\"Fault\"}]}";
+
+ var samplingTargetResponseModel = JsonMapper.ToObject(samplingTargetResponseJson);
+
+ Assert.AreEqual(1.603923208E9, samplingTargetResponseModel.LastRuleModification);
+ Assert.IsTrue(samplingTargetResponseModel.SamplingTargetDocuments.Count > 0);
+ Assert.IsTrue(samplingTargetResponseModel.UnprocessedStatistics.Count > 0);
+
+ foreach (var target in samplingTargetResponseModel.SamplingTargetDocuments)
+ {
+ Assert.AreEqual(0.05, target.FixedRate.GetValueOrDefault());
+ Assert.AreEqual(2, target.Interval.GetValueOrDefault());
+ Assert.AreEqual(1, target.ReservoirQuota.GetValueOrDefault());
+ Assert.AreEqual(1.5, target.ReservoirQuotaTTL.GetValueOrDefault());
+ Assert.AreEqual("Test", target.RuleName);
+ }
+
+ foreach (var unprocessed in samplingTargetResponseModel.UnprocessedStatistics)
+ {
+ Assert.AreEqual("400", unprocessed.ErrorCode);
+ Assert.AreEqual("Unknown rule", unprocessed.Message);
+ Assert.AreEqual("Fault", unprocessed.RuleName);
+ }
+ }
+
+ [TestMethod]
+ public void TestUnmarshallSamplingTargetResponseWithoutSamplingTargetDocuments()
+ {
+ string samplingTargetResponseJson = "{\"LastRuleModification\":1.603923208E9,\"SamplingTargetDocuments\":[],\"UnprocessedStatistics\":[{\"ErrorCode\":\"400\",\"Message\":\"Unknown rule\",\"RuleName\":\"Fault\"}]}";
+
+ var samplingTargetResponseModel = JsonMapper.ToObject(samplingTargetResponseJson);
+
+ Assert.AreEqual(1.603923208E9, samplingTargetResponseModel.LastRuleModification);
+ Assert.IsTrue(samplingTargetResponseModel.SamplingTargetDocuments.Count == 0);
+ Assert.IsTrue(samplingTargetResponseModel.UnprocessedStatistics.Count > 0);
+
+ foreach (var unprocessed in samplingTargetResponseModel.UnprocessedStatistics)
+ {
+ Assert.AreEqual("400", unprocessed.ErrorCode);
+ Assert.AreEqual("Unknown rule", unprocessed.Message);
+ Assert.AreEqual("Fault", unprocessed.RuleName);
+ }
+ }
+
+ [TestMethod]
+ public void TestUnmarshallSamplingTargetResponseWithoutUnprocessedStatistics()
+ {
+ string samplingTargetResponseJson = "{\"LastRuleModification\":1.603923208E9,\"SamplingTargetDocuments\":[{\"FixedRate\":0.05,\"Interval\":2,\"ReservoirQuota\":1,\"ReservoirQuotaTTL\":1.5,\"RuleName\":\"Test\"}],\"UnprocessedStatistics\":[]}";
+
+ var samplingTargetResponseModel = JsonMapper.ToObject(samplingTargetResponseJson);
+
+ Assert.AreEqual(1.603923208E9, samplingTargetResponseModel.LastRuleModification);
+ Assert.IsTrue(samplingTargetResponseModel.SamplingTargetDocuments.Count > 0);
+ Assert.IsTrue(samplingTargetResponseModel.UnprocessedStatistics.Count == 0);
+
+ foreach (var target in samplingTargetResponseModel.SamplingTargetDocuments)
+ {
+ Assert.AreEqual(0.05, target.FixedRate.GetValueOrDefault());
+ Assert.AreEqual(2, target.Interval.GetValueOrDefault());
+ Assert.AreEqual(1, target.ReservoirQuota.GetValueOrDefault());
+ Assert.AreEqual(1.5, target.ReservoirQuotaTTL.GetValueOrDefault());
+ Assert.AreEqual("Test", target.RuleName);
+ }
+ }
+
+ [TestMethod]
+ public void TestUnmarshallSamplingTargetResponseWithEmptyValues()
+ {
+ string samplingTargetResponseJson = "{\"LastRuleModification\":null,\"SamplingTargetDocuments\":[{\"FixedRate\":null,\"Interval\":null,\"ReservoirQuota\":null,\"ReservoirQuotaTTL\":null,\"RuleName\":null}],\"UnprocessedStatistics\":[{\"ErrorCode\":null,\"Message\":null,\"RuleName\":null}]}";
+
+ var samplingTargetResponseModel = JsonMapper.ToObject(samplingTargetResponseJson);
+
+ Assert.AreEqual(0, samplingTargetResponseModel.LastRuleModification.GetValueOrDefault());
+ Assert.IsTrue(samplingTargetResponseModel.SamplingTargetDocuments.Count > 0);
+ Assert.IsTrue(samplingTargetResponseModel.UnprocessedStatistics.Count > 0);
+
+ foreach (var target in samplingTargetResponseModel.SamplingTargetDocuments)
+ {
+ Assert.AreEqual(0, target.FixedRate.GetValueOrDefault());
+ Assert.AreEqual(0, target.Interval.GetValueOrDefault());
+ Assert.AreEqual(0, target.ReservoirQuota.GetValueOrDefault());
+ Assert.AreEqual(0, target.ReservoirQuotaTTL.GetValueOrDefault());
+ Assert.IsNull(target.RuleName);
+ }
+
+ foreach (var unprocessed in samplingTargetResponseModel.UnprocessedStatistics)
+ {
+ Assert.IsNull(unprocessed.ErrorCode);
+ Assert.IsNull(unprocessed.Message);
+ Assert.IsNull(unprocessed.RuleName);
+ }
+ }
+
+ [TestMethod]
+ public void TestUnmarshallSamplingTargetResponseWithInvalidFormat()
+ {
+ string samplingTargetResponseJson = "{\"a\":1.603923208E9,\"b\":[{\"c\":0.05,\"d\":2,\"e\":1,\"f\":1.5,\"g\":\"Test\"}],\"h\":[{\"i\":\"400\",\"j\":\"Unknown rule\",\"k\":\"Fault\"}]}";
+
+ var samplingTargetResponseModel = JsonMapper.ToObject(samplingTargetResponseJson);
+
+ Assert.IsNull(samplingTargetResponseModel.LastRuleModification);
+ Assert.IsTrue(samplingTargetResponseModel.SamplingTargetDocuments.Count == 0);
+ Assert.IsTrue(samplingTargetResponseModel.UnprocessedStatistics.Count == 0);
+ }
+
+ [TestMethod]
+ public void TestUnmarshallSamplingTargetResponseWithNull()
+ {
+ string samplingTargetResponseJson = "";
+
+ var samplingTargetResponseModel = JsonMapper.ToObject(samplingTargetResponseJson);
+
+ Assert.IsNull(samplingTargetResponseModel);
+ }
+ }
+}