Skip to content

Commit

Permalink
usage logging
Browse files Browse the repository at this point in the history
  • Loading branch information
vodorok committed Sep 27, 2019
1 parent bfa6010 commit 50ac659
Show file tree
Hide file tree
Showing 9 changed files with 266 additions and 4 deletions.
3 changes: 2 additions & 1 deletion bundles/org.codechecker.eclipse.plugin/build.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ bin.includes = plugin.xml,\
.,\
icons/,\
contexts.xml,\
log4j.properties
log4j.properties,\
resources/

35 changes: 35 additions & 0 deletions bundles/org.codechecker.eclipse.plugin/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codechecker.eclipse</groupId>
<artifactId>org.codechecker.eclipse.bundles</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<artifactId>org.codechecker.eclipse.plugin</artifactId>
<version>0.0.6-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>

<properties>
<host.log>empty</host.log>
<port.log>0</port.log>
<plugin.version>${project.version}</plugin.version>
</properties>

<build>
<resources>
<resource>
<directory>resources</directory>
<targetPath>resources</targetPath>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
host=${host.log}
port=${port.log}
version=${plugin.version}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -12,6 +13,9 @@
import org.codechecker.eclipse.plugin.runtime.LogI;
import org.codechecker.eclipse.plugin.runtime.SLogger;
import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelper;
import org.codechecker.eclipse.plugin.usage.StatisticUploader;
import org.codechecker.eclipse.plugin.usage.UsageInfo;
import org.codechecker.eclipse.plugin.usage.UsageInfo.CommandType;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
Expand All @@ -36,6 +40,7 @@ public class CodeChecker implements ICodeChecker {
private Path location;
private ShellExecutorHelper she;
private Map<String, File> subMap;
private String version;

/**
*
Expand All @@ -52,7 +57,7 @@ public CodeChecker(Path path, ShellExecutorHelper she) throws InvalidCodeChecker
this.she = she;
subMap = new HashMap<String, File>();
subMap.put(LOCATION_KEY, path.toAbsolutePath().toFile());
getVersion();
version = getVersion();
}

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

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

SLogger.log(LogI.INFO, "Running analyze Command: " + cmd);
new Thread(new StatisticUploader(new UsageInfo(CommandType.analyze_started, version))).start();

Optional<String> ccOutput = she.progressableWaitReturnOutput(cmd, subMap, logToConsole, monitor, taskCount);

return ccOutput.or("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
import org.codechecker.eclipse.plugin.report.job.JobDoneChangeListener;
import org.codechecker.eclipse.plugin.report.job.PlistParseJob;
import org.codechecker.eclipse.plugin.runtime.SLogger;
import org.codechecker.eclipse.plugin.usage.StatisticUploader;
import org.codechecker.eclipse.plugin.usage.UsageInfo;
import org.codechecker.eclipse.plugin.usage.UsageInfo.CommandType;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
Expand Down Expand Up @@ -81,6 +84,8 @@ public IStatus runInUIThread(IProgressMonitor monitor) {
Logger.log(IStatus.INFO, Logger.getStackTrace(e));
}

new Thread(new StatisticUploader(new UsageInfo(CommandType.started, null))).start();

Logger.log(IStatus.INFO, "adding addResourceChangeListener ");
ResourcesPlugin.getWorkspace().addResourceChangeListener(new ResourceChangeListener(),
IResourceChangeEvent.POST_BUILD | IResourceChangeEvent.POST_CHANGE |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package org.codechecker.eclipse.plugin.usage;

import java.io.IOException;
import java.io.InputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.util.Properties;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.osgi.framework.FrameworkUtil;

import com.google.gson.Gson;

/**
* Class for uploading the usage statistics.
*/
public class StatisticUploader implements Runnable {

private UsageInfo info;

/**
* Need to pass an {@link UsageInfo}.
*
* @param info
* This will be uploaded in JSON format.
*/
public StatisticUploader(UsageInfo info) {
this.info = info;
}

/**
* This is the upload logic. The host and port is specified compile time in
* maven.
*/
private void uploadStatistics() {
Integer port = null;
String host = null;

try (InputStream is = FileLocator.openStream(FrameworkUtil.getBundle(getClass()),
new Path("resources/config.properties"), false)) {
Properties prop = new Properties();
prop.load(is);
host = prop.getProperty("host");
try {
port = Integer.parseInt(prop.getProperty("port"));
} catch (Exception e) {
;
}
} catch (IOException e1) {
;
}

try (DatagramSocket socket = new DatagramSocket()) {
if (port != null && host != null) {
DatagramPacket packet = new DatagramPacket(new Gson().toJson(info).getBytes(),
new Gson().toJson(info).getBytes().length,
Inet4Address.getByName(host), port);
socket.send(packet);
}
} catch (IOException e) {
;
}
}

/**
* Uploads usage statistics.
*/
@Override
public void run() {
uploadStatistics();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package org.codechecker.eclipse.plugin.usage;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Properties;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IContributor;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jdt.annotation.Nullable;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;

import com.google.gson.annotations.SerializedName;

/**
* Class for Storing usage logging related info.
*/
public class UsageInfo {
private static final String UNKNOWN = "unknown";
private static final String UNKNOWN_VER = "unknown version";

@SuppressWarnings("unused")
private final String machine;
@SuppressWarnings("unused")
private final String hostname;
//@SuppressWarnings("unused")
//private String clangsa = UNKNOWN;
@SuppressWarnings("unused")
private final String version;
// TODO make this parameter dynamic, from build parameters.
@SuppressWarnings("unused")
private final String pluginVersion;
@SuppressWarnings("unused")
private final String user;
@SuppressWarnings("unused")
@SerializedName("command_type")
private final CommandType commandType;
//@SuppressWarnings("unused")
//private String clang_tidy = UNKNOWN;

/**
* Specify the event type and the CodeChecker version if in context.
*
* @param ct
* The command (event) type to be logged.
* @param ccVersion
* The CodeChecker version to be logged. Not every context has
* CodeChecker.
*/
public UsageInfo(CommandType ct, @Nullable String ccVersion) {
StringBuilder tempos = new StringBuilder(System.getProperty("os.name"));
tempos.append(" ").append(System.getProperty("os.version"));
tempos.append(" / Eclipse ").append(getEclipseVersion());
machine = tempos.toString();
String tHostName = UNKNOWN;
try {
tHostName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException ex) {
;
}
hostname = tHostName;

if (ccVersion != null)
version = ccVersion;
else
version = UNKNOWN_VER;

pluginVersion = setPluginVersion();
user = System.getProperty("user.name");
commandType = ct;
}

/**
* Used for returning the eclipse version number. From:
* https://stackoverflow.com/a/28855362/8149485
*
* @return The eclipse version number in 1.2.3.v19700101-0000 format.
*/
private String getEclipseVersion() {
String version = UNKNOWN_VER;
String product = System.getProperty("eclipse.product");
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint point = registry.getExtensionPoint("org.eclipse.core.runtime.products");
if (point != null) {
IExtension[] extensions = point.getExtensions();
for (IExtension ext : extensions)
if (product.equals(ext.getUniqueIdentifier())) {
IContributor contributor = ext.getContributor();
if (contributor != null) {
Bundle bundle = Platform.getBundle(contributor.getName());
if (bundle != null)
version = bundle.getVersion().toString();
}
}
}
return version;
}

/**
* Sets the plugin version from a properties file, which gets substituted during
* build.
*
* @return The plugin version read from the config file.
*/
private String setPluginVersion() {
String ver = UNKNOWN_VER;
try (InputStream is = FileLocator.openStream(FrameworkUtil.getBundle(getClass()),
new Path("resources/config.properties"), false)) {
Properties prop = new Properties();
prop.load(is);
ver = prop.getProperty("version");
} catch (IOException e1) {
e1.printStackTrace();
}
return ver;
}

/**
* Command (Event) types.
*/
public enum CommandType {
started, analyze_started
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/**
* Usage logging.
*/
package org.codechecker.eclipse.plugin.usage;
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void testVersionReturned() {

try {
String version = codeChecker.getVersion();
assertThat("Missing Version String", version.startsWith("CodeChecker analyzer version:"));
assertThat("Missing Version String", "1.2.3".equals(version));
} catch (InvalidCodeCheckerException e) {
fail("An exception was thrown after a successful initialization!");
}
Expand Down

0 comments on commit 50ac659

Please sign in to comment.