Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ Metrics are selected using a [YAML configuration file](#Configuration).
The exporter is available in two forms:
- A [web application](#web-application) that you deploy to the server from which metrics are to be extracted.
You may include a configuration file directly in the WAR file, and you may temporarily modify the configuration in a
running system by using a web form. If a [coordination configurator](config_coordinator/README.md) is running and configured,
running system by using a web form, either by selecting a replacement configuration or one to append to the current one,
with the caveat that if both the original and appended configurations have filters, the update will be rejected.
If a [coordination configurator](config_coordinator/README.md) is running and configured,
that temporary configuration will be sent to all servers configured to use it.

- A [separate process](#sidecar) that is run alongside a server instance. You supply the configuration to such a
Expand Down Expand Up @@ -288,7 +290,7 @@ vulnerability disclosure process.

## License

Copyright (c) 2019, 2022 Oracle and/or its affiliates.
Copyright (c) 2019, 2023, Oracle and/or its affiliates.

Released under the Universal Permissive License v1.0 as shown at
<https://oss.oracle.com/licenses/upl/>.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021, 2022 Oracle and/or its affiliates.
// Copyright (c) 2021, 2023, Oracle and/or its affiliates.
// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.

package com.oracle.wls.exporter;
Expand All @@ -8,13 +8,15 @@
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;

import static java.time.format.DateTimeFormatter.ISO_LOCAL_TIME;

/**
* A diagnostic class that records requests sent to WLS and the replies received.
*/
public class WlsRestExchanges {

public static final int MAX_EXCHANGES = 5;
private static final String TEMPLATE = "REQUEST to %s:%n%s%nREPLY:%n%s%n";
private static final String TEMPLATE = "At %s, REQUEST to %s:%n%s%nREPLY:%n%s%n";

private static final Queue<String> exchanges = new ConcurrentLinkedDeque<>();

Expand All @@ -35,10 +37,14 @@ public static List<String> getExchanges() {
* @param response the returned JSON string
*/
public static void addExchange(String url, String request, String response) {
exchanges.add(String.format(TEMPLATE, url, request, response));
exchanges.add(String.format(TEMPLATE, getCurrentTime(), url, request, response));
if (exchanges.size() > MAX_EXCHANGES) exchanges.remove();
}

private static String getCurrentTime() {
return ISO_LOCAL_TIME.format(SystemClock.now());
}

/**
* Clears the set of recorded exchanges. Intended for unit testing.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import com.google.gson.Gson;
Expand All @@ -30,13 +29,18 @@ class JsonQuerySpec {
private List<String> selectedKeys = null;
private List<String> excludeFields = null;

JsonQuerySpec asTopLevel() {
addFields();
return this;
}

/**
* Specifies the name of any mbean values which should be retrieved.
* @param newFields the field names to add to any previous defined
*/
void addFields(String... newFields) {
if (fields == null) fields = new ArrayList<>();
Arrays.stream(newFields).filter(Objects::nonNull).forEach(fields::add);
fields.addAll(Arrays.asList(newFields));
}

/**
Expand All @@ -50,8 +54,8 @@ void addChild(String name, JsonQuerySpec child) {
children.put(name, child);
}

void setFilter(String keyName, Set<String> selectedKeys) {
this.keyName = keyName;
void setFilter(Set<String> selectedKeys) {
this.keyName = MBeanSelector.FILTER_KEY;
this.selectedKeys = new ArrayList<>(selectedKeys);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ public class MBeanSelector {
static final String EXCLUDED_KEYS_KEY = "excludedKeyValues";
static final String VALUES_KEY = "values";
static final String STRING_VALUES_KEY = "stringValues";

/** The name of the field on which all runtime mbeans are filtered. **/
static final String FILTER_KEY = "name";
static final String TYPE_FIELD_NAME = "type";
static final MBeanSelector DOMAIN_NAME_SELECTOR = createDomainNameSelector();
static final String NESTING = " ";
Expand Down Expand Up @@ -105,7 +108,6 @@ private MBeanSelector(Map<String, Object> map) {
break;
}
}
validate();
}

private void addNestedSelector(String key, Object selectorValue) {
Expand Down Expand Up @@ -160,13 +162,6 @@ private void addStringValues(Object value) {
}
}

private void validate() {
if (getKey() == null && includedKeys != null)
throw new ConfigurationException("Included key values specified without key field");
if (getKey() == null && excludedKeys != null)
throw new ConfigurationException("Excluded key values specified without key field");
}

/**
* Appends a readable form of this selector as a YAML query to the specified string builder.
* @param sb the string builder into which the selector should be added
Expand Down Expand Up @@ -361,7 +356,7 @@ JsonQuerySpec toQuerySpec() {
selectQueryFields(spec, getQueryValues());
}
if (currentSelectorHasFilter() && !filter.isEmpty())
spec.setFilter(key, filter);
spec.setFilter(filter);

for (Map.Entry<String, MBeanSelector> entry : nestedSelectors.entrySet())
if (entry.getValue().isEnabled())
Expand Down Expand Up @@ -400,13 +395,13 @@ private void selectQueryFields(JsonQuerySpec spec, String[] fields) {
* @return a JSON string
*/
public String getKeyRequest() {
return toKeyQuerySpec().toJson(new Gson());
return toKeyQuerySpec().asTopLevel().toJson(new Gson());
}

JsonQuerySpec toKeyQuerySpec() {
JsonQuerySpec spec = new JsonQuerySpec();
if (currentSelectorHasFilter())
spec.addFields(key);
spec.addFields(FILTER_KEY);
else
spec.addFields();

Expand Down Expand Up @@ -480,8 +475,10 @@ private Stream<JsonElement> getItemsAsStream(JsonObject keyResponse, String subE


private void acceptItem(JsonObject entry) {
final JsonElement keyElement = entry.get(key);
if (keyElement.isJsonPrimitive() && keyElement.getAsJsonPrimitive().isString()) {
final JsonElement keyElement = entry.get(FILTER_KEY);
if (keyElement == null)
offerKeys(entry);
else if (keyElement.isJsonPrimitive() && keyElement.getAsJsonPrimitive().isString()) {
final String offeredKey = keyElement.getAsJsonPrimitive().getAsString();
if (isSelectedKey(offeredKey)) {
filter.add(offeredKey);
Expand Down Expand Up @@ -512,12 +509,18 @@ MBeanSelector merge(MBeanSelector selector) {
}

private MBeanSelector(MBeanSelector first, MBeanSelector second) {
rejectConflicts(first, second);
copyScalars(first);
combineValues(first, second);
combineStringValues(first, second);
combineNestedSelectors(first, second);
}

private void rejectConflicts(MBeanSelector first, MBeanSelector second) {
if (first.hasFilter() && second.hasFilter())
throw new ConfigurationException("May not merge configurations when both have filters.");
}

private void copyScalars(MBeanSelector first) {
this.type = first.type;
this.prefix = first.prefix;
Expand Down
Loading