Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@

## [Unreleased]

## [1.12.0] - 2026-03-08

### Changed

- **Simplified Analytics** - Replaced granular per-action event tracking with a single periodic `plugin_active` heartbeat every 23 hours

### Removed

- Per-action analytics event types (widget clicks, popup actions, onboarding steps, goal events)

## [1.11.0] - 2026-02-27

### Added
Expand Down Expand Up @@ -225,7 +235,8 @@

- Support IntelliJ Platform 2024.3.5

[Unreleased]: https://github.com/codeclocker/codeclocker-intellij-plugin/compare/v1.11.0...HEAD
[Unreleased]: https://github.com/codeclocker/codeclocker-intellij-plugin/compare/v1.12.0...HEAD
[1.12.0]: https://github.com/codeclocker/codeclocker-intellij-plugin/compare/v1.11.0...v1.12.0
[1.11.0]: https://github.com/codeclocker/codeclocker-intellij-plugin/compare/v1.10.0...v1.11.0
[1.10.0]: https://github.com/codeclocker/codeclocker-intellij-plugin/compare/v1.9.0...v1.10.0
[1.9.0]: https://github.com/codeclocker/codeclocker-intellij-plugin/compare/v1.8.0...v1.9.0
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ intellijPlatformTesting {

spotless {
java {
googleJavaFormat()
googleJavaFormat("1.25.2")
importOrder()
removeUnusedImports()
targetExclude("build/**/*.java")
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pluginGroup = com.codeclocker
pluginName = CodeClocker
pluginRepositoryUrl = https://github.com/codeclocker/codeclocker-intellij-plugin
# SemVer format -> https://semver.org
pluginVersion = 1.11.0
pluginVersion = 1.12.0

# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 252
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,5 @@ public final class AnalyticsEventType {

private AnalyticsEventType() {}

// Widget events
public static final String STATUS_BAR_WIDGET_CLICK = "status_bar_widget_click";

// Widget popup actions
public static final String POPUP_WEB_DASHBOARD_CLICK = "popup_web_dashboard_click";
public static final String POPUP_SAVE_HISTORY_CLICK = "popup_save_history_click";
public static final String POPUP_RENEW_SUBSCRIPTION_CLICK = "popup_renew_subscription_click";
public static final String POPUP_SET_GOALS_CLICK = "popup_set_goals_click";
public static final String POPUP_SET_PROJECT_GOALS_CLICK = "popup_set_project_goals_click";
public static final String POPUP_AUTO_PAUSE_CLICK = "popup_auto_pause_click";
public static final String POPUP_DASHBOARD_CLICK = "popup_dashboard_click";
public static final String POPUP_ACTIVITY_REPORT_CLICK = "popup_activity_report_click";

// Plugin lifecycle events
public static final String PLUGIN_STARTED = "plugin_started";
public static final String PLUGIN_STOPPED = "plugin_stopped";

// Onboarding tour events
public static final String TOUR_WELCOME_START = "tour_welcome_start";
public static final String TOUR_WELCOME_SKIP = "tour_welcome_skip";
public static final String TOUR_STATUS_BAR_NEXT = "tour_status_bar_next";
public static final String TOUR_STATUS_BAR_SKIP = "tour_status_bar_skip";
public static final String TOUR_ACTIVITY_POPUP_NEXT = "tour_activity_popup_next";
public static final String TOUR_ACTIVITY_POPUP_SKIP = "tour_activity_popup_skip";
public static final String TOUR_GOALS_SET = "tour_goals_set";
public static final String TOUR_GOALS_LATER = "tour_goals_later";
public static final String TOUR_GOALS_SKIP = "tour_goals_skip";
public static final String TOUR_HUB_CONNECT = "tour_hub_connect";
public static final String TOUR_HUB_SKIP = "tour_hub_skip";

// Goal events
public static final String SET_NEW_GOAL = "set_new_goal";
public static final String PLUGIN_ACTIVE = "plugin_active";
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

/**
Expand All @@ -21,11 +20,13 @@ public class AnalyticsReportingTask implements Disposable {
private static final Logger LOG = Logger.getInstance(AnalyticsReportingTask.class);

private static final int FLUSH_INTERVAL_MINUTES = 5;
private static final int PLUGIN_ACTIVE_INTERVAL_MINUTES = 23 * 60;

private final AnalyticsQueue analyticsQueue;
private final AnalyticsHttpClient analyticsHttpClient;

private ScheduledFuture<?> task;
private ScheduledFuture<?> pluginActiveTask;
private IdeContext cachedIdeContext;

public AnalyticsReportingTask() {
Expand All @@ -40,8 +41,14 @@ public void schedule() {
return;
}

// Track plugin started event
track(AnalyticsEventType.PLUGIN_STARTED);
// Track plugin active event immediately and every 23 hours
trackPluginActive();
pluginActiveTask =
EXECUTOR.scheduleWithFixedDelay(
this::trackPluginActive,
PLUGIN_ACTIVE_INTERVAL_MINUTES,
PLUGIN_ACTIVE_INTERVAL_MINUTES,
MINUTES);

task =
EXECUTOR.scheduleWithFixedDelay(
Expand All @@ -59,14 +66,8 @@ public void track(String eventType) {
analyticsQueue.track(eventType);
}

/**
* Tracks an analytics event with properties.
*
* @param eventType The type of event to track
* @param properties Additional event properties
*/
public void track(String eventType, Map<String, Object> properties) {
analyticsQueue.track(eventType, properties);
private void trackPluginActive() {
track(AnalyticsEventType.PLUGIN_ACTIVE);
}

/** Flushes queued analytics events to the backend. */
Expand Down Expand Up @@ -111,9 +112,6 @@ private IdeContext getIdeContext() {
public void dispose() {
LOG.info("Disposing AnalyticsReportingTask - flushing remaining events");

// Track plugin stopped event
track(AnalyticsEventType.PLUGIN_STOPPED);

try {
// Perform final flush
flushAnalytics();
Expand All @@ -122,6 +120,9 @@ public void dispose() {
LOG.warn("Error during final analytics flush", e);
}

if (pluginActiveTask != null) {
pluginActiveTask.cancel(false);
}
if (task != null) {
task.cancel(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import static com.intellij.notification.NotificationType.INFORMATION;

import com.codeclocker.plugin.intellij.analytics.Analytics;
import com.codeclocker.plugin.intellij.analytics.AnalyticsEventType;
import com.intellij.ide.DataManager;
import com.intellij.notification.NotificationAction;
import com.intellij.notification.NotificationGroupManager;
Expand Down Expand Up @@ -339,7 +337,6 @@ private static class SetNewGoalAction extends com.intellij.notification.Notifica
public void actionPerformed(
com.intellij.openapi.actionSystem.AnActionEvent e,
com.intellij.notification.Notification notification) {
Analytics.track(AnalyticsEventType.SET_NEW_GOAL);
notification.expire();
GoalSettingsDialog.showDialog();
}
Expand All @@ -357,7 +354,6 @@ private static class SetProjectGoalAction extends com.intellij.notification.Noti
public void actionPerformed(
com.intellij.openapi.actionSystem.AnActionEvent e,
com.intellij.notification.Notification notification) {
Analytics.track(AnalyticsEventType.SET_NEW_GOAL);
notification.expire();
Project project = e.getProject();
if (project != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

import static com.intellij.notification.NotificationType.INFORMATION;

import com.codeclocker.plugin.intellij.analytics.Analytics;
import com.codeclocker.plugin.intellij.analytics.AnalyticsEventType;
import com.codeclocker.plugin.intellij.apikey.EnterApiKeyAction;
import com.codeclocker.plugin.intellij.goal.GoalSettingsDialog;
import com.intellij.notification.Notification;
Expand Down Expand Up @@ -40,19 +38,9 @@ private static void showWelcomeStep(Project project, OnboardingService service)
INFORMATION);

notification.addAction(
NotificationAction.createSimpleExpiring(
"Start tour",
() -> {
Analytics.track(AnalyticsEventType.TOUR_WELCOME_START);
service.nextStep();
}));
NotificationAction.createSimpleExpiring("Start tour", service::nextStep));
notification.addAction(
NotificationAction.createSimpleExpiring(
"Skip tour",
() -> {
Analytics.track(AnalyticsEventType.TOUR_WELCOME_SKIP);
service.skipOnboarding();
}));
NotificationAction.createSimpleExpiring("Skip tour", service::skipOnboarding));

notification.notify(project);
}
Expand All @@ -78,19 +66,9 @@ private static void showStatusBarWidgetStep(Project project, OnboardingService s
INFORMATION);

notification.addAction(
NotificationAction.createSimpleExpiring(
"Got it, Next",
() -> {
Analytics.track(AnalyticsEventType.TOUR_STATUS_BAR_NEXT);
service.nextStep();
}));
NotificationAction.createSimpleExpiring("Got it, Next", service::nextStep));
notification.addAction(
NotificationAction.createSimpleExpiring(
"Skip tour",
() -> {
Analytics.track(AnalyticsEventType.TOUR_STATUS_BAR_SKIP);
service.skipOnboarding();
}));
NotificationAction.createSimpleExpiring("Skip tour", service::skipOnboarding));

notification.notify(project);
}
Expand All @@ -110,19 +88,9 @@ private static void showActivityPopupStep(Project project, OnboardingService ser
INFORMATION);

notification.addAction(
NotificationAction.createSimpleExpiring(
"Got it, Next",
() -> {
Analytics.track(AnalyticsEventType.TOUR_ACTIVITY_POPUP_NEXT);
service.nextStep();
}));
NotificationAction.createSimpleExpiring("Got it, Next", service::nextStep));
notification.addAction(
NotificationAction.createSimpleExpiring(
"Skip tour",
() -> {
Analytics.track(AnalyticsEventType.TOUR_ACTIVITY_POPUP_SKIP);
service.skipOnboarding();
}));
NotificationAction.createSimpleExpiring("Skip tour", service::skipOnboarding));

notification.notify(project);
}
Expand All @@ -142,7 +110,6 @@ private static void showGoalsStep(Project project, OnboardingService service) {
NotificationAction.createSimpleExpiring(
"Set goals now",
() -> {
Analytics.track(AnalyticsEventType.TOUR_GOALS_SET);
ApplicationManager.getApplication()
.invokeLater(
() -> {
Expand All @@ -151,19 +118,9 @@ private static void showGoalsStep(Project project, OnboardingService service) {
});
}));
notification.addAction(
NotificationAction.createSimpleExpiring(
"Maybe later",
() -> {
Analytics.track(AnalyticsEventType.TOUR_GOALS_LATER);
service.nextStep();
}));
NotificationAction.createSimpleExpiring("Maybe later", service::nextStep));
notification.addAction(
NotificationAction.createSimpleExpiring(
"Skip tour",
() -> {
Analytics.track(AnalyticsEventType.TOUR_GOALS_SKIP);
service.skipOnboarding();
}));
NotificationAction.createSimpleExpiring("Skip tour", service::skipOnboarding));

notification.notify(project);
}
Expand All @@ -186,7 +143,6 @@ private static void showHubConnectionStep(Project project, OnboardingService ser
NotificationAction.createSimpleExpiring(
"Connect to Hub",
() -> {
Analytics.track(AnalyticsEventType.TOUR_HUB_CONNECT);
ApplicationManager.getApplication()
.invokeLater(
() -> {
Expand All @@ -195,12 +151,7 @@ private static void showHubConnectionStep(Project project, OnboardingService ser
});
}));
notification.addAction(
NotificationAction.createSimpleExpiring(
"Skip, finish tour",
() -> {
Analytics.track(AnalyticsEventType.TOUR_HUB_SKIP);
service.completeOnboarding();
}));
NotificationAction.createSimpleExpiring("Skip, finish tour", service::completeOnboarding));

