Skip to content

Commit 50ac659

Browse files
committed
usage logging
1 parent bfa6010 commit 50ac659

File tree

9 files changed

+266
-4
lines changed

9 files changed

+266
-4
lines changed

bundles/org.codechecker.eclipse.plugin/build.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ bin.includes = plugin.xml,\
55
.,\
66
icons/,\
77
contexts.xml,\
8-
log4j.properties
8+
log4j.properties,\
9+
resources/
910

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
4+
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>org.codechecker.eclipse</groupId>
8+
<artifactId>org.codechecker.eclipse.bundles</artifactId>
9+
<version>1.0.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>org.codechecker.eclipse.plugin</artifactId>
13+
<version>0.0.6-SNAPSHOT</version>
14+
<packaging>eclipse-plugin</packaging>
15+
16+
<properties>
17+
<host.log>empty</host.log>
18+
<port.log>0</port.log>
19+
<plugin.version>${project.version}</plugin.version>
20+
</properties>
21+
22+
<build>
23+
<resources>
24+
<resource>
25+
<directory>resources</directory>
26+
<targetPath>resources</targetPath>
27+
<filtering>true</filtering>
28+
<includes>
29+
<include>**/*.properties</include>
30+
</includes>
31+
</resource>
32+
</resources>
33+
</build>
34+
35+
</project>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
host=${host.log}
2+
port=${port.log}
3+
version=${plugin.version}

bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeChecker.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.File;
44
import java.nio.file.Path;
55
import java.nio.file.Paths;
6+
import java.util.Arrays;
67
import java.util.HashMap;
78
import java.util.Map;
89

@@ -12,6 +13,9 @@
1213
import org.codechecker.eclipse.plugin.runtime.LogI;
1314
import org.codechecker.eclipse.plugin.runtime.SLogger;
1415
import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelper;
16+
import org.codechecker.eclipse.plugin.usage.StatisticUploader;
17+
import org.codechecker.eclipse.plugin.usage.UsageInfo;
18+
import org.codechecker.eclipse.plugin.usage.UsageInfo.CommandType;
1519
import org.eclipse.core.runtime.IProgressMonitor;
1620
import org.eclipse.jdt.annotation.NonNull;
1721
import org.eclipse.jdt.annotation.Nullable;
@@ -36,6 +40,7 @@ public class CodeChecker implements ICodeChecker {
3640
private Path location;
3741
private ShellExecutorHelper she;
3842
private Map<String, File> subMap;
43+
private String version;
3944

4045
/**
4146
*
@@ -52,7 +57,7 @@ public CodeChecker(Path path, ShellExecutorHelper she) throws InvalidCodeChecker
5257
this.she = she;
5358
subMap = new HashMap<String, File>();
5459
subMap.put(LOCATION_KEY, path.toAbsolutePath().toFile());
55-
getVersion();
60+
version = getVersion();
5661
}
5762

5863
@Override
@@ -70,7 +75,8 @@ public String getVersion() throws InvalidCodeCheckerException {
7075
Optional<String> ccOutput = she.waitReturnOutput(cmd, subMap, false);
7176
if (!ccOutput.isPresent() || ccOutput.get().isEmpty())
7277
throw new InvalidCodeCheckerException("Couldn't run CodeChecker version!");
73-
return ccOutput.get();
78+
return Arrays.stream(ccOutput.get().split("\n")).filter(line -> line.contains("Base package version"))
79+
.findFirst().get().split("\\|")[1].trim();
7480
}
7581

7682
@Override
@@ -87,6 +93,8 @@ public String analyze(Path logFile, boolean logToConsole, IProgressMonitor monit
8793
String cmd = getSubstituteAnalyzeString(config);
8894

8995
SLogger.log(LogI.INFO, "Running analyze Command: " + cmd);
96+
new Thread(new StatisticUploader(new UsageInfo(CommandType.analyze_started, version))).start();
97+
9098
Optional<String> ccOutput = she.progressableWaitReturnOutput(cmd, subMap, logToConsole, monitor, taskCount);
9199

92100
return ccOutput.or("");

bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/init/StartupJob.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
import org.codechecker.eclipse.plugin.report.job.JobDoneChangeListener;
1414
import org.codechecker.eclipse.plugin.report.job.PlistParseJob;
1515
import org.codechecker.eclipse.plugin.runtime.SLogger;
16+
import org.codechecker.eclipse.plugin.usage.StatisticUploader;
17+
import org.codechecker.eclipse.plugin.usage.UsageInfo;
18+
import org.codechecker.eclipse.plugin.usage.UsageInfo.CommandType;
1619
import org.eclipse.cdt.core.model.CoreModel;
1720
import org.eclipse.core.resources.IProject;
1821
import org.eclipse.core.resources.IResource;
@@ -81,6 +84,8 @@ public IStatus runInUIThread(IProgressMonitor monitor) {
8184
Logger.log(IStatus.INFO, Logger.getStackTrace(e));
8285
}
8386

87+
new Thread(new StatisticUploader(new UsageInfo(CommandType.started, null))).start();
88+
8489
Logger.log(IStatus.INFO, "adding addResourceChangeListener ");
8590
ResourcesPlugin.getWorkspace().addResourceChangeListener(new ResourceChangeListener(),
8691
IResourceChangeEvent.POST_BUILD | IResourceChangeEvent.POST_CHANGE |
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package org.codechecker.eclipse.plugin.usage;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.net.DatagramPacket;
6+
import java.net.DatagramSocket;
7+
import java.net.Inet4Address;
8+
import java.util.Properties;
9+
10+
import org.eclipse.core.runtime.FileLocator;
11+
import org.eclipse.core.runtime.Path;
12+
import org.osgi.framework.FrameworkUtil;
13+
14+
import com.google.gson.Gson;
15+
16+
/**
17+
* Class for uploading the usage statistics.
18+
*/
19+
public class StatisticUploader implements Runnable {
20+
21+
private UsageInfo info;
22+
23+
/**
24+
* Need to pass an {@link UsageInfo}.
25+
*
26+
* @param info
27+
* This will be uploaded in JSON format.
28+
*/
29+
public StatisticUploader(UsageInfo info) {
30+
this.info = info;
31+
}
32+
33+
/**
34+
* This is the upload logic. The host and port is specified compile time in
35+
* maven.
36+
*/
37+
private void uploadStatistics() {
38+
Integer port = null;
39+
String host = null;
40+
41+
try (InputStream is = FileLocator.openStream(FrameworkUtil.getBundle(getClass()),
42+
new Path("resources/config.properties"), false)) {
43+
Properties prop = new Properties();
44+
prop.load(is);
45+
host = prop.getProperty("host");
46+
try {
47+
port = Integer.parseInt(prop.getProperty("port"));
48+
} catch (Exception e) {
49+
;
50+
}
51+
} catch (IOException e1) {
52+
;
53+
}
54+
55+
try (DatagramSocket socket = new DatagramSocket()) {
56+
if (port != null && host != null) {
57+
DatagramPacket packet = new DatagramPacket(new Gson().toJson(info).getBytes(),
58+
new Gson().toJson(info).getBytes().length,
59+
Inet4Address.getByName(host), port);
60+
socket.send(packet);
61+
}
62+
} catch (IOException e) {
63+
;
64+
}
65+
}
66+
67+
/**
68+
* Uploads usage statistics.
69+
*/
70+
@Override
71+
public void run() {
72+
uploadStatistics();
73+
}
74+
75+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package org.codechecker.eclipse.plugin.usage;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.net.InetAddress;
6+
import java.net.UnknownHostException;
7+
import java.util.Properties;
8+
9+
import org.eclipse.core.runtime.FileLocator;
10+
import org.eclipse.core.runtime.IContributor;
11+
import org.eclipse.core.runtime.IExtension;
12+
import org.eclipse.core.runtime.IExtensionPoint;
13+
import org.eclipse.core.runtime.IExtensionRegistry;
14+
import org.eclipse.core.runtime.Path;
15+
import org.eclipse.core.runtime.Platform;
16+
import org.eclipse.jdt.annotation.Nullable;
17+
import org.osgi.framework.Bundle;
18+
import org.osgi.framework.FrameworkUtil;
19+
20+
import com.google.gson.annotations.SerializedName;
21+
22+
/**
23+
* Class for Storing usage logging related info.
24+
*/
25+
public class UsageInfo {
26+
private static final String UNKNOWN = "unknown";
27+
private static final String UNKNOWN_VER = "unknown version";
28+
29+
@SuppressWarnings("unused")
30+
private final String machine;
31+
@SuppressWarnings("unused")
32+
private final String hostname;
33+
//@SuppressWarnings("unused")
34+
//private String clangsa = UNKNOWN;
35+
@SuppressWarnings("unused")
36+
private final String version;
37+
// TODO make this parameter dynamic, from build parameters.
38+
@SuppressWarnings("unused")
39+
private final String pluginVersion;
40+
@SuppressWarnings("unused")
41+
private final String user;
42+
@SuppressWarnings("unused")
43+
@SerializedName("command_type")
44+
private final CommandType commandType;
45+
//@SuppressWarnings("unused")
46+
//private String clang_tidy = UNKNOWN;
47+
48+
/**
49+
* Specify the event type and the CodeChecker version if in context.
50+
*
51+
* @param ct
52+
* The command (event) type to be logged.
53+
* @param ccVersion
54+
* The CodeChecker version to be logged. Not every context has
55+
* CodeChecker.
56+
*/
57+
public UsageInfo(CommandType ct, @Nullable String ccVersion) {
58+
StringBuilder tempos = new StringBuilder(System.getProperty("os.name"));
59+
tempos.append(" ").append(System.getProperty("os.version"));
60+
tempos.append(" / Eclipse ").append(getEclipseVersion());
61+
machine = tempos.toString();
62+
String tHostName = UNKNOWN;
63+
try {
64+
tHostName = InetAddress.getLocalHost().getHostName();
65+
} catch (UnknownHostException ex) {
66+
;
67+
}
68+
hostname = tHostName;
69+
70+
if (ccVersion != null)
71+
version = ccVersion;
72+
else
73+
version = UNKNOWN_VER;
74+
75+
pluginVersion = setPluginVersion();
76+
user = System.getProperty("user.name");
77+
commandType = ct;
78+
}
79+
80+
/**
81+
* Used for returning the eclipse version number. From:
82+
* https://stackoverflow.com/a/28855362/8149485
83+
*
84+
* @return The eclipse version number in 1.2.3.v19700101-0000 format.
85+
*/
86+
private String getEclipseVersion() {
87+
String version = UNKNOWN_VER;
88+
String product = System.getProperty("eclipse.product");
89+
IExtensionRegistry registry = Platform.getExtensionRegistry();
90+
IExtensionPoint point = registry.getExtensionPoint("org.eclipse.core.runtime.products");
91+
if (point != null) {
92+
IExtension[] extensions = point.getExtensions();
93+
for (IExtension ext : extensions)
94+
if (product.equals(ext.getUniqueIdentifier())) {
95+
IContributor contributor = ext.getContributor();
96+
if (contributor != null) {
97+
Bundle bundle = Platform.getBundle(contributor.getName());
98+
if (bundle != null)
99+
version = bundle.getVersion().toString();
100+
}
101+
}
102+
}
103+
return version;
104+
}
105+
106+
/**
107+
* Sets the plugin version from a properties file, which gets substituted during
108+
* build.
109+
*
110+
* @return The plugin version read from the config file.
111+
*/
112+
private String setPluginVersion() {
113+
String ver = UNKNOWN_VER;
114+
try (InputStream is = FileLocator.openStream(FrameworkUtil.getBundle(getClass()),
115+
new Path("resources/config.properties"), false)) {
116+
Properties prop = new Properties();
117+
prop.load(is);
118+
ver = prop.getProperty("version");
119+
} catch (IOException e1) {
120+
e1.printStackTrace();
121+
}
122+
return ver;
123+
}
124+
125+
/**
126+
* Command (Event) types.
127+
*/
128+
public enum CommandType {
129+
started, analyze_started
130+
}
131+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/**
2+
* Usage logging.
3+
*/
4+
package org.codechecker.eclipse.plugin.usage;

tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/CodeCheckerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public void testVersionReturned() {
7878

7979
try {
8080
String version = codeChecker.getVersion();
81-
assertThat("Missing Version String", version.startsWith("CodeChecker analyzer version:"));
81+
assertThat("Missing Version String", "1.2.3".equals(version));
8282
} catch (InvalidCodeCheckerException e) {
8383
fail("An exception was thrown after a successful initialization!");
8484
}

0 commit comments

Comments
 (0)