-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Andre Dietisheim <[email protected]>
- Loading branch information
Showing
26 changed files
with
3,120 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
...java/com/redhat/devtools/intellij/telemetry/core/configuration/limits/Configurations.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/******************************************************************************* | ||
* 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.diagnostic.Logger; | ||
import com.redhat.devtools.intellij.telemetry.core.util.Directories; | ||
import okhttp3.OkHttpClient; | ||
import okhttp3.Request; | ||
import okhttp3.Response; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.StandardCopyOption; | ||
import java.nio.file.attribute.BasicFileAttributes; | ||
import java.nio.file.attribute.FileTime; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.stream.Collectors; | ||
|
||
class Configurations { | ||
|
||
private static final Logger LOGGER = Logger.getInstance(Configurations.class); | ||
static final Path LOCAL = Directories.RED_HAT.resolve("telemetry-config.json"); | ||
static final String EMBEDDED = "/telemetry-config.json"; | ||
static final String REMOTE = "https://raw.githubusercontent.com/adietish/intellij-redhat-telemetry/issue-82/src/main/resources/telemetry-config.json"; | ||
|
||
private final OkHttpClient client = new OkHttpClient.Builder() | ||
.connectTimeout(5, TimeUnit.SECONDS) | ||
.readTimeout(5, TimeUnit.SECONDS) | ||
.writeTimeout(5, TimeUnit.SECONDS) | ||
.build(); | ||
|
||
public String getRemote() { | ||
Request request = new Request.Builder() | ||
.url(REMOTE) | ||
.addHeader("Content-Type", "application/json") | ||
.build(); | ||
try (Response response = client.newCall(request).execute()) { | ||
if (response.body() != null) { | ||
Files.copy(response.body().byteStream(), LOCAL, StandardCopyOption.REPLACE_EXISTING); | ||
} | ||
return getLocal(); | ||
} catch (Throwable e) { | ||
LOGGER.warn("Could not download remote limits configurations.", e); | ||
return null; | ||
} | ||
} | ||
|
||
public boolean localExists() { | ||
return Files.exists(LOCAL); | ||
} | ||
|
||
public FileTime getLocalLastModified() { | ||
try { | ||
if (!Files.exists(LOCAL)) { | ||
return null; | ||
} | ||
return Files.getLastModifiedTime(LOCAL); | ||
} catch (Throwable e) { | ||
return null; | ||
} | ||
} | ||
|
||
public String getLocal() { | ||
try { | ||
return toString(Files.newInputStream(LOCAL)); | ||
} catch (IOException e) { | ||
return null; | ||
} | ||
} | ||
|
||
public String getEmbedded() { | ||
return toString(Configurations.class.getResourceAsStream(EMBEDDED)); | ||
} | ||
|
||
private String toString(InputStream in) { | ||
if (in == null) { | ||
return null; | ||
} | ||
BufferedReader reader = new BufferedReader(new InputStreamReader(in)); | ||
return reader.lines().collect(Collectors.joining()); | ||
} | ||
|
||
} |
42 changes: 42 additions & 0 deletions
42
src/main/java/com/redhat/devtools/intellij/telemetry/core/configuration/limits/Enabled.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
146 changes: 146 additions & 0 deletions
146
...ain/java/com/redhat/devtools/intellij/telemetry/core/configuration/limits/EventState.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/******************************************************************************* | ||
* 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 java.time.Instant; | ||
import java.time.LocalDateTime; | ||
import java.time.ZoneId; | ||
import java.time.ZoneOffset; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
@Service | ||
@State( | ||
name = " com.redhat.devtools.intellij.telemetry.core.configuration.limits.EventState", | ||
storages = @Storage(value = "eventState.xml") | ||
) | ||
public final class EventState implements PersistentStateComponent<EventState> { | ||
|
||
public static EventState getInstance() { | ||
return ApplicationManager.getApplication().getService(EventState.class); | ||
} | ||
|
||
private static final String COUNT_VALUES_SEPARATOR = ","; | ||
|
||
public final Map<String, String> properties = new HashMap<>(); | ||
|
||
@Override | ||
public EventState getState() { | ||
return this; | ||
} | ||
|
||
@Override | ||
public void loadState(@NotNull EventState state) { | ||
XmlSerializerUtil.copyBean(state, this); | ||
} | ||
|
||
@Override | ||
public void noStateLoaded() { | ||
PersistentStateComponent.super.noStateLoaded(); | ||
} | ||
|
||
@Override | ||
public void initializeComponent() { | ||
PersistentStateComponent.super.initializeComponent(); | ||
} | ||
|
||
Count getCount(@NotNull Event event) { | ||
String key = toKey(event); | ||
String countString = properties.get(key); | ||
return toCount(countString); | ||
} | ||
|
||
private Count toCount(String string) { | ||
if (StringUtils.isEmpty(string)) { | ||
return null; | ||
} | ||
String[] split = string.split(COUNT_VALUES_SEPARATOR); | ||
LocalDateTime lastOccurrence = toLastOccurrence(split[1]); | ||
int total = toTotal(split[0]); | ||
return new Count(lastOccurrence, total); | ||
} | ||
|
||
private LocalDateTime toLastOccurrence(String value) { | ||
try { | ||
long epochSeconds = Long.parseLong(value); | ||
return LocalDateTime.ofEpochSecond(epochSeconds, 0, getOffset()); | ||
} catch (NumberFormatException e) { | ||
return null; | ||
} | ||
} | ||
|
||
private int toTotal(String value) { | ||
try { | ||
return Integer.parseInt(value); | ||
} catch (NumberFormatException e) { | ||
return 0; | ||
} | ||
} | ||
|
||
public void setCount(Event event, Count count) { | ||
if (event == null) { | ||
return; | ||
} | ||
String key = toKey(event); | ||
count = count.addOccurrence(); | ||
properties.put(key, toString(count)); | ||
} | ||
|
||
private String toKey(@NotNull Event event) { | ||
return event.getName().replaceAll("[^a-zA-Z0-9]", "_"); | ||
} | ||
|
||
String toString(Count count) { | ||
; | ||
long epochSecond = count.lastOccurrence.toEpochSecond(getOffset()); | ||
return epochSecond + COUNT_VALUES_SEPARATOR + count.total; | ||
} | ||
|
||
private ZoneOffset getOffset() { | ||
return ZoneId.systemDefault().getRules().getOffset(Instant.now()); | ||
} | ||
|
||
static class Count { | ||
private final LocalDateTime lastOccurrence; | ||
private final int total; | ||
|
||
Count() { | ||
this(LocalDateTime.now(), 0); | ||
} | ||
|
||
Count(LocalDateTime lastOccurrence, int total) { | ||
this.lastOccurrence = lastOccurrence; | ||
this.total = total; | ||
} | ||
|
||
public LocalDateTime lastOccurrence() { | ||
return lastOccurrence; | ||
} | ||
|
||
public int total() { | ||
return total; | ||
} | ||
|
||
public Count addOccurrence() { | ||
return new Count(LocalDateTime.now(), total + 1); | ||
} | ||
} | ||
} |
86 changes: 86 additions & 0 deletions
86
src/main/java/com/redhat/devtools/intellij/telemetry/core/configuration/limits/Filter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 percentile); | ||
|
||
boolean isExcludedByRatio(float percentile); | ||
|
||
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) { | ||
String value = event.getProperties().get(name); | ||
return glob.matches(value); | ||
} | ||
|
||
@Override | ||
public boolean isIncludedByRatio(float percentile) { | ||
return true; | ||
} | ||
|
||
@Override | ||
public boolean isExcludedByRatio(float percentile) { | ||
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 percentile) { | ||
return ratio != 0 | ||
&& percentile <= ratio; | ||
} | ||
|
||
@Override | ||
public boolean isExcludedByRatio(float percentile) { | ||
return 1 - ratio < percentile; | ||
} | ||
} | ||
} |
Oops, something went wrong.