//-----------------------------------------------------------------------------
//
// 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.Sampling;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using Amazon.XRay.Recorder.Core.Exceptions;
namespace Amazon.XRay.Recorder.Core.Internal.Entities
{
///
/// A trace segment tracks a period of time associated with a computation or action, along with annotations and key / value data.
/// A set of trace segments all of which share the same tracing ID form a trace.
///
///
[Serializable]
public class Segment : Entity
{
private long _size; // Total number of subsegments
private Lazy> _lazyService = new Lazy>();
///
/// Initializes a new instance of the class.
///
/// Name of the node or service component.
/// Unique id for the trace.
/// Unique id of the upstream segment.
public Segment(string name, string traceId = null, string parentId = null) : base(name)
{
if (traceId != null)
{
this.TraceId = traceId;
}
else
{
this.TraceId = Entities.TraceId.NewId();
}
if (parentId != null)
{
this.ParentId = parentId;
}
RootSegment = this;
}
///
/// Gets or Sets the User for the segment
///
public string User { get; set; }
///
/// Gets or sets the origin of the segment.
///
public string Origin { get; set; }
///
/// Gets the size of subsegments.
///
public long Size
{
get
{
return Interlocked.Read(ref _size);
}
}
///
/// Gets the service.
///
public IDictionary Service
{
get
{
return _lazyService.Value;
}
}
///
/// Gets a value indicating whether any value has been added to service.
///
public bool IsServiceAdded
{
get
{
return _lazyService.IsValueCreated && !_lazyService.Value.IsEmpty;
}
}
///
/// Increment the size count.
///
public void IncrementSize()
{
Interlocked.Increment(ref _size);
}
///
/// Decrement the size count.
///
public void DecrementSize()
{
Interlocked.Decrement(ref _size);
}
///
/// Release reference to this instance of segment.
///
/// Reference count after release.
public override long Release()
{
return DecrementReferenceCounter();
}
///
/// Check if this segment or the root segment that this segment belongs to is ok to emit.
///
/// If the segment is ready to emit.
public override bool IsEmittable()
{
return Reference == 0;
}
///
/// Checks if the segment has been streamed already
///
/// The segment has been already streamed and no further operation can be performed on it.
private void HasAlreadyStreamed()
{
if(HasStreamed)
{
throw new AlreadyEmittedException("Segment " + Name + " has already been emitted.");
}
}
///
/// Gets the value of the User for this segment
///
public string GetUser()
{
return User;
}
///
/// Sets the User for this segment
///
/// the name of the user
/// The value of user cannot be null.
public void SetUser(string user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
HasAlreadyStreamed();
this.User = user;
}
}
}