mirror of
https://github.com/elastic/logstash.git
synced 2025-04-23 22:27:21 -04:00
Fix bug where hot threads did not work with duplicate names / add thread_id
The hot threads endpoint used to require thread names to be unique in a map and would crash otherwise. This patch fixes this by internally using a List instead of a Map to store these thread ids. Additionally, this patch adds the `thread_id` to the response to allow for disambiguation of of threads for any client applications. Fixes https://github.com/elastic/logstash/issues/7608 Fixes #7617
This commit is contained in:
parent
bff61d59fe
commit
1811283250
5 changed files with 23 additions and 11 deletions
|
@ -17,7 +17,12 @@ class HotThreadsReport
|
|||
report << '=' * STRING_SEPARATOR_LENGTH
|
||||
report << "\n"
|
||||
hash[:threads].each do |thread|
|
||||
thread_report = "#{I18n.t("logstash.web_api.hot_threads.thread_title", :percent_of_cpu_time => thread[:percent_of_cpu_time], :thread_state => thread[:state], :thread_name => thread[:name])} \n"
|
||||
line_str = I18n.t("logstash.web_api.hot_threads.thread_title",
|
||||
:percent_of_cpu_time => thread[:percent_of_cpu_time],
|
||||
:thread_state => thread[:state],
|
||||
:thread_name => thread[:name],
|
||||
:thread_id => thread[:thread_id])
|
||||
thread_report = "#{line_str} \n"
|
||||
thread_report << "#{thread[:path]}\n" if thread[:path]
|
||||
thread[:traces].each do |trace|
|
||||
thread_report << "\t#{trace}\n"
|
||||
|
@ -31,9 +36,10 @@ class HotThreadsReport
|
|||
|
||||
def to_hash
|
||||
hash = { :time => Time.now.iso8601, :busiest_threads => @thread_dump.top_count, :threads => [] }
|
||||
@thread_dump.each do |thread_name, _hash|
|
||||
@thread_dump.each do |_hash|
|
||||
thread_name, thread_path = _hash["thread.name"].split(": ")
|
||||
thread = { :name => thread_name,
|
||||
:thread_id => _hash["thread.id"],
|
||||
:percent_of_cpu_time => cpu_time_as_percent(_hash),
|
||||
:state => _hash["thread.state"]
|
||||
}
|
||||
|
|
|
@ -19,12 +19,13 @@ module LogStash
|
|||
|
||||
def each(&block)
|
||||
i=0
|
||||
dump.each_pair do |thread_name, _hash|
|
||||
dump.each do |hash|
|
||||
thread_name = hash["thread.name"]
|
||||
break if i >= top_count
|
||||
if ignore
|
||||
next if idle_thread?(thread_name, _hash)
|
||||
next if idle_thread?(thread_name, hash)
|
||||
end
|
||||
block.call(thread_name, _hash)
|
||||
block.call(hash)
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
|
|
@ -81,7 +81,7 @@ en:
|
|||
::: {%{hostname}}
|
||||
Hot threads at %{time}, busiestThreads=%{top_count}:
|
||||
thread_title: |-
|
||||
%{percent_of_cpu_time} % of cpu usage, state: %{thread_state}, thread name: '%{thread_name}'
|
||||
%{percent_of_cpu_time} % of cpu usage, state: %{thread_state}, thread name: '%{thread_name}', thread id: %{thread_id}
|
||||
logging:
|
||||
unrecognized_option: |-
|
||||
unrecognized option [%{option}]
|
||||
|
|
|
@ -43,6 +43,7 @@ public final class HotThreadsMonitor {
|
|||
private static final String THREAD_NAME = "thread.name";
|
||||
private static final String THREAD_STATE = "thread.state";
|
||||
private static final String THREAD_STACKTRACE = "thread.stacktrace";
|
||||
private static final String THREAD_ID = "thread.id";
|
||||
|
||||
private Map<String, Object> map = new HashMap<>();
|
||||
|
||||
|
@ -53,6 +54,7 @@ public final class HotThreadsMonitor {
|
|||
map.put(WAITED_COUNT, info.getWaitedCount());
|
||||
map.put(WAITED_TIME, info.getWaitedTime());
|
||||
map.put(THREAD_NAME, info.getThreadName());
|
||||
map.put(THREAD_ID, info.getThreadId());
|
||||
map.put(THREAD_STATE, info.getThreadState().name().toLowerCase());
|
||||
map.put(THREAD_STACKTRACE, stackTraceAsString(info.getStackTrace()));
|
||||
}
|
||||
|
@ -71,6 +73,10 @@ public final class HotThreadsMonitor {
|
|||
return (String) map.get(THREAD_NAME);
|
||||
}
|
||||
|
||||
public long getThreadId() {
|
||||
return (long) map.get(THREAD_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
|
|
@ -21,13 +21,12 @@ public class ThreadsReport {
|
|||
* stacktrace_size - max depth of stack trace
|
||||
* @return A Map containing hot threads information
|
||||
*/
|
||||
public static Map<String, Object> generate(Map<String, String> options) {
|
||||
public static List<Map<String, Object>> generate(Map<String, String> options) {
|
||||
List<HotThreadsMonitor.ThreadReport> reports = HotThreadsMonitor.detect(options);
|
||||
return reports
|
||||
.stream()
|
||||
.collect(Collectors
|
||||
.toMap(HotThreadsMonitor.ThreadReport::getThreadName,
|
||||
HotThreadsMonitor.ThreadReport::toMap));
|
||||
.map(HotThreadsMonitor.ThreadReport::toMap)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,7 +34,7 @@ public class ThreadsReport {
|
|||
* Generate a report with current Thread information
|
||||
* @return A Map containing the hot threads information
|
||||
*/
|
||||
public static Map<String, Object> generate() {
|
||||
public static List<Map<String, Object>> generate() {
|
||||
Map<String, String> options = new HashMap<>();
|
||||
options.put("order_by", "cpu");
|
||||
return generate(options);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue