1
1
package fr .adrienbrault .idea .symfony2plugin .profiler ;
2
2
3
+ import com .google .common .cache .Cache ;
4
+ import com .google .common .cache .CacheBuilder ;
3
5
import com .intellij .lang .html .HTMLLanguage ;
6
+ import com .intellij .openapi .application .ApplicationManager ;
4
7
import com .intellij .openapi .project .Project ;
5
- import com .intellij .openapi .util .Condition ;
6
8
import com .intellij .psi .PsiElement ;
7
9
import com .intellij .psi .PsiFileFactory ;
8
10
import com .intellij .psi .impl .source .html .HtmlFileImpl ;
9
- import com .intellij .psi .search .PsiElementProcessor ;
10
- import com .intellij .psi .util .PsiElementFilter ;
11
11
import com .intellij .psi .util .PsiTreeUtil ;
12
12
import com .intellij .psi .xml .XmlTag ;
13
13
import com .intellij .psi .xml .XmlTagValue ;
14
- import com .intellij .util .containers .ContainerUtil ;
15
14
import fr .adrienbrault .idea .symfony2plugin .Symfony2ProjectComponent ;
16
- import fr .adrienbrault .idea .symfony2plugin .profiler .dict .ProfilerRequest ;
15
+ import fr .adrienbrault .idea .symfony2plugin .profiler .dict .HttpCollectorProfilerRequest ;
16
+ import fr .adrienbrault .idea .symfony2plugin .profiler .dict .HttpDefaultDataCollector ;
17
+ import fr .adrienbrault .idea .symfony2plugin .profiler .dict .HttpProfilerRequest ;
18
+ import fr .adrienbrault .idea .symfony2plugin .profiler .dict .ProfilerRequestInterface ;
17
19
import org .apache .commons .lang .ArrayUtils ;
18
20
import org .apache .commons .lang .StringUtils ;
19
21
import org .jetbrains .annotations .NotNull ;
26
28
import java .net .URLConnection ;
27
29
import java .nio .charset .StandardCharsets ;
28
30
import java .util .*;
31
+ import java .util .concurrent .*;
29
32
import java .util .stream .Collectors ;
30
33
31
34
public class ProfilerUtil {
32
35
36
+ /**
37
+ * Cache for url content
38
+ */
39
+ private static Cache <String , String > REQUEST_CACHE = CacheBuilder .newBuilder ()
40
+ .maximumSize (50 )
41
+ .expireAfterWrite (5 , TimeUnit .MINUTES )
42
+ .build ();
43
+
33
44
@ Nullable
34
45
public static File findProfilerCsv (Project project ) {
35
46
@@ -50,7 +61,7 @@ public static File findProfilerCsv(Project project) {
50
61
public static String getProfilerIndexViaHttp (@ NotNull String url ) {
51
62
URLConnection conn ;
52
63
try {
53
- conn = new URL ("http://127.0.0.1:8000/_profiler/empty/search/results?ip=& limit=10" ).openConnection ();
64
+ conn = new URL (url + "? limit=10" ).openConnection ();
54
65
} catch (IOException e ) {
55
66
return null ;
56
67
}
@@ -67,7 +78,7 @@ public static String getProfilerIndexViaHttp(@NotNull String url) {
67
78
* We dont have complete xpath with html support inside so reuse internal html parser
68
79
*/
69
80
@ NotNull
70
- public static Collection <ProfilerRequest > createRequestsFromIndexHtml (@ NotNull Project project , @ NotNull String html ) {
81
+ public static Collection <ProfilerRequestInterface > createRequestsFromIndexHtml (@ NotNull Project project , @ NotNull String html ) {
71
82
HtmlFileImpl htmlFile = (HtmlFileImpl ) PsiFileFactory .getInstance (project ).createFileFromText (HTMLLanguage .INSTANCE , html );
72
83
73
84
PsiElement [] results = PsiTreeUtil .collectElements (htmlFile , psiElement ->
@@ -83,7 +94,7 @@ public static Collection<ProfilerRequest> createRequestsFromIndexHtml(@NotNull P
83
94
return Collections .emptyList ();
84
95
}
85
96
86
- Collection <ProfilerRequest > requests = new ArrayList <>();
97
+ Collection <ProfilerRequestInterface > requests = new ArrayList <>();
87
98
for (XmlTag tr : tbody .findSubTags ("tr" )) {
88
99
List <String > values = new ArrayList <>();
89
100
for (XmlTag td : tr .findSubTags ("td" )) {
@@ -95,13 +106,42 @@ public static Collection<ProfilerRequest> createRequestsFromIndexHtml(@NotNull P
95
106
}
96
107
97
108
requests .add (
98
- new ProfilerRequest ( new String [] { values .get (5 ), "" , values .get (2 ), values .get (3 ), values .get (4 )}, new ProfilerIndex ( new File ( "aa" ) ))
109
+ new HttpProfilerRequest ( project , values .get (5 ), null , values .get (2 ), values .get (3 ), values .get (4 ))
99
110
);
100
111
}
101
112
102
113
return requests ;
103
114
}
104
115
116
+ @ NotNull
117
+ public static Collection <ProfilerRequestInterface > collectHttpDataForRequest (@ NotNull Project project , @ NotNull Collection <ProfilerRequestInterface > requests ) {
118
+ ExecutorService executor = Executors .newFixedThreadPool (10 );
119
+
120
+ Collection <ProfilerRequestInterface > requestsDecorated = new ArrayList <>();
121
+
122
+ Collection <Callable <ProfilerRequestInterface >> callable = requests .stream ().map (
123
+ request -> new MyProfilerRequestDecoratedCollectorCallable (project , request )).collect (Collectors .toCollection (ArrayList ::new )
124
+ );
125
+
126
+ List <Future <ProfilerRequestInterface >> futures ;
127
+ try {
128
+ futures = executor .invokeAll (callable );
129
+ } catch (InterruptedException e ) {
130
+ return requests ;
131
+ }
132
+
133
+ for (Future <ProfilerRequestInterface > future : futures ) {
134
+ try {
135
+ requestsDecorated .add (future .get ());
136
+ } catch (ExecutionException | InterruptedException ignored ) {
137
+ }
138
+ }
139
+
140
+ executor .shutdown ();
141
+
142
+ return requestsDecorated ;
143
+ }
144
+
105
145
/**
106
146
* "_controller" and "_route"
107
147
* "/_profiler/242e61?panel=request"
@@ -227,4 +267,56 @@ private static String stripHtmlTags(@NotNull String text)
227
267
{
228
268
return text .replaceAll ("<[^>]*>" , "" );
229
269
}
270
+
271
+ @ Nullable
272
+ public static String getProfilerUrlContent (@ NotNull String url ) {
273
+ System .out .println (url );
274
+ URLConnection conn ;
275
+ try {
276
+ conn = new URL (url ).openConnection ();
277
+ } catch (IOException e ) {
278
+ e .printStackTrace ();
279
+ return null ;
280
+ }
281
+
282
+ try {
283
+ try (BufferedReader reader = new BufferedReader (new InputStreamReader (conn .getInputStream (), StandardCharsets .UTF_8 ))) {
284
+ return reader .lines ().collect (Collectors .joining ("\n " ));
285
+ }
286
+ } catch (IOException e ) {
287
+ e .printStackTrace ();
288
+ return null ;
289
+ }
290
+ }
291
+
292
+ private static class MyProfilerRequestDecoratedCollectorCallable implements Callable <ProfilerRequestInterface > {
293
+ private final Project project ;
294
+ private final ProfilerRequestInterface request ;
295
+
296
+ MyProfilerRequestDecoratedCollectorCallable (@ NotNull Project project , @ NotNull ProfilerRequestInterface request ) {
297
+ this .project = project ;
298
+ this .request = request ;
299
+ }
300
+
301
+ @ Override
302
+ public ProfilerRequestInterface call () throws Exception {
303
+ Map <String , String > requestAttributes = new HashMap <>();
304
+ String url = "http://127.0.0.1:8000/_profiler/" + request .getHash () + "?panel=request" ;
305
+
306
+ String contents = REQUEST_CACHE .getIfPresent (url );
307
+ if (contents == null ) {
308
+ contents = ProfilerUtil .getProfilerUrlContent (url );
309
+ REQUEST_CACHE .put (url , contents );
310
+ }
311
+
312
+ if (contents != null ) {
313
+ String finalContents = contents ;
314
+ ApplicationManager .getApplication ().runReadAction (() -> {
315
+ requestAttributes .putAll (ProfilerUtil .getRequestAttributes (project , finalContents ));
316
+ });
317
+ }
318
+
319
+ return new HttpCollectorProfilerRequest (request , new HttpDefaultDataCollector (requestAttributes ));
320
+ }
321
+ }
230
322
}
0 commit comments