22using System . Collections . Generic ;
33using System . Threading . Tasks ;
44using Elasticsearch . Net ;
5+ using System . IO ;
6+ using System . Linq ;
57
68namespace Nest
79{
10+ using NodesHotThreadConverter = Func < IElasticsearchResponse , Stream , NodesHotThreadsResponse > ;
11+ using System . Text . RegularExpressions ;
12+ using System . Text ;
13+
814 public partial class ElasticClient
915 {
1016 /// <inheritdoc />
@@ -85,5 +91,86 @@ public Task<INodeStatsResponse> NodesStatsAsync(INodesStatsRequest nodesStatsReq
8591 ( p , d ) => this . RawDispatch . NodesStatsDispatchAsync < NodeStatsResponse > ( p )
8692 ) ;
8793 }
94+
95+ /// <inheritdoc />
96+ public INodesHotThreadsResponse NodesHotThreads ( Func < NodesHotThreadsDescriptor , NodesHotThreadsDescriptor > selector = null )
97+ {
98+ selector = selector ?? ( s => s ) ;
99+ return this . Dispatch < NodesHotThreadsDescriptor , NodesHotThreadsRequestParameters , NodesHotThreadsResponse > (
100+ selector ,
101+ ( p , d ) => this . RawDispatch . NodesHotThreadsDispatch < NodesHotThreadsResponse > (
102+ p . DeserializationState ( new NodesHotThreadConverter ( DeserializeNodesHotThreadResponse ) ) )
103+ ) ;
104+ }
105+
106+ /// <inheritdoc />
107+ public INodesHotThreadsResponse NodesHotThreads ( INodesHotThreadsRequest nodesHotThreadsRequest )
108+ {
109+ return this . Dispatch < INodesHotThreadsRequest , NodesHotThreadsRequestParameters , NodesHotThreadsResponse > (
110+ nodesHotThreadsRequest ,
111+ ( p , d ) => this . RawDispatch . NodesHotThreadsDispatch < NodesHotThreadsResponse > (
112+ p . DeserializationState ( new NodesHotThreadConverter ( DeserializeNodesHotThreadResponse ) ) )
113+ ) ;
114+ }
115+
116+ /// <inheritdoc />
117+ public Task < INodesHotThreadsResponse > NodesHotThreadsAsync ( Func < NodesHotThreadsDescriptor , NodesHotThreadsDescriptor > selector = null )
118+ {
119+ selector = selector ?? ( s => s ) ;
120+ return this . DispatchAsync < NodesHotThreadsDescriptor , NodesHotThreadsRequestParameters , NodesHotThreadsResponse , INodesHotThreadsResponse > (
121+ selector ,
122+ ( p , d ) => this . RawDispatch . NodesHotThreadsDispatchAsync < NodesHotThreadsResponse > (
123+ p . DeserializationState ( new NodesHotThreadConverter ( DeserializeNodesHotThreadResponse ) ) )
124+ ) ;
125+ }
126+
127+ /// <inheritdoc />
128+ public Task < INodesHotThreadsResponse > NodesHotThreadsAsync ( INodesHotThreadsRequest nodesHotThreadsRequest )
129+ {
130+ return this . DispatchAsync < INodesHotThreadsRequest , NodesHotThreadsRequestParameters , NodesHotThreadsResponse , INodesHotThreadsResponse > (
131+ nodesHotThreadsRequest ,
132+ ( p , d ) => this . RawDispatch . NodesHotThreadsDispatchAsync < NodesHotThreadsResponse > (
133+ p . DeserializationState ( new NodesHotThreadConverter ( DeserializeNodesHotThreadResponse ) ) )
134+ ) ;
135+ }
136+
137+ /// <summary>
138+ /// Because the nodes.hot_threads endpoint returns plain text instead of JSON, we have to
139+ /// manually parse the response text into a typed response object.
140+ /// </summary>
141+ private NodesHotThreadsResponse DeserializeNodesHotThreadResponse ( IElasticsearchResponse response , Stream stream )
142+ {
143+ var typedResponse = new NodesHotThreadsResponse ( ) ;
144+ var plainTextResponse = Encoding . UTF8 . GetString ( response . ResponseRaw ) ;
145+
146+ // If the response doesn't start with :::, which is the pattern that delimits
147+ // each node section in the response, then the response format isn't recognized.
148+ // Just return an empty response object. This is especially useful when unit
149+ // testing against an in-memory connection where you won't get a real response.
150+ if ( ! plainTextResponse . StartsWith ( ":::" ) )
151+ return typedResponse ;
152+
153+ var sections = plainTextResponse . Split ( new string [ ] { ":::" } , StringSplitOptions . RemoveEmptyEntries ) ;
154+
155+ foreach ( var section in sections )
156+ {
157+ var sectionLines = section . Split ( new string [ ] { "\n \n " } , StringSplitOptions . None ) ;
158+
159+ if ( sectionLines . Length > 0 )
160+ {
161+ var hotThreadInfo = new HotThreadInformation
162+ {
163+ // First line contains the node name between [ ]
164+ Node = sectionLines . First ( ) . Split ( '[' ) [ 1 ] . TrimEnd ( ']' ) ,
165+ // The rest of the lines are hot threads
166+ Threads = sectionLines . Skip ( 1 ) . Take ( sectionLines . Length - 1 ) . ToList ( )
167+ } ;
168+
169+ typedResponse . HotThreads . Add ( hotThreadInfo ) ;
170+ }
171+ }
172+
173+ return typedResponse ;
174+ }
88175 }
89176}
0 commit comments