的
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
# binjr-adapter-jrds
|
||||
|
||||
[](https://search.maven.org/search?q=g:%22eu.binjr%22%20AND%20a:%22binjr-adapter-jrds%22)
|
||||
|
||||
This module implements a DataAdapter capable of consuming data from a [JRDS](https://github.com/fbacchella/jrds) instance.
|
||||
|
||||
JRDS is a monitoring and performance collection application. It already proposes a web based front-end that allow end-users
|
||||
to visualize time-series as graphs which is based on [RRD4J](https://github.com/rrd4j/rrd4j), but does so by producing static images that can’t be
|
||||
zoomed in or out.
|
||||
|
||||
Using this DataAdapter, you can connect to a JRDS server via HTTP and use the flexibility offered by binjr to
|
||||
navigate through the data.
|
||||
|
||||
This adapter supports authentication via Kerberos (see [here](https://github.com/binjr/binjr/wiki/Troubleshooting#kerberos-authentication-issues)
|
||||
if you need help getting it to work).
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2018-2021 Frederic Thevenet
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
dependencies {
|
||||
compileOnly project(':binjr-core')
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes(
|
||||
'Specification-Title': project.name,
|
||||
'Specification-Version': project.version,
|
||||
'Implementation-Title': project.name,
|
||||
'Implementation-Version': project.version,
|
||||
'Build-Number': BINJR_BUILD_NUMBER
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2017-2020 Frederic Thevenet
|
||||
*
|
||||
* 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 eu.binjr.sources.jrds.adapters;
|
||||
|
||||
import jakarta.xml.bind.annotation.*;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A annotated POJO class used to deserialize JRDS graph descriptor XML messages return by {@code /graphdesc?id=""} service.
|
||||
*
|
||||
* @author Frederic Thevenet
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlRootElement(name = "graphdec")
|
||||
class Graphdesc {
|
||||
@XmlElement(name = "name")
|
||||
String name;
|
||||
@XmlElement(name = "graphName")
|
||||
String graphName;
|
||||
@XmlElement(name = "graphClass")
|
||||
String graphClass;
|
||||
@XmlElement(name = "graphTitle")
|
||||
String graphTitle;
|
||||
@XmlElementWrapper(name = "unit")
|
||||
@XmlElements({
|
||||
@XmlElement(name = "SI", type = JrdsMetricUnitType.class),
|
||||
@XmlElement(name = "binary", type = JrdsBinaryUnitType.class)
|
||||
})
|
||||
List<JrdsUnitType> unit;
|
||||
@XmlElement(name = "verticalLabel")
|
||||
String verticalLabel;
|
||||
@XmlElement(name = "upperLimit")
|
||||
String upperLimit;
|
||||
@XmlElement(name = "lowerLimit")
|
||||
String lowerLimit;
|
||||
@XmlElement(name = "logarithmic")
|
||||
String logarithmic;
|
||||
@XmlElement(name = "add")
|
||||
List<SeriesDesc> seriesDescList;
|
||||
@XmlElement(name = "tree")
|
||||
List<Tree> trees;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("Graphdesc{");
|
||||
sb.append("name='").append(name).append('\'');
|
||||
sb.append(", graphName='").append(graphName).append('\'');
|
||||
sb.append(", graphClass='").append(graphClass).append('\'');
|
||||
sb.append(", graphTitle='").append(graphTitle).append('\'');
|
||||
sb.append(", unit='").append(unit).append('\'');
|
||||
sb.append(", verticalLabel='").append(verticalLabel).append('\'');
|
||||
sb.append(", upperLimit='").append(upperLimit).append('\'');
|
||||
sb.append(", lowerLimit='").append(lowerLimit).append('\'');
|
||||
sb.append(", logarithmic='").append(logarithmic).append('\'');
|
||||
sb.append(", seriesDescList=").append(seriesDescList.stream().map(SeriesDesc::toString).collect(Collectors.joining(";")));
|
||||
sb.append(", trees=").append(trees.stream().map(Tree::toString).collect(Collectors.joining(";")));
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlRootElement(name = "add")
|
||||
static class SeriesDesc {
|
||||
@XmlElement(name = "name")
|
||||
String name = "";
|
||||
@XmlElement(name = "dsName")
|
||||
String dsName = "";
|
||||
@XmlElement(name = "graphType")
|
||||
String graphType = "";
|
||||
@XmlElement(name = "color")
|
||||
String color = "";
|
||||
@XmlElement(name = "legend")
|
||||
String legend = "";
|
||||
@XmlElement(name = "rpn")
|
||||
String rpn = "";
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("SeriesDesc{");
|
||||
sb.append("name='").append(name).append('\'');
|
||||
sb.append(", dsName='").append(dsName).append('\'');
|
||||
sb.append(", graphType='").append(graphType).append('\'');
|
||||
sb.append(", color='").append(color).append('\'');
|
||||
sb.append(", legend='").append(legend).append('\'');
|
||||
sb.append(", rpn='").append(rpn).append('\'');
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlRootElement(name = "tree")
|
||||
static class Tree {
|
||||
@XmlElement(name = "pathstring")
|
||||
List<String> pathstring;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder("Tree{");
|
||||
sb.append("pathstring=").append(pathstring);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@XmlSeeAlso({JrdsMetricUnitType.class, JrdsBinaryUnitType.class})
|
||||
public static abstract class JrdsUnitType {
|
||||
}
|
||||
|
||||
@XmlType(name = "SI")
|
||||
public static class JrdsMetricUnitType extends JrdsUnitType {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SI";
|
||||
}
|
||||
}
|
||||
|
||||
@XmlType(name = "binary")
|
||||
public static class JrdsBinaryUnitType extends JrdsUnitType {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "binary";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2017-2020 Frederic Thevenet
|
||||
*
|
||||
* 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 eu.binjr.sources.jrds.adapters;
|
||||
|
||||
import eu.binjr.core.data.adapters.DataAdapter;
|
||||
import eu.binjr.core.data.exceptions.DataAdapterException;
|
||||
import eu.binjr.core.dialogs.DataAdapterDialog;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.VPos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ChoiceBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
|
||||
import java.net.URI;
|
||||
import java.time.ZoneId;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* An implementation of the {@link DataAdapterDialog} class that presents a dialog box to retrieve the parameters specific {@link JrdsDataAdapter}
|
||||
*
|
||||
* @author Frederic Thevenet
|
||||
*/
|
||||
public class JrdsAdapterDialog extends DataAdapterDialog<URI> {
|
||||
private final ChoiceBox<JrdsTreeViewTab> tabsChoiceBox;
|
||||
private final TextField extraArgumentTextField;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@link JrdsAdapterDialog} class.
|
||||
*
|
||||
* @param owner the owner window for the dialog
|
||||
*/
|
||||
public JrdsAdapterDialog(Node owner) {
|
||||
super(owner, Mode.URI, "mostRecentJrdsUrls", true);
|
||||
this.setDialogHeaderText("Connect to a JRDS source");
|
||||
this.tabsChoiceBox = new ChoiceBox<>();
|
||||
tabsChoiceBox.getItems().addAll(JrdsTreeViewTab.values());
|
||||
this.extraArgumentTextField = new TextField();
|
||||
HBox.setHgrow(extraArgumentTextField, Priority.ALWAYS);
|
||||
HBox hBox = new HBox(tabsChoiceBox, extraArgumentTextField);
|
||||
hBox.setSpacing(10);
|
||||
|
||||
GridPane.setConstraints(hBox, 1, 2, 1, 1, HPos.LEFT, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS, new Insets(4, 0, 4, 0));
|
||||
tabsChoiceBox.getSelectionModel().select(JrdsTreeViewTab.HOSTS_TAB);
|
||||
Label tabsLabel = new Label("Sorted By:");
|
||||
GridPane.setConstraints(tabsLabel, 0, 2, 1, 1, HPos.LEFT, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS, new Insets(4, 0, 4, 0));
|
||||
getParamsGridPane().getChildren().addAll(tabsLabel, hBox);
|
||||
extraArgumentTextField.visibleProperty().bind(Bindings.createBooleanBinding(() -> this.tabsChoiceBox.valueProperty().get().getArgument() != null, this.tabsChoiceBox.valueProperty()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<DataAdapter> getDataAdapters() throws DataAdapterException {
|
||||
return List.of(JrdsDataAdapter.fromUrl(
|
||||
getSourceUri(),
|
||||
ZoneId.of(getSourceTimezone()),
|
||||
this.tabsChoiceBox.getValue(),
|
||||
this.extraArgumentTextField.getText()));
|
||||
}
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2020 Frederic Thevenet
|
||||
*
|
||||
* 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 eu.binjr.sources.jrds.adapters;
|
||||
|
||||
import eu.binjr.common.logging.Logger;
|
||||
import eu.binjr.core.data.adapters.TimeSeriesBinding;
|
||||
import eu.binjr.core.data.workspace.ChartType;
|
||||
import eu.binjr.core.data.workspace.UnitPrefixes;
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
/**
|
||||
* Factory used to build instances of {@link eu.binjr.core.data.adapters.SourceBinding} from values
|
||||
* configured by the setters, for use with {@link JrdsDataAdapter}
|
||||
*/
|
||||
public class JrdsBindingBuilder extends TimeSeriesBinding.Builder {
|
||||
private static final Logger logger = Logger.create(JrdsBindingBuilder.class);
|
||||
|
||||
@Override
|
||||
protected JrdsBindingBuilder self() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the builder with all the parameters contained in a {@link Graphdesc} instance.
|
||||
*
|
||||
* @param graphdesc the graphdesc
|
||||
* @return This builder.
|
||||
*/
|
||||
public JrdsBindingBuilder withGraphDesc(Graphdesc graphdesc) {
|
||||
withLabel(isNullOrEmpty(graphdesc.name) ?
|
||||
(isNullOrEmpty(graphdesc.graphName) ?
|
||||
"???" : graphdesc.graphName) : graphdesc.name);
|
||||
withGraphType(getChartType(graphdesc));
|
||||
withPrefix(findPrefix(graphdesc));
|
||||
withUnitName(graphdesc.verticalLabel);
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the builder with all the parameters contained in the {@link eu.binjr.sources.jrds.adapters.Graphdesc.SeriesDesc}
|
||||
* at the provided index
|
||||
*
|
||||
* @param graphdesc the graphdesc
|
||||
* @param idx the index
|
||||
* @return This builder.
|
||||
*/
|
||||
public JrdsBindingBuilder withGraphDesc(Graphdesc graphdesc, int idx) {
|
||||
Graphdesc.SeriesDesc desc = graphdesc.seriesDescList.get(idx);
|
||||
withLabel(isNullOrEmpty(desc.name) ?
|
||||
(isNullOrEmpty(desc.dsName) ?
|
||||
(isNullOrEmpty(desc.legend) ?
|
||||
"???" : desc.legend) : desc.dsName) : desc.name);
|
||||
Color c = null;
|
||||
try {
|
||||
if (!isNullOrEmpty(desc.color)) {
|
||||
c = Color.web(desc.color);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.warn("Invalid color string for binding " + toString());
|
||||
}
|
||||
withColor(c);
|
||||
withLegend(isNullOrEmpty(desc.legend) ?
|
||||
(isNullOrEmpty(desc.name) ?
|
||||
(isNullOrEmpty(desc.dsName) ?
|
||||
"???" : desc.dsName) : desc.name) : desc.legend);
|
||||
withGraphType(getChartType(desc));
|
||||
withPrefix(findPrefix(graphdesc));
|
||||
withUnitName(graphdesc.verticalLabel);
|
||||
return self();
|
||||
}
|
||||
|
||||
private UnitPrefixes findPrefix(Graphdesc graphdesc) {
|
||||
if (graphdesc.unit != null && graphdesc.unit.size() > 0) {
|
||||
if (graphdesc.unit.get(0) instanceof Graphdesc.JrdsMetricUnitType) {
|
||||
return UnitPrefixes.METRIC;
|
||||
}
|
||||
if (graphdesc.unit.get(0) instanceof Graphdesc.JrdsBinaryUnitType) {
|
||||
return UnitPrefixes.BINARY;
|
||||
}
|
||||
}
|
||||
return UnitPrefixes.UNDEFINED;
|
||||
}
|
||||
|
||||
private ChartType getChartType(Graphdesc graphdesc) {
|
||||
return graphdesc.seriesDescList.stream()
|
||||
.filter(desc -> !desc.graphType.equalsIgnoreCase("none") && !desc.graphType.equalsIgnoreCase("comment"))
|
||||
.reduce((last, n) -> n)
|
||||
.map(this::getChartType)
|
||||
.orElse(ChartType.UNDEFINED);
|
||||
}
|
||||
|
||||
private ChartType getChartType(Graphdesc.SeriesDesc desc) {
|
||||
return switch (desc.graphType.toLowerCase()) {
|
||||
case "area" -> ChartType.AREA;
|
||||
case "line" -> ChartType.LINE;
|
||||
case "stacked" -> ChartType.STACKED;
|
||||
default -> ChartType.UNDEFINED;
|
||||
};
|
||||
}
|
||||
|
||||
private boolean isNullOrEmpty(String s) {
|
||||
return s == null || s.trim().length() == 0;
|
||||
}
|
||||
}
|
||||
+404
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* Copyright 2016-2023 Frederic Thevenet
|
||||
*
|
||||
* 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 eu.binjr.sources.jrds.adapters;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonParseException;
|
||||
import eu.binjr.common.logging.Logger;
|
||||
import eu.binjr.common.xml.XmlUtils;
|
||||
import eu.binjr.core.data.adapters.*;
|
||||
import eu.binjr.core.data.codec.csv.CsvDecoder;
|
||||
import eu.binjr.core.data.exceptions.DataAdapterException;
|
||||
import eu.binjr.core.data.exceptions.FetchingDataFromAdapterException;
|
||||
import eu.binjr.core.data.exceptions.InvalidAdapterParameterException;
|
||||
import eu.binjr.core.data.exceptions.SourceCommunicationException;
|
||||
import eu.binjr.core.data.timeseries.DoubleTimeSeriesProcessor;
|
||||
import eu.binjr.core.dialogs.Dialogs;
|
||||
import eu.binjr.sources.jrds.adapters.json.JsonJrdsItem;
|
||||
import eu.binjr.sources.jrds.adapters.json.JsonJrdsTree;
|
||||
import jakarta.xml.bind.JAXB;
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import org.eclipse.fx.ui.controls.tree.FilterableTreeItem;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* This class provides an implementation of {@link SerializedDataAdapter} for JRDS.
|
||||
*
|
||||
* @author Frederic Thevenet
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class JrdsDataAdapter extends HttpDataAdapter<Double> {
|
||||
private static final String JRDS_FILTER = "filter";
|
||||
private static final String JRDS_TREE = "tree";
|
||||
private static final String ENCODING_PARAM_NAME = "encoding";
|
||||
private static final String ZONE_ID_PARAM_NAME = "zoneId";
|
||||
private static final String TREE_VIEW_TAB_PARAM_NAME = "treeViewTab";
|
||||
private static final Logger logger = Logger.create(JrdsDataAdapter.class);
|
||||
private static final char DELIMITER = ',';
|
||||
private final Gson gson;
|
||||
private CsvDecoder decoder;
|
||||
private String filter;
|
||||
private ZoneId zoneId;
|
||||
private String encoding;
|
||||
private JrdsTreeViewTab treeViewTab;
|
||||
|
||||
/**
|
||||
* Initialises a new instance of the {@link JrdsDataAdapter} class.
|
||||
*
|
||||
* @throws DataAdapterException if an error occurs while initializing the adapter.
|
||||
*/
|
||||
public JrdsDataAdapter() throws DataAdapterException {
|
||||
this(null, ZoneId.systemDefault(), "utf-8", JrdsTreeViewTab.HOSTS_TAB, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@link JrdsDataAdapter} class.
|
||||
*
|
||||
* @param baseURL the URL to the JRDS webapp.
|
||||
* @param zoneId the id of the time zone used to record dates.
|
||||
* @param encoding the encoding used by the download servlet.
|
||||
* @param treeViewTab the tab to apply.
|
||||
* @param filter the filter to apply to the tree view.
|
||||
* @throws DataAdapterException if an error occurs while initializing the adapter.
|
||||
*/
|
||||
public JrdsDataAdapter(URL baseURL, ZoneId zoneId, String encoding, JrdsTreeViewTab treeViewTab, String filter) throws DataAdapterException {
|
||||
super(baseURL);
|
||||
this.zoneId = zoneId;
|
||||
this.encoding = encoding;
|
||||
this.treeViewTab = treeViewTab;
|
||||
this.filter = filter;
|
||||
this.decoder = decoderFactory(zoneId);
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new instance of the {@link JrdsDataAdapter} class from the provided parameters.
|
||||
*
|
||||
* @param address the URL to the JRDS webapp.
|
||||
* @param zoneId the id of the time zone used to record dates.
|
||||
* @param treeViewTab the tab to apply.
|
||||
* @param filter the filter to apply to the tree view.
|
||||
* @return a new instance of the {@link JrdsDataAdapter} class.
|
||||
* @throws DataAdapterException if an error occurs while initializing the adapter.
|
||||
*/
|
||||
public static JrdsDataAdapter fromUrl(String address, ZoneId zoneId, JrdsTreeViewTab treeViewTab, String filter) throws DataAdapterException {
|
||||
return new JrdsDataAdapter(urlFromString(address), zoneId, "utf-8", treeViewTab, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterableTreeItem<SourceBinding> getBindingTree() throws DataAdapterException {
|
||||
try {
|
||||
JsonJrdsTree t = gson.fromJson(getJsonTree(treeViewTab.getCommand(), treeViewTab.getArgument(), filter), JsonJrdsTree.class);
|
||||
Map<String, JsonJrdsItem> m = Arrays.stream(t.items).collect(Collectors.toMap(o -> o.id, (o -> o)));
|
||||
FilterableTreeItem<SourceBinding> tree = new FilterableTreeItem<>(
|
||||
new JrdsBindingBuilder()
|
||||
.withLabel(getSourceName())
|
||||
.withPath("/")
|
||||
.withAdapter(this)
|
||||
.build());
|
||||
for (JsonJrdsItem branch : Arrays.stream(t.items)
|
||||
.filter(jsonJrdsItem -> JRDS_TREE.equals(jsonJrdsItem.type) || JRDS_FILTER.equals(jsonJrdsItem.type))
|
||||
.collect(Collectors.toList())) {
|
||||
attachNode(tree, branch.id, m);
|
||||
}
|
||||
return tree;
|
||||
} catch (JsonParseException e) {
|
||||
throw new DataAdapterException("An error occurred while parsing the json response to getBindingTree request", e);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new SourceCommunicationException("Error building URI for request", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected URI craftFetchUri(String path, Instant begin, Instant end) throws DataAdapterException {
|
||||
return craftRequestUri("download",
|
||||
new UriParameter("id", path),
|
||||
new UriParameter("begin", Long.toString(begin.toEpochMilli())),
|
||||
new UriParameter("end", Long.toString(end.toEpochMilli()))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceName() {
|
||||
return new StringBuilder("[JRDS] ")
|
||||
.append(getBaseAddress() != null ? getBaseAddress().getHost() : "???")
|
||||
.append((getBaseAddress() != null && getBaseAddress().getPort() > 0) ? ":" + getBaseAddress().getPort() : "")
|
||||
.append(" - ")
|
||||
.append(treeViewTab != null ? treeViewTab : "???")
|
||||
.append(filter != null ? filter : "")
|
||||
.append(" (")
|
||||
.append(zoneId != null ? zoneId : "???")
|
||||
.append(")").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getParams() {
|
||||
Map<String, String> params = new HashMap<>(super.getParams());
|
||||
params.put(ZONE_ID_PARAM_NAME, zoneId.toString());
|
||||
params.put(ENCODING_PARAM_NAME, encoding);
|
||||
params.put(TREE_VIEW_TAB_PARAM_NAME, treeViewTab.name());
|
||||
params.put(JRDS_FILTER, this.filter);
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadParams(Map<String, String> params) throws DataAdapterException {
|
||||
if (params == null) {
|
||||
throw new InvalidAdapterParameterException("Could not find parameter list for adapter " + getSourceName());
|
||||
}
|
||||
super.loadParams(params);
|
||||
encoding = validateParameterNullity(params, ENCODING_PARAM_NAME);
|
||||
zoneId = validateParameter(params, ZONE_ID_PARAM_NAME,
|
||||
s -> {
|
||||
if (s == null) {
|
||||
throw new InvalidAdapterParameterException("Parameter " + ZONE_ID_PARAM_NAME + " is missing in adapter " + getSourceName());
|
||||
}
|
||||
return ZoneId.of(s);
|
||||
});
|
||||
treeViewTab = validateParameter(params, TREE_VIEW_TAB_PARAM_NAME, s -> s == null ? JrdsTreeViewTab.valueOf(params.get(TREE_VIEW_TAB_PARAM_NAME)) : JrdsTreeViewTab.HOSTS_TAB);
|
||||
this.filter = params.get(JRDS_FILTER);
|
||||
this.decoder = decoderFactory(zoneId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZoneId getTimeZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CsvDecoder getDecoder() {
|
||||
return decoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of filters provided by the JRDS server.
|
||||
*
|
||||
* @return a collection of filters provided by the JRDS server.
|
||||
* @throws DataAdapterException if an error occurs while parsing the server's response.
|
||||
* @throws URISyntaxException if the generated url is not valid.
|
||||
*/
|
||||
public Collection<String> discoverFilters() throws DataAdapterException, URISyntaxException {
|
||||
try {
|
||||
JsonJrdsTree t = gson.fromJson(getJsonTree(treeViewTab.getCommand(), treeViewTab.getArgument()), JsonJrdsTree.class);
|
||||
return Arrays.stream(t.items).filter(jsonJrdsItem -> JRDS_FILTER.equals(jsonJrdsItem.type)).map(i -> i.filter).collect(Collectors.toList());
|
||||
} catch (JsonParseException e) {
|
||||
throw new DataAdapterException("An error occurred while parsing the json response to getBindingTree request", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void attachNode(FilterableTreeItem<SourceBinding> tree, String id, Map<String, JsonJrdsItem> nodes) throws DataAdapterException {
|
||||
JsonJrdsItem n = nodes.get(id);
|
||||
String currentPath = normalizeId(n.id);
|
||||
FilterableTreeItem<SourceBinding> newBranch = new FilterableTreeItem<>(
|
||||
new JrdsBindingBuilder()
|
||||
.withParent(tree.getValue())
|
||||
.withLabel(n.name)
|
||||
.withPath(currentPath)
|
||||
.withAdapter(this)
|
||||
.build());
|
||||
if (JRDS_FILTER.equals(n.type)) {
|
||||
// add a dummy node so that the branch can be expanded
|
||||
newBranch.getInternalChildren().add(new FilterableTreeItem<>(null));
|
||||
// add a listener that will get the treeview filtered according to the selected filter/tag
|
||||
newBranch.expandedProperty().addListener(new FilteredViewListener(n, newBranch));
|
||||
} else {
|
||||
if (n.children != null) {
|
||||
for (JsonJrdsItem.JsonTreeRef ref : n.children) {
|
||||
attachNode(newBranch, ref._reference, nodes);
|
||||
}
|
||||
} else {
|
||||
// add a dummy node so that the branch can be expanded
|
||||
newBranch.getInternalChildren().add(new FilterableTreeItem<>(null));
|
||||
// add a listener so that bindings for individual datastore are added lazily to avoid
|
||||
// dozens of individual call to "graphdesc" when the tree is built.
|
||||
newBranch.expandedProperty().addListener(new GraphDescListener(currentPath, newBranch, tree));
|
||||
}
|
||||
}
|
||||
tree.getInternalChildren().add(newBranch);
|
||||
}
|
||||
|
||||
private String normalizeId(String id) {
|
||||
if (id == null || id.trim().length() == 0) {
|
||||
throw new IllegalArgumentException("Argument id cannot be null or blank");
|
||||
}
|
||||
String[] data = id.split("\\.");
|
||||
return data[data.length - 1];
|
||||
}
|
||||
|
||||
private String getJsonTree(String tabName, String argName) throws DataAdapterException, URISyntaxException {
|
||||
return getJsonTree(tabName, argName, null);
|
||||
}
|
||||
|
||||
private String getJsonTree(String tabName, String argName, String argValue) throws DataAdapterException, URISyntaxException {
|
||||
List<NameValuePair> params = new ArrayList<>();
|
||||
params.add(new UriParameter("tab", tabName));
|
||||
if (argName != null && argValue != null && argValue.trim().length() > 0) {
|
||||
params.add(new UriParameter(argName, argValue));
|
||||
}
|
||||
String entityString = doHttpGetJson(craftRequestUri("jsontree", params));
|
||||
logger.trace(entityString);
|
||||
return entityString;
|
||||
}
|
||||
|
||||
|
||||
private Graphdesc getGraphDescriptor(String id) throws DataAdapterException {
|
||||
URI requestUri = craftRequestUri("graphdesc", new UriParameter("id", id));
|
||||
return doHttpGet(requestUri, responseInfo -> HttpResponse.BodySubscribers.mapping(HttpResponse.BodySubscribers.ofInputStream(), body -> {
|
||||
if (responseInfo.statusCode() == 404) {
|
||||
// This is probably an older version of JRDS that doesn't provide the graphdesc service,
|
||||
// so we're falling back to recovering the datastore name from the csv file provided by
|
||||
// the download service.
|
||||
logger.warn("Cannot found graphdesc service; falling back to legacy mode.");
|
||||
try {
|
||||
return getGraphDescriptorLegacy(id);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
if (body == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return JAXB.unmarshal(XmlUtils.toNonValidatingSAXSource(body), Graphdesc.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to unmarshall graphdesc response", e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private Graphdesc getGraphDescriptorLegacy(String id) throws DataAdapterException {
|
||||
Instant now = ZonedDateTime.now().toInstant();
|
||||
try (InputStream in = fetchRawData(id, now.minusSeconds(300), now, false)) {
|
||||
List<String> headers = getDecoder().getDataColumnHeaders(in);
|
||||
Graphdesc desc = new Graphdesc();
|
||||
desc.seriesDescList = new ArrayList<>();
|
||||
for (String header : headers) {
|
||||
Graphdesc.SeriesDesc d = new Graphdesc.SeriesDesc();
|
||||
d.name = header;
|
||||
desc.seriesDescList.add(d);
|
||||
}
|
||||
return desc;
|
||||
} catch (IOException e) {
|
||||
throw new FetchingDataFromAdapterException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private CsvDecoder decoderFactory(ZoneId zoneId) {
|
||||
return new CsvDecoder(getEncoding(), DELIMITER,
|
||||
DoubleTimeSeriesProcessor::new,
|
||||
s -> ZonedDateTime.parse(s, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(zoneId)));
|
||||
}
|
||||
|
||||
private class GraphDescListener implements ChangeListener<Boolean> {
|
||||
private final String currentPath;
|
||||
private final FilterableTreeItem<SourceBinding> newBranch;
|
||||
private final FilterableTreeItem<SourceBinding> tree;
|
||||
|
||||
public GraphDescListener(String currentPath, FilterableTreeItem<SourceBinding> newBranch, FilterableTreeItem<SourceBinding> tree) {
|
||||
this.currentPath = currentPath;
|
||||
this.newBranch = newBranch;
|
||||
this.tree = tree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
|
||||
if (newValue) {
|
||||
try {
|
||||
Graphdesc graphdesc = getGraphDescriptor(currentPath);
|
||||
newBranch.setValue(new JrdsBindingBuilder()
|
||||
.withGraphDesc(graphdesc)
|
||||
.withParent(tree.getValue())
|
||||
.withLegend(newBranch.getValue().getLegend())
|
||||
.withPath(currentPath)
|
||||
.withAdapter(JrdsDataAdapter.this)
|
||||
.build());
|
||||
for (int i = 0; i < graphdesc.seriesDescList.size(); i++) {
|
||||
String graphType = graphdesc.seriesDescList.get(i).graphType;
|
||||
if (!"none".equalsIgnoreCase(graphType) && !"comment".equalsIgnoreCase(graphType)) {
|
||||
newBranch.getInternalChildren().add(new FilterableTreeItem<>((new JrdsBindingBuilder()
|
||||
.withGraphDesc(graphdesc, i)
|
||||
.withParent(newBranch.getValue())
|
||||
.withPath(currentPath)
|
||||
.withAdapter(JrdsDataAdapter.this)
|
||||
.build())));
|
||||
}
|
||||
}
|
||||
//remove dummy node
|
||||
newBranch.getInternalChildren().remove(0);
|
||||
// remove the listener so it isn't executed next time node is expanded
|
||||
newBranch.expandedProperty().removeListener(this);
|
||||
} catch (Exception e) {
|
||||
Dialogs.notifyException("Failed to retrieve graph description", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class FilteredViewListener implements ChangeListener<Boolean> {
|
||||
private final JsonJrdsItem n;
|
||||
private final FilterableTreeItem<SourceBinding> newBranch;
|
||||
|
||||
public FilteredViewListener(JsonJrdsItem n, FilterableTreeItem<SourceBinding> newBranch) {
|
||||
this.n = n;
|
||||
this.newBranch = newBranch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
|
||||
if (newValue) {
|
||||
try {
|
||||
JsonJrdsTree t = gson.fromJson(getJsonTree(treeViewTab.getCommand(), JRDS_FILTER, n.name), JsonJrdsTree.class);
|
||||
Map<String, JsonJrdsItem> m = Arrays.stream(t.items).collect(Collectors.toMap(o -> o.id, (o -> o)));
|
||||
for (JsonJrdsItem branch : Arrays.stream(t.items).filter(jsonJrdsItem -> JRDS_TREE.equals(jsonJrdsItem.type) || JRDS_FILTER.equals(jsonJrdsItem.type)).collect(Collectors.toList())) {
|
||||
attachNode(newBranch, branch.id, m);
|
||||
}
|
||||
//remove dummy node
|
||||
newBranch.getInternalChildren().remove(0);
|
||||
// remove the listener so it isn't executed next time node is expanded
|
||||
newBranch.expandedProperty().removeListener(this);
|
||||
} catch (Exception e) {
|
||||
Dialogs.notifyException("Failed to retrieve graph description", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2017-2023 Frederic Thevenet
|
||||
*
|
||||
* 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 eu.binjr.sources.jrds.adapters;
|
||||
|
||||
import eu.binjr.core.data.adapters.AdapterMetadata;
|
||||
import eu.binjr.core.data.adapters.BaseDataAdapterInfo;
|
||||
import eu.binjr.core.data.adapters.SourceLocality;
|
||||
import eu.binjr.core.data.adapters.VisualizationType;
|
||||
import eu.binjr.core.data.exceptions.CannotInitializeDataAdapterException;
|
||||
import eu.binjr.core.preferences.AppEnvironment;
|
||||
|
||||
/**
|
||||
* Defines the metadata associated with the JrdsDataAdapter.
|
||||
*
|
||||
* @author Frederic Thevenet
|
||||
*/
|
||||
@AdapterMetadata(
|
||||
name = "JRDS",
|
||||
description = "JRDS Data Adapter",
|
||||
copyright = AppEnvironment.COPYRIGHT_NOTICE,
|
||||
license = AppEnvironment.LICENSE,
|
||||
siteUrl = AppEnvironment.HTTP_WWW_BINJR_EU,
|
||||
adapterClass = JrdsDataAdapter.class,
|
||||
dialogClass = JrdsAdapterDialog.class,
|
||||
sourceLocality = SourceLocality.REMOTE,
|
||||
apiLevel = AppEnvironment.PLUGIN_API_LEVEL,
|
||||
visualizationType = VisualizationType.CHARTS
|
||||
)
|
||||
public class JrdsDataAdapterInfo extends BaseDataAdapterInfo {
|
||||
|
||||
/**
|
||||
* Initialises a new instance of the {@link JrdsDataAdapterInfo} class.
|
||||
*
|
||||
* @throws CannotInitializeDataAdapterException if the adapter's initialization failed
|
||||
*/
|
||||
public JrdsDataAdapterInfo() throws CannotInitializeDataAdapterException {
|
||||
super(JrdsDataAdapterInfo.class);
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2017-2020 Frederic Thevenet
|
||||
*
|
||||
* 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 eu.binjr.sources.jrds.adapters;
|
||||
|
||||
/**
|
||||
* An enumeration of JRDS tree tabs.
|
||||
*
|
||||
* @author Frederic Thevenet
|
||||
*/
|
||||
public enum JrdsTreeViewTab {
|
||||
/**
|
||||
* All Hosts
|
||||
*/
|
||||
HOSTS_TAB("All Hosts", "hoststab", null),
|
||||
/**
|
||||
* Single Host
|
||||
*/
|
||||
SINGLE_HOST("Host: ", "hoststab", "host"),
|
||||
/**
|
||||
* All Services
|
||||
*/
|
||||
SERVICE_TAB("All Services", "servicestab", null),
|
||||
/**
|
||||
* All Views
|
||||
*/
|
||||
VIEWS_TAB("All Views", "viewstab", null),
|
||||
/**
|
||||
* All Filters
|
||||
*/
|
||||
FILTER_TAB("All Filters", "filtertab", null),
|
||||
/**
|
||||
* Single Filter
|
||||
*/
|
||||
SINGLE_FILTER("Filter: ", "filtertab", "filter"),
|
||||
/**
|
||||
* All Tags
|
||||
*/
|
||||
TAGS_TAB("All Tags", "tagstab", null),
|
||||
/**
|
||||
* Single Tag
|
||||
*/
|
||||
SINGLE_TAG("Tag: ", "tagstab", "filter");
|
||||
|
||||
private final String argument;
|
||||
private final String label;
|
||||
private final String command;
|
||||
|
||||
JrdsTreeViewTab(String label, String command, String argument) {
|
||||
this.label = label;
|
||||
this.command = command;
|
||||
this.argument = argument;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command keyword associated with the enum entry
|
||||
*
|
||||
* @return the command keyword associated with the enum entry
|
||||
*/
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the argument associated with the enum entry
|
||||
*
|
||||
* @return the argument associated with the enum entry
|
||||
*/
|
||||
public String getArgument() {
|
||||
return argument;
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2017-2018 Frederic Thevenet
|
||||
*
|
||||
* 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 eu.binjr.sources.jrds.adapters.json;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* JRDS item data class
|
||||
*/
|
||||
public class JsonJrdsItem {
|
||||
/**
|
||||
* The name
|
||||
*/
|
||||
public String name;
|
||||
/**
|
||||
* The id
|
||||
*/
|
||||
public String id;
|
||||
/**
|
||||
* The type
|
||||
*/
|
||||
public String type;
|
||||
/**
|
||||
* The filter
|
||||
*/
|
||||
public String filter;
|
||||
/**
|
||||
* Children list
|
||||
*/
|
||||
public JsonTreeRef[] children;
|
||||
|
||||
/**
|
||||
* TreeRef
|
||||
*/
|
||||
public static class JsonTreeRef {
|
||||
/**
|
||||
* reference
|
||||
*/
|
||||
public String _reference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JsonJrdsItem{" +
|
||||
"name='" + name + '\'' +
|
||||
", id='" + id + '\'' +
|
||||
", type='" + type + '\'' +
|
||||
", filter='" + filter + '\'' +
|
||||
", children=" + Arrays.toString(children) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2017-2018 Frederic Thevenet
|
||||
*
|
||||
* 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 eu.binjr.sources.jrds.adapters.json;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Data class for JRDS status
|
||||
*/
|
||||
public class JsonJrdsStatus {
|
||||
/**
|
||||
* Hosts
|
||||
*/
|
||||
public int Hosts;
|
||||
/**
|
||||
* Probes
|
||||
*/
|
||||
public int Probes;
|
||||
/**
|
||||
* Timers
|
||||
*/
|
||||
public JsonJrdsTimer[] Timers;
|
||||
/**
|
||||
* Generation
|
||||
*/
|
||||
public int Generation;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JsonJrdsStatus{" +
|
||||
"Hosts=" + Hosts +
|
||||
", Probes=" + Probes +
|
||||
", Timers=" + Arrays.toString(Timers) +
|
||||
", Generation=" + Generation +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2017-2018 Frederic Thevenet
|
||||
*
|
||||
* 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 eu.binjr.sources.jrds.adapters.json;
|
||||
|
||||
/**
|
||||
* Data class for JRDS Timer
|
||||
*/
|
||||
public class JsonJrdsTimer {
|
||||
/**
|
||||
* Name
|
||||
*/
|
||||
public String Name;
|
||||
/**
|
||||
* Last collect
|
||||
*/
|
||||
public long LastCollect;
|
||||
/**
|
||||
* Last duration
|
||||
*/
|
||||
public long LastDuration;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JsonJrdsTimer{" +
|
||||
"Name='" + Name + '\'' +
|
||||
", LastCollect=" + LastCollect +
|
||||
", LastDuration=" + LastDuration +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2017-2018 Frederic Thevenet
|
||||
*
|
||||
* 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 eu.binjr.sources.jrds.adapters.json;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* POJO definition used to decode JSON message.
|
||||
*/
|
||||
public class JsonJrdsTree {
|
||||
/**
|
||||
* indentifier
|
||||
*/
|
||||
public String identifier;
|
||||
/**
|
||||
* label
|
||||
*/
|
||||
public String label;
|
||||
/**
|
||||
* Items
|
||||
*/
|
||||
public JsonJrdsItem[] items;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JsonJrdsTree{" +
|
||||
"identifier='" + identifier + '\'' +
|
||||
", label='" + label + '\'' +
|
||||
", items=" + Arrays.toString(items) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# Copyright 2017-2018 Frederic Thevenet
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# JRDS Data adapter service implementation
|
||||
eu.binjr.sources.jrds.adapters.JrdsDataAdapterInfo
|
||||
Reference in New Issue
Block a user