FUS: extract statistics api into separate module (IDEA-229155)

GitOrigin-RevId: 0b857d510c226af4b8a64b3312f5350687985b69
This commit is contained in:
Svetlana.Zemlyanskaya
2019-12-18 17:12:26 +00:00
committed by intellij-monorepo-bot
parent 810b1534bd
commit 5c0785eba2
95 changed files with 321 additions and 91 deletions
+1
View File
@@ -658,6 +658,7 @@
<module fileurl="file://$PROJECT_DIR$/platform/script-debugger/debugger-ui/intellij.platform.scriptDebugger.ui.iml" filepath="$PROJECT_DIR$/platform/script-debugger/debugger-ui/intellij.platform.scriptDebugger.ui.iml" />
<module fileurl="file://$PROJECT_DIR$/platform/service-container/intellij.platform.serviceContainer.iml" filepath="$PROJECT_DIR$/platform/service-container/intellij.platform.serviceContainer.iml" />
<module fileurl="file://$PROJECT_DIR$/platform/smRunner/intellij.platform.smRunner.iml" filepath="$PROJECT_DIR$/platform/smRunner/intellij.platform.smRunner.iml" />
<module fileurl="file://$PROJECT_DIR$/platform/statistics/intellij.platform.statistics.iml" filepath="$PROJECT_DIR$/platform/statistics/intellij.platform.statistics.iml" />
<module fileurl="file://$PROJECT_DIR$/platform/structuralsearch/intellij.platform.structuralSearch.iml" filepath="$PROJECT_DIR$/platform/structuralsearch/intellij.platform.structuralSearch.iml" />
<module fileurl="file://$PROJECT_DIR$/platform/structuralsearch/intellij.platform.structuralSearch.tests.iml" filepath="$PROJECT_DIR$/platform/structuralsearch/intellij.platform.structuralSearch.tests.iml" />
<module fileurl="file://$PROJECT_DIR$/platform/structure-view-impl/intellij.platform.structureView.impl.iml" filepath="$PROJECT_DIR$/platform/structure-view-impl/intellij.platform.structureView.impl.iml" />
@@ -145,6 +145,7 @@ class DistributionJARsBuilder {
withModule("intellij.json")
withModule("intellij.spellchecker")
withModule("intellij.platform.images")
withModule("intellij.platform.statistics")
withModule("intellij.relaxng", "intellij-xml.jar")
withModule("intellij.xml.analysis.impl", "intellij-xml.jar")
@@ -0,0 +1,21 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.plugins;
import com.intellij.openapi.progress.ProgressIndicator;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.List;
public interface PluginInfoProvider {
/**
* Reads cached plugin descriptors from a file. Returns {@code null} if cache file does not exist.
*/
List<IdeaPluginDescriptor> loadCachedPlugins() throws IOException;
/**
* Loads list of plugins, compatible with a current build, from a main plugin repository.
*/
List<IdeaPluginDescriptor> loadPlugins(@Nullable ProgressIndicator indicator) throws IOException;
}
@@ -29,7 +29,7 @@ class ExternalSystemActionsCollector {
if (place != null) {
data.addPlace(place).addData("context_menu", isFromContextMenu)
}
executor?.let { data.addExecutor(it) }
executor?.let { data.addData("executor", it.id) }
addExternalSystemId(data, systemId)
@@ -22,7 +22,7 @@ public class RunConfigurationUsageTriggerCollector {
public static IdeActivity trigger(@NotNull Project project, @NotNull ConfigurationFactory factory, @NotNull Executor executor) {
final ConfigurationType configurationType = factory.getType();
return new IdeActivity(project, "run.configuration.exec").startedWithData(data -> {
data.addAll(newFeatureUsageData(configurationType, factory).addExecutor(executor));
data.addAll(newFeatureUsageData(configurationType, factory).addData("executor", executor.getId()));
});
}
@@ -66,5 +66,6 @@
<orderEntry type="module" module-name="intellij.platform.serviceContainer" />
<orderEntry type="library" name="jcef" level="project" />
<orderEntry type="module" module-name="intellij.platform.diagnostic" scope="RUNTIME" />
<orderEntry type="module" module-name="intellij.platform.statistics" exported="" />
</component>
</module>
@@ -0,0 +1,20 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.plugins;
import com.intellij.openapi.progress.ProgressIndicator;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.List;
public class PluginInfoProviderImpl implements PluginInfoProvider {
@Override
public List<IdeaPluginDescriptor> loadCachedPlugins() throws IOException {
return RepositoryHelper.loadCachedPlugins();
}
@Override
public List<IdeaPluginDescriptor> loadPlugins(@Nullable ProgressIndicator indicator) throws IOException {
return RepositoryHelper.loadPlugins(indicator);
}
}
@@ -1,56 +0,0 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic
import com.intellij.openapi.application.PermanentInstallationID
import com.intellij.openapi.application.ex.ApplicationInfoEx
import com.intellij.openapi.application.impl.ApplicationInfoImpl
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.text.StringUtil
import java.text.SimpleDateFormat
import java.util.*
import java.util.prefs.Preferences
object DeviceIdManager {
private val LOG = Logger.getInstance(DeviceIdManager::class.java)
private const val DEVICE_ID_SHARED_FILE = "PermanentDeviceId"
private const val DEVICE_ID_PREFERENCE_KEY = "device_id"
fun getOrGenerateId(): String {
val appInfo = ApplicationInfoImpl.getShadowInstance()
val prefs = getPreferences(appInfo)
var deviceId = prefs.get(DEVICE_ID_PREFERENCE_KEY, null)
if (StringUtil.isEmptyOrSpaces(deviceId)) {
deviceId = generateId(Calendar.getInstance(Locale.ENGLISH), getOSChar())
prefs.put(DEVICE_ID_PREFERENCE_KEY, deviceId)
LOG.info("Generating new Device ID")
}
if (appInfo.isVendorJetBrains && SystemInfo.isWindows) {
deviceId = PermanentInstallationID.syncWithSharedFile(DEVICE_ID_SHARED_FILE, deviceId, prefs, DEVICE_ID_PREFERENCE_KEY)
}
return deviceId
}
private fun getPreferences(appInfo: ApplicationInfoEx): Preferences {
val companyName = appInfo.shortCompanyName
val name = if (StringUtil.isEmptyOrSpaces(companyName)) "jetbrains" else companyName.toLowerCase(Locale.US)
return Preferences.userRoot().node(name)
}
/**
* Device id is generating by concatenating following values:
* Current date, written in format ddMMyy, where year coerced between 2000 and 2099
* Character, representing user's OS (see [getOSChar])
* [toString] call on representation of [UUID.randomUUID]
*/
fun generateId(calendar: Calendar, OSChar: Char): String {
calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR).coerceIn(2000, 2099))
return SimpleDateFormat("ddMMyy", Locale.ENGLISH).format(calendar.time) + OSChar + UUID.randomUUID().toString()
}
private fun getOSChar() = if (SystemInfo.isWindows) '1' else if (SystemInfo.isMac) '2' else if (SystemInfo.isLinux) '3' else '0'
}
@@ -307,6 +307,8 @@
<applicationService serviceImplementation="com.intellij.internal.statistic.collectors.fus.actions.persistence.ToolWindowCollector"/>
<applicationService serviceInterface="com.intellij.internal.statistic.eventLog.FeatureUsageUiEvents"
serviceImplementation="com.intellij.internal.statistic.eventLog.fus.FeatureUsageUiEventsImpl"/>
<applicationService serviceInterface="com.intellij.ide.plugins.PluginInfoProvider"
serviceImplementation="com.intellij.ide.plugins.PluginInfoProviderImpl"/>
<applicationService serviceImplementation="com.intellij.openapi.util.DimensionService"/>
<applicationService serviceInterface="com.intellij.openapi.util.WindowStateService"
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="intellij.platform.core.impl" />
<orderEntry type="library" name="kotlin-stdlib-jdk8" level="project" />
<orderEntry type="library" name="gson" level="project" />
<orderEntry type="library" name="Log4J" level="project" />
<orderEntry type="library" name="jetbrains-annotations" level="project" />
<orderEntry type="library" name="JDOM" level="project" />
<orderEntry type="library" name="Guava" level="project" />
<orderEntry type="module" module-name="intellij.platform.ide" />
</component>
</module>
@@ -0,0 +1,117 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import org.jetbrains.annotations.NotNull;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
import java.util.UUID;
import java.util.prefs.Preferences;
public class DeviceIdManager {
private static final Logger LOG = Logger.getInstance(DeviceIdManager.class);
private static final String DEVICE_ID_SHARED_FILE = "PermanentDeviceId";
private static final String DEVICE_ID_PREFERENCE_KEY = "device_id";
public static String getOrGenerateId() {
ApplicationInfoEx appInfo = ApplicationInfoImpl.getShadowInstance();
Preferences prefs = getPreferences(appInfo);
String deviceId = prefs.get(DEVICE_ID_PREFERENCE_KEY, null);
if (StringUtil.isEmptyOrSpaces(deviceId)) {
deviceId = generateId(Calendar.getInstance(Locale.ENGLISH), getOSChar());
prefs.put(DEVICE_ID_PREFERENCE_KEY, deviceId);
LOG.info("Generating new Device ID");
}
if (appInfo.isVendorJetBrains() && SystemInfo.isWindows) {
deviceId = syncWithSharedFile(DEVICE_ID_SHARED_FILE, deviceId, prefs, DEVICE_ID_PREFERENCE_KEY);
}
return deviceId;
}
@NotNull
public static String syncWithSharedFile(@NotNull String fileName,
@NotNull String installationId,
@NotNull Preferences prefs,
@NotNull String prefsKey) {
final String appdata = System.getenv("APPDATA");
if (appdata != null) {
final File dir = new File(appdata, "JetBrains");
if (dir.exists() || dir.mkdirs()) {
final File permanentIdFile = new File(dir, fileName);
try {
String fromFile = "";
if (permanentIdFile.exists()) {
fromFile = loadFromFile(permanentIdFile).trim();
}
if (!fromFile.isEmpty()) {
if (!fromFile.equals(installationId)) {
installationId = fromFile;
prefs.put(prefsKey, installationId);
}
}
else {
writeToFile(permanentIdFile, installationId);
}
}
catch (IOException ignored) { }
}
}
return installationId;
}
@NotNull
private static String loadFromFile(@NotNull File file) throws IOException {
try (FileInputStream is = new FileInputStream(file)) {
final byte[] bytes = FileUtilRt.loadBytes(is);
final int offset = CharsetToolkit.hasUTF8Bom(bytes) ? CharsetToolkit.UTF8_BOM.length : 0;
return new String(bytes, offset, bytes.length - offset, StandardCharsets.UTF_8);
}
}
private static void writeToFile(@NotNull File file, @NotNull String text) throws IOException {
try (DataOutputStream stream = new DataOutputStream(new FileOutputStream(file))) {
stream.write(text.getBytes(StandardCharsets.UTF_8));
}
}
@NotNull
private static Preferences getPreferences(ApplicationInfoEx appInfo) {
String companyName = appInfo.getShortCompanyName();
String name = StringUtil.isEmptyOrSpaces(companyName) ? "jetbrains" : companyName.toLowerCase(Locale.US);
return Preferences.userRoot().node(name);
}
/**
* Device id is generating by concatenating following values:
* Current date, written in format ddMMyy, where year coerced between 2000 and 2099
* Character, representing user's OS (see [getOSChar])
* [toString] call on representation of [UUID.randomUUID]
*/
public static String generateId(Calendar calendar, char OSChar) {
int year = calendar.get(Calendar.YEAR);
if (year < 2000) year = 2000;
if (year > 2099) year = 2099;
calendar.set(Calendar.YEAR, year);
return new SimpleDateFormat("ddMMyy", Locale.ENGLISH).format(calendar.getTime()) + OSChar + UUID.randomUUID().toString();
}
private static char getOSChar() {
if (SystemInfo.isWindows) return '1';
else if (SystemInfo.isMac) return '2';
else if (SystemInfo.isLinux) return '3';
return '0';
}
}
@@ -0,0 +1,87 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.connect;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.io.HttpRequests;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
public abstract class SettingsConnectionService {
private static final Logger LOG = Logger.getInstance(SettingsConnectionService.class);
protected static final String SERVICE_URL_ATTR_NAME = "url";
private Map<String, String> myAttributesMap;
@NotNull
protected String[] getAttributeNames() {
return new String[]{SERVICE_URL_ATTR_NAME};
}
@Nullable
private final String mySettingsUrl;
@Nullable
private final String myDefaultServiceUrl;
protected SettingsConnectionService(@Nullable String settingsUrl, @Nullable String defaultServiceUrl) {
mySettingsUrl = settingsUrl;
myDefaultServiceUrl = defaultServiceUrl;
}
@SuppressWarnings("unused")
@Deprecated
@Nullable
public String getSettingsUrl() {
return mySettingsUrl;
}
@Nullable
public String getDefaultServiceUrl() {
return myDefaultServiceUrl;
}
@Nullable
private Map<String, String> readSettings(final String... attributes) {
if (mySettingsUrl == null) return Collections.emptyMap();
return HttpRequests.request(mySettingsUrl)
.productNameAsUserAgent()
.connect(request -> {
Map<String, String> settings = new LinkedHashMap<>();
try {
Element root = JDOMUtil.load(request.getReader());
for (String s : attributes) {
String attributeValue = root.getAttributeValue(s);
if (StringUtil.isNotEmpty(attributeValue)) {
settings.put(s, attributeValue);
}
}
}
catch (JDOMException e) {
LOG.info(e);
}
return settings;
}, Collections.emptyMap(), LOG);
}
@Nullable
public String getServiceUrl() {
final String serviceUrl = getSettingValue(SERVICE_URL_ATTR_NAME);
return serviceUrl == null ? getDefaultServiceUrl() : serviceUrl;
}
@Nullable
protected String getSettingValue(@NotNull String attributeValue) {
if (myAttributesMap == null || myAttributesMap.isEmpty()) {
myAttributesMap = readSettings(getAttributeNames());
}
return myAttributesMap != null ? myAttributesMap.get(attributeValue) : null;
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.internal.statistic.connect;
import com.intellij.facet.frameworks.SettingsConnectionService;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -1,10 +1,10 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.eventLog;
import com.intellij.facet.frameworks.SettingsConnectionService;
import com.intellij.internal.statistic.connect.SettingsConnectionService;
import com.intellij.internal.statistic.service.fus.FUSWhitelist;
import com.intellij.internal.statistic.service.fus.FUStatisticsWhiteListGroupsService;
import com.intellij.internal.statistic.utils.StatisticsUploadAssistant;
import com.intellij.internal.statistic.utils.StatisticsTestHelper;
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.diagnostic.Logger;
@@ -87,7 +87,7 @@ public class EventLogExternalSettingsService extends SettingsConnectionService i
@Override
public boolean isInternal() {
return StatisticsUploadAssistant.isTestStatisticsEnabled();
return StatisticsTestHelper.isTestStatisticsEnabled();
}
@Nullable
@@ -1,7 +1,6 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.eventLog
import com.intellij.execution.Executor
import com.intellij.internal.statistic.eventLog.StatisticsEventEscaper.escapeFieldName
import com.intellij.internal.statistic.utils.PluginInfo
import com.intellij.internal.statistic.utils.addPluginInfoTo
@@ -188,11 +187,6 @@ class FeatureUsageData {
return ActionPlaces.isCommonPlace(place) || ActionPlaces.TOOLWINDOW_POPUP == place
}
@FeatureUsageDataBuilder(additionalDataFields = ["executor:util#run_config_executor"])
fun addExecutor(executor: Executor): FeatureUsageData {
return addData("executor", executor.id)
}
@FeatureUsageDataBuilder(additionalDataFields = ["file_path:util#hash"])
fun addAnonymizedPath(path: String?): FeatureUsageData {
data["file_path"] = path?.let { EventLogConfiguration.anonymize(path) } ?: "undefined"
@@ -1,9 +1,6 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.eventLog.validator;
import com.intellij.internal.statistic.collectors.fus.ClassNameRuleValidator;
import com.intellij.internal.statistic.collectors.fus.actions.persistence.ActionsCollectorImpl;
import com.intellij.internal.statistic.collectors.fus.fileTypes.FileTypeUsagesCollector;
import com.intellij.internal.statistic.eventLog.EventLogGroup;
import com.intellij.internal.statistic.eventLog.FeatureUsageData;
import com.intellij.internal.statistic.eventLog.validator.rules.EventContext;
@@ -55,7 +52,7 @@ import static com.intellij.internal.statistic.utils.StatisticsUtilKt.addPluginIn
* <li>
* <b>Custom rule</b>: class which inherits {@link CustomWhiteListRule} and validates dynamic data like action id or file type, e.g.
* <i>"{util#class_name}"</i> checks that the value is a class name from platform, JB plugin or a plugin from JB plugin repository.<br/>
* See: {@link ClassNameRuleValidator}
* See: {@link com.intellij.internal.statistic.collectors.fus.ClassNameRuleValidator}
* </li>
* </ol>
* </p>
@@ -67,7 +64,9 @@ import static com.intellij.internal.statistic.utils.StatisticsUtilKt.addPluginIn
*
* <p>Example:</p>
* <ul>
* <li><i>"actions"</i> collector records invoked actions ({@link ActionsCollectorImpl}).<br/>
* <li><i>"actions"</i> collector records invoked actions
* ({@link com.intellij.internal.statistic.collectors.fus.actions.persistence.ActionsCollectorImpl}).<br/>
*
* It is validated by the following rules:
* <pre>
* {
@@ -85,7 +84,9 @@ import static com.intellij.internal.statistic.utils.StatisticsUtilKt.addPluginIn
* }
* </pre></li>
*
* <li><i>"file.types"</i> collector records information about project files ({@link FileTypeUsagesCollector}).<br/>
* <li><i>"file.types"</i> collector records information about project files
* ({@link com.intellij.internal.statistic.collectors.fus.fileTypes.FileTypeUsagesCollector}).<br/>
*
* It is validated by the following rules:
* <pre>
* {
@@ -1,7 +1,6 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.eventLog.validator.persistence;
import com.intellij.internal.statistic.persistence.UsageStatisticsPersistenceComponent;
import com.intellij.openapi.components.*;
import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Element;
@@ -13,9 +12,11 @@ import java.util.Map;
@State(
name = "EventLogWhitelist",
storages = @Storage(value = UsageStatisticsPersistenceComponent.USAGE_STATISTICS_XML, roamingType = RoamingType.DISABLED)
storages = @Storage(value = EventLogWhitelistSettingsPersistence.USAGE_STATISTICS_XML, roamingType = RoamingType.DISABLED)
)
public class EventLogWhitelistSettingsPersistence implements PersistentStateComponent<Element> {
public static final String USAGE_STATISTICS_XML = "usage.statistics.xml";
private final Map<String, Long> myLastModifications = new HashMap<>();
private final Map<String, WhitelistPathSettings> myRecorderToPathSettings = new HashMap<>();
@@ -2,8 +2,8 @@
package com.intellij.internal.statistic.eventLog.validator.rules.beans;
import com.intellij.internal.statistic.eventLog.FeatureUsageData;
import com.intellij.internal.statistic.eventLog.validator.rules.EventContext;
import com.intellij.internal.statistic.eventLog.validator.ValidationResultType;
import com.intellij.internal.statistic.eventLog.validator.rules.EventContext;
import com.intellij.internal.statistic.eventLog.validator.rules.FUSRule;
import com.intellij.internal.statistic.eventLog.validator.rules.impl.EnumWhiteListRule;
import com.intellij.internal.statistic.eventLog.validator.rules.utils.WhiteListSimpleRuleFactory;
@@ -1,8 +1,6 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.eventLog.validator.rules.impl;
import com.intellij.internal.statistic.collectors.fus.ClassNameRuleValidator;
import com.intellij.internal.statistic.collectors.fus.LangCustomRuleValidator;
import com.intellij.internal.statistic.eventLog.validator.SensitiveDataValidator;
import com.intellij.internal.statistic.eventLog.validator.ValidationResultType;
import com.intellij.internal.statistic.eventLog.validator.rules.EventContext;
@@ -25,7 +23,9 @@ import org.jetbrains.annotations.Nullable;
* For more information see {@link SensitiveDataValidator}.
* </p>
*
* <p><i>Example:</i> {@link ClassNameRuleValidator}, {@link LangCustomRuleValidator}, etc.</p>
* <p><i>Example:</i>
* {@link com.intellij.internal.statistic.collectors.fus.ClassNameRuleValidator},
* {@link com.intellij.internal.statistic.collectors.fus.LangCustomRuleValidator}, etc.</p>
*
* @see SensitiveDataValidator
*/
@@ -10,7 +10,10 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
@@ -5,14 +5,16 @@ import com.intellij.internal.statistic.eventLog.validator.ValidationResultType;
import com.intellij.internal.statistic.eventLog.validator.rules.FUSRegexpAwareRule;
import com.intellij.internal.statistic.eventLog.validator.rules.FUSRule;
import com.intellij.internal.statistic.eventLog.validator.rules.beans.WhiteListGroupContextData;
import com.intellij.internal.statistic.eventLog.validator.rules.impl.*;
import com.intellij.internal.statistic.eventLog.validator.rules.impl.CustomWhiteListRule;
import com.intellij.internal.statistic.eventLog.validator.rules.impl.EnumWhiteListRule;
import com.intellij.internal.statistic.eventLog.validator.rules.impl.RegexpWhiteListRule;
import com.intellij.internal.statistic.eventLog.validator.rules.impl.UtilExpressionWhiteListRule;
import com.intellij.internal.statistic.utils.PluginInfoDetectorKt;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -17,8 +17,6 @@ import java.util.Collections;
import java.util.Map;
import java.util.Set;
import static com.intellij.internal.statistic.utils.StatisticsUploadAssistant.LOCK;
/**
* <p>Called by a scheduler once a day and records IDE/project state.</p> <br/>
*
@@ -28,6 +26,8 @@ import static com.intellij.internal.statistic.utils.StatisticsUploadAssistant.LO
* <p>To record IDE events (e.g. invoked action, opened dialog) use {@link FUCounterUsageLogger}</p>
*/
public class FUStateUsagesLogger implements UsagesCollectorConsumer {
public static final Object LOCK = new Object();
/**
* System event which indicates that the collector was called.
* Used to calculate metric baseline.
@@ -1,7 +1,7 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.service.fus.collectors;
import com.intellij.internal.statistic.persistence.UsageStatisticsPersistenceComponent;
import com.intellij.internal.statistic.eventLog.validator.persistence.EventLogWhitelistSettingsPersistence;
import com.intellij.openapi.components.*;
import com.intellij.openapi.project.Project;
import com.intellij.util.SmartList;
@@ -13,7 +13,7 @@ import java.util.List;
@State(name = "FUSProjectUsageTrigger", storages = {
@Storage(value = StoragePathMacros.CACHE_FILE, deprecated = true),
@Storage(value = StoragePathMacros.WORKSPACE_FILE, deprecated = true),
@Storage(value = UsageStatisticsPersistenceComponent.USAGE_STATISTICS_XML, deprecated = true),
@Storage(value = EventLogWhitelistSettingsPersistence.USAGE_STATISTICS_XML, deprecated = true),
})
final public class LegacyFUSProjectUsageTrigger implements PersistentStateComponent<LegacyFUSProjectUsageTrigger.State> {
private final State myState = new State();
@@ -0,0 +1,12 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.utils;
import com.intellij.openapi.util.text.StringUtil;
public class StatisticsTestHelper {
private static final String ENABLE_LOCAL_STATISTICS_WITHOUT_REPORT = "idea.local.statistics.without.report";
public static boolean isTestStatisticsEnabled() {
return Boolean.getBoolean(ENABLE_LOCAL_STATISTICS_WITHOUT_REPORT) || StringUtil.isNotEmpty(System.getenv("TEAMCITY_VERSION"));
}
}
@@ -1,13 +1,14 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.internal.statistic.utils
import com.intellij.ide.plugins.PluginInfoProvider
import com.intellij.ide.plugins.PluginManager
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.ide.plugins.RepositoryHelper
import com.intellij.internal.statistic.beans.*
import com.intellij.internal.statistic.eventLog.EventLogConfiguration
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ex.ApplicationInfoEx
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.extensions.PluginDescriptor
import com.intellij.openapi.extensions.PluginId
import com.intellij.openapi.project.Project
@@ -203,7 +204,7 @@ private fun addAll(result: ObjectIntHashMap<String>, usages: Set<UsageDescriptor
private val pluginIdsFromOfficialJbPluginRepo: Getter<Set<PluginId>> = TimeoutCachedValue(1, TimeUnit.HOURS) {
// before loading default repository plugins lets check it's not changed, and is really official JetBrains repository
try {
val cached = RepositoryHelper.loadCachedPlugins()
val cached = getPluginInfoProvider()?.loadCachedPlugins()
if (cached != null) {
return@TimeoutCachedValue cached.mapNotNullTo(HashSet(cached.size)) { it.pluginId }
}
@@ -214,7 +215,7 @@ private val pluginIdsFromOfficialJbPluginRepo: Getter<Set<PluginId>> = TimeoutCa
// schedule plugins loading, will take them the next time
ApplicationManager.getApplication().executeOnPooledThread {
try {
RepositoryHelper.loadPlugins(null)
getPluginInfoProvider()?.loadPlugins(null) ?: emptySet<PluginId>()
}
catch (ignored: IOException) {
}
@@ -224,6 +225,10 @@ private val pluginIdsFromOfficialJbPluginRepo: Getter<Set<PluginId>> = TimeoutCa
emptySet<PluginId>()
}
fun getPluginInfoProvider(): PluginInfoProvider? {
return ApplicationManager.getApplication()?.let { ServiceManager.getService(PluginInfoProvider::class.java) }
}
/**
* Checks this plugin is created by JetBrains or from official repository, so API from it may be reported
*/
@@ -29,7 +29,7 @@ class MavenActionsUsagesCollector {
if (place != null) {
data.addPlace(place).addData("context_menu", isFromContextMenu)
}
executor?.let { data.addExecutor(it) }
executor?.let { data.addData("executor", it.id) }
FUCounterUsageLogger.getInstance().logEvent(GROUP_ID, actionID.name, data)
}