JAL-4001 Working Plausible analytics
authorBen Soares <b.soares@dundee.ac.uk>
Tue, 20 Jun 2023 17:53:21 +0000 (18:53 +0100)
committerBen Soares <b.soares@dundee.ac.uk>
Tue, 20 Jun 2023 17:53:21 +0000 (18:53 +0100)
src/jalview/analytics/Plausible.java
src/jalview/bin/Cache.java

index 381bcb8..0d6cd65 100644 (file)
@@ -22,6 +22,7 @@ import java.util.Map;
 
 import jalview.bin.Cache;
 import jalview.bin.Console;
+import jalview.bin.Jalview;
 import jalview.util.ChannelProperties;
 
 public class Plausible
@@ -35,7 +36,7 @@ public class Plausible
 
   private static final String DOMAIN = "jalview.org";
 
-  private static final String BASE_URL = "https://plausible.io/api/event";
+  private static final String API_BASE_URL = "https://plausible.io/api/event";
 
   public static final String APPLICATION_BASE_URL = "desktop://localhost";
 
@@ -49,6 +50,8 @@ public class Plausible
 
   private static boolean ENABLED = false;
 
+  private static boolean DEBUG = true;
+
   private static Plausible instance = null;
 
   private static final Map<String, String> defaultParams;
@@ -93,9 +96,10 @@ public class Plausible
     ENABLED = b;
   }
 
-  public void sendAnalytics(String eventName, String... paramsStrings)
+  public void sendEvent(String eventName, String path,
+          String... paramsStrings)
   {
-    sendAnalytics(eventName, false, paramsStrings);
+    sendEvent(eventName, path, false, paramsStrings);
   }
 
   /**
@@ -113,8 +117,8 @@ public class Plausible
    *          event. To emulate a webpage view use "page_location" as the URL in
    *          a "page_view" event.
    */
-  public void sendAnalytics(String eventName, boolean sendDefaultParams,
-          String... paramsStrings)
+  public void sendEvent(String eventName, String path,
+          boolean sendDefaultParams, String... paramsStrings)
   {
     // clear out old lists
     this.resetLists();
@@ -130,6 +134,10 @@ public class Plausible
     if (sendDefaultParams)
     {
       params.putAll(defaultParams);
+      if (Jalview.isHeadlessMode())
+      {
+        params.put("headless", "true");
+      }
     }
 
     // add (and overwrite with) the passed in params
@@ -148,17 +156,25 @@ public class Plausible
       }
     }
 
+    addJsonValue("domain", DOMAIN);
+    addJsonValue("name", eventName);
+    StringBuilder recordedUrlSb = new StringBuilder(APPLICATION_BASE_URL);
+    if (!APPLICATION_BASE_URL.endsWith("/") && !path.startsWith("/"))
+    {
+      recordedUrlSb.append("/");
+    }
+    recordedUrlSb.append(path);
+    addJsonValue("url", recordedUrlSb.toString());
     addEvent(eventName, params);
-    addQueryStringValue("measurement_id", MEASUREMENT_ID);
-    addQueryStringValue("api_secret", API_SECRET);
-    addQueryStringValue("_geo", "1");
-    addQueryStringValue("ep.anonymize_ip", "false");
-    addJsonValue("client_id", CLIENT_ID);
-    addJsonValues("events", Event.toObjectList(events));
+    addJsonObject("props", params);
     StringBuilder urlSb = new StringBuilder();
-    urlSb.append(BASE_URL);
-    urlSb.append('?');
-    urlSb.append(buildQueryString());
+    urlSb.append(API_BASE_URL);
+    String qs = buildQueryString();
+    if (qs != null && qs.length() > 0)
+    {
+      urlSb.append('?');
+      urlSb.append(qs);
+    }
     try
     {
       URL url = new URL(urlSb.toString());
@@ -169,15 +185,17 @@ public class Plausible
 
       String jsonString = buildJson();
 
-      Console.debug("GA4: HTTP Request is: '" + urlSb.toString() + "'");
-      Console.debug("GA4: POSTed JSON is:\n" + jsonString);
+      Console.debug(
+              "Plausible: HTTP Request is: '" + urlSb.toString() + "'");
+      Console.debug("Plausible: POSTed JSON is:\n" + jsonString);
 
       byte[] jsonBytes = jsonString.getBytes(StandardCharsets.UTF_8);
       int jsonLength = jsonBytes.length;
 
       httpURLConnection.setFixedLengthStreamingMode(jsonLength);
       httpURLConnection.setRequestProperty("Content-Type",
-              "application/json; charset=UTF-8");
+              "application/json");
+      httpURLConnection.setRequestProperty("User-Agent", USER_AGENT);
       httpURLConnection.connect();
       try (OutputStream os = httpURLConnection.getOutputStream())
       {
@@ -219,9 +237,8 @@ public class Plausible
       return;
     } catch (IOException e)
     {
-      Console.debug(
-              "Connection to Plausible BASE_URL '" + BASE_URL + "' failed.",
-              e);
+      Console.debug("Connection to Plausible BASE_URL '" + API_BASE_URL
+              + "' failed.", e);
     } catch (ClassCastException e)
     {
       Console.debug(
@@ -244,8 +261,19 @@ public class Plausible
     events.add(event);
   }
 
+  private void addJsonObject(String key, Map<String, String> map)
+  {
+    List<Map.Entry<String, ? extends Object>> list = new ArrayList<>();
+    for (String k : map.keySet())
+    {
+      list.add(stringEntry(k, map.get(k)));
+    }
+    addJsonObject(key, list);
+
+  }
+
   private void addJsonObject(String key,
-          List<Map.Entry<String, Object>> object)
+          List<Map.Entry<String, ? extends Object>> object)
   {
     jsonObject.add(objectEntry(key, object));
   }
@@ -495,53 +523,4 @@ public class Plausible
   {
     return new AbstractMap.SimpleEntry<String, String>(s, v);
   }
-
-  private static class Event
-  {
-    private String name;
-
-    private List<Map.Entry<String, String>> params;
-
-    @SafeVarargs
-    public Event(String name, Map.Entry<String, String>... paramEntries)
-    {
-      this.name = name;
-      this.params = new ArrayList<Map.Entry<String, String>>();
-      for (Map.Entry<String, String> paramEntry : paramEntries)
-      {
-        if (paramEntry == null)
-        {
-          continue;
-        }
-        params.add(paramEntry);
-      }
-    }
-
-    public void addParam(String param, String value)
-    {
-      params.add(Plausible.stringEntry(param, value));
-    }
-
-    protected List<Map.Entry<String, Object>> toObject()
-    {
-      List<Map.Entry<String, Object>> object = new ArrayList<>();
-      object.add(Plausible.objectEntry("name", (Object) name));
-      if (params.size() > 0)
-      {
-        object.add(Plausible.objectEntry("params", (Object) params));
-      }
-      return object;
-    }
-
-    protected static List<Object> toObjectList(List<Event> events)
-    {
-      List<Object> eventObjectList = new ArrayList<>();
-      for (Event event : events)
-      {
-        eventObjectList.add((Object) event.toObject());
-      }
-      return eventObjectList;
-    }
-  }
-
 }
\ No newline at end of file
index 4e73b82..fbd70dd 100755 (executable)
@@ -53,7 +53,7 @@ import java.util.TreeSet;
 import javax.swing.LookAndFeel;
 import javax.swing.UIManager;
 
-import jalview.analytics.GoogleAnalytics4;
+import jalview.analytics.Plausible;
 import jalview.datamodel.PDBEntry;
 import jalview.gui.Preferences;
 import jalview.gui.UserDefinedColours;
@@ -964,7 +964,7 @@ public class Cache
 
   public static void initGoogleTracker(boolean headless)
   {
-    GoogleAnalytics4.setEnabled(true);
+    Plausible.setEnabled(true);
 
     String appName = ChannelProperties.getProperty("app_name") + " Desktop";
     String version = Cache.getProperty("VERSION") + "_"
@@ -991,31 +991,14 @@ public class Cache
     /*
     }
     */
-    GoogleAnalytics4 ga4 = GoogleAnalytics4.getInstance();
-
-    // This will add a page_view similar to the old UA analytics.
-    // We probably want to get rid of this once the application_launch event
-    // is being processed properly.
-    String[] params;
-    if (headless)
-    {
-      params = new String[] { "page_location",
-          GoogleAnalytics4.APPLICATION_BASE_URL + path, "page_title",
-          APPLICATION_STARTED, "headless", "true" };
-    }
-    else
-    {
-      params = new String[] { "page_location", path, "page_title",
-          APPLICATION_STARTED };
-    }
-    ga4.sendAnalytics("page_view", params);
+    Plausible plausible = Plausible.getInstance();
 
     // This will send a new "application_launch" event with parameters
     // including the old-style "path", the channel name and version
-    ga4.sendAnalytics("application_launch", true, params);
+    plausible.sendEvent("application_launch", path, true);
   }
 
-  private static final String APPLICATION_STARTED = "Application Started.";
+  private static final String APPLICATION_STARTED = "Application Started";
 
   /**
    * get the user's default colour if available