| 248 | } |
| 249 | |
| 250 | void ThreadMgr::ThreadGroupUrlCallback(const Webserver::WebRequest& req, |
| 251 | Document* document) { |
| 252 | lock_guard<mutex> l(lock_); |
| 253 | vector<const ThreadCategory*> categories_to_print; |
| 254 | const auto& args = req.parsed_args; |
| 255 | Webserver::ArgumentMap::const_iterator category_it = args.find("group"); |
| 256 | string category_name = (category_it == args.end()) ? "all" : category_it->second; |
| 257 | if (category_name != "all") { |
| 258 | ThreadCategoryMap::const_iterator category = |
| 259 | thread_categories_.find(category_name); |
| 260 | if (category == thread_categories_.end()) { |
| 261 | return; |
| 262 | } |
| 263 | categories_to_print.push_back(&category->second); |
| 264 | Value val(kObjectType); |
| 265 | Value name(category->first.c_str(), document->GetAllocator()); |
| 266 | val.AddMember("category", name, document->GetAllocator()); |
| 267 | val.AddMember("size", static_cast<uint64_t>(category->second.threads_by_id.size()), |
| 268 | document->GetAllocator()); |
| 269 | document->AddMember("thread-group", val, document->GetAllocator()); |
| 270 | } else { |
| 271 | for (const ThreadCategoryMap::value_type& category: thread_categories_) { |
| 272 | categories_to_print.push_back(&category.second); |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | Value lst(kArrayType); |
| 277 | for (const ThreadCategory* category: categories_to_print) { |
| 278 | for (const auto& thread : category->threads_by_id) { |
| 279 | Value val(kObjectType); |
| 280 | Value name(thread.second.name().c_str(), document->GetAllocator()); |
| 281 | val.AddMember("name", name, document->GetAllocator()); |
| 282 | val.AddMember("id", thread.second.thread_id(), document->GetAllocator()); |
| 283 | ThreadStats stats; |
| 284 | Status status = GetThreadStats(thread.second.thread_id(), &stats); |
| 285 | if (!status.ok()) { |
| 286 | LOG_EVERY_N(INFO, 100) << "Could not get per-thread statistics: " |
| 287 | << status.GetDetail(); |
| 288 | } else { |
| 289 | val.AddMember("user_s", static_cast<double>(stats.user_ns) / 1e9, |
| 290 | document->GetAllocator()); |
| 291 | val.AddMember("kernel_s", static_cast<double>(stats.kernel_ns) / 1e9, |
| 292 | document->GetAllocator()); |
| 293 | val.AddMember("iowait_s", static_cast<double>(stats.iowait_ns) / 1e9, |
| 294 | document->GetAllocator()); |
| 295 | } |
| 296 | lst.PushBack(val, document->GetAllocator()); |
| 297 | } |
| 298 | } |
| 299 | document->AddMember("threads", lst, document->GetAllocator()); |
| 300 | } |
| 301 | |
| 302 | bool ThreadMgr::GetThreadNameByTid(int64_t tid, string* name) { |
| 303 | DCHECK(name != nullptr); |
no test coverage detected