(target, thisArg, args: Parameters<Span['end']>)
| 140 | // eslint-disable-next-line @typescript-eslint/unbound-method |
| 141 | span.end = new Proxy(span.end, { |
| 142 | apply(target, thisArg, args: Parameters<Span['end']>) { |
| 143 | if (beforeSpanEnd) { |
| 144 | beforeSpanEnd(span); |
| 145 | } |
| 146 | |
| 147 | // If the span is non-recording, nothing more to do here... |
| 148 | // This is the case if tracing is enabled but this specific span was not sampled |
| 149 | if (spanIsNonRecordingSpan(thisArg)) { |
| 150 | return; |
| 151 | } |
| 152 | |
| 153 | // Just ensuring that this keeps working, even if we ever have more arguments here |
| 154 | const [definedEndTimestamp, ...rest] = args; |
| 155 | const timestamp = definedEndTimestamp || timestampInSeconds(); |
| 156 | const spanEndTimestamp = spanTimeInputToSeconds(timestamp); |
| 157 | |
| 158 | // Ensure we end with the last span timestamp, if possible |
| 159 | const spans = getSpanDescendants(span).filter(child => child !== span); |
| 160 | |
| 161 | const spanJson = spanToJSON(span); |
| 162 | |
| 163 | // If we have no spans, we just end, nothing else to do here |
| 164 | // Likewise, if users explicitly ended the span, we simply end the span without timestamp adjustment |
| 165 | if (!spans.length || !trimIdleSpanEndTimestamp) { |
| 166 | onIdleSpanEnded(spanEndTimestamp); |
| 167 | return Reflect.apply(target, thisArg, [spanEndTimestamp, ...rest]); |
| 168 | } |
| 169 | |
| 170 | const ignoreSpans = client.getOptions().ignoreSpans; |
| 171 | |
| 172 | const latestSpanEndTimestamp = spans?.reduce((acc: number | undefined, current) => { |
| 173 | const currentSpanJson = spanToJSON(current); |
| 174 | if (!currentSpanJson.timestamp) { |
| 175 | return acc; |
| 176 | } |
| 177 | // Ignored spans will get dropped later (in the client) but since we already adjust |
| 178 | // the idle span end timestamp here, we can already take to-be-ignored spans out of |
| 179 | // the calculation here. |
| 180 | if ( |
| 181 | ignoreSpans && |
| 182 | shouldIgnoreSpan( |
| 183 | { description: currentSpanJson.description, op: currentSpanJson.op, attributes: currentSpanJson.data }, |
| 184 | ignoreSpans, |
| 185 | ) |
| 186 | ) { |
| 187 | return acc; |
| 188 | } |
| 189 | return acc ? Math.max(acc, currentSpanJson.timestamp) : currentSpanJson.timestamp; |
| 190 | }, undefined); |
| 191 | |
| 192 | // In reality this should always exist here, but type-wise it may be undefined... |
| 193 | const spanStartTimestamp = spanJson.start_timestamp; |
| 194 | |
| 195 | // The final endTimestamp should: |
| 196 | // * Never be before the span start timestamp |
| 197 | // * Be the latestSpanEndTimestamp, if there is one, and it is smaller than the passed span end timestamp |
| 198 | // * Otherwise be the passed end timestamp |
| 199 | // Final timestamp can never be after finalTimeout |
nothing calls this directly
no test coverage detected