| 144 | } |
| 145 | |
| 146 | void MethodSampler::SampleCall(InboundCall* call) { |
| 147 | // First determine which sample bucket to put this in. |
| 148 | int duration_ms = call->timing().TotalDuration().ToMilliseconds(); |
| 149 | |
| 150 | SampleBucket* bucket = &buckets_[kNumBuckets - 1]; |
| 151 | for (int i = 0 ; i < kNumBuckets - 1; i++) { |
| 152 | if (duration_ms < kBucketThresholdsMs[i]) { |
| 153 | bucket = &buckets_[i]; |
| 154 | break; |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | MicrosecondsInt64 now = GetMonoTimeMicros(); |
| 159 | int64_t us_since_trace = now - bucket->last_sample_time.Load(); |
| 160 | if (us_since_trace > kSampleIntervalMs * 1000) { |
| 161 | Sample new_sample = {call->header(), call->trace(), duration_ms}; |
| 162 | { |
| 163 | std::unique_lock<simple_spinlock> lock(bucket->sample_lock, std::try_to_lock); |
| 164 | // If another thread is already taking a sample, it's not worth waiting. |
| 165 | if (!lock.owns_lock()) { |
| 166 | return; |
| 167 | } |
| 168 | std::swap(bucket->sample, new_sample); |
| 169 | bucket->last_sample_time.Store(now); |
| 170 | } |
| 171 | VLOG(2) << "Sampled call " << call->ToString(); |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | void MethodSampler::GetTraceMetrics(const Trace& t, |
| 176 | const string& child_path, |
no test coverage detected