Skip to content

Commit

Permalink
feat: allow message limits (#82)
Browse files Browse the repository at this point in the history
Signed-off-by: Andre Dietisheim <[email protected]>
  • Loading branch information
adietish committed Jun 28, 2024
1 parent eba5ef4 commit 2f8cb7e
Show file tree
Hide file tree
Showing 48 changed files with 4,203 additions and 60 deletions.
10 changes: 10 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ dependencies {
}

test {
// Discover and execute all other JUnit5-based tests
useJUnitPlatform()
afterSuite { desc, result ->
if (!desc.parent)
Expand All @@ -64,6 +65,15 @@ test {
}
}

tasks.register('platformTests', Test) {
// Discover and execute JUnit4-based EventCountsTest
useJUnit()
description = 'Runs the platform tests.'
group = 'verification'
outputs.upToDateWhen { false }
mustRunAfter test
}

configurations {
implementation {
exclude group: 'org.slf4j', module: 'slf4j-api'
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ideaVersion = IC-2020.3
ideaVersion = IC-2022.1
# build number ranges
# https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html
sinceIdeaBuild=203
sinceIdeaBuild=211
projectVersion=1.2.0-SNAPSHOT
intellijPluginVersion=1.16.1
jetBrainsToken=invalid
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
package com.redhat.devtools.intellij.telemetry.core;

import com.intellij.openapi.extensions.PluginDescriptor;
import com.redhat.devtools.intellij.telemetry.core.service.Environment;
import com.redhat.devtools.intellij.telemetry.core.service.Event;

public interface IMessageBroker {
void send(Event event);
void dispose();

interface IMessageBrokerFactory {
IMessageBroker create(boolean isDebug, PluginDescriptor descriptor);
IMessageBroker create(boolean isDebug, Environment environment, PluginDescriptor descriptor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
******************************************************************************/
package com.redhat.devtools.intellij.telemetry.core.configuration;

import org.jetbrains.annotations.Nullable;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.nio.file.Path;
Expand All @@ -28,7 +30,7 @@ public ClasspathConfiguration(Path file, ClassLoader classLoader) {
}

@Override
protected InputStream createInputStream(Path path) throws FileNotFoundException {
protected InputStream createInputStream(Path path) {
if (path == null) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
******************************************************************************/
package com.redhat.devtools.intellij.telemetry.core.configuration;

import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.Objects;

public abstract class CompositeConfiguration implements IConfiguration {

@Nullable
@Override
public String get(final String key) {
List<IConfiguration> configurations = getConfigurations();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class TelemetryConfiguration extends CompositeConfiguration {
private static final SaveableFileConfiguration FILE = new SaveableFileConfiguration(
Directories.RED_HAT.resolve("com.redhat.devtools.intellij.telemetry"));

private static TelemetryConfiguration INSTANCE = new TelemetryConfiguration();
private static final TelemetryConfiguration INSTANCE = new TelemetryConfiguration();

public static TelemetryConfiguration getInstance() {
return INSTANCE;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*******************************************************************************
* Copyright (c) 2024 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package com.redhat.devtools.intellij.telemetry.core.configuration.limits;

import com.intellij.openapi.util.text.StringUtil;

import java.util.Arrays;

public enum Enabled {
ALL("all"),
ERROR("error"),
CRASH("crash"),
OFF("off");

private final String value;

Enabled(String value) {
this.value = value;
}

private boolean hasValue(String value) {
if (StringUtil.isEmptyOrSpaces(value)) {
return this.value == null;
}
return value.equals(this.value);
}

public static Enabled safeValueOf(String value) {
return Arrays.stream(values())
.filter(instance -> instance.hasValue(value))
.findAny()
.orElse(ALL);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*******************************************************************************
* Copyright (c) 2024 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package com.redhat.devtools.intellij.telemetry.core.configuration.limits;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.Service;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.util.xmlb.XmlSerializerUtil;
import com.redhat.devtools.intellij.telemetry.core.service.Event;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import static com.redhat.devtools.intellij.telemetry.core.util.TimeUtils.isToday;

/**
* A counter that stores daily occurrences of events.
* The state is persisted and loaded by the IDEA platform
*
* @see PersistentStateComponent
*/
@Service
@State(
name = " com.redhat.devtools.intellij.telemetry.core.configuration.limits.EventCounts",
storages = @Storage(value = "eventCounts.xml")
)
public final class EventCounts implements PersistentStateComponent<EventCounts> {

public static EventCounts getInstance() {
return ApplicationManager.getApplication().getService(EventCounts.class);
}

private static final String COUNT_VALUES_SEPARATOR = ",";

EventCounts() {}

public final Map<String, String> counts = new HashMap<>();

@Override
public EventCounts getState() {
return this;
}

@Override
public void loadState(@NotNull EventCounts state) {
XmlSerializerUtil.copyBean(state, this);
}

@Override
public void noStateLoaded() {
PersistentStateComponent.super.noStateLoaded();
}

@Override
public void initializeComponent() {
PersistentStateComponent.super.initializeComponent();
}

@Nullable
public Count get(Event event) {
if (event == null) {
return null;
}
String countString = counts.get(event.getName());
return toCount(countString);
}

public void put(Event event) {
Count count = createOrUpdateCount(event);
put(event, count);
}

EventCounts put(Event event, Count count) {
if (event == null) {
return this;
}
counts.put(event.getName(), toString(count));
return this;
}

private Count createOrUpdateCount(Event event) {
Count count = get(event);
if (count != null) {
// update existing
count = count.newOccurrence();
} else {
// create new
count = new Count();
}
return count;
}

private Count toCount(String string) {
if (StringUtils.isEmpty(string)) {
return null;
}
String[] split = string.split(COUNT_VALUES_SEPARATOR);
LocalDateTime lastOccurrence = toLastOccurrence(split[0]);
int total = toTotal(split[1]);
return new Count(lastOccurrence, total);
}

private LocalDateTime toLastOccurrence(String value) {
try {
long epochSeconds = Long.parseLong(value);
return LocalDateTime.ofEpochSecond(epochSeconds, 0, ZonedDateTime.now().getOffset());
} catch (NumberFormatException e) {
return null;
}
}

private int toTotal(String value) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
return 0;
}
}

String toString(@NotNull Count count) {
long epochSecond = count.lastOccurrence.toEpochSecond(ZonedDateTime.now().getOffset());
return epochSecond + COUNT_VALUES_SEPARATOR + count.dailyTotal;
}

public static class Count {
private final LocalDateTime lastOccurrence;
private final int dailyTotal;

Count() {
this(LocalDateTime.now(), 1);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Count)) return false;
Count count = (Count) o;
return dailyTotal == count.dailyTotal && Objects.equals(lastOccurrence, count.lastOccurrence);
}

@Override
public int hashCode() {
return Objects.hash(lastOccurrence, dailyTotal);
}

Count(LocalDateTime lastOccurrence, int dailyTotal) {
this.lastOccurrence = lastOccurrence;
this.dailyTotal = dailyTotal;
}

public LocalDateTime getLastOccurrence() {
return lastOccurrence;
}

public int getDailyTotal() {
if (isToday(lastOccurrence)) {
return dailyTotal;
} else {
return 0;
}
}

public Count newOccurrence() {
return new Count(LocalDateTime.now(), getDailyTotal() + 1);
}
}
}
Loading

0 comments on commit 2f8cb7e

Please sign in to comment.