@@ -18,10 +18,10 @@ package kamon
1818package trace
1919
2020import java .time .{Duration , Instant }
21-
2221import kamon .context .Context
2322import kamon .tag .TagSet
2423import kamon .trace .Span .Link
24+ import kamon .trace .Span .Local ._logger
2525import kamon .trace .Trace .SamplingDecision
2626import kamon .util .Clock
2727import org .slf4j .LoggerFactory
@@ -77,6 +77,10 @@ sealed abstract class Span extends Sampler.Operation {
7777 */
7878 def trace : Trace
7979
80+ /**
81+ * Returns true if this Span was finished.
82+ */
83+
8084 /**
8185 * Returns true if this Span was initially created in another process and then transferred to this process.
8286 */
@@ -225,7 +229,7 @@ sealed abstract class Span extends Sampler.Operation {
225229
226230}
227231
228- object Span {
232+ object Span extends Configuration {
229233
230234 /**
231235 * Key used to store and retrieve Span instances from the Context
@@ -417,6 +421,7 @@ object Span {
417421 private var _trackMetrics : Boolean = initialTrackMetrics
418422 private var _trackDelayedSpanMetrics : Boolean = true
419423 private var _isOpen : Boolean = true
424+ private var _debug : Boolean = config().getBoolean(" kamon.trace.debug" )
420425 private var _hasError : Boolean = false
421426 private var _operationName : String = initialOperationName
422427 private var _marks : List [Mark ] = initialMarks
@@ -435,55 +440,81 @@ object Span {
435440 _startedAt = at
436441 _isDelayedStarted = true
437442 mark(MarkKeys .SpanStarted , at)
438- }
443+ } else if (warnOnClosed)
444+ _logger.warn(s " Cannot start finished span with name: ${_operationName}" )
439445 this
440446 }
441447
442448 override def tag (key : String , value : String ): Span = synchronized {
443- if (isSampled && _isOpen)
449+ if (isSampled && _isOpen) {
444450 _spanTags.add(key, value)
451+ } else if (warnOnClosed) {
452+ _logger.warn(s " Cannot apply tag: Tag( ${key}, ${value}) to finished span with name: ${_operationName}" )
453+ }
445454 this
446455 }
447456
448457 override def tag (key : String , value : Long ): Span = synchronized {
449- if (isSampled && _isOpen)
458+ if (isSampled && _isOpen) {
450459 _spanTags.add(key, value)
460+ } else if (warnOnClosed) {
461+ _logger.warn(s " Cannot apply tag: Tag( ${key}, ${value}) to finished span with name: ${_operationName}" )
462+ }
451463 this
452464 }
453465
454466 override def tag (key : String , value : Boolean ): Span = synchronized {
455- if (isSampled && _isOpen)
467+ if (isSampled && _isOpen) {
456468 _spanTags.add(key, value)
469+ } else if (warnOnClosed) {
470+ _logger.warn(s " Cannot apply tag: Tag( ${key}, ${value}) to finished span with name: ${_operationName}" )
471+ }
457472 this
458473 }
459474
460475 override def tag (tags : TagSet ): Span = synchronized {
461- if (isSampled && _isOpen)
476+ if (isSampled && _isOpen) {
462477 _spanTags.add(tags)
478+ } else if (warnOnClosed) {
479+ _logger.warn(s " Cannot apply tags: ${tags} to finished span with name: ${_operationName}" )
480+ }
463481 this
464482 }
465483
466484 override def tagMetrics (key : String , value : String ): Span = synchronized {
467- if (_isOpen && _trackMetrics)
485+ if (_isOpen && _trackMetrics) {
468486 _metricTags.add(key, value)
487+ } else if (warnOnClosed) {
488+ _logger.warn(s " Cannot apply metric: Metric( ${key}, ${value}) to finished span with name: ${_operationName}" )
489+ }
469490 this
470491 }
471492
472493 override def tagMetrics (key : String , value : Long ): Span = synchronized {
473- if (_isOpen && _trackMetrics)
494+ if (_isOpen && _trackMetrics) {
474495 _metricTags.add(key, value)
475- this
496+ } else if (warnOnClosed) {
497+ _logger.warn(s " Cannot apply metric: Metric( ${key}, ${value}) to finished span with name: ${_operationName}" )
498+ }
499+ this
476500 }
477501
478502 override def tagMetrics (key : String , value : Boolean ): Span = synchronized {
479- if (_isOpen && _trackMetrics)
503+ if (_isOpen && _trackMetrics) {
480504 _metricTags.add(key, value)
505+ } else if (warnOnClosed) {
506+ _logger.warn(s " Cannot apply metric: Metric( ${key}, ${value}) to finished span with name: ${_operationName}" )
507+ }
508+
481509 this
482510 }
483511
484512 override def tagMetrics (tags : TagSet ): Span = synchronized {
485- if (_isOpen && _trackMetrics)
513+ if (_isOpen && _trackMetrics) {
486514 _metricTags.add(tags)
515+ } else if (warnOnClosed) {
516+ _logger.warn(s " Cannot apply tag metrics: ${tags} to finished span with name: ${_operationName}" )
517+ }
487518 this
488519 }
489520
@@ -492,14 +523,21 @@ object Span {
492523 }
493524
494525 override def mark (key : String , at : Instant ): Span = synchronized {
495- if (_isOpen)
526+ if (_isOpen) {
496527 _marks = Mark (at, key) :: _marks
528+ } else if (warnOnClosed) {
529+ _logger.warn(s " Cannot apply mark: Mark( ${key}, ${at}) to finished span with name: ${_operationName}" )
530+ }
497531 this
498532 }
499533
500534 override def link (span : Span , kind : Link .Kind ): Span = synchronized {
501- if (_isOpen)
535+ if (_isOpen) {
502536 _links = Link (kind, span.trace, span.id) :: _links
537+ } else if (warnOnClosed) {
538+ _logger.warn(s " Cannot link span ${span.operationName()} to finished span with name: ${_operationName}" )
539+ }
540+
503541 this
504542 }
505543
@@ -509,6 +547,8 @@ object Span {
509547
510548 if (isSampled)
511549 _spanTags.add(TagKeys .ErrorMessage , message)
550+ } else if (warnOnClosed) {
551+ _logger.warn(s " Cannot fail finished span with name: ${_operationName}" )
512552 }
513553 this
514554 }
@@ -523,6 +563,8 @@ object Span {
523563 if (includeErrorStacktrace)
524564 _spanTags.add(TagKeys .ErrorStacktrace , toStackTraceString(throwable))
525565 }
566+ } else if (warnOnClosed) {
567+ _logger.warn(s " Cannot fail finished span with name: ${_operationName}" )
526568 }
527569 this
528570 }
@@ -537,7 +579,10 @@ object Span {
537579 if (includeErrorStacktrace)
538580 _spanTags.add(TagKeys .ErrorStacktrace , toStackTraceString(throwable))
539581 }
582+ } else if (warnOnClosed) {
583+ _logger.warn(s " Cannot fail finished span with name: ${_operationName}" )
540584 }
585+
541586 this
542587 }
543588
@@ -578,8 +623,12 @@ object Span {
578623 }
579624
580625 override def name (operationName : String ): Span = synchronized {
581- if (_isOpen)
626+ if (_isOpen) {
582627 _operationName = operationName
628+ } else if (warnOnClosed) {
629+ _logger.warn(s " Cannot name finished span with name: ${_operationName}" )
630+ }
631+
583632 this
584633 }
585634
@@ -608,7 +657,14 @@ object Span {
608657 val finalMetricTags = createMetricTags()
609658 recordSpanMetrics(finishedAt, finalMetricTags)
610659 reportSpan(finishedAt, finalMetricTags)
660+ } else if (warnOnClosed) {
661+ _logger.warn(s " Cannot finish already finished span with name: ${_operationName}" )
611662 }
663+
664+ }
665+
666+ private def warnOnClosed = {
667+ _debug && ! _isOpen
612668 }
613669
614670 private def isSampled : Boolean =
@@ -667,7 +723,6 @@ object Span {
667723 object Local {
668724 private val _logger = LoggerFactory .getLogger(classOf [Span .Local ])
669725 }
670-
671726 /**
672727 * A immutable, no-op Span that can be used to signal that there is no Span information. An empty Span completely
673728 * ignores all writes made to it.
@@ -680,29 +735,38 @@ object Span {
680735 override def isRemote : Boolean = false
681736 override def isEmpty : Boolean = true
682737 override def position (): Position = Position .Unknown
683- override def tag (key : String , value : String ): Span = this
684- override def tag (key : String , value : Long ): Span = this
685- override def tag (key : String , value : Boolean ): Span = this
686- override def tag (tagSet : TagSet ): Span = this
687- override def tagMetrics (key : String , value : String ): Span = this
688- override def tagMetrics (key : String , value : Long ): Span = this
689- override def tagMetrics (key : String , value : Boolean ): Span = this
690- override def tagMetrics (tagSet : TagSet ): Span = this
691- override def mark (key : String ): Span = this
692- override def mark (key : String , at : Instant ): Span = this
693- override def link (span : Span , kind : Link .Kind ): Span = this
694- override def fail (errorMessage : String ): Span = this
695- override def fail (cause : Throwable ): Span = this
696- override def fail (errorMessage : String , cause : Throwable ): Span = this
697- override def name (name : String ): Span = this
738+ override def tag (key : String , value : String ): Span = warnAndDiscard()
739+ override def tag (key : String , value : Long ): Span = warnAndDiscard()
740+ override def tag (key : String , value : Boolean ): Span = warnAndDiscard()
741+ override def tag (tagSet : TagSet ): Span = warnAndDiscard()
742+ override def tagMetrics (key : String , value : String ): Span = warnAndDiscard()
743+ override def tagMetrics (key : String , value : Long ): Span = warnAndDiscard()
744+ override def tagMetrics (key : String , value : Boolean ): Span = warnAndDiscard()
745+ override def tagMetrics (tagSet : TagSet ): Span = warnAndDiscard()
746+ override def mark (key : String ): Span = warnAndDiscard()
747+ override def mark (key : String , at : Instant ): Span = warnAndDiscard()
748+ override def link (span : Span , kind : Link .Kind ): Span = warnAndDiscard()
749+ override def fail (errorMessage : String ): Span = warnAndDiscard()
750+ override def fail (cause : Throwable ): Span = warnAndDiscard()
751+ override def fail (errorMessage : String , cause : Throwable ): Span = warnAndDiscard()
752+ override def name (name : String ): Span = warnAndDiscard()
698753 override def trackMetrics (): Span = this
699754 override def doNotTrackMetrics (): Span = this
700755 override def takeSamplingDecision (): Span = this
701- override def finish (): Unit = {}
702- override def finish (at : Instant ): Unit = {}
703- override def finishAfter (duration : Duration ): Unit = {}
756+ override def finish (): Unit = { warnAndDiscard(); {} }
757+ override def finish (at : Instant ): Unit = { warnAndDiscard(); {} }
758+ override def finishAfter (duration : Duration ): Unit = { warnAndDiscard(); {} }
704759 override def operationName (): String = " empty"
705760 override def toString (): String = " Span.Empty"
761+
762+ private val _logger = LoggerFactory .getLogger(classOf [Span ])
763+ private def _debug : Boolean = config().getBoolean(" kamon.trace.debug" )
764+ private def warnAndDiscard (): Span = {
765+ if (_debug) {
766+ _logger.debug(" Cannot perform operations on Empty spans." )
767+ }
768+ this
769+ }
706770 }
707771
708772
@@ -716,29 +780,38 @@ object Span {
716780 override def isRemote : Boolean = true
717781 override def isEmpty : Boolean = false
718782 override def position (): Position = Position .Unknown
719- override def tag (key : String , value : String ): Span = this
720- override def tag (key : String , value : Long ): Span = this
721- override def tag (key : String , value : Boolean ): Span = this
722- override def tag (tagSet : TagSet ): Span = this
723- override def tagMetrics (key : String , value : String ): Span = this
724- override def tagMetrics (key : String , value : Long ): Span = this
725- override def tagMetrics (key : String , value : Boolean ): Span = this
726- override def tagMetrics (tagSet : TagSet ): Span = this
727- override def mark (key : String ): Span = this
728- override def mark (key : String , at : Instant ): Span = this
729- override def link (span : Span , kind : Link .Kind ): Span = this
730- override def fail (errorMessage : String ): Span = this
731- override def fail (cause : Throwable ): Span = this
732- override def fail (errorMessage : String , cause : Throwable ): Span = this
733- override def name (name : String ): Span = this
783+ override def tag (key : String , value : String ): Span = warnAndDiscard()
784+ override def tag (key : String , value : Long ): Span = warnAndDiscard()
785+ override def tag (key : String , value : Boolean ): Span = warnAndDiscard()
786+ override def tag (tagSet : TagSet ): Span = warnAndDiscard()
787+ override def tagMetrics (key : String , value : String ): Span = warnAndDiscard()
788+ override def tagMetrics (key : String , value : Long ): Span = warnAndDiscard()
789+ override def tagMetrics (key : String , value : Boolean ): Span = warnAndDiscard()
790+ override def tagMetrics (tagSet : TagSet ): Span = warnAndDiscard()
791+ override def mark (key : String ): Span = warnAndDiscard()
792+ override def mark (key : String , at : Instant ): Span = warnAndDiscard()
793+ override def link (span : Span , kind : Link .Kind ): Span = warnAndDiscard()
794+ override def fail (errorMessage : String ): Span = warnAndDiscard()
795+ override def fail (cause : Throwable ): Span = warnAndDiscard()
796+ override def fail (errorMessage : String , cause : Throwable ): Span = warnAndDiscard()
797+ override def name (name : String ): Span = warnAndDiscard()
734798 override def trackMetrics (): Span = this
735799 override def doNotTrackMetrics (): Span = this
736800 override def takeSamplingDecision (): Span = this
737- override def finish (): Unit = {}
738- override def finish (at : Instant ): Unit = {}
739- override def finishAfter (duration : Duration ): Unit = {}
801+ override def finish (): Unit = { warnAndDiscard(); {} }
802+ override def finish (at : Instant ): Unit = { warnAndDiscard(); {} }
803+ override def finishAfter (duration : Duration ): Unit = { warnAndDiscard(); {} }
740804 override def operationName (): String = " empty"
741805 override def toString (): String = s " Span.Remote{id= ${id.string},parentId= ${parentId.string},trace= ${trace}"
806+
807+ private val _logger = LoggerFactory .getLogger(classOf [Span .Remote ])
808+ private def _debug : Boolean = config().getBoolean(" kamon.trace.debug" )
809+ private def warnAndDiscard (): Span = {
810+ if (_debug) {
811+ _logger.debug(" Cannot perform operations on Remote spans." )
812+ }
813+ this
814+ }
742815 }
743816
744817
0 commit comments