//-----------------------------------------------------------------------------
//
// 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 System;
using Amazon.Runtime.Internal.Util;
using Amazon.XRay.Recorder.Core.Exceptions;
using Amazon.XRay.Recorder.Core.Internal.Emitters;
using Amazon.XRay.Recorder.Core.Internal.Entities;
using Amazon.XRay.Recorder.Core.Sampling;
using Amazon.XRay.Recorder.Core.Internal.Utils;
using Amazon.XRay.Recorder.Core.Strategies;
namespace Amazon.XRay.Recorder.Core
{
///
/// A collection of methods used to record tracing information for AWS X-Ray.
///
///
public class AWSXRayRecorder : AWSXRayRecorderImpl
{
private static readonly Logger _logger = Logger.GetLogger(typeof(AWSXRayRecorder));
public static bool IsCustomRecorder;
///
/// Initializes a new instance of the class
/// with default configuration.
///
public AWSXRayRecorder() : this(new UdpSegmentEmitter())
{
}
///
/// Initializes a new instance of the class
/// with given instance of .
///
/// Segment emitter
internal AWSXRayRecorder(ISegmentEmitter emitter):base(emitter)
{
PopulateContexts();
SamplingStrategy = new DefaultSamplingStrategy(AppSettings.SamplingRuleManifest);
}
///
/// Gets the singleton instance of with default configuration.
/// The default configuration uses and read all configuration
/// value from AppSettings.
///
/// An instance of class.
public static AWSXRayRecorder Instance
{
get
{
return LazyDefaultRecorder.Value;
}
private set
{
LazyDefaultRecorder = new Lazy(() => value);
}
}
///
/// Sets provided instance of the to AWSXRayRecorder.Instance
///
/// Instance of .
public static void InitializeInstance(AWSXRayRecorder recorder)
{
if (recorder != null)
{
_logger.DebugFormat("Using custom X-Ray recorder.");
Instance = recorder;
IsCustomRecorder = true;
}
else
{
_logger.DebugFormat("Provided X-Ray recorder is null, using defaul recorder.");
}
}
///
/// Begin a tracing subsegment. A new segment will be created and added as a subsegment to previous segment.
///
/// Name of the operation.
/// Sets the start time for the subsegment.
/// The argument has a null value.
/// Entity is not available in trace context.
public override void BeginSubsegment(string name, DateTime? timestamp = null)
{
try
{
if (IsTracingDisabled())
{
_logger.DebugFormat("X-Ray tracing is disabled, do not start subsegment");
return;
}
// If the request is not sampled, a segment will still be available in TraceContext to
// stores the information of the trace. The trace information will still propagated to
// downstream service, in case downstream may overwrite the sample decision.
Entity parentEntity = TraceContext.GetEntity();
// If the segment is not sampled, do nothing and exit.
if (parentEntity.Sampled != SampleDecision.Sampled)
{
_logger.DebugFormat("Do not start subsegment because the segment doesn't get sampled. ({0})", name);
return;
}
Subsegment subsegment = new Subsegment(name);
parentEntity.AddSubsegment(subsegment);
subsegment.Sampled = parentEntity.Sampled;
if (timestamp == null)
{
subsegment.SetStartTimeToNow();
}
else
{
subsegment.SetStartTime(timestamp.Value);
}
TraceContext.SetEntity(subsegment);
}
catch (EntityNotAvailableException e)
{
HandleEntityNotAvailableException(e, "Failed to start subsegment because the parent segment is not available.");
}
}
///
/// End a subsegment.
///
/// Sets the end time of the subsegment
/// Entity is not available in trace context.
public override void EndSubsegment(DateTime? timestamp = null)
{
try
{
if (IsTracingDisabled())
{
_logger.DebugFormat("X-Ray tracing is disabled, do not end subsegment");
return;
}
ProcessEndSubsegment(timestamp);
}
catch (EntityNotAvailableException e)
{
HandleEntityNotAvailableException(e, "Failed to end subsegment because subsegment is not available in trace context.");
}
catch (InvalidCastException e)
{
HandleEntityNotAvailableException(new EntityNotAvailableException("Failed to cast the entity to Subsegment.", e), "Failed to cast the entity to Subsegment.");
}
}
///
/// Checks whether Tracing is enabled or disabled.
///
/// Returns true if Tracing is disabled else false.
public override bool IsTracingDisabled()
{
return AppSettings.IsXRayTracingDisabled;
}
}
}