Пример #1
0
        public void End()
        {
            if (Duration.HasValue)
            {
                _logger.Trace()
                ?.Log("Ended {Span} (with Duration already set)." +
                      " Start time: {Time} (as timestamp: {Timestamp}), Duration: {Duration}ms",
                      this, TimeUtils.FormatTimestampForLog(Timestamp), Timestamp, Duration);
            }
            else
            {
                Assertion.IfEnabled?.That(!_isEnded,
                                          $"Span's Duration doesn't have value even though {nameof(End)} method was already called." +
                                          $" It contradicts the invariant enforced by {nameof(End)} method - Duration should have value when {nameof(End)} method exits" +
                                          $" and {nameof(_isEnded)} field is set to true only when {nameof(End)} method exits." +
                                          $" Context: this: {this}; {nameof(_isEnded)}: {_isEnded}");

                var endTimestamp = TimeUtils.TimestampNow();
                Duration = TimeUtils.DurationBetweenTimestamps(Timestamp, endTimestamp);
                _logger.Trace()
                ?.Log("Ended {Span}. Start time: {Time} (as timestamp: {Timestamp})," +
                      " End time: {Time} (as timestamp: {Timestamp}), Duration: {Duration}ms",
                      this, TimeUtils.FormatTimestampForLog(Timestamp), Timestamp,
                      TimeUtils.FormatTimestampForLog(endTimestamp), endTimestamp, Duration);
            }

            var isFirstEndCall = !_isEnded;

            _isEnded = true;
            if (IsSampled && isFirstEndCall)
            {
                _payloadSender.QueueSpan(this);
            }
        }
Пример #2
0
        public void End()
        {
            if (Duration.HasValue)
            {
                _logger.Trace()
                ?.Log("Ended {Span} (with Duration already set)." +
                      " Start time: {Time} (as timestamp: {Timestamp}), Duration: {Duration}ms",
                      this, TimeUtils.FormatTimestampForLog(Timestamp), Timestamp, Duration);
            }
            else
            {
                Assertion.IfEnabled?.That(!_isEnded,
                                          $"Span's Duration doesn't have value even though {nameof(End)} method was already called." +
                                          $" It contradicts the invariant enforced by {nameof(End)} method - Duration should have value when {nameof(End)} method exits" +
                                          $" and {nameof(_isEnded)} field is set to true only when {nameof(End)} method exits." +
                                          $" Context: this: {this}; {nameof(_isEnded)}: {_isEnded}");

                var endTimestamp = TimeUtils.TimestampNow();
                Duration = TimeUtils.DurationBetweenTimestamps(Timestamp, endTimestamp);
                _logger.Trace()
                ?.Log("Ended {Span}. Start time: {Time} (as timestamp: {Timestamp})," +
                      " End time: {Time} (as timestamp: {Timestamp}), Duration: {Duration}ms",
                      this, TimeUtils.FormatTimestampForLog(Timestamp), Timestamp,
                      TimeUtils.FormatTimestampForLog(endTimestamp), endTimestamp, Duration);
            }

            var isFirstEndCall = !_isEnded;

            _isEnded = true;

            if (ShouldBeSentToApmServer && isFirstEndCall)
            {
                try
                {
                    DeduceDestination();
                }
                catch (Exception e)
                {
                    _logger.Warning()?.LogException(e, "Failed deducing destination fields for span.");
                }

                // Spans are sent only for sampled transactions so it's only worth capturing stack trace for sampled spans
                // ReSharper disable once CompareOfFloatsByEqualityOperator
                if (ConfigSnapshot.StackTraceLimit != 0 && ConfigSnapshot.SpanFramesMinDurationInMilliseconds != 0 && RawStackTrace == null &&
                    (Duration >= ConfigSnapshot.SpanFramesMinDurationInMilliseconds ||
                     ConfigSnapshot.SpanFramesMinDurationInMilliseconds < 0))
                {
                    RawStackTrace = new StackTrace(true);
                }

                _payloadSender.QueueSpan(this);
            }

            if (isFirstEndCall)
            {
                _currentExecutionSegmentsContainer.CurrentSpan = _parentSpan;
            }
        }
Пример #3
0
 public void End()
 {
     _logger.Debug()?.Log("Ending {SpanDetails}", ToString());
     if (!Duration.HasValue)
     {
         Duration = (DateTimeOffset.UtcNow - _start).TotalMilliseconds;
     }
     _payloadSender.QueueSpan(this);
 }
Пример #4
0
        public void End()
        {
            if (Duration.HasValue)
            {
                _logger.Trace()
                ?.Log("Ended {Span} (with Duration already set)." +
                      " Start time: {Time} (as timestamp: {Timestamp}), Duration: {Duration}ms",
                      this, TimeUtils.FormatTimestampForLog(Timestamp), Timestamp, Duration);
            }
            else
            {
                Assertion.IfEnabled?.That(!_isEnded,
                                          $"Span's Duration doesn't have value even though {nameof(End)} method was already called." +
                                          $" It contradicts the invariant enforced by {nameof(End)} method - Duration should have value when {nameof(End)} method exits" +
                                          $" and {nameof(_isEnded)} field is set to true only when {nameof(End)} method exits." +
                                          $" Context: this: {this}; {nameof(_isEnded)}: {_isEnded}");

                var endTimestamp = TimeUtils.TimestampNow();
                Duration = TimeUtils.DurationBetweenTimestamps(Timestamp, endTimestamp);
                _logger.Trace()
                ?.Log("Ended {Span}. Start time: {Time} (as timestamp: {Timestamp})," +
                      " End time: {Time} (as timestamp: {Timestamp}), Duration: {Duration}ms",
                      this, TimeUtils.FormatTimestampForLog(Timestamp), Timestamp,
                      TimeUtils.FormatTimestampForLog(endTimestamp), endTimestamp, Duration);
            }

            var isFirstEndCall = !_isEnded;

            _isEnded = true;

            if (!IsSampled || !isFirstEndCall)
            {
                return;
            }

            // Spans are sent only for sampled transactions so it's only worth capturing stack trace for sampled spans
            // ReSharper disable once CompareOfFloatsByEqualityOperator
            if (_configurationReader.StackTraceLimit != 0 && _configurationReader.SpanFramesMinDurationInMilliseconds != 0)
            {
                if (Duration >= _configurationReader.SpanFramesMinDurationInMilliseconds ||
                    _configurationReader.SpanFramesMinDurationInMilliseconds < 0)
                {
                    StackTrace = StacktraceHelper.GenerateApmStackTrace(new StackTrace(true).GetFrames(), _logger,
                                                                        _configurationReader, $"Span `{Name}'");
                }
            }

            _payloadSender.QueueSpan(this);

            _currentExecutionSegmentsContainer.CurrentSpan = _parentSpan;
        }