perf: Reuse a single JsonProvider.

This speeds up the formatter significantly.

Before:

    Benchmark                                         Mode  Cnt     Score      Error  Units
    FormatterBenchmark.massivelyStructuredLogRecord  thrpt   10  6552.727 ± 2169.572  ops/s
    FormatterBenchmark.simpleLogRecord               thrpt   10  8126.699 ± 2259.912  ops/s
    FormatterBenchmark.structuredLogRecord           thrpt   10  5594.849 ± 1129.151  ops/s

After:

    Benchmark                                         Mode  Cnt       Score        Error  Units
    FormatterBenchmark.massivelyStructuredLogRecord  thrpt   10  137879.001 ±  30467.644  ops/s
    FormatterBenchmark.simpleLogRecord               thrpt   10  896085.217 ± 249890.421  ops/s
    FormatterBenchmark.structuredLogRecord           thrpt   10  553428.807 ± 194787.754  ops/s

Change-Id: If184327a4ff0de0d92b769493dbf6270ba3a8c8e
diff --git a/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/Formatter.java b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/Formatter.java
index c4e36de..72b0b50 100644
--- a/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/Formatter.java
+++ b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/Formatter.java
@@ -4,6 +4,7 @@
 
 package eu.mulk.quarkus.googlecloud.jsonlogging;
 
+import jakarta.json.spi.JsonProvider;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
@@ -38,6 +39,7 @@
 
   private final List<StructuredParameterProvider> parameterProviders;
   private final List<LabelProvider> labelProviders;
+  private final JsonProvider json;
 
   /**
    * Constructs a {@link Formatter} with custom configuration.
@@ -53,6 +55,7 @@
       Collection<LabelProvider> labelProviders) {
     this.parameterProviders = List.copyOf(parameterProviders);
     this.labelProviders = List.copyOf(labelProviders);
+    this.json = JsonProvider.provider();
   }
 
   /**
@@ -152,7 +155,7 @@
             ndc,
             logRecord.getLevel().intValue() >= 1000 ? ERROR_EVENT_TYPE : null);
 
-    return entry.json().build().toString() + "\n";
+    return entry.json(json).build().toString() + "\n";
   }
 
   /**
diff --git a/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/LogEntry.java b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/LogEntry.java
index 5655373..8517bde 100644
--- a/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/LogEntry.java
+++ b/core/src/main/java/eu/mulk/quarkus/googlecloud/jsonlogging/LogEntry.java
@@ -5,9 +5,9 @@
 package eu.mulk.quarkus.googlecloud.jsonlogging;
 
 import io.smallrye.common.constraint.Nullable;
-import jakarta.json.Json;
 import jakarta.json.JsonObject;
 import jakarta.json.JsonObjectBuilder;
+import jakarta.json.spi.JsonProvider;
 import java.time.Instant;
 import java.util.List;
 import java.util.Map;
@@ -74,8 +74,8 @@
       this.function = function;
     }
 
-    JsonObject json() {
-      var b = Json.createObjectBuilder();
+    JsonObject json(JsonProvider json) {
+      var b = json.createObjectBuilder();
 
       if (file != null) {
         b.add("file", file);
@@ -107,13 +107,13 @@
       this(t.getEpochSecond(), t.getNano());
     }
 
-    JsonObject json() {
-      return Json.createObjectBuilder().add("seconds", seconds).add("nanos", nanos).build();
+    JsonObject json(JsonProvider json) {
+      return json.createObjectBuilder().add("seconds", seconds).add("nanos", nanos).build();
     }
   }
 
-  JsonObjectBuilder json() {
-    var b = Json.createObjectBuilder();
+  JsonObjectBuilder json(JsonProvider json) {
+    var b = json.createObjectBuilder();
 
     if (trace != null) {
       b.add("logging.googleapis.com/trace", trace);
@@ -128,7 +128,7 @@
     }
 
     if (!labels.isEmpty()) {
-      b.add("logging.googleapis.com/labels", jsonOfStringMap(labels));
+      b.add("logging.googleapis.com/labels", jsonOfStringMap(json, labels));
     }
 
     if (type != null) {
@@ -137,24 +137,25 @@
 
     return b.add("message", message)
         .add("severity", severity)
-        .add("timestamp", timestamp.json())
-        .add("logging.googleapis.com/sourceLocation", sourceLocation.json())
-        .addAll(jsonOfStringMap(mappedDiagnosticContext))
-        .addAll(jsonOfParameterMap(parameters));
+        .add("timestamp", timestamp.json(json))
+        .add("logging.googleapis.com/sourceLocation", sourceLocation.json(json))
+        .addAll(jsonOfStringMap(json, mappedDiagnosticContext))
+        .addAll(jsonOfParameterMap(json, parameters));
   }
 
-  private static JsonObjectBuilder jsonOfStringMap(Map<String, String> stringMap) {
+  private JsonObjectBuilder jsonOfStringMap(JsonProvider json, Map<String, String> stringMap) {
     return stringMap.entrySet().stream()
         .reduce(
-            Json.createObjectBuilder(),
+            json.createObjectBuilder(),
             (acc, x) -> acc.add(x.getKey(), x.getValue()),
             JsonObjectBuilder::addAll);
   }
 
-  private static JsonObjectBuilder jsonOfParameterMap(List<StructuredParameter> parameters) {
+  private JsonObjectBuilder jsonOfParameterMap(
+      JsonProvider json, List<StructuredParameter> parameters) {
     return parameters.stream()
         .reduce(
-            Json.createObjectBuilder(),
+            json.createObjectBuilder(),
             (acc, p) -> acc.addAll(p.json()),
             JsonObjectBuilder::addAll);
   }
diff --git a/core/src/test/java/eu/mulk/quarkus/googlecloud/jsonlogging/FormatterTest.java b/core/src/test/java/eu/mulk/quarkus/googlecloud/jsonlogging/FormatterTest.java
index b755230..6d40b15 100644
--- a/core/src/test/java/eu/mulk/quarkus/googlecloud/jsonlogging/FormatterTest.java
+++ b/core/src/test/java/eu/mulk/quarkus/googlecloud/jsonlogging/FormatterTest.java
@@ -2,7 +2,7 @@
 
 import static org.junit.jupiter.api.Assertions.assertLinesMatch;
 
-import jakarta.json.Json;
+import jakarta.json.spi.JsonProvider;
 import java.util.Collection;
 import java.util.List;
 import org.jboss.logmanager.ExtLogRecord;
@@ -11,6 +11,8 @@
 
 class FormatterTest {
 
+  private static final JsonProvider JSON = JsonProvider.provider();
+
   @Test
   void simpleRecord() {
     var logRecord = makeSimpleRecord();
@@ -43,7 +45,7 @@
         new StructuredParameterProvider() {
           @Override
           public StructuredParameter getParameter() {
-            var b = Json.createObjectBuilder();
+            var b = JSON.createObjectBuilder();
             b.add("traceId", "39f9a49a9567a8bd7087b708f8932550");
             b.add("spanId", "c7431b14630b633d");
             return () -> b;
@@ -88,7 +90,7 @@
     logRecord.setParameters(
         new Object[] {
           (StructuredParameter)
-              () -> Json.createObjectBuilder().add("one", 1).add("two", 2.0).add("yes", true),
+              () -> JSON.createObjectBuilder().add("one", 1).add("two", 2.0).add("yes", true),
           Label.of("a", "b")
         });
     return logRecord;
@@ -128,7 +130,7 @@
         new Object[] {
           (StructuredParameter)
               () -> {
-                var b = Json.createObjectBuilder();
+                var b = JSON.createObjectBuilder();
                 for (int i = 0; i < 10; i++) {
                   b.add("int-" + i, i);
                 }