notification.notify(project);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import static com.codeclocker.plugin.intellij.services.vcs.ChangesActivityTracker.GLOBAL_REMOVALS;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

import com.codeclocker.plugin.intellij.analytics.Analytics;
import com.codeclocker.plugin.intellij.analytics.AnalyticsEventType;
import com.codeclocker.plugin.intellij.apikey.ApiKeyLifecycle;
import com.codeclocker.plugin.intellij.apikey.ApiKeyPersistence;
import com.codeclocker.plugin.intellij.apikey.EnterApiKeyAction;
Expand Down Expand Up @@ -120,28 +118,20 @@ public boolean isSelectable(String value) {
@Override
public PopupStep<?> onChosen(String selectedValue, boolean finalChoice) {
if (WEB_DASHBOARD.equals(selectedValue)) {
Analytics.track(AnalyticsEventType.POPUP_WEB_DASHBOARD_CLICK);
BrowserUtil.browse(HUB_UI_HOST);
} else if (SAVE_HISTORY.equals(selectedValue)) {
Analytics.track(AnalyticsEventType.POPUP_SAVE_HISTORY_CLICK);
EnterApiKeyAction.showAction();
} else if (RENEW_SUBSCRIPTION.equals(selectedValue)) {
Analytics.track(AnalyticsEventType.POPUP_RENEW_SUBSCRIPTION_CLICK);
BrowserUtil.browse(HUB_UI_HOST + "/payment");
} else if (SET_GOALS.equals(selectedValue)) {
Analytics.track(AnalyticsEventType.POPUP_SET_GOALS_CLICK);
GoalSettingsDialog.showDialog();
} else if (SET_PROJECT_GOALS.equals(selectedValue)) {
Analytics.track(AnalyticsEventType.POPUP_SET_PROJECT_GOALS_CLICK);
ProjectGoalSettingsDialog.showDialog(project);
} else if (AUTO_PAUSE.equals(selectedValue)) {
Analytics.track(AnalyticsEventType.POPUP_AUTO_PAUSE_CLICK);
TrackingSettingsDialog.showDialog();
} else if (DASHBOARD.equals(selectedValue)) {
Analytics.track(AnalyticsEventType.POPUP_DASHBOARD_CLICK);
openToolWindowTab(project, "Dashboard");
} else if (ACTIVITY_REPORT.equals(selectedValue)) {
Analytics.track(AnalyticsEventType.POPUP_ACTIVITY_REPORT_CLICK);
openToolWindowTab(project, "Activity");
}
return FINAL_CHOICE;
Expand Down
Loading
Loading