/* * Copyright 2013 Rackspace * * 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 com.rackspacecloud.blueflood.io; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Lists; import com.rackspacecloud.blueflood.service.Configuration; import com.rackspacecloud.blueflood.service.ElasticClientManager; import com.rackspacecloud.blueflood.service.ElasticIOConfig; import com.rackspacecloud.blueflood.service.RemoteElasticSearchServer; import com.rackspacecloud.blueflood.types.IMetric; import com.rackspacecloud.blueflood.types.Locator; import com.rackspacecloud.blueflood.types.Metric; import com.codahale.metrics.Timer; import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.client.Client; import org.elasticsearch.search.SearchHit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.*; public class ElasticIO extends AbstractElasticIO { public static final String ES_DOCUMENT_TYPE = "metrics"; private static final Logger log = LoggerFactory.getLogger(DiscoveryIO.class);; public ElasticIO() { this(RemoteElasticSearchServer.getInstance()); } public ElasticIO(Client client) { this.client = client; } public ElasticIO(ElasticClientManager manager) { this(manager.getClient()); } public void insertDiscovery(IMetric metric) throws IOException { List<IMetric> batch = new ArrayList<IMetric>(); batch.add(metric); insertDiscovery(batch); } public void insertDiscovery(List<IMetric> batch) throws IOException { batchHistogram.update(batch.size()); if (batch.size() == 0) { return; } // TODO: check bulk insert result and retry Timer.Context ctx = writeTimer.time(); try { BulkRequestBuilder bulk = client.prepareBulk(); for (Object obj : batch) { if (!(obj instanceof IMetric)) { classCastExceptionMeter.mark(); continue; } IMetric metric = (IMetric)obj; Locator locator = metric.getLocator(); Discovery discovery = new Discovery(locator.getTenantId(), locator.getMetricName()); Map<String, Object> fields = new HashMap<String, Object>(); if (obj instanceof Metric && getUnit((Metric)metric) != null) { // metric units may be null fields.put(ESFieldLabel.unit.toString(), getUnit((Metric) metric)); } discovery.withSourceFields(fields); bulk.add(createSingleRequest(discovery)); } bulk.execute().actionGet(); } finally { ctx.stop(); } } private String getUnit(Metric metric) { return metric.getUnit(); } IndexRequestBuilder createSingleRequest(Discovery md) throws IOException { if (md.getMetricName() == null) { throw new IllegalArgumentException("trying to insert metric discovery without a metricName"); } return client.prepareIndex(ELASTICSEARCH_INDEX_NAME_WRITE, ES_DOCUMENT_TYPE) .setId(md.getDocumentId()) .setSource(md.createSourceContent()) .setCreate(true) .setRouting(md.getTenantId()); } @VisibleForTesting public void setINDEX_NAME_WRITE (String indexNameWrite) { ELASTICSEARCH_INDEX_NAME_WRITE = indexNameWrite; } @VisibleForTesting public void setINDEX_NAME_READ (String indexNameRead) { ELASTICSEARCH_INDEX_NAME_READ = indexNameRead; } @Override protected String[] getIndexesToSearch() { return new String[] {ELASTICSEARCH_INDEX_NAME_READ}; } @Override protected SearchResult convertHitToMetricDiscoveryResult(SearchHit hit) { Map<String, Object> source = hit.getSource(); String metricName = (String)source.get(ESFieldLabel.metric_name.toString()); String tenantId = (String)source.get(ESFieldLabel.tenantId.toString()); String unit = (String)source.get(ESFieldLabel.unit.toString()); SearchResult result = new SearchResult(tenantId, metricName, unit); return result; } @Override protected List<SearchResult> dedupResults(List<SearchResult> results) { HashMap<String, SearchResult> dedupedResults = new HashMap<String, SearchResult>(); for (SearchResult result : results) dedupedResults.put(result.getMetricName(), result); return Lists.newArrayList(dedupedResults.values()); } @VisibleForTesting public void setClient(Client client) { this.client = client; } }