summaryrefslogtreecommitdiffstats
path: root/service-monitor/src/main/java/com/yahoo/vespa/service/monitor/ServiceNameUtil.java
blob: 4f77c5fb0c715cbd2b513a8ed29cafc7ca4dbf63 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.service.monitor;

import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * This class provides utilities for working with slobrok-registered service names.
 *
 * @author bakksjo
 */
public class ServiceNameUtil {
    // Utility class; prevents instantiation.
    private ServiceNameUtil() {
    }

    static Set<String> convertSlobrokServicesToConfigIds(final Set<String> registeredServices) {
        return registeredServices.stream()
                        .map(ALL_RECOGNIZER)
                        .filter(Optional::isPresent)
                        .map(Optional::get)
                        .collect(Collectors.toSet());
    }

    // This is basically a typedef.
    private interface ServiceNameRecognizer extends Function<String, Optional<String>> {}

    private static class RegexpServiceNameRecognizer implements ServiceNameRecognizer {
        private final Pattern pattern;
        private final Function<Matcher, String> nameConverter;

        public RegexpServiceNameRecognizer(
                final String patternString,
                final Function<Matcher, String> nameConverter) {
            this.pattern = Pattern.compile(patternString);
            this.nameConverter = nameConverter;
        }

        @Override
        public Optional<String> apply(final String serviceName) {
            final Matcher matcher = pattern.matcher(serviceName);
            if (!matcher.matches()) {
                return Optional.empty();
            }
            return Optional.of(nameConverter.apply(matcher));
        }
    }

    private static class SingleGroupRegexpServiceNameRecognizer extends RegexpServiceNameRecognizer {
        public SingleGroupRegexpServiceNameRecognizer(final String patternString) {
            super(patternString, matcher -> matcher.group(1));
        }
    }


    // TODO: The regexps below almost certainly hard-code names that are dynamically set in config.

    // storage/cluster.basicsearch/storage/0 -> basicsearch/storage/0
    static final ServiceNameRecognizer STORAGENODE_RECOGNIZER = new SingleGroupRegexpServiceNameRecognizer(
            "^storage/cluster\\.([^/]+/storage/[^/]+)$");

    // storage/cluster.basicsearch/distributor/0 -> basicsearch/distributor/0
    static final ServiceNameRecognizer DISTRIBUTOR_RECOGNIZER = new SingleGroupRegexpServiceNameRecognizer(
            "^storage/cluster\\.([^/]+/distributor/[^/]+)$");

    // docproc/cluster.basicsearch.indexing/0/chain.indexing -> docproc/cluster.basicsearch.indexing/0
    static final ServiceNameRecognizer DOCPROC_RECOGNIZER = new SingleGroupRegexpServiceNameRecognizer(
            "^(docproc/cluster\\.[^/.]+\\.indexing/[^/]+)/.*$");

    // basicsearch/search/cluster.basicsearch/0/realtimecontroller -> basicsearch/search/cluster.basicsearch/0
    static final ServiceNameRecognizer SEARCH_RECOGNIZER = new SingleGroupRegexpServiceNameRecognizer(
            "^(basicsearch/search/cluster.basicsearch/[^/.]+)/.*$");

    static final ServiceNameRecognizer ALL_RECOGNIZER = serviceName -> Stream.of(
            STORAGENODE_RECOGNIZER,
            DISTRIBUTOR_RECOGNIZER,
            DOCPROC_RECOGNIZER,
            SEARCH_RECOGNIZER)
            .map(recognizer -> recognizer.apply(serviceName))
            .filter(optional -> optional.isPresent())
            .findFirst()
            .orElse(Optional.empty());
}