• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

knowledgepixels / nanopub-registry / 28155387420

25 Jun 2026 07:53AM UTC coverage: 31.926% (-0.2%) from 32.089%
28155387420

push

github

web-flow
chore: enhance and standardize logging across multiple components (#116)

* chore(EntryStatus): enhance logging for null and unsupported status value handling

* chore(logging): standardize logger variable names across multiple classes

* chore(CoverageFilter): enhance logging for coverage filter initialization and type checks

* chore(RegistryPeerConnector): enhance logging for peer connection and nanopub fetching

* chore(logging): enhance logging for request handling and error reporting in multiple pages

* chore(MainVerticle): enhance logging for HTTP server startup, request routing, and POST processing

* chore(Task): improve logging messages

* chore(Task): enhance logging for server status checks and account loading processes

* chore(RegistryInfo): add logging messages for RegistryInfo snapshot assembly and JSON serialization

* chore(logging): enhance logging throughout various components for better traceability and debugging

* chore(Utils): enhance logging for user IRI extraction in IntroNanopub

* chore(TrustStatePage): enhance logging for trust-state snapshot resolution and querying

* chore(NanopubLoader): enhance logging for nanopub retrieval and processing

* chore(Task): enhance logging for task execution and status transitions

313 of 1106 branches covered (28.3%)

Branch coverage included in aggregate %.

1048 of 3157 relevant lines covered (33.2%)

5.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
src/main/java/com/knowledgepixels/registry/MainVerticle.java
1
package com.knowledgepixels.registry;
2

3
import com.mongodb.client.ClientSession;
4
import io.micrometer.prometheus.PrometheusMeterRegistry;
5
import io.vertx.core.AbstractVerticle;
6
import io.vertx.core.Handler;
7
import io.vertx.core.Promise;
8
import io.vertx.core.http.HttpMethod;
9
import io.vertx.core.http.HttpServer;
10
import io.vertx.ext.web.Router;
11
import io.vertx.ext.web.RoutingContext;
12
import io.vertx.micrometer.PrometheusScrapingHandler;
13
import io.vertx.micrometer.backends.BackendRegistries;
14
import net.trustyuri.TrustyUriUtils;
15
import org.eclipse.rdf4j.rio.RDFFormat;
16
import org.eclipse.rdf4j.rio.Rio;
17
import org.nanopub.MalformedNanopubException;
18
import org.nanopub.Nanopub;
19
import org.nanopub.NanopubImpl;
20
import org.slf4j.Logger;
21
import org.slf4j.LoggerFactory;
22

23
import java.util.concurrent.TimeUnit;
24

25
import static com.knowledgepixels.registry.RegistryDB.has;
26

27
public class MainVerticle extends AbstractVerticle {
×
28

29
    private final Logger logger = LoggerFactory.getLogger(MainVerticle.class);
×
30

31
    @Override
32
    public void start(Promise<Void> startPromise) {
33
        HttpServer server = vertx.createHttpServer();
×
34
        Router router = Router.router(vertx);
×
35
        server.requestHandler(router);
×
36

37
        server.listen(9292, ar -> {
×
38
            if (ar.succeeded()) {
×
39
                logger.info("HTTP server started and listening on port 9292");
×
40
            } else {
41
                logger.error("Failed to start HTTP server on port 9292", ar.cause());
×
42
            }
43
        });
×
44

45
        router.route(HttpMethod.GET, "/agent*").handler(c -> {
×
46
            // /agent/... | /agents | /agentAccounts
47
            logger.debug("Routing GET /agent* -> ListPage for {}", c.request().path());
×
48
            ListPage.show(c);
×
49
        });
×
50
        router.route(HttpMethod.GET, "/nanopubs*").handler(c -> {
×
51
            logger.debug("Routing GET /nanopubs* -> ListPage for {}", c.request().path());
×
52
            ListPage.show(c);
×
53
        });
×
54
        router.route(HttpMethod.GET, "/list*").handler(c -> {
×
55
            logger.debug("Routing GET /list* -> ListPage for {}", c.request().path());
×
56
            ListPage.show(c);
×
57
        });
×
58
        router.route(HttpMethod.GET, "/pubkeys*").handler(c -> {
×
59
            logger.debug("Routing GET /pubkeys* -> ListPage for {}", c.request().path());
×
60
            ListPage.show(c);
×
61
        });
×
62
        router.route(HttpMethod.GET, "/np/").handler(c -> {
×
63
            logger.debug("Redirecting /np/ to / for {}", c.request().remoteAddress());
×
64
            c.response().putHeader("Location", "/").setStatusCode(307).end();
×
65
        });
×
66
        router.route(HttpMethod.GET, "/np/*").handler(c -> {
×
67
            logger.debug("Routing GET /np/* -> NanopubPage for {}", c.request().path());
×
68
            NanopubPage.show(c);
×
69
        });
×
70
        router.route(HttpMethod.GET, "/get/").handler(c -> {
×
71
            logger.debug("Redirecting /get/ to / for {}", c.request().remoteAddress());
×
72
            c.response().putHeader("Location", "/").setStatusCode(307).end();
×
73
        });
×
74
        router.route(HttpMethod.GET, "/get/*").handler(c -> {
×
75
            logger.debug("Routing GET /get/* -> NanopubPage (forwardHtml=true) for {}", c.request().path());
×
76
            NanopubPage.show(c, true);
×
77
        });
×
78
        router.route(HttpMethod.GET, "/debug/*").handler(c -> {
×
79
            logger.debug("Routing GET /debug/* -> DebugPage for {}", c.request().path());
×
80
            DebugPage.show(c);
×
81
        });
×
82
        router.route(HttpMethod.GET, "/trust-state*").handler(c -> {
×
83
            logger.debug("Routing GET /trust-state* -> TrustStatePage for {}", c.request().path());
×
84
            TrustStatePage.show(c);
×
85
        });
×
86
        router.route(HttpMethod.GET, "/style.css").handler(c -> {
×
87
            logger.debug("Routing GET /style.css -> ResourcePage for {}", c.request().path());
×
88
            ResourcePage.show(c, "style.css", "text/css");
×
89
        });
×
90

91
        // Metrics
92
        final var metricsHttpServer = vertx.createHttpServer();
×
93
        final var metricsRouter = Router.router(vertx);
×
94
        metricsHttpServer.requestHandler(metricsRouter).listen(9293, ar -> {
×
95
            if (ar.succeeded()) {
×
96
                logger.info("Metrics HTTP server started and listening on port 9293");
×
97
            } else {
98
                logger.error("Failed to start metrics HTTP server on port 9293", ar.cause());
×
99
            }
100
        });
×
101

102
        final var metricsRegistry = (PrometheusMeterRegistry) BackendRegistries.getDefaultNow();
×
103
        if (metricsRegistry == null) {
×
104
            logger.warn("PrometheusMeterRegistry not available (metrics will not be exposed)");
×
105
        } else {
106
            logger.debug("PrometheusMeterRegistry retrieved for metrics exposure");
×
107
        }
108
        final var collector = new MetricsCollector(metricsRegistry);
×
109
        metricsRouter.route("/metrics").handler(PrometheusScrapingHandler.create(metricsRegistry));
×
110

111
        router.route(HttpMethod.GET, "/*").handler(c -> {
×
112
            logger.debug("Routing GET /* -> MainPage for {}", c.request().path());
×
113
            MainPage.show(c);
×
114
        });
×
115
        router.route(HttpMethod.HEAD, "/*").handler(c -> {
×
116
            logger.debug("Routing HEAD /* -> MainPage for {}", c.request().path());
×
117
            MainPage.show(c);
×
118
        });
×
119

120
        Handler<RoutingContext> postHandler = c -> {
×
121
            logger.info("Received POST {}", c.request().path());
×
122
            c.request().bodyHandler(bh -> {
×
123
                String contentType = c.request().getHeader("Content-Type");
×
124
                int bodySize = bh.length();
×
125
                logger.debug("POST content-type={} body-size={} for {}", contentType, bodySize, c.request().remoteAddress());
×
126

127
                vertx.<Void>executeBlocking(() -> {
×
128
                    Nanopub np = null;
×
129
                    try {
130
                        np = new NanopubImpl(bh.toString(), Rio.getParserFormatForMIMEType(contentType).orElse(RDFFormat.TRIG));
×
131
                    } catch (MalformedNanopubException ex) {
×
132
                        logger.warn("Malformed nanopub received on {}: {}", c.request().path(), ex.getMessage(), ex);
×
133
                    } catch (Exception ex) {
×
134
                        logger.warn("Failed to parse nanopub on {}: {}", c.request().path(), ex.getMessage(), ex);
×
135
                    }
×
136
                    if (np != null) {
×
137
                        try (ClientSession s = RegistryDB.getClient().startSession()) {
×
138
                            String ac = TrustyUriUtils.getArtifactCode(np.getUri().toString());
×
139
                            if (has(s, Collection.NANOPUBS.toString(), ac)) {
×
140
                                logger.info("POST: known nanopub {}", ac);
×
141
                            } else {
142
                                logger.info("POST: new nanopub {}", ac);
×
143

144
                                // Check if this nanopub's types are covered by this registry
145
                                if (!CoverageFilter.isCovered(np)) {
×
146
                                    throw new RuntimeException("Nanopub types not covered by this registry: " + np.getUri());
×
147
                                }
148

149
                                // Verify signature once, pass through to avoid redundant verification:
150
                                String pubkey = RegistryDB.getPubkey(np);
×
151
                                if (pubkey == null) {
×
152
                                    throw new RuntimeException("Nanopublication not supported: " + np.getUri());
×
153
                                }
154

155
                                // Check agent/quota restrictions
156
                                String pubkeyHash = Utils.getHash(pubkey);
×
157
                                if (!AgentFilter.isAllowed(s, pubkeyHash)) {
×
158
                                    throw new RuntimeException("Pubkey not authorized on this registry: " + pubkeyHash);
×
159
                                }
160
                                if (AgentFilter.isOverQuota(s, pubkeyHash)) {
×
161
                                    throw new RuntimeException("Quota exceeded for pubkey: " + pubkeyHash);
×
162
                                }
163

164
                                // Load to nanopub store:
165
                                boolean success = RegistryDB.loadNanopubVerified(s, np, pubkey, null);
×
166
                                if (!success) {
×
167
                                    throw new RuntimeException("Nanopublication not supported: " + np.getUri());
×
168
                                }
169
                                // Load to lists, if applicable:
170
                                NanopubLoader.simpleLoad(s, np, pubkey);
×
171
                            }
172
                        }
173
                    } else {
174
                        logger.debug("No nanopub parsed from POST body for {}", c.request().path());
×
175
                    }
176
                    return null;
×
177
                }).onComplete(ar -> {
×
178
                    if (ar.succeeded()) {
×
179
                        c.response().setStatusCode(201).end();
×
180
                        logger.info("POST {} processed successfully (201)", c.request().path());
×
181
                    } else {
182
                        Throwable cause = ar.cause();
×
183
                        logger.warn("POST {} processing failed: {}", c.request().path(), cause == null ? "unknown error" : cause.getMessage(), cause);
×
184
                        c.response().setStatusCode(400)
×
185
                                .setStatusMessage("Error processing nanopub: " + ar.cause().getMessage()).end();
×
186
                    }
187
                });
×
188
            });
×
189
        };
×
190
        router.route(HttpMethod.POST, "/").handler(postHandler);
×
191
        router.route(HttpMethod.POST, "/np/").handler(postHandler);
×
192

193
        // INIT
194
        vertx.executeBlocking(() -> {
×
195
            logger.info("Starting DB initialization...");
×
196
            CoverageFilter.init();
×
197
            AgentFilter.init();
×
198
            RegistryDB.init();
×
199

200
            new Thread(Task::runTasks).start();
×
201

202
            return null;
×
203
        }).onComplete(res -> logger.info("DB initialization finished"));
×
204

205
        // Periodic metrics update
206
        vertx.setPeriodic(1000, id -> collector.updateMetrics());
×
207

208
        // SHUTDOWN
209
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
×
210
            try {
211
                logger.info("Gracefully shutting down...");
×
212
                RegistryDB.getClient().close();
×
213
                vertx.close().toCompletionStage().toCompletableFuture().get(5, TimeUnit.SECONDS);
×
214
                logger.info("Graceful shutdown completed");
×
215
            } catch (Exception ex) {
×
216
                logger.error("Graceful shutdown failed", ex);
×
217
            }
×
218
        }));
×
219

220
        logger.info("Route registration completed");
×
221

222
    }
×
223

224
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc