Skip to content

Commit

Permalink
HAL-2006: add runtime view for Resource Adapters statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
michpetrov committed Jan 31, 2025
1 parent df08977 commit c4c4453
Show file tree
Hide file tree
Showing 21 changed files with 1,373 additions and 1 deletion.
12 changes: 12 additions & 0 deletions app/src/main/java/org/jboss/hal/client/ConsoleModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@
import org.jboss.hal.client.runtime.subsystem.messaging.JmsQueueView;
import org.jboss.hal.client.runtime.subsystem.microprofile.health.MicroProfileHealthPresenter;
import org.jboss.hal.client.runtime.subsystem.microprofile.health.MicroProfileHealthView;
import org.jboss.hal.client.runtime.subsystem.resourceadapter.ChildResourcePresenter;
import org.jboss.hal.client.runtime.subsystem.resourceadapter.ChildResourceView;
import org.jboss.hal.client.skeleton.FooterPresenter;
import org.jboss.hal.client.skeleton.FooterView;
import org.jboss.hal.client.skeleton.HeaderPresenter;
Expand Down Expand Up @@ -600,6 +602,16 @@ protected void configure() {
Mbui_ResourceAdapterView.class,
ResourceAdapterPresenter.MyProxy.class);

bindPresenter(org.jboss.hal.client.runtime.subsystem.resourceadapter.ResourceAdapterPresenter.class,
org.jboss.hal.client.runtime.subsystem.resourceadapter.ResourceAdapterPresenter.MyView.class,
org.jboss.hal.client.runtime.subsystem.resourceadapter.ResourceAdapterView.class,
org.jboss.hal.client.runtime.subsystem.resourceadapter.ResourceAdapterPresenter.MyProxy.class);

bindPresenter(ChildResourcePresenter.class,
ChildResourcePresenter.MyView.class,
ChildResourceView.class,
ChildResourcePresenter.MyProxy.class);

