X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fanalytics%2FGoogleAnalytics4.java;h=bbbbee830652949c33c245379990114028ea9845;hb=fecbdab721ea3f701b9c8107a5aac5371617943d;hp=39975438910e048e43cc7206c305d6e478801953;hpb=7f2fffff9499545aff4f6189455b21ce1fa50501;p=jalview.git diff --git a/src/jalview/analytics/GoogleAnalytics4.java b/src/jalview/analytics/GoogleAnalytics4.java index 3997543..bbbbee8 100644 --- a/src/jalview/analytics/GoogleAnalytics4.java +++ b/src/jalview/analytics/GoogleAnalytics4.java @@ -10,12 +10,16 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.AbstractMap; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; import java.util.UUID; +import jalview.bin.Cache; import jalview.bin.Console; +import jalview.util.ChannelProperties; public class GoogleAnalytics4 { @@ -43,37 +47,67 @@ public class GoogleAnalytics4 private static boolean ENABLED = false; - public GoogleAnalytics4() + private static GoogleAnalytics4 instance = null; + + private static final String appName; + + private static final String version; + + static { - this.reset(); + appName = ChannelProperties.getProperty("app_name") + " Desktop"; + version = Cache.getProperty("VERSION") + "_" + + Cache.getDefault("BUILD_DATE", "unknown"); } - private static void setEnabled(boolean b) + private GoogleAnalytics4() { - ENABLED = b; + this.resetLists(); } - public void sendAnalytics() + public static void setEnabled(boolean b) { - sendAnalytics(null); + ENABLED = b; } - public void sendAnalytics(String path) + public void sendAnalytics(String eventName, String... paramsStrings) { + // clear out old lists + this.resetLists(); + if (!ENABLED) { Console.debug("GoogleAnalytics4 not enabled."); return; } - if (path != null) + Map params = new HashMap<>(); + + // add these to all events from this application instance + params.put("app_name", appName); + params.put("version", version); + params.put("TEST", "you've got to pick a pocket or twoooooo"); + + // can be overwritten by passed in params + if (paramsStrings != null && paramsStrings.length > 0) { - addEvent("page_event", path); + if (paramsStrings.length % 2 != 0) + { + Console.warn( + "Cannot addEvent with odd number of paramsStrings. Ignoring the last one."); + } + for (int i = 0; i < paramsStrings.length - 1; i += 2) + { + String key = paramsStrings[i]; + String value = paramsStrings[i + 1]; + params.put(key, value); + } } + + addEvent(eventName, params); addQueryStringValue("measurement_id", MEASUREMENT_ID); addQueryStringValue("api_secret", API_SECRET); addJsonValue("client_id", CLIENT_ID); addJsonValues("events", Event.toObjectList(events)); - // addJsonValue("events", ) StringBuilder urlSb = new StringBuilder(); urlSb.append(BASE_URL); urlSb.append('?'); @@ -88,8 +122,8 @@ public class GoogleAnalytics4 String jsonString = buildJson(); - Console.debug("##### HTTP Request is: '" + urlSb.toString() + "'"); - Console.debug("##### POSTed JSON is:\n" + jsonString); + Console.debug("GA4: HTTP Request is: '" + urlSb.toString() + "'"); + Console.debug("GA4: POSTed JSON is:\n" + jsonString); byte[] jsonBytes = jsonString.getBytes(StandardCharsets.UTF_8); int jsonLength = jsonBytes.length; @@ -132,20 +166,16 @@ public class GoogleAnalytics4 } } - public void addEvent(String name, String... paramsStrings) + public void addEvent(String name, Map params) { - if (paramsStrings.length % 2 != 0) - { - Console.error( - "Cannot addEvent with odd number of paramsStrings. Ignoring."); - return; - } Event event = new Event(name); - for (int i = 0; i < paramsStrings.length - 1; i += 2) + if (params != null && params.size() > 0) { - String key = paramsStrings[i]; - String value = paramsStrings[i + 1]; - event.addParam(key, value); + for (String key : params.keySet()) + { + String value = params.get(key); + event.addParam(key, value); + } } events.add(event); } @@ -186,7 +216,7 @@ public class GoogleAnalytics4 cookieValues.add(stringEntry(key, value)); } - public void reset() + private void resetLists() { jsonObject = new ArrayList<>(); events = new ArrayList(); @@ -194,6 +224,20 @@ public class GoogleAnalytics4 cookieValues = new ArrayList<>(); } + public static GoogleAnalytics4 getInstance() + { + if (instance == null) + { + instance = new GoogleAnalytics4(); + } + return instance; + } + + public static void reset() + { + getInstance().resetLists(); + } + private String buildQueryString() { StringBuilder sb = new StringBuilder(); @@ -227,23 +271,31 @@ public class GoogleAnalytics4 List> entries) { indent(sb, indent); - sb.append("{\n"); - for (Map.Entry entry : entries) + sb.append('{'); + newline(sb); + Iterator> entriesI = entries.iterator(); + while (entriesI.hasNext()) { + Map.Entry entry = entriesI.next(); String key = entry.getKey(); // TODO sensibly escape " characters in key Object value = entry.getValue(); - indent(sb, indent); - sb.append('"').append(key).append('"'); - sb.append(": "); - if (List.class.equals(value.getClass())) + indent(sb, indent + 1); + sb.append('"').append(quoteEscape(key)).append('"').append(':'); + space(sb); + if (value != null && value instanceof List) { - sb.append('\n'); + newline(sb); } - addJsonValue(sb, indent + 1, value); - sb.append(",\n"); + addJsonValue(sb, indent + 2, value); + if (entriesI.hasNext()) + { + sb.append(','); + } + newline(sb); } - sb.append("}\n"); + indent(sb, indent); + sb.append('}'); } private void addJsonValue(StringBuilder sb, int indent, Object value) @@ -254,66 +306,107 @@ public class GoogleAnalytics4 } try { - Class c = value.getClass(); - if (Map.Entry.class.equals(c)) + if (value instanceof Map.Entry) { Map.Entry entry = (Map.Entry) value; List> object = new ArrayList<>(); object.add(entry); - addJsonObject(sb, indent + 1, object); + addJsonObject(sb, indent, object); } - else if (List.class.equals(c)) + else if (value instanceof List) { // list of Map.Entries or list of values? List valueList = (List) value; - if (valueList.size() > 0 - && Map.Entry.class.equals(valueList.get(0).getClass())) + if (valueList.size() > 0 && valueList.get(0) instanceof Map.Entry) { // entries - indent(sb, indent); + // indent(sb, indent); List> entryList = (List>) value; - addJsonObject(sb, indent + 1, entryList); + addJsonObject(sb, indent, entryList); } else { // values indent(sb, indent); - sb.append("[\n"); - for (Object v : valueList) + sb.append('['); + newline(sb); + Iterator valueListI = valueList.iterator(); + while (valueListI.hasNext()) { - indent(sb, indent + 1); + Object v = valueListI.next(); addJsonValue(sb, indent + 1, v); - sb.append(",\n"); + if (valueListI.hasNext()) + { + sb.append(','); + } + newline(sb); } indent(sb, indent); sb.append("]"); } } - else if (String.class.equals(c)) + else if (value instanceof String) { - sb.append('"'); - sb.append((String) value); - sb.append('"'); + sb.append('"').append(quoteEscape((String) value)).append('"'); } - else if (Integer.class.equals(c)) + else if (value instanceof Integer) { sb.append(((Integer) value).toString()); } - else if (Boolean.class.equals(c)) + else if (value instanceof Boolean) { - sb.append(((Boolean) value).toString()); + sb.append('"').append(((Boolean) value).toString()).append('"'); } } catch (ClassCastException e) { Console.debug( - "Could not deal with type of jsonObject " + value.toString(), + "Could not deal with type of json Object " + value.toString(), e); } } - private void indent(StringBuilder sb, int indent) + private static String quoteEscape(String s) + { + if (s == null) + { + return null; + } + // this escapes quotation marks (") that aren't already escaped (in the + // string) ready to go into a quoted JSON string value + return s.replaceAll("((?= 0 && whitespace != null) + { + sb.append(whitespace.repeat(repeat)); + } + else + { + sb.append(whitespace); + } + } + + private static void indent(StringBuilder sb, int indent) + { + prettyWhitespace(sb, " ", indent); + } + + private static void newline(StringBuilder sb) + { + prettyWhitespace(sb, "\n", -1); + } + + private static void space(StringBuilder sb) { - sb.append(" ".repeat(indent)); + prettyWhitespace(sb, " ", -1); } protected static Map.Entry objectEntry(String s, Object o)