All Downloads are FREE. Search and download functionalities are using the official Maven repository.

internal.sdmxdl.util.ext.UptimeRobot Maven / Gradle / Ivy

package internal.sdmxdl.util.ext;

import nbbrd.design.MightBePromoted;
import nbbrd.io.function.IOFunction;
import nbbrd.io.text.Parser;
import nbbrd.io.xml.Stax;
import nbbrd.io.xml.Xml;
import nbbrd.service.ServiceProvider;
import org.checkerframework.checker.nullness.qual.NonNull;
import sdmxdl.util.web.SdmxWebEvents;
import sdmxdl.web.SdmxWebMonitor;
import sdmxdl.web.SdmxWebMonitorReport;
import sdmxdl.web.SdmxWebSource;
import sdmxdl.web.SdmxWebStatus;
import sdmxdl.web.spi.SdmxWebContext;
import sdmxdl.web.spi.SdmxWebMonitoring;

import javax.net.ssl.HttpsURLConnection;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.*;
import java.nio.charset.StandardCharsets;

@ServiceProvider(SdmxWebMonitoring.class)
public final class UptimeRobot implements SdmxWebMonitoring {

    private final URL url = Parser.onURL().parseValue("https://api.uptimerobot.com/v2/getMonitors").orElseThrow(RuntimeException::new);

    @Override
    public String getProviderName() {
        return "UptimeRobot";
    }

    @Override
    public SdmxWebMonitorReport getReport(SdmxWebSource source, SdmxWebContext context) throws IOException, IllegalArgumentException {
        checkMonitor(source.getMonitor());
        Query query = getQuery(source.getMonitor());
        Xml.Parser parser = Stax.StreamParser.valueOf(UptimeRobot::parseReport);
        return post(url, query.toBody(), parser::parseReader, context, source);
    }

    private void checkMonitor(SdmxWebMonitor monitor) {
        if (monitor == null) {
            throw new IllegalArgumentException("Expecting monitor not to be null");
        }
        if (!monitor.getProvider().equals(getProviderName())) {
            throw new IllegalArgumentException(monitor.toString());
        }
    }

    private static Query getQuery(SdmxWebMonitor monitor) {
        return Query
                .builder()
                .apiKey(monitor.getId())
                .allTimeUptimeRatio(true)
                .responseTimesAverage(false)
                .build();
    }

    @lombok.Value
    @lombok.Builder
    private static class Query {

        @lombok.NonNull
        String apiKey;

        @lombok.Builder.Default
        boolean logs = false;

        @lombok.Builder.Default
        boolean allTimeUptimeRatio = false;

        @lombok.Builder.Default
        boolean responseTimesAverage = false;

        @NonNull
        public String toBody() {
            return "api_key=" + apiKey
                    + "&format=" + "xml"
                    + "&logs=" + format(logs)
                    + "&all_time_uptime_ratio=" + format(allTimeUptimeRatio)
                    + "&response_times_average=" + format(responseTimesAverage);
        }

        private String format(boolean value) {
            return value ? "1" : "0";
        }
    }

    @lombok.AllArgsConstructor
    @lombok.Getter
    private enum Status {
        PAUSED(0, SdmxWebStatus.UNKNOWN),
        NOT_CHECKED_YET(1, SdmxWebStatus.UNKNOWN),
        UP(2, SdmxWebStatus.UP),
        SEEMS_DOWN(8, SdmxWebStatus.DOWN),
        DOWN(9, SdmxWebStatus.DOWN);

        int code;
        SdmxWebStatus report;
    }

    private static final Parser STATUS_PARSER =
            Parser.onEnum(Status.class, Status::getCode).andThen(Status::getReport);

    @SuppressWarnings("SwitchStatementWithTooFewBranches")
    private static SdmxWebMonitorReport parseReport(XMLStreamReader reader) throws XMLStreamException {
        while (reader.hasNext()) {
            switch (reader.next()) {
                case XMLStreamReader.START_ELEMENT:
                    if (reader.getLocalName().equals("monitor")) {
                        return SdmxWebMonitorReport
                                .builder()
                                .source(reader.getAttributeValue(null, "friendly_name"))
                                .status(STATUS_PARSER.parseValue(reader.getAttributeValue(null, "status")).orElseThrow(() -> new XMLStreamException("Cannot parse status")))
                                .uptimeRatio(Parser.onDouble().parse(reader.getAttributeValue(null, "all_time_uptime_ratio")))
                                .averageResponseTime(Parser.onLong().parse(reader.getAttributeValue(null, "average_response_time")))
                                .build();
                    }
                    break;
            }
        }
        throw new RuntimeException("Not found");
    }

    private static URI toURI(URL url) throws IOException {
        try {
            return url.toURI();
        } catch (URISyntaxException ex) {
            throw new IOException(ex);
        }
    }

    @MightBePromoted
    private static  T post(URL url, String query, IOFunction factory, SdmxWebContext context, SdmxWebSource source) throws IOException {
        byte[] data = query.getBytes(StandardCharsets.UTF_8);

        Proxy proxy = context.getProxySelector().select(toURI(url)).stream().findFirst().orElse(Proxy.NO_PROXY);

        if (context.getEventListener().isEnabled()) {
            context.getEventListener().onWebSourceEvent(source, SdmxWebEvents.onQuery(url, proxy));
        }

        HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);

        if (conn instanceof HttpsURLConnection) {
            ((HttpsURLConnection) conn).setSSLSocketFactory(context.getSslSocketFactory());
            ((HttpsURLConnection) conn).setHostnameVerifier(context.getHostnameVerifier());
        }

        conn.setDoOutput(true);
        conn.setInstanceFollowRedirects(false);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("cache-control", "no-cache");
        conn.setRequestProperty("charset", "utf-8");
        conn.setRequestProperty("Content-Length", Integer.toString(data.length));
        conn.setUseCaches(false);

        try (OutputStream wr = conn.getOutputStream()) {
            wr.write(data);
        }

        try (Reader reader = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8)) {
            return factory.applyWithIO(reader);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy