Skip to content

Commit

Permalink
Removed google analytics (#66), action_config required instead of act…
Browse files Browse the repository at this point in the history
…ions, .data no longer created or used, removed all java.io.File usages
  • Loading branch information
retrodaredevil committed Jun 26, 2023
1 parent e277c10 commit fbe2025
Show file tree
Hide file tree
Showing 28 changed files with 173 additions and 264 deletions.
2 changes: 1 addition & 1 deletion client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ dependencies {
implementation "org.apache.logging.log4j:log4j-core:$log4jVersion" // used for our custom error handler, otherwise not a necessary dependency
implementation "org.apache.logging.log4j:log4j-jcl:$log4jVersion" // commons logging bridge.
implementation "org.apache.logging.log4j:log4j-slf4j2-impl:$log4jVersion"
implementation 'com.brsanthu:google-analytics-java:2.0.0'

// https://github.com/slackapi/java-slack-sdk/releases
implementation 'com.slack.api:slack-api-client:1.29.2'
Expand All @@ -36,6 +35,7 @@ dependencies {

implementation 'info.debatty:java-string-similarity:2.0.0'

// TODO do we need this dependency?
implementation group: 'biz.paluch.logging', name: 'logstash-gelf', version: '1.15.0'

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import me.retrodaredevil.solarthing.util.sync.ResourceManager;
import okhttp3.OkHttpClient;

import java.io.File;
import java.nio.file.Path;
import java.time.Duration;
import java.time.ZoneId;
import java.util.Arrays;
Expand Down Expand Up @@ -51,15 +51,15 @@ public class SlackChatBotActionNode implements ActionNode {
private final String channelId;
private final Map<String, List<String>> permissionMap;
private final String sender;
private final File keyDirectory;
private final Path keyDirectory;

public SlackChatBotActionNode(
String appToken,
String authToken,
String channelId,
Map<String, List<String>> permissionMap,
String sender,
File keyDirectory
Path keyDirectory
) {
this.appToken = appToken;
this.authToken = authToken;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import me.retrodaredevil.action.node.convenient.SingleActionNode;
import me.retrodaredevil.action.node.environment.ActionEnvironment;

import java.io.File;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;

Expand All @@ -22,7 +22,7 @@ public WrappedSlackChatBotActionNode(
@JsonProperty(value = "channel_id", required = true) String channelId,
@JsonProperty(value = "permissions", required = true) Map<String, List<String>> permissionMap,
@JsonProperty(value = "sender", required = true) String sender,
@JsonProperty(value = "key_directory", required = true) File keyDirectory
@JsonProperty(value = "key_directory", required = true) Path keyDirectory
) {
// Wrap the RawActionNode in a SingleActionNode so that only one is active at a time -- the first one created and executed will be the one that is used
actionNode = SingleActionNode.create(new SlackChatBotActionNode(appToken, authToken, channelId, permissionMap, sender, keyDirectory));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,27 @@
import me.retrodaredevil.action.node.ActionNode;
import me.retrodaredevil.action.node.environment.ActionEnvironment;
import me.retrodaredevil.solarthing.AlterPacketsProvider;
import me.retrodaredevil.solarthing.actions.environment.*;
import me.retrodaredevil.solarthing.actions.environment.AlterPacketsEnvironment;
import me.retrodaredevil.solarthing.actions.environment.AuthorizationEnvironment;
import me.retrodaredevil.solarthing.actions.environment.OpenDatabaseCacheEnvironment;
import me.retrodaredevil.solarthing.actions.environment.SolarThingDatabaseEnvironment;
import me.retrodaredevil.solarthing.actions.environment.SourceIdEnvironment;
import me.retrodaredevil.solarthing.actions.environment.TimeZoneEnvironment;
import me.retrodaredevil.solarthing.commands.util.CommandManager;
import me.retrodaredevil.solarthing.database.SolarThingDatabase;
import me.retrodaredevil.solarthing.database.cache.DatabaseCache;

import java.io.File;
import java.nio.file.Path;

public class AlterManagerActionNode implements ActionNode {

private final String sender;
private final File keyDirectory;
private final Path keyDirectory;
private final int fragmentId;

public AlterManagerActionNode(
@JsonProperty(value = "sender", required = true) String sender,
@JsonProperty(value = "key_directory", required = true) File keyDirectory,
@JsonProperty(value = "key_directory", required = true) Path keyDirectory,
@JsonProperty(value = "fragment", required = true) int fragmentId) {
this.sender = sender;
this.keyDirectory = keyDirectory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import me.retrodaredevil.action.node.convenient.SingleActionNode;
import me.retrodaredevil.action.node.environment.ActionEnvironment;

import java.io.File;
import java.nio.file.Path;

/**
* Providing a fragment for something in the automation program is not something you would be expecting to see.
Expand All @@ -20,7 +20,7 @@ public class WrappedAlterManagerActionNode implements ActionNode {

public WrappedAlterManagerActionNode(
@JsonProperty(value = "sender", required = true) String sender,
@JsonProperty(value = "key_directory", required = true) File keyDirectory,
@JsonProperty(value = "key_directory", required = true) Path keyDirectory,
@JsonProperty(value = "fragment", required = true) int fragmentId
) {
actionNode = SingleActionNode.create(new AlterManagerActionNode(sender, keyDirectory, fragmentId));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,112 +1,42 @@
package me.retrodaredevil.solarthing.analytics;

import com.brsanthu.googleanalytics.GoogleAnalytics;
import com.brsanthu.googleanalytics.GoogleAnalyticsConfig;
import com.brsanthu.googleanalytics.request.DefaultRequest;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import me.retrodaredevil.solarthing.SolarThingConstants;
import me.retrodaredevil.solarthing.config.options.ProgramType;
import me.retrodaredevil.solarthing.program.JarUtil;
import me.retrodaredevil.solarthing.util.JacksonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;

public class AnalyticsManager {
/*
For future self setting this up again: in the View Settings in Google Analytics, you must have "Bot Filtering" turned off.
*/
private static final ObjectMapper MAPPER = JacksonUtil.defaultMapper();
private static final String ANALYTICS_NOTE = "(Note) For this SolarThing version, analytics are not sent. This will be changed in a future version. If you see this log message, a future version of SolarThing may send analytics data (if you decide to update).";
private static final Logger LOGGER = LoggerFactory.getLogger(AnalyticsManager.class);
private final GoogleAnalytics googleAnalytics;
private final boolean isEnabled;

public AnalyticsManager(boolean isEnabled, Path dataDirectory) {
/**
* Constructs the object. No connections should be created here and no analytics collection should be done just because the constructor was invoked.
*
* @param isEnabled true if analytics are enabled, false otherwise
*/
public AnalyticsManager(boolean isEnabled) {
this.isEnabled = isEnabled;
if (isEnabled) {
LOGGER.info(SolarThingConstants.SUMMARY_MARKER, "Google Analytics is ENABLED!");
Path file = dataDirectory.resolve("analytics_data.json");
AnalyticsData analyticsData = null;
try {
analyticsData = MAPPER.readValue(Files.newInputStream(file), AnalyticsData.class);
} catch (IOException e) {
LOGGER.debug(SolarThingConstants.NO_CONSOLE, "Couldn't read analytics data, but that's OK!", e);
}
if (analyticsData == null) {
analyticsData = new AnalyticsData(UUID.randomUUID());
LOGGER.info(SolarThingConstants.SUMMARY_MARKER, "Generated a new Analytics UUID");
try {
MAPPER.writeValue(Files.newOutputStream(file), analyticsData);
} catch (IOException e) {
LOGGER.warn(SolarThingConstants.SUMMARY_MARKER, "Couldn't save analytics data!", e);
}
}
final String clientId = analyticsData.uuid.toString();
LOGGER.debug("Using Analytics UUID: " + clientId);
googleAnalytics = GoogleAnalytics.builder()
.withConfig(new GoogleAnalyticsConfig()
.setThreadTimeoutSecs(5)
)
.withDefaultRequest(new DefaultRequest()
.applicationName("solarthing-program")
.applicationVersion("V-UNKNOWN")
.clientId(clientId)
)
.withTrackingId("UA-70767765-2")
.build();
LOGGER.info(SolarThingConstants.SUMMARY_MARKER, "Analytics are ENABLED! " + ANALYTICS_NOTE);
} else {
// TODO when the --validate argument is present, this is always printed. Think about if we want to let the user know what the actual configuration is
LOGGER.info(SolarThingConstants.SUMMARY_MARKER, "Google Analytics is disabled");
googleAnalytics = null;
LOGGER.info(SolarThingConstants.SUMMARY_MARKER, "Analytics are disabled");
}
}

public void sendStartUp(ProgramType programType) {
if (googleAnalytics != null) {
LOGGER.info("Sending program type to Google Analytics");
googleAnalytics.screenView()
.screenName(programType.getName())
.sendAsync();
googleAnalytics.event()
.eventCategory("startup")
.eventAction(programType.getName())
.eventLabel(JarUtil.getJarFileName()) // so we know what version they're running
.sendAsync();
if (isEnabled) {
LOGGER.info("Sending program type to analytics (" + programType + ") " + ANALYTICS_NOTE);
}
}
public void sendMateStatus(String data, int uptimeHours) {
if (googleAnalytics != null) {
LOGGER.info("Sending Mate status to Google Analytics. data=" + data + " uptime hours=" + uptimeHours);
googleAnalytics.event()
.eventCategory("status")
.eventAction("mate")
.eventLabel(data)
.eventValue(uptimeHours)
.sendAsync();
if (isEnabled) {
LOGGER.info("Sending Mate status to analytics. data=" + data + " uptime hours=" + uptimeHours + " " + ANALYTICS_NOTE);
}
}
public void sendRoverStatus(String data, int uptimeHours) {
if (googleAnalytics != null) {
LOGGER.info("Sending Rover status to Google Analytics. data=" + data + " uptime hours=" + uptimeHours);
googleAnalytics.event()
.eventCategory("status")
.eventAction("rover")
.eventLabel(data)
.eventValue(uptimeHours)
.sendAsync();
}
}
private static final class AnalyticsData {
@JsonProperty("uuid")
private final UUID uuid;

@JsonCreator
private AnalyticsData(@JsonProperty(value = "uuid", required = true) UUID uuid) {
this.uuid = uuid;
if (isEnabled) {
LOGGER.info("Sending Rover status to analytics. data=" + data + " uptime hours=" + uptimeHours + " " + ANALYTICS_NOTE);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
import me.retrodaredevil.solarthing.config.databases.DatabaseType;
import me.retrodaredevil.solarthing.config.databases.SimpleDatabaseType;

import java.io.File;
import java.nio.file.Path;

@JsonTypeName("latest")
public final class LatestFileDatabaseSettings implements DatabaseSettings {
public static final DatabaseType TYPE = new SimpleDatabaseType("latest");

private final File file;
private final Path file;

@JsonCreator
public LatestFileDatabaseSettings(@JsonProperty(value = "file", required = true) File file) {
public LatestFileDatabaseSettings(@JsonProperty(value = "file", required = true) Path file) {
this.file = file;
}

Expand All @@ -25,7 +25,7 @@ public String toString() {
return "Latest " + file;
}

public File getFile(){
public Path getFile(){
return file;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,28 @@
import me.retrodaredevil.solarthing.solar.renogy.rover.modbus.LocalRoverModbusSlave;
import me.retrodaredevil.solarthing.util.JacksonUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;

@JsonTypeName("rover")
public class DummyRoverModbusSlave implements DummyModbusSlave {
private static final ObjectMapper MAPPER = JacksonUtil.defaultMapper();

private final File file;
private final Path file;

@JsonCreator
public DummyRoverModbusSlave(@JsonProperty("file") File file) {
public DummyRoverModbusSlave(@JsonProperty("file") Path file) {
this.file = file;
}

@Override
public ModbusSlave createModbusSlave() {
final FileInputStream fileInputStream;
final InputStream fileInputStream;
try {
fileInputStream = new FileInputStream(file);
} catch (FileNotFoundException e) {
fileInputStream = Files.newInputStream(file);
} catch (IOException e) {
throw new RuntimeException("The dummy file was not found!", e);
}
final RoverStatusPacket roverStatusPacket;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
package me.retrodaredevil.solarthing.config.options;

import java.io.File;
import java.util.List;

/**
* Represents some sort of {@link ProgramOptions} that can contain actions that would usually
* be executed each "iteration".
*/
public interface ActionsOption extends ProgramOptions {
/**
* A legacy configuration option that currently is still supported, but will be removed in a future version
*/
List<File> getActionNodeFiles();

/**
* This will not be null, but may be {@link ActionConfig#EMPTY} by default.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package me.retrodaredevil.solarthing.config.options;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.annotation.JsonTypeName;
import me.retrodaredevil.solarthing.SolarThingConstants;
import me.retrodaredevil.solarthing.annotations.JsonExplicit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.time.Duration;
import java.util.Collections;
import java.util.List;

import static java.util.Objects.requireNonNull;
Expand All @@ -15,8 +17,8 @@
@JsonTypeName("automation")
@JsonExplicit
public class AutomationProgramOptions extends DatabaseTimeZoneOptionBase implements ActionsOption {
@JsonProperty("actions")
private List<File> actionNodeFiles = Collections.emptyList();
private static final Logger LOGGER = LoggerFactory.getLogger(AutomationProgramOptions.class);

@JsonProperty("action_config")
private ActionConfig actionConfig = ActionConfig.EMPTY;

Expand All @@ -28,11 +30,6 @@ public ProgramType getProgramType() {
return ProgramType.AUTOMATION;
}

@Override
public List<File> getActionNodeFiles() {
return requireNonNull(actionNodeFiles, "You cannot supply a null value here!");
}

@Override
public ActionConfig getActionConfig() {
return requireNonNull(actionConfig);
Expand All @@ -41,4 +38,11 @@ public ActionConfig getActionConfig() {
public long getPeriodMillis() {
return Duration.parse(periodDurationString).toMillis();
}

@JsonSetter("actions")
private void setActionNodeFiles(List<String> actionNodeFiles) {
LOGGER.error(SolarThingConstants.SUMMARY_MARKER, "(Deprecated) Please use action_config configuration instead of actions!");
// TODO use a different exception here
throw new RuntimeException("Migration required! You must now use action_config instead of actions to configure actions!");
}
}
Loading

0 comments on commit fbe2025

Please sign in to comment.