Skip to content

Commit d59efe0

Browse files
committed
profiler should support http urls as data source #798
refactor profiler to support http with html crawling in additional to local filesystem #798 also resolves debug urls #540, #522
1 parent 096a433 commit d59efe0

40 files changed

+2434
-481
lines changed

META-INF/plugin.xml

+7
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,13 @@
285285
nonDefaultProject="true"
286286
/>
287287

288+
<projectConfigurable instance="fr.adrienbrault.idea.symfony2plugin.profiler.ui.ProfilerSettingsDialog"
289+
displayName="Profiler"
290+
parentId="Symfony2.SettingsForm"
291+
id="Symfony.ProfilerSettingsForm"
292+
nonDefaultProject="true"
293+
/>
294+
288295
<php.typeProvider2 implementation="fr.adrienbrault.idea.symfony2plugin.dic.SymfonyContainerTypeProvider"/>
289296
<php.typeProvider2 implementation="fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectRepositoryTypeProvider"/>
290297
<php.typeProvider2 implementation="fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectRepositoryResultTypeProvider"/>

build-test.xml

+1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
<include name="**/*.json"/>
111111
<include name="**/*.xlf"/>
112112
<include name="**/*.xliff"/>
113+
<include name="**/*.html"/>
113114
</patternset>
114115

115116
<copy toDir="@{dest}">

src/fr/adrienbrault/idea/symfony2plugin/Settings.java

