com.bigdata.ganglia.GangliaMetadataMessage Maven / Gradle / Ivy
/*
Copyright (C) SYSTAP, LLC 2006-2012. All rights reserved.
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.bigdata.ganglia;
import java.util.Arrays;
import java.util.Map;
/**
* A ganglia metric metadata (aka declaration) record.
*
* This record must be sent if a service is reporting a metric for the first
* time. In addition, ganglia resends the metadata records periodically by
* tracking their age (but send_metadata_interval = 0
in the
* default gmond.conf
).
*/
public class GangliaMetadataMessage extends AbstractGangliaMessage implements
IGangliaMetadataMessage {
private final GangliaMessageTypeEnum metricType;
private final String metricName2;
private final String units;
private final GangliaSlopeEnum slope;
private final int tmax;
private final int dmax;
private final Map extraValues;
public GangliaMetadataMessage(
final String hostName, final String metricName,
final boolean spoof, final GangliaMessageTypeEnum metricType,
final String metricName2, final String units,
final GangliaSlopeEnum slope, final int tmax, final int dmax,
final Map extraValues) {
super(GangliaMessageTypeEnum.METADATA, hostName, metricName,
spoof);
if (metricType == null)
throw new IllegalArgumentException();
if (metricName2 == null)
throw new IllegalArgumentException();
if (!metricName.equals(metricName2))
throw new IllegalArgumentException();
if (units == null)
throw new IllegalArgumentException();
if (slope == null)
throw new IllegalArgumentException();
if (extraValues == null)
throw new IllegalArgumentException();
this.metricType = metricType;
this.metricName2 = metricName2;
this.units = units;
this.slope = slope;
this.tmax = tmax;
this.dmax = dmax;
this.extraValues = extraValues;
}
@Override
public boolean isMetricValue() {
return false;
}
@Override
public boolean isMetricRequest() {
return false;
}
@Override
public boolean isMetricMetadata() {
return true;
}
@Override
public GangliaMessageTypeEnum getMetricType() {
return metricType;
}
@Override
public String getMetricName2() {
return metricName2;
}
@Override
public String getUnits() {
return units;
}
@Override
public GangliaSlopeEnum getSlope() {
return slope;
}
@Override
public int getTMax() {
return tmax;
}
@Override
public int getDMax() {
return dmax;
}
@Override
public Map getExtraValues() {
return extraValues;
}
public String[] getGroups() {
return extraValues.get(IGangliaAttributes.ATTR_GROUP);
}
public String getTitle() {
return getFirstValue(IGangliaAttributes.ATTR_TITLE);
}
public String getDescription() {
return getFirstValue(IGangliaAttributes.ATTR_DESC);
}
public String getFirstValue(final String key) {
final String[] a = extraValues.get(key);
if (a == null || a.length == 0)
return null;
return a[0];
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(128);
sb.append(getClass().getSimpleName());
sb.append("{ recordType=");
sb.append(getRecordType());
sb.append(", hostName=");
sb.append(getHostName());
sb.append(", metricName=");
sb.append(getMetricName());
sb.append(", spoof=");
sb.append(isSpoof());
sb.append(", metricType=");
sb.append(getMetricType());
sb.append(", metricName2=");
sb.append(getMetricName2());
sb.append(", units=");
sb.append(getUnits());
sb.append(", slope=");
sb.append(getSlope());
sb.append(", tmax=");
sb.append(getTMax());
sb.append(", dmax=");
sb.append(getDMax());
sb.append(", extraValues=");
{
sb.append("{");
if (!extraValues.isEmpty()) {
boolean first = true;
for (Map.Entry e : extraValues.entrySet()) {
if (!first)
sb.append(",");
first = false;
sb.append(e.getKey());
sb.append("=");
final String[] v = e.getValue();
if (v.length == 0) {
// Nothing given. Should not happen.
sb.append("[]");
} else if (v.length == 1) {
sb.append('\"');
sb.append(v[0]);
sb.append('\"');
} else {
sb.append("[");
for (int i = 0; i < v.length; i++) {
if (i > 1)
sb.append(",");
sb.append('\"');
sb.append(v[i]);
sb.append('\"');
}
sb.append("]");
}
}
} // if(!extraValues.isEmpty()) ...
sb.append("}");
}
sb.append("}");
return sb.toString();
}
@Override
public boolean equals(final Object o) {
if (o == this)
return true;
final IGangliaMetadataMessage t = (IGangliaMetadataMessage) o;
if (!getRecordType().equals(t.getRecordType()))
return false;
if (!getHostName().equals(t.getHostName()))
return false;
if (!getMetricName().equals(t.getMetricName()))
return false;
if (isSpoof() != t.isSpoof())
return false;
if (!getMetricType().equals(t.getMetricType()))
return false;
if (!getMetricName2().equals(t.getMetricName2()))
return false;
if (!getUnits().equals(t.getUnits()))
return false;
if (!getSlope().equals(t.getSlope()))
return false;
if (getTMax() != t.getTMax())
return false;
if (getDMax() != t.getDMax())
return false;
final Map e1 = getExtraValues();
final Map e2 = t.getExtraValues();
if (e1.size() != e2.size())
return false;
for (Map.Entry e : e1.entrySet()) {
final String key = e.getKey();
final String[] val1 = e.getValue();
final String[] val2 = e2.get(key);
if (!Arrays.equals(val1, val2))
return false;
}
return true;
}
@Override
public int hashCode() {
return getMetricName().hashCode();
}
/**
* {@inheritDoc}
*
* The default implementation is an identity transform. In order for this
* method to be applied the application MUST resolve metadata declarations
* received over the wire to local declarations in which this method has the
* desired behavior. This resolution step is necessary because the ganglia
* wire protocol is data-only and the translation steps can not be readily
* expressed as data (unless they are turned into a full formula evaluation
* model, adding substantial complexity to the ganglia integration).
*
* TODO We could also add a method which return true iff two values differ
* sufficient for an updated metric record to be sent out.
*/
@Override
public Object translateValue(final Object value) {
return value;
}
/**
* {@inheritDoc}
*
* The default implementation returns true
iff the two values
* are not equals().
*/
@Override
public boolean isChanged(final Object oldValue, final Object newValue) {
final boolean changed = !oldValue.equals(newValue);
return changed;
}
}