package org.stagemonitor.core.elasticsearch; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; import com.codahale.metrics.Clock; import org.stagemonitor.util.StringUtils; public class IndexSelector { private final Clock clock; public IndexSelector(Clock clock) { this.clock = clock; } /** * Returns an Elasticsearch index pattern that only includes indices that are older than the specified amount of days * <p/> * Your indices are ought to have the pattern [prefix]YYYY.MM.DD * <p/> * See also https://www.elastic.co/guide/en/elasticsearch/reference/current/multi-index.html * @param prefix the index prefix e.g. 'stagemonitor-metrics-' * @param days the number days that should be excluded * @return The Elasticsearch index pattern that only includes indices that are older than the specified amount of days */ public String getIndexPatternOlderThanDays(String prefix, int days) { // select all indices, then exclude months and days that are not older than the days parameter // Example: // stagemonitor-metrics-*,-stagemonitor-metrics-2015.10.*,-stagemonitor-metrics-2015.09.30 final StringBuilder indexPattern = new StringBuilder(prefix).append('*'); final GregorianCalendar now = getNowUTC(); final GregorianCalendar lastDayToExclude = getLastDayToExclude(days); final GregorianCalendar alreadyExcluded = getNowUTC(); excludeMonths(prefix, now, indexPattern, lastDayToExclude, alreadyExcluded); excludeDays(prefix, indexPattern, lastDayToExclude, alreadyExcluded); return indexPattern.toString(); } private void excludeMonths(String prefix, GregorianCalendar now, StringBuilder sb, GregorianCalendar lastDayToExclude, GregorianCalendar alreadyExcluded) { int excludedMonths = now.get(Calendar.MONTH) - lastDayToExclude.get(Calendar.MONTH); if (excludedMonths < 0) { excludedMonths += 12; } for (int i = 0; i < excludedMonths; i++) { // ,[prefix]YYYY.MM.* final int year = alreadyExcluded.get(Calendar.YEAR); final int month = alreadyExcluded.get(Calendar.MONTH); sb.append(",-") .append(prefix) .append(formatTwoDigitsLeadingZero(year)).append('.') .append(formatTwoDigitsLeadingZero(month + 1)).append(".*"); alreadyExcluded.set(year, month, 0); } } private void excludeDays(String prefix, StringBuilder sb, GregorianCalendar lastDayToExclude, GregorianCalendar alreadyExcluded) { for (; alreadyExcluded.after(lastDayToExclude) || alreadyExcluded.equals(lastDayToExclude); alreadyExcluded.add(Calendar.DAY_OF_YEAR, -1)) { sb.append(",-").append(prefix).append(StringUtils.getLogstashStyleDate(alreadyExcluded.getTimeInMillis())); } } private GregorianCalendar getLastDayToExclude(int days) { final GregorianCalendar lastDayToExclude = getNowUTC(); lastDayToExclude.add(Calendar.DAY_OF_YEAR, days * -1); return lastDayToExclude; } private GregorianCalendar getNowUTC() { final GregorianCalendar now = new GregorianCalendar(); now.setTimeZone(TimeZone.getTimeZone("UTC")); now.setTime(new Date(clock.getTime())); return now; } private static String formatTwoDigitsLeadingZero(int i) { return String.format("%02d", i); } }