+8
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ public class Settings implements PersistentStateComponent<Settings> {
8888

8989
public boolean dismissEnableNotification = false;
9090

91+
public boolean profilerLocalEnabled = false;
92+
public String profilerLocalUrl = "http://127.0.0.1:8000";
93+
public String profilerCsvPath;
94+
95+
public boolean profilerHttpEnabled = false;
96+
public String profilerHttpUrl = "http://127.0.0.1:8000";
97+
9198
@Nullable
9299
public List<TwigNamespaceSetting> twigNamespaces = new ArrayList<>();
93100

@@ -102,6 +109,7 @@ public class Settings implements PersistentStateComponent<Settings> {
102109

103110
@Nullable
104111
public List<MethodSignatureSetting> methodSignatureSettings = new ArrayList<>();
112+
;
105113

106114
public static Settings getInstance(Project project) {
107115
return ServiceManager.getService(project, Settings.class);

src/fr/adrienbrault/idea/symfony2plugin/Symfony2ProjectComponent.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper;
1919
import fr.adrienbrault.idea.symfony2plugin.util.IdeHelper;
2020
import fr.adrienbrault.idea.symfony2plugin.util.service.ServiceXmlParserFactory;
21-
import fr.adrienbrault.idea.symfony2plugin.widget.SymfonyProfilerWidget;
21+
import fr.adrienbrault.idea.symfony2plugin.profiler.widget.SymfonyProfilerWidget;
2222
import org.jetbrains.annotations.NotNull;
2323
import org.jetbrains.annotations.Nullable;
2424

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package fr.adrienbrault.idea.symfony2plugin.profiler;
2+
3+
import com.intellij.openapi.project.Project;
4+
import fr.adrienbrault.idea.symfony2plugin.profiler.dict.ProfilerRequestInterface;
5+
import fr.adrienbrault.idea.symfony2plugin.profiler.utils.ProfilerUtil;
6+
import org.apache.commons.lang.StringUtils;
7+
import org.jetbrains.annotations.NotNull;
8+
import org.jetbrains.annotations.Nullable;
9+
10+
import java.util.ArrayList;
11+
import java.util.Collections;
12+
import java.util.List;
13+
14+
/**
15+
* @author Daniel Espendiller <daniel@espendiller.net>
16+
*/
17+
public class HttpProfilerIndex implements ProfilerIndexInterface {
18+
/**
19+
* http://127.0.0.1:8080/_profiler
20+
*/
21+
private static String PROFILER_PATH = "_profiler";
22+
23+
@NotNull
24+
private final Project project;
25+
26+
@NotNull
27+
private final String url;
28+
29+
public HttpProfilerIndex(@NotNull Project project, @NotNull String url) {
30+
this.project = project;
31+
this.url = StringUtils.stripEnd(url, "/");
32+
}
33+
34+
@NotNull
35+
@Override
36+
public List<ProfilerRequestInterface> getRequests() {
37+
String content = ProfilerUtil.getProfilerUrlContent(String.format("%s/%s/empty/search/results?ip=&limit=10", this.url, PROFILER_PATH));
38+
if(content == null) {
39+
return Collections.emptyList();
40+
}
41+
42+
return new ArrayList<>(ProfilerUtil.collectHttpDataForRequest(
43+
project, ProfilerUtil.createRequestsFromIndexHtml(this.project, content, this.url))
44+
);
45+
}
46+
47+
@Nullable
48+
@Override
49+
public String getUrlForRequest(@NotNull ProfilerRequestInterface request) {
50+
return this.url + "/" + StringUtils.stripStart(request.getProfilerUrl(), "/");
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package fr.adrienbrault.idea.symfony2plugin.profiler;
2+
3+
import com.intellij.util.containers.ContainerUtil;
4+
import fr.adrienbrault.idea.symfony2plugin.profiler.collector.LocalDefaultDataCollector;
5+
import fr.adrienbrault.idea.symfony2plugin.profiler.collector.LocalMailCollector;
6+
import fr.adrienbrault.idea.symfony2plugin.profiler.dict.LocalProfilerRequest;
7+
import fr.adrienbrault.idea.symfony2plugin.profiler.dict.ProfilerRequestInterface;
8+
import fr.adrienbrault.idea.symfony2plugin.profiler.reader.ReverseFileLineReader;
9+
import fr.adrienbrault.idea.symfony2plugin.profiler.utils.ProfilerUtil;
10+
import org.apache.commons.lang.StringUtils;
11+
import org.jetbrains.annotations.NotNull;
12+
import org.jetbrains.annotations.Nullable;
13+
14+
import java.io.BufferedReader;
15+
import java.io.File;
16+
import java.io.FileReader;
17+
import java.io.IOException;
18+
import java.util.ArrayList;
19+
import java.util.Collection;
20+
import java.util.List;
21+
import java.util.concurrent.Callable;
22+
23+
/**
24+
* @author Daniel Espendiller <daniel@espendiller.net>
25+
*/
26+
public class LocalProfilerIndex implements ProfilerIndexInterface {
27+
@NotNull
28+
private File file;
29+
30+
@Nullable
31+
private String baseUrl;
32+
33+
public LocalProfilerIndex(@NotNull File file) {
34+
this.file = file;
35+
}
36+
37+
public LocalProfilerIndex(@NotNull File file, @Nullable String baseUrl) {
38+
this.file = file;
39+
this.baseUrl = baseUrl;
40+
}
41+
42+
@NotNull
43+
public List<ProfilerRequestInterface> getRequests() {
44+
List<String> lines = new ArrayList<>();
45+
46+
try {
47+
// empty line and end of line need +1
48+
ContainerUtil.addAll(lines, new ReverseFileLineReader(this.file, "UTF-8", 11).readLines());
49+
} catch (IOException ignored) {
50+
}
51+
52+
Collection<Callable<ProfilerRequestInterface>> callable = new ArrayList<>();
53+
54+
// build thread callable collection
55+
lines.stream().filter(StringUtils::isNotBlank).forEachOrdered(line -> {
56+
String[] split = line.split(",");
57+
if (split.length < 6) {
58+
return;
59+
}
60+
61+
callable.add(new MyProfilerRequestBuilderCallable(split));
62+
});
63+
64+
return ProfilerUtil.getProfilerRequestCollectorDecorated(callable, 15);
65+
}
66+
67+
@Nullable
68+
@Override
69+
public String getUrlForRequest(@NotNull ProfilerRequestInterface request) {
70+
if(this.baseUrl != null) {
71+
return this.baseUrl + "/" + StringUtils.stripStart(request.getProfilerUrl(), "/");
72+
}
73+
74+
return ProfilerUtil.getBaseProfilerUrlFromRequest(request.getProfilerUrl());
75+
}
76+
77+
@NotNull
78+
private String getPath(@NotNull String hash) {
79+
String[] hashSplit = hash.split("(?<=\\G.{2})");
80+
return hashSplit[2] + "/" + hashSplit[1] + "/" + hash;
81+
}
82+
83+
@Nullable
84+
private File getFile(@NotNull String hash) {
85+
String path = this.getPath(hash);
86+
87+
File file = new File(this.file.getParentFile().getAbsolutePath() + "/" + path);
88+
if(!file.exists()) {
89+
return null;
90+
}
91+
92+
return file;
93+
}
94+
95+
@Nullable
96+
private String getContentForHash(@NotNull String hash) {
97+
File file = this.getFile(hash);
98+
if(file == null) {
99+
return null;
100+
}
101+
102+
StringBuilder content = new StringBuilder();
103+
104+
try {
105+
BufferedReader in = new BufferedReader(new FileReader(file));
106+
String str;
107+
while ((str = in.readLine()) != null) {
108+
content.append(str);
109+
}
110+
in.close();
111+
} catch (IOException ignored) {
112+
}
113+
114+
return content.toString();
115+
}
116+
117+
private class MyProfilerRequestBuilderCallable implements Callable<ProfilerRequestInterface> {
118+
private final String[] split;
119+
120+
MyProfilerRequestBuilderCallable(String[] split) {
121+
this.split = split;
122+
}
123+
124+
@Override
125+
public ProfilerRequestInterface call() throws Exception {
126+
String content = getContentForHash(split[0]);
127+
if(content == null) {
128+
return new LocalProfilerRequest(split);
129+
}
130+
131+
return new LocalProfilerRequest(
132+
split,
133+
new LocalDefaultDataCollector(content),
134+
new LocalMailCollector(content)
135+
);
136+
}
137+
}
138+
}

src/fr/adrienbrault/idea/symfony2plugin/profiler/ProfilerIndex.java

-95
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package fr.adrienbrault.idea.symfony2plugin.profiler;
2+
3+
import fr.adrienbrault.idea.symfony2plugin.profiler.dict.ProfilerRequestInterface;
4+
import org.jetbrains.annotations.NotNull;
5+
import org.jetbrains.annotations.Nullable;
6+
7+
import java.util.List;
8+
9+
/**
10+
* @author Daniel Espendiller <daniel@espendiller.net>
11+
*/
12+
public interface ProfilerIndexInterface {
13+
@NotNull
14+
List<ProfilerRequestInterface> getRequests();
15+
16+
@Nullable
17+
String getUrlForRequest(@NotNull ProfilerRequestInterface request);
18+
}

src/fr/adrienbrault/idea/symfony2plugin/profiler/ProfilerUtil.java

-27
This file was deleted.

0 commit comments

Comments
 (0)