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
5 changes: 5 additions & 0 deletions .changeset/quiet-otters-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
bump: patch
---

Anonymous usage metrics now record a command under the exact label typed, so a command and its aliases are counted separately instead of both at once.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
import java.util.Locale;

/**
* Counts every SetHomesTwo command typed by a player or the console, by
* canonical name and by the label actually typed. Commands owned by other
* plugins are ignored. Never cancels or alters the event.
* Counts every SetHomesTwo command typed by a player or the console, once,
* under the label actually typed: the canonical name goes to COMMAND and an
* alias to ALIAS, so the two can be retired on separate evidence. Commands
* owned by other plugins are ignored. Never cancels or alters the event.
*/
public class CommandUsageListener implements Listener {

Expand Down Expand Up @@ -50,8 +51,11 @@ void count(String commandLine) {
String typed = label.startsWith(namespace) ? label.substring(namespace.length()) : label;

UsageCounters counters = plugin.getUsageCounters();
counters.increment(UsageCounters.Family.COMMAND, command.getName());
counters.increment(UsageCounters.Family.ALIAS, typed);
if (typed.equals(command.getName().toLowerCase(Locale.ROOT))) {
counters.increment(UsageCounters.Family.COMMAND, command.getName());
} else {
counters.increment(UsageCounters.Family.ALIAS, typed);
}
} catch (RuntimeException ignored) {
// Counting is best effort.
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ private static final class BStatsHandle implements AutoCloseable {
metrics.addCustomChart(new SingleLineChart(commandChartId(command),
() -> share.count(UsageCounters.Family.COMMAND, command)));
}
metrics.addCustomChart(new SingleLineChart("commands_total", () -> share.total(UsageCounters.Family.COMMAND)));
metrics.addCustomChart(new SingleLineChart("commands_total",
() -> share.total(UsageCounters.Family.COMMAND, UsageCounters.Family.ALIAS)));

for (String alias : declaredAliases(plugin)) {
metrics.addCustomChart(new SingleLineChart(aliasChartId(alias),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ int count(UsageCounters.Family family, String key) {
return window(family).getOrDefault(key, 0);
}

/** Sum of every key in the window. */
int total(UsageCounters.Family family) {
/** Sum of every key in the window, across one family or several. */
int total(UsageCounters.Family... families) {
int sum = 0;
for (int value : window(family).values()) sum += value;
for (UsageCounters.Family family : families) {
for (int value : window(family).values()) sum += value;
}
return sum;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void aCanonicalCommandCountsUnderItsOwnName() {
playerTypes("/go-home base");

assertEquals(1, commands().get("go-home"));
assertEquals(1, aliases().get("go-home"));
assertTrue(aliases().isEmpty(), "a canonical name is not an alias use");
}

@Test
Expand All @@ -45,21 +45,30 @@ void aDispatchedCommandIsCounted() {
}

@Test
void anAliasCountsUnderTheCanonicalNameAndTheTypedAlias() {
void anAliasCountsOnlyUnderTheTypedAlias() {
playerTypes("/sethome base");

assertEquals(1, commands().get("create-home"));
assertEquals(1, aliases().get("sethome"));
assertTrue(!aliases().containsKey("create-home"));
assertTrue(commands().isEmpty(), "an alias use is not a use of the canonical name");
}

@Test
void aCommandAndItsAliasAreCountedSeparately() {
playerTypes("/create-home one");
playerTypes("/sethome two");
playerTypes("/sethome three");

assertEquals(1, commands().get("create-home"));
assertEquals(2, aliases().get("sethome"));
}

@Test
void theNamespacedFormCountsOnceWithoutTheNamespace() {
playerTypes("/sethomestwo:home base");

assertEquals(1, commands().get("go-home"));
assertEquals(1, aliases().get("home"));
assertEquals(1, commands().size());
assertEquals(1, aliases().size());
assertTrue(commands().isEmpty());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import static com.samleighton.sethomestwo.metrics.UsageCounters.Family.ALIAS;
import static com.samleighton.sethomestwo.metrics.UsageCounters.Family.COMMAND;
import static com.samleighton.sethomestwo.metrics.UsageCounters.Family.GUI_ACTION;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
Expand Down Expand Up @@ -76,6 +77,19 @@ void anEmptyWindowIsStillOneWindow() {
assertEquals(1, share.total(COMMAND));
}

@Test
void aTotalOverSeveralFamiliesAddsUpOneWindowOfEach() {
UsageCounters counters = new UsageCounters();
counters.increment(COMMAND, "create-home");
counters.increment(ALIAS, "sethome");
counters.increment(ALIAS, "sethome");
WindowShare share = share(counters);

assertEquals(3, share.total(COMMAND, ALIAS));
assertEquals(1, share.count(COMMAND, "create-home"), "each family is drained once, not twice");
assertEquals(2, share.count(ALIAS, "sethome"));
}

@Test
void familiesDoNotLeakIntoEachOther() {
UsageCounters counters = new UsageCounters();
Expand Down
Loading