8.3 DeviceExtensoinPoint webui DeviceDetails

Hello,

Does anyone know how to provide the necessary information for a device’s DeviceExtensoinPoint View Details? (webui DeviceDetails)

 public List<MenuAction> getMenuActions() {
   return List.of(new MenuAction("View Details", "View device details.", (WebUiComponent)new ReactComponentInfo("DeviceDetails", null))); 
}

Connections → Devices → Connections

Are you trying to provide a custom link and react page for one of your devices, or provide the information necessary for your device to have a "Details" diagnostics page like some of the other Ignition devices?

Second option: I want to provide the necessary information so my device can have a ‘Details’ diagnostics page like some of the other Ignition devices.

Ah, then implement DeviceExtensionPoint::getSamplingMetrics.

1 Like

Looks like Javadoc for the opc-ua-gateway-api module isn't being published... hopefully I can get that resolved before we release 8.3.0.

3 Likes

I assume these are the metrics to declare.

  public static class SamplingMetricsSerializer implements JsonSerializer<SamplingMetrics> {
    public JsonElement serialize(SamplingMetrics metrics, Type type, JsonSerializationContext context) {
      JsonObject aggregateObject = new JsonObject();
      aggregateObject.addProperty("requestCount", Integer.valueOf(metrics.aggregateStats().requestCount()));
      aggregateObject.addProperty("monitoredItemCount", Integer.valueOf(metrics.aggregateStats().monitoredItemCount()));
      aggregateObject.add("histogram", context.serialize(metrics.aggregateStats().histogram()));
      aggregateObject.addProperty("meanThroughput", Double.valueOf(metrics.aggregateStats().meanThroughput()));
      aggregateObject.addProperty("oneMinuteThroughput", Double.valueOf(metrics.aggregateStats().oneMinuteThroughput()));
      JsonArray samplingGroupsArray = new JsonArray();
      for (SamplingMetrics.SamplingGroupStats group : metrics.samplingGroupStats()) {
        JsonObject groupObject = new JsonObject();
        groupObject.addProperty("requestCount", Integer.valueOf(group.requestCount()));
        groupObject.addProperty("samplingInterval", Integer.valueOf(group.samplingInterval()));
        groupObject.addProperty("queueDuration", Double.valueOf(group.queueDuration()));
        groupObject.addProperty("overloadFactor", Double.valueOf(group.overloadFactor()));
        groupObject.add("histogram", context.serialize(group.histogram()));
        groupObject.addProperty("meanThroughput", Double.valueOf(group.meanThroughput()));
        groupObject.addProperty("oneMinuteThroughput", Double.valueOf(group.oneMinuteThroughput()));
        samplingGroupsArray.add((JsonElement)groupObject);
      } 
      JsonObject object = new JsonObject();
      object.add("aggregate", (JsonElement)aggregateObject);
      object.add("samplingGroups", (JsonElement)samplingGroupsArray);
      return (JsonElement)object;
    }
  }

Yes, but you should be able to intuit that from the constructors and not the JSON serialization:

public record SamplingMetrics(
    AggregateStats aggregateStats,
    List<SamplingGroupStats> samplingGroupStats
) {

    public record AggregateStats(
        int requestCount,
        int monitoredItemCount,
        Snapshot histogram,
        double meanThroughput,
        double oneMinuteThroughput
    ) {}

    public record SamplingGroupStats(
        int requestCount,
        int samplingInterval,
        double queueDuration,
        double overloadFactor,
        Snapshot histogram,
        double meanThroughput,
        double oneMinuteThroughput
    ) {}
2 Likes

The Snapshot objects come from instances of com.codahale.metrics.Timer. The whole sampling metrics concept is meant for devices that measure their request executions with a Timer.

1 Like

Thanks! That looks good to me for Aggregate Statistics.

What about Log Activity? Can we set the loggers and the minimum log level?

The log activity is any log statements where the MDC key "device-name" is set to the name of the device instance being viewed. Nothing can be controlled.

1 Like

Is there any chance that interface could be extended to allow the device to supply the actual sampling interval for each group? (Cough...)

For the community’s reference :

LoggerEx log = LoggerEx.newBuilder()
    .mdcContext(new Object[] { "device-name", context.name})
    .build(String.format("drivers.%s", getClass().getSimpleName()));
val logger = LoggerEx.newBuilder()
    .mdcContext("device-name", context.name)
    .build("drivers.${javaClass.simpleName}")
3 Likes