Skip to content

Commit

Permalink
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 May 29, 2024
1 parent e09e6a0 commit 201a513
Show file tree
Hide file tree
Showing 17 changed files with 2,279 additions and 4 deletions.
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,86 @@
/*******************************************************************************
* 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.redhat.devtools.intellij.telemetry.core.service.Event;
import com.redhat.devtools.intellij.telemetry.core.util.BasicGlobPattern;

public interface Filter {

boolean isMatching(Event event);

boolean isIncludedByRatio(float hashLocation);

boolean isExcludedByRatio(float hashLocation);

class EventPropertyFilter implements Filter {
private final String name;
private final BasicGlobPattern glob;

EventPropertyFilter(String name, String valueGlob) {
this.name = name;
this.glob = BasicGlobPattern.compile(valueGlob);
}

@Override
public boolean isMatching(Event event) {
Object value = event.getProperties().get(name);
return value instanceof String
&& glob.matches((String) value);
}

@Override
public boolean isIncludedByRatio(float hashLocation) {
return true;
}

@Override
public boolean isExcludedByRatio(float hashLocation) {
return false;
}

}

class EventNameFilter implements Filter {
private final BasicGlobPattern name;
private final float ratio;
private final String dailyLimit;

EventNameFilter(String name, float ratio, String dailyLimit) {
this.name = BasicGlobPattern.compile(name);
this.ratio = ratio;
this.dailyLimit = dailyLimit;
}

public float getRatio() {
return ratio;
}

public String getDailyLimit() {
return dailyLimit;
}

@Override
public boolean isMatching(Event event) {
return name.matches(event.getName());
}

@Override
public boolean isIncludedByRatio(float hashLocation) {
return hashLocation <= ratio;
}

@Override
public boolean isExcludedByRatio(float hashLocation) {
return hashLocation > 1 - ratio;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*******************************************************************************
* 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 java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class MessageLimits {

private static MessageLimits INSTANCE = null;

public static MessageLimits getInstance() {
if (INSTANCE == null) {
INSTANCE = Factory.create();
}
return INSTANCE;
}

static class Factory {

static MessageLimits create() {
return create(readConfig());
}

static MessageLimits create(String config) {
List<PluginLimits> limits = createLimits(config);
return new MessageLimits(limits);
}

static String readConfig() {
InputStream inputStream = MessageLimits.class.getResourceAsStream("/telemetry-config.json");
if (inputStream == null) {
return null;
}
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
return reader.lines().collect(Collectors.joining());
}


private static List<PluginLimits> createLimits(String config) {
if (config == null) {
return Collections.emptyList();
}
try {
return PluginLimitsDeserialization.createPluginLimits(config);
} catch (IOException e) {
return new ArrayList<>();
}
}
}

private final List<PluginLimits> limits;

MessageLimits(List<PluginLimits> limits) {
this.limits = limits;
}

List<PluginLimits> get() {
return limits;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*******************************************************************************
* 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.redhat.devtools.intellij.telemetry.core.service.Event;
import com.redhat.devtools.intellij.telemetry.core.service.UserId;

import java.util.List;

public class PluginLimits {
private final String name;
private final Enabled enabled;
private final int refresh;
private final float ratio;
private final List<Filter> includes;
private final List<Filter> excludes;
private final UserId userId;

PluginLimits(String name, Enabled enabled, int refresh, float ratio, List<Filter> includes, List<Filter> excludes) {
this(name, enabled, refresh, ratio, includes, excludes, UserId.INSTANCE);
}

PluginLimits(String name, Enabled enabled, int refresh, float ratio, List<Filter> includes, List<Filter> excludes, UserId userId) {
this.name = name;
this.enabled = enabled;
this.refresh = refresh;
this.ratio = ratio;
this.includes = includes;
this.excludes = excludes;
this.userId = userId;
}

public boolean isDefault() {
return "*".equals(name);
}

Enabled getEnabled() {
return enabled;
}

int getRefresh() {
return refresh;
}

float getRatio() {
return ratio;
}


public boolean canSend(Event event) {
if (event == null) {
return false;
}
if (!isEnabled()
|| (isErrorOnly() && !event.hasError())) {
return false;
}

if (isOffRatio()) {
return false;
}

return isIncluded(event)
&& !isExcluded(event);
}

private boolean isOffRatio() {
if (userId == null) {
return false;
}
return ratio < userId.getPercentile();
}

boolean isEnabled() {
Enabled enabled = getEnabled();
return enabled != null
&& enabled != Enabled.OFF;
}

boolean isErrorOnly() {
Enabled enabled = getEnabled();
return enabled == Enabled.CRASH
|| enabled == Enabled.ERROR;
}

List<Filter> getIncludes() {
return includes;
}

boolean isIncluded(Event event) {
Filter matching = includes.stream()
.filter(filter -> filter.isMatching(event))
.findAny()
.orElse(null);
return matching == null
|| matching.isIncludedByRatio(userId.getPercentile());
}

boolean isExcluded(Event event) {
Filter matching = excludes.stream()
.filter(filter -> filter.isMatching(event))
.findAny()
.orElse(null);
return matching != null
&& matching.isExcludedByRatio(userId.getPercentile());
}

List<Filter> getExcludes() {
return excludes;
}

}
Loading

0 comments on commit 201a513

Please sign in to comment.