// Path: common/src/main/java/nl/crowndov/displaydirect/common/stats/domain/Metric.java
// public class Metric {
// 
//     private final LocalDateTime created;
//     private final String name;
//     private final long value;
// 
//     public Metric(String name, long value) {
//         this.name = name;
//         this.value = value;
//         this.created = LocalDateTime.now();
//     }
// 
//     public Metric(String name, long value, LocalDateTime created) {
//         this.name = name;
//         this.value = value;
//         this.created = created;
//     }
// 
//     public LocalDateTime getCreated() {
//         return created;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public long getValue() {
//         return value;
//     }
// }


import nl.crowndov.displaydirect.common.stats.domain.Metric;
import java.time.LocalDateTime;
import java.time.temporal.TemporalUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
        buckets.get(name).put(bucketSlot, new Metric(name, value, bucketSlot));
    }

    public void increaseBucketValue(String name, TemporalUnit bucket) {
        ensureMetricInBucket(name);
        LocalDateTime key = LocalDateTime.now().truncatedTo(bucket);
        if (!buckets.get(name).containsKey(key)) {
            buckets.get(name).put(key, new Metric(name, 1));
        } else {
            Metric previous = buckets.get(name).get(key);
            buckets.get(name).put(key, new Metric(name, previous.getValue() + 1, key));
        }
    }

    private void ensureMetricInBucket(String name) {
        if (!buckets.containsKey(name)) {
            buckets.put(name, new ConcurrentSkipListMap<>());
        }
    }

    public Map<String, List<Metric>> getMetrics() {
        return Stream.concat(buckets.values().stream().flatMap(m -> m.values().stream()),  metrics.stream())
                .collect(Collectors.groupingBy(Metric::getName));
    }

    public List<Metric> getMetric(String name) {
        if (buckets.containsKey(name)) {
            return new ArrayList<>(buckets.get(name).values());
        }
        return metrics.parallelStream()
// Path: common/src/main/java/nl/crowndov/displaydirect/common/stats/domain/Metric.java
// public class Metric {
// 
//     private final LocalDateTime created;
//     private final String name;
//     private final long value;
// 
//     public Metric(String name, long value) {
//         this.name = name;
//         this.value = value;
//         this.created = LocalDateTime.now();
//     }
// 
//     public Metric(String name, long value, LocalDateTime created) {
//         this.name = name;
//         this.value = value;
//         this.created = created;
//     }
// 
//     public LocalDateTime getCreated() {
//         return created;
//     }
// 
//     public String getName() {
//         return name;
//     }
// 
//     public long getValue() {
//         return value;
//     }
// }


// Path: distribution/src/main/java/nl/crowndov/displaydirect/distribution/stats/MetricStore.java
import nl.crowndov.displaydirect.common.stats.domain.Metric;
import java.time.LocalDateTime;
import java.time.temporal.TemporalUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

        buckets.get(name).put(bucketSlot, new Metric(name, value, bucketSlot));
    }

    public void increaseBucketValue(String name, TemporalUnit bucket) {
        ensureMetricInBucket(name);
        LocalDateTime key = LocalDateTime.now().truncatedTo(bucket);
        if (!buckets.get(name).containsKey(key)) {
            buckets.get(name).put(key, new Metric(name, 1));
        } else {
            Metric previous = buckets.get(name).get(key);
            buckets.get(name).put(key, new Metric(name, previous.getValue() + 1, key));
        }
    }

    private void ensureMetricInBucket(String name) {
        if (!buckets.containsKey(name)) {
            buckets.put(name, new ConcurrentSkipListMap<>());
        }
    }

    public Map<String, List<Metric>> getMetrics() {
        return Stream.concat(buckets.values().stream().flatMap(m -> m.values().stream()),  metrics.stream())
                .collect(Collectors.groupingBy(Metric::getName));
    }

    public List<Metric> getMetric(String name) {
        if (buckets.containsKey(name)) {
            return new ArrayList<>(buckets.get(name).values());
        }
        return metrics.parallelStream()
                .filter(m -> m.getName().equalsIgnoreCase(name))