| 184 | } |
| 185 | |
| 186 | void JeControlProfile(Controller* cntl) { |
| 187 | const brpc::URI& uri = cntl->http_request().uri(); |
| 188 | // http:ip:port/pprof/heap?display=(text|svg|stats|flamegraph)&extra_options=(inuse_space|inuse_objects..) |
| 189 | const std::string* uri_display = uri.GetQuery("display"); |
| 190 | |
| 191 | butil::IOBuf& buf = cntl->response_attachment(); |
| 192 | cntl->http_response().set_content_type("text/plain"); |
| 193 | |
| 194 | // support ip:port/pprof/heap?display=stats |
| 195 | if (uri_display != nullptr && *uri_display == "stats") { |
| 196 | const std::string* uri_opts = uri.GetQuery("opts"); |
| 197 | std::string opts = !uri_opts || uri_opts->empty() ? "Ja" : *uri_opts; |
| 198 | buf.append(StatsPrint(opts)); |
| 199 | return; |
| 200 | } |
| 201 | |
| 202 | if (!HasEnableJemallocProfile()) { |
| 203 | cntl->SetFailed(ENOMETHOD, "Heap profiler is not enabled, (no MALLOC_CONF=prof:true in env)"); |
| 204 | return; |
| 205 | } |
| 206 | |
| 207 | // only dump profile |
| 208 | const std::string prof_name = JeProfileDump(); |
| 209 | if (prof_name.empty()) { |
| 210 | cntl->SetFailed(-1, "Fail to dump profile"); |
| 211 | buf.append("\nFail to dump profile"); |
| 212 | return; |
| 213 | } |
| 214 | |
| 215 | // support jeprof ip:port/pprof/heap |
| 216 | if (uri_display == nullptr || uri_display->empty()) { |
| 217 | std::string content; |
| 218 | if (!butil::ReadFileToString(butil::FilePath(prof_name), &content)) { |
| 219 | LOG(WARNING) << "read " << prof_name << " fail"; |
| 220 | return; |
| 221 | } |
| 222 | buf.append(content); |
| 223 | return; |
| 224 | } |
| 225 | |
| 226 | // support curl/browser |
| 227 | buf.append(prof_name); |
| 228 | |
| 229 | std::string jeprof; |
| 230 | const char* f_jeprof = std::getenv("JEPROF_FILE"); |
| 231 | if (f_jeprof != nullptr && butil::PathExists(butil::FilePath(f_jeprof))) { |
| 232 | jeprof = f_jeprof; |
| 233 | } else { |
| 234 | LOG(WARNING) << "env JEPROF_FILE invalid"; |
| 235 | buf.append("\nenv JEPROF_FILE invalid"); |
| 236 | jeprof = "jeprof "; // use PATH |
| 237 | } |
| 238 | |
| 239 | char process_path[500] = {}; |
| 240 | ssize_t len = butil::GetProcessAbsolutePath(process_path, sizeof(process_path)); |
| 241 | if (len == -1) { |
| 242 | LOG(WARNING) << "GetProcessAbsolutePath of process err"; |
| 243 | buf.append("\nGetProcessAbsolutePath of process err"); |
no test coverage detected