bindPresenter(RhcpPresenter.class,
RhcpPresenter.MyView.class,
RhcpView.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2022 Red Hat
*
* 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
*
* https://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 org.jboss.hal.client.runtime.subsystem.resourceadapter;

import org.jboss.hal.meta.AddressTemplate;

interface AddressTemplates {

String EXTENDED_STATISTICS = "/statistics=extended";
String POOL_STATISTICS = "/statistics=pool";

String RESOURCE_ADAPTER_SUBSYSTEM = "/subsystem=resource-adapters";
String RESOURCE_ADAPTER_SUBSYSTEM_ADDRESS = "/{selected.host}/{selected.server}" + RESOURCE_ADAPTER_SUBSYSTEM;
String RESOURCE_ADAPTER_ADDRESS = RESOURCE_ADAPTER_SUBSYSTEM_ADDRESS + "/resource-adapter=*";
String RESOURCE_ADAPTER_CONFIGURATION_ADDRESS = RESOURCE_ADAPTER_SUBSYSTEM + "/resource-adapter=*";
String CONNECTION_DEFINITION_ADDRESS = RESOURCE_ADAPTER_ADDRESS + "/connection-definitions=*";
String ADMIN_OBJECT_ADDRESS = RESOURCE_ADAPTER_ADDRESS + "/admin-objects=*";

String RESOURCE_ADAPTER_STATS_ADDRESS = AddressTemplate.OPTIONAL + "/" + RESOURCE_ADAPTER_ADDRESS + EXTENDED_STATISTICS;
String ADMIN_OBJECT_STATS_ADDRESS = AddressTemplate.OPTIONAL + "/" + ADMIN_OBJECT_ADDRESS + EXTENDED_STATISTICS;
String CONN_DEF_EXT_STATS_ADDRESS = AddressTemplate.OPTIONAL + "/" + CONNECTION_DEFINITION_ADDRESS + EXTENDED_STATISTICS;
String CONN_DEF_POOL_STATS_ADDRESS = CONNECTION_DEFINITION_ADDRESS + POOL_STATISTICS;

AddressTemplate RESOURCE_ADAPTER_SUBSYSTEM_TEMPLATE = AddressTemplate.of(RESOURCE_ADAPTER_SUBSYSTEM_ADDRESS);
AddressTemplate RESOURCE_ADAPTER_TEMPLATE = AddressTemplate.of(RESOURCE_ADAPTER_ADDRESS);

AddressTemplate ADMIN_OBJECT_TEMPLATE = AddressTemplate.of(ADMIN_OBJECT_ADDRESS);
AddressTemplate CONN_DEF_TEMPLATE = AddressTemplate.of(CONNECTION_DEFINITION_ADDRESS);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* Copyright 2022 Red Hat
*
* 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
*
* https://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 org.jboss.hal.client.runtime.subsystem.resourceadapter;

import org.jboss.hal.core.finder.Finder;
import org.jboss.hal.core.finder.FinderPath;
import org.jboss.hal.core.finder.FinderPathFactory;
import org.jboss.hal.core.mvp.ApplicationFinderPresenter;
import org.jboss.hal.core.mvp.HalView;
import org.jboss.hal.core.mvp.HasPresenter;
import org.jboss.hal.dmr.Operation;
import org.jboss.hal.dmr.ResourceAddress;
import org.jboss.hal.dmr.dispatch.Dispatcher;
import org.jboss.hal.meta.AddressTemplate;
import org.jboss.hal.meta.StatementContext;
import org.jboss.hal.resources.Ids;
import org.jboss.hal.resources.Names;
import org.jboss.hal.resources.Resources;

import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.mvp.client.proxy.ProxyPlace;
import com.gwtplatform.mvp.shared.proxy.PlaceRequest;

import static org.jboss.hal.client.runtime.subsystem.resourceadapter.AddressTemplates.EXTENDED_STATISTICS;
import static org.jboss.hal.client.runtime.subsystem.resourceadapter.AddressTemplates.POOL_STATISTICS;
import static org.jboss.hal.dmr.ModelDescriptionConstants.INCLUDE_RUNTIME;
import static org.jboss.hal.dmr.ModelDescriptionConstants.NAME;
import static org.jboss.hal.dmr.ModelDescriptionConstants.READ_RESOURCE_OPERATION;
import static org.jboss.hal.dmr.ModelDescriptionConstants.RECURSIVE;
import static org.jboss.hal.dmr.ModelDescriptionConstants.RESOURCE_ADAPTERS;
import static org.jboss.hal.dmr.ModelDescriptionConstants.TYPE;

public abstract class BasePresenter<V extends BasePresenter.MyView<?>, P extends BasePresenter.MyProxy<?>>
extends ApplicationFinderPresenter<V, P> {

private final FinderPathFactory finderPathFactory;
private final Dispatcher dispatcher;
private final StatementContext statementContext;
private final Resources resources;
private String resourceName;
private String parentName;
private StatisticsResource.ResourceType type;

public BasePresenter(EventBus eventBus,
V view,
P myProxy,
Finder finder,
FinderPathFactory finderPathFactory,
Dispatcher dispatcher,
StatementContext statementContext,
Resources resources) {
super(eventBus, view, myProxy, finder);
this.finderPathFactory = finderPathFactory;
this.dispatcher = dispatcher;
this.statementContext = statementContext;
this.resources = resources;
}

@Override
public void prepareFromRequest(PlaceRequest request) {
super.prepareFromRequest(request);
parentName = request.getParameter("parent", null);
resourceName = request.getParameter(NAME, null);
type = StatisticsResource.ResourceType.valueOf(request.getParameter(TYPE, null));
getView().setup();
}

@Override
public FinderPath finderPath() {
FinderPath path = finderPathFactory.runtimeServerPath()
.append(Ids.RUNTIME_SUBSYSTEM, RESOURCE_ADAPTERS, resources.constants().monitor(),
Names.RESOURCE_ADAPTERS);

String raName = type == StatisticsResource.ResourceType.RESOURCE_ADAPTER ? resourceName : parentName;
path.append(Ids.RESOURCE_ADAPTER_RUNTIME, Ids.resourceAdapterRuntime(raName), Names.RESOURCE_ADAPTER, raName);

if (type != StatisticsResource.ResourceType.RESOURCE_ADAPTER) {
path.append(Ids.RESOURCE_ADAPTER_CHILD_RUNTIME, Ids.resourceAdapterChildRuntime(parentName, resourceName),
Names.RESOURCE_ADAPTER + " Child", resourceName);
}
return path;
}

@Override
protected void reload() {
ResourceAddress address = getResourceAddress().resolve(statementContext);
Operation operation = new Operation.Builder(address, READ_RESOURCE_OPERATION)
.param(INCLUDE_RUNTIME, true)
.param(RECURSIVE, true)
.build();
dispatcher.execute(operation,
result -> getView().update(new StatisticsResource(parentName, resourceName, type, result)));
}

public StatisticsResource.ResourceType getType() {
return type;
}

public AddressTemplate getResourceAddress() {
AddressTemplate template = type.getTemplate();
return type == StatisticsResource.ResourceType.RESOURCE_ADAPTER
? template.replaceWildcards(resourceName)
: template.replaceWildcards(parentName, resourceName);
}

public AddressTemplate getExtendedStatsAddress() {
return getResourceAddress().append(EXTENDED_STATISTICS);
}

public AddressTemplate getPoolStatsAddress() {
return getResourceAddress().append(POOL_STATISTICS);
}

public interface MyProxy<P extends BasePresenter<?, ?>> extends ProxyPlace<P> {
}

public interface MyView<P extends BasePresenter<?, ?>> extends HalView, HasPresenter<P> {
void setup();

void update(StatisticsResource resource);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Copyright 2022 Red Hat
*
* 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
*
* https://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 org.jboss.hal.client.runtime.subsystem.resourceadapter;

import javax.inject.Inject;

import org.jboss.hal.ballroom.Alert;
import org.jboss.hal.ballroom.Tabs;
import org.jboss.hal.ballroom.form.Form;
import org.jboss.hal.core.mbui.form.ModelNodeForm;
import org.jboss.hal.core.mvp.HalViewImpl;
import org.jboss.hal.dmr.ModelNode;
import org.jboss.hal.meta.Metadata;
import org.jboss.hal.meta.MetadataRegistry;
import org.jboss.hal.meta.MissingMetadataException;
import org.jboss.hal.resources.Icons;
import org.jboss.hal.resources.Ids;
import org.jboss.hal.resources.Names;
import org.jboss.hal.resources.Resources;

import elemental2.dom.HTMLElement;

import static org.jboss.elemento.Elements.a;
import static org.jboss.elemento.Elements.h;
import static org.jboss.elemento.Elements.p;
import static org.jboss.elemento.Elements.span;
import static org.jboss.elemento.EventType.click;
import static org.jboss.hal.ballroom.LayoutBuilder.column;
import static org.jboss.hal.ballroom.LayoutBuilder.row;
import static org.jboss.hal.dmr.ModelDescriptionConstants.STATISTICS_ENABLED;
import static org.jboss.hal.resources.CSS.clearfix;
import static org.jboss.hal.resources.CSS.clickable;
import static org.jboss.hal.resources.CSS.fontAwesome;
import static org.jboss.hal.resources.CSS.marginRight5;
import static org.jboss.hal.resources.CSS.pullRight;

public abstract class BaseView<P extends BasePresenter<?, ?>> extends HalViewImpl
implements BasePresenter.MyView<P> {

private final MetadataRegistry metadataRegistry;
private final Resources resources;
private P presenter;
private HTMLElement header;
private Form<ModelNode> poolForm;
private Form<ModelNode> extendedForm;

@Inject
public BaseView(MetadataRegistry metadataRegistry, Resources resources) {
this.metadataRegistry = metadataRegistry;
this.resources = resources;
}

@Override
public void setup() {
// The metadata for the "statistic" resources is only available for existing resource-adapters.
// That's why we cannot set up the UI in the constructor like in other views and
// using wildcards in the address templates. As a workaround we defer the UI setup
// until the RA name is known and replace the wildcards with the RA name.
Metadata poolMeta;
Metadata extendedMeta = null;
try {
extendedMeta = metadataRegistry.lookup(presenter.getExtendedStatsAddress());
} catch (MissingMetadataException mme) {
// "extended" statistics are only present if the underlying class implements them
}

boolean isConnDef = presenter.getType() == StatisticsResource.ResourceType.CONNECTION_DEFINITION;
HTMLElement extendedElement;
HTMLElement statsElement;
if (extendedMeta != null) {
extendedForm = new ModelNodeForm.Builder<>(Ids.build(Ids.RESOURCE_ADAPTER_RUNTIME, "extended", Ids.FORM),
extendedMeta)
.readOnly()
.includeRuntime()
.exclude(STATISTICS_ENABLED)
.build();
extendedElement = extendedForm.element();

registerAttachable(extendedForm);
} else {
extendedElement = new Alert(Icons.INFO, resources.messages().noStatistics()).element();
}

if (!isConnDef) {
statsElement = extendedElement;
} else {
poolMeta = metadataRegistry.lookup(presenter.getPoolStatsAddress());
poolForm = new ModelNodeForm.Builder<>(Ids.build(Ids.RESOURCE_ADAPTER_CHILD_RUNTIME, Ids.POOL, Ids.FORM), poolMeta)
.readOnly()
.includeRuntime()
.exclude(STATISTICS_ENABLED)
.build();

Tabs tabs = new Tabs(Ids.RESOURCE_ADAPTER_CHILD_RUNTIME_TAB_CONTAINER);
tabs.add(Ids.build(Ids.RESOURCE_ADAPTER_CHILD_RUNTIME, "pool", Ids.TAB), Names.POOL, poolForm.element());
tabs.add(Ids.build(Ids.RESOURCE_ADAPTER_CHILD_RUNTIME, "extended", Ids.TAB), "Extended", extendedElement);

statsElement = tabs.element();

registerAttachable(poolForm);
}

HTMLElement root = row()
.add(column()
.add(header = h(1).textContent("RA resource").element())
.add(extendedMeta != null ? p().css(clearfix)
.add(a().css(clickable, pullRight).on(click, event -> refresh())
.add(span().css(fontAwesome("refresh"), marginRight5))
.add(span().textContent(resources.constants().refresh())))
: null)
.add(statsElement))
.element();

initElement(root);
}

@Override
public void setPresenter(P presenter) {
this.presenter = presenter;
}

@Override
public void update(StatisticsResource resource) {
header.textContent = resource.getName();

if (resource.hasExtendedStats()) {
extendedForm.view(resource.getExtendedStats());
}
if (presenter.getType() == StatisticsResource.ResourceType.CONNECTION_DEFINITION) {
poolForm.view(resource.getPoolStats());
}
}

private void refresh() {
if (presenter != null) {
presenter.reload();
}
}
}
Loading

0 comments on commit c4c4453

Please sign in to comment.