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

io.trino.gateway.ha.clustermonitor.ClusterStatsJdbcMonitor Maven / Gradle / Ivy

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.trino.gateway.ha.clustermonitor;

import com.google.common.util.concurrent.SimpleTimeLimiter;
import io.airlift.log.Logger;
import io.trino.gateway.ha.config.BackendStateConfiguration;
import io.trino.gateway.ha.config.ProxyBackendConfiguration;

import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class ClusterStatsJdbcMonitor
        implements ClusterStatsMonitor
{
    private static final Logger log = Logger.get(ClusterStatsJdbcMonitor.class);

    private final Properties properties; // TODO Avoid using a mutable field

    private static final String STATE_QUERY = "SELECT state, COUNT(*) as count "
            + "FROM runtime.queries "
            + "WHERE user != ? AND date_diff('hour',created,now()) <= 1 "
            + "GROUP BY state";

    public ClusterStatsJdbcMonitor(BackendStateConfiguration backendStateConfiguration)
    {
        properties = new Properties();
        properties.setProperty("user", backendStateConfiguration.getUsername());
        properties.setProperty("password", backendStateConfiguration.getPassword());
        properties.setProperty("SSL", String.valueOf(backendStateConfiguration.getSsl()));
        log.info("state check configured");
    }

    @Override
    public ClusterStats monitor(ProxyBackendConfiguration backend)
    {
        String url = backend.getProxyTo();
        ClusterStats.Builder clusterStats = ClusterStatsMonitor.getClusterStatsBuilder(backend);
        String jdbcUrl;
        try {
            URL parsedUrl = new URL(url);
            jdbcUrl = String
                    .format("jdbc:trino://%s:%s/system",
                            parsedUrl.getHost(),
                            parsedUrl.getPort() == -1 ? parsedUrl.getDefaultPort() : parsedUrl.getPort());
            // automatically set ssl config based on url protocol
            properties.setProperty("SSL", String.valueOf(parsedUrl.getProtocol().equals("https")));
        }
        catch (MalformedURLException e) {
            log.error("could not parse backend url %s ", url);
            return clusterStats.build(); // TODO Invalid configuration should fail
        }

        try (Connection conn = DriverManager.getConnection(jdbcUrl, properties)) {
            PreparedStatement stmt = SimpleTimeLimiter.create(Executors.newSingleThreadExecutor())
                    .callWithTimeout(() -> conn.prepareStatement(STATE_QUERY), 10, TimeUnit.SECONDS);
            stmt.setString(1, (String) properties.get("user"));
            Map partialState = new HashMap<>();
            ResultSet rs = stmt.executeQuery();
            while (rs.next()) {
                partialState.put(rs.getString("state"), rs.getInt("count"));
            }
            return clusterStats
                    .healthy(true)
                    .queuedQueryCount(partialState.getOrDefault("QUEUED", 0))
                    .runningQueryCount(partialState.getOrDefault("RUNNING", 0))
                    .build();
        }
        catch (TimeoutException e) {
            log.error(e, "timed out fetching status for %s backend", url);
        }
        catch (Exception e) {
            log.error(e, "could not fetch status for %s backend", url);
        }
        return clusterStats.build();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy