/* * This file is part of a module with proprietary Enterprise Features. * * Licensed to Crate.io Inc. ("Crate.io") under one or more contributor * license agreements. See the NOTICE file distributed with this work for * additional information regarding copyright ownership. * * Unauthorized copying of this file, via any medium is strictly prohibited. * * To use this file, Crate.io must have given you permission to enable and * use such Enterprise Features and you must have a valid Enterprise or * Subscription Agreement with Crate.io. If you enable or use the Enterprise * Features, you represent and warrant that you have a valid Enterprise or * Subscription Agreement with Crate.io. Your use of the Enterprise Features * if governed by the terms and conditions of your Enterprise or Subscription * Agreement with Crate.io. */ package io.crate.beans; import com.google.common.collect.ImmutableList; import io.crate.action.sql.BaseResultReceiver; import io.crate.action.sql.SQLOperations; import io.crate.data.Row; import io.crate.data.RowN; import io.crate.types.DataType; import org.apache.lucene.util.BytesRef; import org.elasticsearch.common.settings.Settings; import org.junit.BeforeClass; import org.junit.Test; import java.util.Arrays; import java.util.List; import static io.crate.action.sql.SQLOperations.Session.UNNAMED; import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyListOf; import static org.mockito.Mockito.*; import static org.mockito.Mockito.eq; public class QueryStatsTest { private static final List<Row> ROWS = ImmutableList.of( new RowN(new Object[]{1.0, 1.1, new BytesRef("select")}), new RowN(new Object[]{2.0, 2.1, new BytesRef("update")}), new RowN(new Object[]{3.0, 3.1, new BytesRef("insert")}), new RowN(new Object[]{4.0, 4.1, new BytesRef("delete")}) ); private static QueryStats queryStats; private static SQLOperations.Session session = mock(SQLOperations.Session.class); @BeforeClass public static void beforeClass() { SQLOperations sqlOperations = mock(SQLOperations.class); when(sqlOperations.createSession(anyString(), anyString(), anyObject(), anyInt())).thenReturn(session); doNothing().when(session).parse(anyString(), anyString(), anyListOf(DataType.class)); queryStats = spy(new QueryStats(sqlOperations, Settings.EMPTY)); } @Test public void testUpdateAndGetLastQueryExecutionTimestamp() throws InterruptedException { // If a query for a metric was executed for the first time, then the last executed ts will // be updated with the current timestamp and this value will be returned. long firstAvg = queryStats.updateAndGetLastExecutedTsFor("select" + QueryStats.MetricType.AVERAGE_DURATION); long firstQps = queryStats.updateAndGetLastExecutedTsFor("select" + QueryStats.MetricType.FREQUENCY); // The second call for the same metrics must return the last executed ts // (assigned to firstQps, firstAvg) and update them with a current timestamp. long lastAvg = queryStats.updateAndGetLastExecutedTsFor("select" + QueryStats.MetricType.AVERAGE_DURATION); long lastQps = queryStats.updateAndGetLastExecutedTsFor("select" + QueryStats.MetricType.FREQUENCY); assertThat(firstQps, is(lastQps)); assertThat(firstAvg, is(lastAvg)); // All the further invocation of the updateAndGetLastExecutedTsFor must return later ts. assertThat(lastAvg, lessThanOrEqualTo(queryStats.updateAndGetLastExecutedTsFor("select" + QueryStats.MetricType.AVERAGE_DURATION))); assertThat(lastQps, lessThanOrEqualTo(queryStats.updateAndGetLastExecutedTsFor("select" + QueryStats.MetricType.FREQUENCY))); } @Test public void testFrequencyMetricExtractedCorrectlyFromResponse() { assertThat(queryStats.getMetricValue(ROWS, "select", QueryStats.MetricType.FREQUENCY.ordinal()), is(1.0)); assertThat(queryStats.getMetricValue(ROWS, "update", QueryStats.MetricType.FREQUENCY.ordinal()), is(2.0)); assertThat(queryStats.getMetricValue(ROWS, "insert", QueryStats.MetricType.FREQUENCY.ordinal()), is(3.0)); assertThat(queryStats.getMetricValue(ROWS, "delete", QueryStats.MetricType.FREQUENCY.ordinal()), is(4.0)); assertThat(queryStats.getTotalMetricValue(ROWS, QueryStats.MetricType.FREQUENCY.ordinal()), is(10.0)); } @Test public void testAverageDurationMetricExtractedCorrectlyFromResponse() { assertThat(queryStats.getMetricValue(ROWS, "select", QueryStats.MetricType.AVERAGE_DURATION.ordinal()), is(1.1)); assertThat(queryStats.getMetricValue(ROWS, "update", QueryStats.MetricType.AVERAGE_DURATION.ordinal()), is(2.1)); assertThat(queryStats.getMetricValue(ROWS, "insert", QueryStats.MetricType.AVERAGE_DURATION.ordinal()), is(3.1)); assertThat(queryStats.getMetricValue(ROWS, "delete", QueryStats.MetricType.AVERAGE_DURATION.ordinal()), is(4.1)); assertThat(queryStats.getTotalMetricValue(ROWS, QueryStats.MetricType.AVERAGE_DURATION.ordinal()), is(10.4)); } @Test public void testGetMetricResultInCorrectSessionCalls() { queryStats.getDeleteQueryFrequency(); String queryUID = "delete" + QueryStats.MetricType.FREQUENCY; verify(session, times(1)).bind( eq(UNNAMED), eq(QueryStats.NAME), eq(Arrays.asList( queryStats.lastQueried.get(queryUID), "^\\s*(delete).*", queryStats.lastQueried.get(queryUID), "^\\s*(delete).*" )), eq(null) ); verify(session, times(1)).execute(eq(""), eq(0), any(BaseResultReceiver.class)); verify(session, times(1)).sync(); } }