From c60f1be9b3bc723431cb8d1f09e82bdd63c4d3cf Mon Sep 17 00:00:00 2001 From: pajlada Date: Sun, 25 Aug 2024 10:49:13 +0200 Subject: [PATCH] refactor: file writing (#8) Co-authored-by: iProdigy --- .gitignore | 2 +- .../java/actionlogger/ActionLoggerPlugin.java | 37 +++++------ .../java/actionlogger/writers/JsonWriter.java | 61 +++++++++++++------ 3 files changed, 60 insertions(+), 40 deletions(-) diff --git a/.gitignore b/.gitignore index a28bff2..df285b4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ build .classpath nbactions.xml nb-configuration.xml -nbproject/ \ No newline at end of file +nbproject/ diff --git a/src/main/java/actionlogger/ActionLoggerPlugin.java b/src/main/java/actionlogger/ActionLoggerPlugin.java index bf0fe45..32a6bdc 100644 --- a/src/main/java/actionlogger/ActionLoggerPlugin.java +++ b/src/main/java/actionlogger/ActionLoggerPlugin.java @@ -6,18 +6,16 @@ import com.google.gson.Gson; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; -import net.runelite.client.RuneLite; import net.runelite.client.eventbus.EventBus; +import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.events.ClientShutdown; import net.runelite.client.input.KeyManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import javax.inject.Inject; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; -import java.nio.file.Path; +import java.util.concurrent.ScheduledExecutorService; @Slf4j @PluginDescriptor(name = "Action Logger", description = "Log user & server actions to disk", tags = {"actionlogger"}) @@ -26,22 +24,15 @@ public class ActionLoggerPlugin extends Plugin { private @Inject EventBus eventBus; private @Inject Client client; private @Inject Gson gson; + private @Inject ScheduledExecutorService executor; private DialogueTracker dialogueTracker = null; private VarTracker varTracker = null; - private FileOutputStream fh = null; private JsonWriter writer = null; @Override - protected void startUp() throws FileNotFoundException { - var dir = new File(RuneLite.RUNELITE_DIR, "action-logger"); - //noinspection ResultOfMethodCallIgnored - dir.mkdir(); - - var path = Path.of(dir.getPath()).resolve(String.format("%d-logs.txt", System.currentTimeMillis())).toString(); - fh = new FileOutputStream(path); - - writer = new JsonWriter(gson, client, fh); + protected void startUp() throws IOException { + writer = new JsonWriter(gson, client, executor); dialogueTracker = new DialogueTracker(writer, client); eventBus.register(dialogueTracker); @@ -62,14 +53,18 @@ protected void shutDown() throws IOException { eventBus.unregister(varTracker); varTracker = null; + writer.close(); writer = null; - if (fh != null) { - fh.flush(); - fh.close(); - fh = null; - } - log.debug("Shut down Action Logger"); } + + @Subscribe + protected void onClientShutdown(ClientShutdown event) { + try { + writer.close(); + } catch (Exception e) { + log.warn("Failed to close writer", e); + } + } } diff --git a/src/main/java/actionlogger/writers/JsonWriter.java b/src/main/java/actionlogger/writers/JsonWriter.java index ead68a2..d717208 100644 --- a/src/main/java/actionlogger/writers/JsonWriter.java +++ b/src/main/java/actionlogger/writers/JsonWriter.java @@ -2,36 +2,61 @@ import actionlogger.Utils; import com.google.gson.Gson; -import lombok.RequiredArgsConstructor; +import lombok.Value; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; +import net.runelite.client.RuneLite; import javax.annotation.Nonnull; -import java.io.FileOutputStream; +import java.io.BufferedWriter; +import java.io.Closeable; +import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.util.concurrent.ExecutorService; @Slf4j -@RequiredArgsConstructor -public class JsonWriter { +public class JsonWriter implements Closeable { private final Gson gson; private final Client client; - private final FileOutputStream fh; + private final ExecutorService executor; + private final BufferedWriter fh; + + public JsonWriter(Gson gson, Client client, ExecutorService executor) throws IOException { + this.gson = gson; + this.client = client; + this.executor = executor; + + var dir = new File(RuneLite.RUNELITE_DIR, "action-logger"); + //noinspection ResultOfMethodCallIgnored + dir.mkdir(); + + var path = dir.toPath().resolve(String.format("%d-logs.txt", System.currentTimeMillis())); + this.fh = Files.newBufferedWriter(path); + } public void write(@Nonnull String type, @Nonnull Object data) { - try { - var payload = new Payload(this.client.getTickCount(), Utils.getTimestamp(), type, data); - fh.write(gson.toJson(payload).getBytes()); - fh.write('\n'); - } catch (IOException e) { - log.warn("Failed to write DialogueTracker data: {}", e.getMessage()); - } + var payload = new Payload(this.client.getTickCount(), Utils.getTimestamp(), type, data); + executor.execute(() -> { + try { + fh.write(gson.toJson(payload)); + fh.newLine(); + } catch (IOException e) { + log.warn("Failed to write DialogueTracker data: {}", e.getMessage()); + } + }); + } + + @Override + public void close() throws IOException { + fh.close(); } - @RequiredArgsConstructor - static private class Payload { - private final Integer tickCount; - private final String timestamp; - private final String type; - private final Object data; + @Value + private static class Payload { + int tickCount; + String timestamp; + String type; + Object data; } }