package io.dropwizard.metrics.jdbi.strategies; import static io.dropwizard.metrics.MetricRegistry.name; import org.skife.jdbi.v2.ClasspathStatementLocator; import org.skife.jdbi.v2.StatementContext; import io.dropwizard.metrics.MetricName; import java.lang.reflect.Method; import java.util.regex.Matcher; import java.util.regex.Pattern; public final class NameStrategies { public static final StatementNameStrategy CHECK_EMPTY = new CheckEmptyStrategy(); public static final StatementNameStrategy CHECK_RAW = new CheckRawStrategy(); public static final StatementNameStrategy SQL_OBJECT = new SqlObjectStrategy(); public static final StatementNameStrategy NAIVE_NAME = new NaiveNameStrategy(); public static final StatementNameStrategy CONTEXT_CLASS = new ContextClassStrategy(); public static final StatementNameStrategy CONTEXT_NAME = new ContextNameStrategy(); /** * An empty SQL statement. */ private static final MetricName EMPTY_SQL = MetricName.build("sql.empty"); /** * Unknown SQL. */ static final MetricName UNKNOWN_SQL = MetricName.build("sql.unknown"); /** * Context attribute name for the metric class. */ public static final String STATEMENT_CLASS = "_metric_class"; /** * Context attribute name for the metric group. */ public static final String STATEMENT_GROUP = "_metric_group"; /** * Context attribute name for the metric type. */ public static final String STATEMENT_TYPE = "_metric_type"; /** * Context attribute name for the metric name. */ public static final String STATEMENT_NAME = "_metric_name"; private static MetricName forRawSql(String rawSql) { return name("sql", "raw", rawSql); } static final class CheckEmptyStrategy implements StatementNameStrategy { private CheckEmptyStrategy() { } @Override public MetricName getStatementName(StatementContext statementContext) { final String rawSql = statementContext.getRawSql(); if (rawSql == null || rawSql.length() == 0) { return EMPTY_SQL; } return null; } } static final class CheckRawStrategy implements StatementNameStrategy { private CheckRawStrategy() { } @Override public MetricName getStatementName(StatementContext statementContext) { final String rawSql = statementContext.getRawSql(); if (ClasspathStatementLocator.looksLikeSql(rawSql)) { return forRawSql(rawSql); } return null; } } static final class NaiveNameStrategy implements StatementNameStrategy { private NaiveNameStrategy() { } @Override public MetricName getStatementName(StatementContext statementContext) { final String rawSql = statementContext.getRawSql(); // Is it using the template loader? final int colon = rawSql.indexOf(':'); if (colon == -1) { // No package? Just return the name, JDBI figured out somehow on how to find the raw sql for this statement. return forRawSql(rawSql); } final String group = rawSql.substring(0, colon); final String name = rawSql.substring(colon + 1); return name(group, name); } } static final class SqlObjectStrategy implements StatementNameStrategy { private SqlObjectStrategy() { } @Override public MetricName getStatementName(StatementContext statementContext) { final Class<?> clazz = statementContext.getSqlObjectType(); final Method method = statementContext.getSqlObjectMethod(); if (clazz != null) { final String rawSql = statementContext.getRawSql(); final String group = clazz.getPackage().getName(); final String name = clazz.getSimpleName(); final String type = method == null ? rawSql : method.getName(); return name(group, name, type); } return null; } } static final class ContextClassStrategy implements StatementNameStrategy { private ContextClassStrategy() { } @Override public MetricName getStatementName(StatementContext statementContext) { final Object classObj = statementContext.getAttribute(STATEMENT_CLASS); final Object nameObj = statementContext.getAttribute(STATEMENT_NAME); if (classObj == null || nameObj == null) { return null; } final String className = (String) classObj; final String statementName = (String) nameObj; final int dotPos = className.lastIndexOf('.'); if (dotPos == -1) { return null; } return name(className.substring(0, dotPos), className.substring(dotPos + 1), statementName); } } static final class ContextNameStrategy implements StatementNameStrategy { /** * File pattern to shorten the group name. */ private static final Pattern SHORT_PATTERN = Pattern.compile("^(.*?)/(.*?)(-sql)?\\.st(g)?$"); private ContextNameStrategy() { } @Override public MetricName getStatementName(StatementContext statementContext) { final Object groupObj = statementContext.getAttribute(STATEMENT_GROUP); final Object typeObj = statementContext.getAttribute(STATEMENT_TYPE); final Object nameObj = statementContext.getAttribute(STATEMENT_NAME); if (groupObj == null || nameObj == null) { return null; } final String group = (String) groupObj; final String statementName = (String) nameObj; if (typeObj == null) { final Matcher matcher = SHORT_PATTERN.matcher(group); if (matcher.matches()) { final String groupName = matcher.group(1); final String typeName = matcher.group(2); return name(groupName, typeName, statementName); } return name(group, statementName, ""); } else { final String type = (String) typeObj; return name(group, type, statementName); } } } private NameStrategies() { } }