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

knowledgepixels / nanopub-registry / 24134532645

08 Apr 2026 12:08PM UTC coverage: 32.376% (-0.4%) from 32.824%
24134532645

Pull #98

github

web-flow
Merge 03ec4a037 into 689a63b39
Pull Request #98: Revert seqNum batch allocation, use atomic counter

265 of 912 branches covered (29.06%)

Branch coverage included in aggregate %.

783 of 2325 relevant lines covered (33.68%)

5.66 hits per line

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

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

3
import com.mongodb.client.ClientSession;
4
import io.micrometer.core.instrument.Gauge;
5
import io.micrometer.core.instrument.MeterRegistry;
6
import org.slf4j.Logger;
7
import org.slf4j.LoggerFactory;
8

9
import java.util.Map;
10
import java.util.Optional;
11
import java.util.concurrent.ConcurrentHashMap;
12
import java.util.concurrent.atomic.AtomicInteger;
13

14
import static com.knowledgepixels.registry.RegistryDB.*;
15

16
public final class MetricsCollector {
17

18
    private final Logger logger = LoggerFactory.getLogger(MetricsCollector.class);
×
19
    private final AtomicInteger loadCounter = new AtomicInteger(0);
×
20
    private final AtomicInteger nanopubCount = new AtomicInteger(0);
×
21
    private final AtomicInteger trustStateCounter = new AtomicInteger(0);
×
22
    private final AtomicInteger agentCount = new AtomicInteger(0);
×
23
    private final AtomicInteger accountCount = new AtomicInteger(0);
×
24

25
    private final Map<ServerStatus, AtomicInteger> statusStates = new ConcurrentHashMap<>();
×
26

27
    public MetricsCollector(MeterRegistry meterRegistry) {
×
28
        // Numeric metrics
29
        Gauge.builder("registry.load.counter", loadCounter, AtomicInteger::get).register(meterRegistry);
×
30
        Gauge.builder("registry.nanopub.count", nanopubCount, AtomicInteger::get).register(meterRegistry);
×
31
        Gauge.builder("registry.trust.state.counter", trustStateCounter, AtomicInteger::get).register(meterRegistry);
×
32
        Gauge.builder("registry.agent.count", agentCount, AtomicInteger::get).register(meterRegistry);
×
33
        Gauge.builder("registry.account.count", accountCount, AtomicInteger::get).register(meterRegistry);
×
34

35
        // Status label metrics
36
        for (final var status : ServerStatus.values()) {
×
37
            AtomicInteger stateGauge = new AtomicInteger(0);
×
38
            statusStates.put(status, stateGauge);
×
39
            Gauge.builder("registry.server.status", stateGauge, AtomicInteger::get)
×
40
                    .description("Server status (1 if current)")
×
41
                    .tag("status", status.name())
×
42
                    .register(meterRegistry);
×
43
        }
44
    }
×
45

46
    public void updateMetrics() {
47
        try (final var session = RegistryDB.getClient().startSession()) {
×
48
            // Update numeric metrics
49
            extractMaximalIntegerValueFromField(session, Collection.NANOPUBS.toString(), "counter")
×
50
                    .ifPresent(loadCounter::set);
×
51
            nanopubCount.set((int) collection(Collection.NANOPUBS.toString()).estimatedDocumentCount());
×
52

53
            extractIntegerValueFromField(session, Collection.SERVER_INFO.toString(), "trustStateCounter")
×
54
                    .ifPresent(trustStateCounter::set);
×
55

56
            agentCount.set(countDocumentsInCollection(session, Collection.AGENTS.toString()));
×
57
            accountCount.set(countDocumentsInCollection(session, Collection.ACCOUNTS.toString()));
×
58

59
            // Update status gauge
60
            final var currentStatus = extractStringValueFromField(session, Collection.SERVER_INFO.toString(), "status")
×
61
                    .map(ServerStatus::valueOf)
×
62
                    .orElse(null);
×
63
            for (final var status : ServerStatus.values()) {
×
64
                statusStates.get(status).set(status.equals(currentStatus) ? 1 : 0);
×
65
            }
66
        } catch (Exception e) {
×
67
            logger.error("Error updating metrics: {}", e.getMessage());
×
68
        }
×
69
    }
×
70

71
    private Optional<Integer> extractMaximalIntegerValueFromField(
72
            ClientSession session,
73
            String collectionName,
74
            String fieldName
75
    ) {
76
        return Optional
×
77
                .ofNullable(getMaxValue(session, collectionName, fieldName))
×
78
                .filter(Number.class::isInstance)
×
79
                .map(Number.class::cast)
×
80
                .map(Number::intValue);
×
81
    }
82

83
    private Optional<Integer> extractIntegerValueFromField(
84
            ClientSession session,
85
            String collectionName,
86
            String fieldName
87
    ) {
88
        return Optional
×
89
                .ofNullable(getValue(session, collectionName, fieldName))
×
90
                .filter(Number.class::isInstance)
×
91
                .map(Number.class::cast)
×
92
                .map(Number::intValue);
×
93
    }
94

95
    private Optional<String> extractStringValueFromField(
96
            ClientSession session,
97
            String collectionName,
98
            String fieldName
99
    ) {
100
        return Optional
×
101
                .ofNullable(getValue(session, collectionName, fieldName))
×
102
                .filter(String.class::isInstance)
×
103
                .map(String.class::cast);
×
104
    }
105

106
    private int countDocumentsInCollection(ClientSession session, String collectionName) {
107
        return (int) collection(collectionName).countDocuments(session);
×
108
    }
109
}
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