diff --git a/runtime/binding-echo/src/test/java/io/aklivity/zilla/runtime/binding/echo/internal/bench/EchoWorker.java b/runtime/binding-echo/src/test/java/io/aklivity/zilla/runtime/binding/echo/internal/bench/EchoWorker.java index 0ef4b86779..5ca0a81270 100644 --- a/runtime/binding-echo/src/test/java/io/aklivity/zilla/runtime/binding/echo/internal/bench/EchoWorker.java +++ b/runtime/binding-echo/src/test/java/io/aklivity/zilla/runtime/binding/echo/internal/bench/EchoWorker.java @@ -325,6 +325,12 @@ public ConverterHandler supplyWriteConverter( return null; } + @Override + public LongConsumer supplyUtilizationMetric() + { + return null; + } + @Override public Path resolvePath( String location) diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/TcpBindingContext.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/TcpBindingContext.java index 3f596751c5..9d8edd1981 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/TcpBindingContext.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/TcpBindingContext.java @@ -15,15 +15,12 @@ */ package io.aklivity.zilla.runtime.binding.tcp.internal; -import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_WORKER_CAPACITY; import static io.aklivity.zilla.runtime.engine.config.KindConfig.CLIENT; import static io.aklivity.zilla.runtime.engine.config.KindConfig.SERVER; import java.util.EnumMap; import java.util.Map; -import org.agrona.collections.MutableInteger; - import io.aklivity.zilla.runtime.binding.tcp.internal.stream.TcpClientFactory; import io.aklivity.zilla.runtime.binding.tcp.internal.stream.TcpServerFactory; import io.aklivity.zilla.runtime.binding.tcp.internal.stream.TcpStreamFactory; @@ -41,7 +38,7 @@ final class TcpBindingContext implements BindingContext TcpConfiguration config, EngineContext context) { - MutableInteger capacity = new MutableInteger(ENGINE_WORKER_CAPACITY.getAsInt(config)); + TcpCapacityTracker capacity = new TcpCapacityTracker(config, context); Map factories = new EnumMap<>(KindConfig.class); factories.put(SERVER, new TcpServerFactory(config, context, capacity)); factories.put(CLIENT, new TcpClientFactory(config, context, capacity)); diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/TcpCapacityTracker.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/TcpCapacityTracker.java new file mode 100644 index 0000000000..37fb4ce85e --- /dev/null +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/TcpCapacityTracker.java @@ -0,0 +1,82 @@ +/* + * Copyright 2021-2024 Aklivity Inc. + * + * Aklivity licenses this file to you 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 io.aklivity.zilla.runtime.binding.tcp.internal; + +import static io.aklivity.zilla.runtime.engine.EngineConfiguration.ENGINE_WORKER_CAPACITY; + +import java.util.function.LongConsumer; + +import org.agrona.collections.MutableInteger; + +import io.aklivity.zilla.runtime.engine.EngineContext; + +public final class TcpCapacityTracker +{ + private final MutableInteger capacity; + private final LongConsumer capacityUsage; + private final int initialCapacity; + + private int capacityPercentage; + + public TcpCapacityTracker( + TcpConfiguration config, + EngineContext context) + { + this.initialCapacity = ENGINE_WORKER_CAPACITY.getAsInt(config); + this.capacity = new MutableInteger(initialCapacity); + this.capacityUsage = context.supplyUtilizationMetric(); + } + + public int capacity() + { + return capacity.get(); + } + + public int incrementAndGet() + { + int newCapacity = capacity.incrementAndGet(); + capacityChanged(newCapacity); + + return newCapacity; + } + + public int decrementAndGet() + { + int newCapacity = capacity.decrementAndGet(); + capacityChanged(newCapacity); + + return newCapacity; + } + + public int get() + { + return capacity.get(); + } + + private void capacityChanged( + int newCapacity) + { + final int newCapacityPercentage = 100 - (newCapacity * 100 / initialCapacity); + final int percentageDiff = newCapacityPercentage - capacityPercentage; + + if (Math.abs(percentageDiff) >= 1) + { + capacityUsage.accept(percentageDiff); + } + + capacityPercentage = newCapacityPercentage; + } +} diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/TcpEventFormatter.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/TcpEventFormatter.java index 66fbad7cf0..3598a9ff5b 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/TcpEventFormatter.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/TcpEventFormatter.java @@ -46,12 +46,10 @@ public String format( switch (extension.kind()) { case DNS_FAILED: - { - final TcpDnsFailedExFW ex = extension.dnsFailed(); - result = String.format("Unable to resolve host dns for address (%s).", asString(ex.address())); + final TcpDnsFailedExFW dnsFailed = extension.dnsFailed(); + result = String.format("Unable to resolve host dns for address (%s).", asString(dnsFailed.address())); break; } - } return result; } diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientFactory.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientFactory.java index 61c069320c..8bac1363b4 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientFactory.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientFactory.java @@ -40,11 +40,12 @@ import org.agrona.CloseHelper; import org.agrona.DirectBuffer; import org.agrona.MutableDirectBuffer; -import org.agrona.collections.MutableInteger; import org.agrona.concurrent.UnsafeBuffer; import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; +import io.aklivity.zilla.runtime.binding.tcp.internal.TcpCapacityTracker; import io.aklivity.zilla.runtime.binding.tcp.internal.TcpConfiguration; +import io.aklivity.zilla.runtime.binding.tcp.internal.TcpEventContext; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpBindingConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.types.Flyweight; import io.aklivity.zilla.runtime.binding.tcp.internal.types.OctetsFW; @@ -100,9 +101,10 @@ public class TcpClientFactory implements TcpStreamFactory public TcpClientFactory( TcpConfiguration config, EngineContext context, - MutableInteger capacity) + TcpCapacityTracker capacity) { - this.router = new TcpClientRouter(context, capacity); + TcpEventContext event = new TcpEventContext(context); + this.router = new TcpClientRouter(context, event, capacity); this.writeBuffer = context.writeBuffer(); this.writeByteBuffer = ByteBuffer.allocateDirect(writeBuffer.capacity()).order(nativeOrder()); this.bufferPool = context.bufferPool(); diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientRouter.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientRouter.java index 9b20b5a979..456098c65f 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientRouter.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpClientRouter.java @@ -27,9 +27,9 @@ import java.util.function.Predicate; import org.agrona.collections.Long2ObjectHashMap; -import org.agrona.collections.MutableInteger; import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; +import io.aklivity.zilla.runtime.binding.tcp.internal.TcpCapacityTracker; import io.aklivity.zilla.runtime.binding.tcp.internal.TcpEventContext; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpBindingConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpRouteConfig; @@ -49,18 +49,19 @@ public final class TcpClientRouter private final byte[] ipv6ros = new byte[16]; private final Function resolveHost; - private final MutableInteger capacity; + private final TcpCapacityTracker capacity; private final Long2ObjectHashMap bindings; private final TcpEventContext event; public TcpClientRouter( EngineContext context, - MutableInteger capacity) + TcpEventContext event, + TcpCapacityTracker capacity) { this.resolveHost = context::resolveHost; + this.event = event; this.capacity = capacity; this.bindings = new Long2ObjectHashMap<>(); - this.event = new TcpEventContext(context); } public void attach( diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpServerFactory.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpServerFactory.java index cb4c0d6344..c0cb1dca90 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpServerFactory.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpServerFactory.java @@ -40,10 +40,10 @@ import org.agrona.DirectBuffer; import org.agrona.LangUtil; import org.agrona.MutableDirectBuffer; -import org.agrona.collections.MutableInteger; import org.agrona.concurrent.UnsafeBuffer; import io.aklivity.zilla.runtime.binding.tcp.config.TcpOptionsConfig; +import io.aklivity.zilla.runtime.binding.tcp.internal.TcpCapacityTracker; import io.aklivity.zilla.runtime.binding.tcp.internal.TcpConfiguration; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpBindingConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpRouteConfig; @@ -103,7 +103,7 @@ public class TcpServerFactory implements TcpStreamFactory public TcpServerFactory( TcpConfiguration config, EngineContext context, - MutableInteger capacity) + TcpCapacityTracker capacity) { this.router = new TcpServerRouter(context, this::handleAccept, capacity); this.writeBuffer = context.writeBuffer(); diff --git a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpServerRouter.java b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpServerRouter.java index 4a30e4c158..4c8d631cbe 100644 --- a/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpServerRouter.java +++ b/runtime/binding-tcp/src/main/java/io/aklivity/zilla/runtime/binding/tcp/internal/stream/TcpServerRouter.java @@ -27,8 +27,8 @@ import org.agrona.CloseHelper; import org.agrona.collections.Long2ObjectHashMap; -import org.agrona.collections.MutableInteger; +import io.aklivity.zilla.runtime.binding.tcp.internal.TcpCapacityTracker; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpBindingConfig; import io.aklivity.zilla.runtime.binding.tcp.internal.config.TcpServerBindingConfig; import io.aklivity.zilla.runtime.engine.EngineContext; @@ -40,14 +40,14 @@ public final class TcpServerRouter private final ToIntFunction acceptHandler; private final Function supplyPollerKey; private final Long2ObjectHashMap serversById; - private final MutableInteger capacity; + private final TcpCapacityTracker capacity; private boolean unbound; public TcpServerRouter( EngineContext context, ToIntFunction acceptHandler, - MutableInteger capacity) + TcpCapacityTracker capacity) { this.bindings = new Long2ObjectHashMap<>(); this.supplyPollerKey = context::supplyPollerKey; @@ -115,7 +115,8 @@ public void close( { CloseHelper.quietClose(channel); - if (unbound && capacity.incrementAndGet() > 0) + int newCapacity = capacity.incrementAndGet(); + if (unbound && newCapacity > 0) { bindings.values().stream() .filter(b -> b.kind == SERVER) diff --git a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/bench/TlsWorker.java b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/bench/TlsWorker.java index 1c59591591..58da38f435 100644 --- a/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/bench/TlsWorker.java +++ b/runtime/binding-tls/src/test/java/io/aklivity/zilla/runtime/binding/tls/internal/bench/TlsWorker.java @@ -391,6 +391,12 @@ public ConverterHandler supplyWriteConverter( return null; } + @Override + public LongConsumer supplyUtilizationMetric() + { + return null; + } + @Override public Path resolvePath( String location) diff --git a/runtime/command-metrics/src/main/java/io/aklivity/zilla/runtime/command/metrics/internal/printer/MetricsPrinter.java b/runtime/command-metrics/src/main/java/io/aklivity/zilla/runtime/command/metrics/internal/printer/MetricsPrinter.java index c9a2babe5a..e514b606cd 100644 --- a/runtime/command-metrics/src/main/java/io/aklivity/zilla/runtime/command/metrics/internal/printer/MetricsPrinter.java +++ b/runtime/command-metrics/src/main/java/io/aklivity/zilla/runtime/command/metrics/internal/printer/MetricsPrinter.java @@ -69,8 +69,8 @@ private void calculateColumnWidths() for (MetricRecord metric : records) { - namespaceWidth = Math.max(namespaceWidth, metric.namespace().length()); - bindingWidth = Math.max(bindingWidth, metric.binding().length()); + namespaceWidth = Math.max(namespaceWidth, metric.namespace() != null ? metric.namespace().length() : 0); + bindingWidth = Math.max(bindingWidth, metric.binding() != null ? metric.binding().length() : 0); metricWidth = Math.max(metricWidth, metric.metric().length()); valueWidth = Math.max(valueWidth, metricValues.get(metric).length()); } @@ -84,7 +84,10 @@ private void printRecords( out.format(format, NAMESPACE_HEADER, BINDING_HEADER, METRIC_HEADER, VALUE_HEADER); for (MetricRecord metric : records) { - out.format(format, metric.namespace(), metric.binding(), metric.metric(), metricValues.get(metric)); + String namespace = metric.namespace() != null ? metric.namespace() : ""; + String binding = metric.binding() != null ? metric.binding() : ""; + + out.format(format, namespace, binding, metric.metric(), metricValues.get(metric)); } out.println(); } diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/EngineContext.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/EngineContext.java index 1fac875102..f117863f39 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/EngineContext.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/EngineContext.java @@ -161,6 +161,8 @@ ConverterHandler supplyReadConverter( ConverterHandler supplyWriteConverter( ModelConfig config); + LongConsumer supplyUtilizationMetric(); + Path resolvePath( String location); diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/metrics/EngineMetricGroup.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/metrics/EngineMetricGroup.java new file mode 100644 index 0000000000..a4f81b9244 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/metrics/EngineMetricGroup.java @@ -0,0 +1,65 @@ +/* + * Copyright 2021-2024 Aklivity Inc. + * + * Aklivity licenses this file to you 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 io.aklivity.zilla.runtime.engine.internal.metrics; + +import java.net.URL; +import java.util.Collection; +import java.util.Map; +import java.util.function.Supplier; + +import io.aklivity.zilla.runtime.engine.Configuration; +import io.aklivity.zilla.runtime.engine.metrics.Metric; +import io.aklivity.zilla.runtime.engine.metrics.MetricGroup; + +public class EngineMetricGroup implements MetricGroup +{ + public static final String NAME = "engine"; + + private final Map> engineMetrics = Map.of( + "engine.worker.utilization", EngineWorkerUtilizationMetric::new, + "engine.worker.count", EngineWorkerCountMetric::new + ); + + public EngineMetricGroup( + Configuration config) + { + } + + @Override + public String name() + { + return NAME; + } + + @Override + public URL type() + { + return getClass().getResource("schema/engine.schema.patch.json"); + } + + @Override + public Metric supply( + String name) + { + return engineMetrics.getOrDefault(name, () -> null).get(); + } + + @Override + public Collection metricNames() + { + return engineMetrics.keySet(); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/metrics/EngineMetricGroupFactorySpi.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/metrics/EngineMetricGroupFactorySpi.java new file mode 100644 index 0000000000..de9325f3b1 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/metrics/EngineMetricGroupFactorySpi.java @@ -0,0 +1,36 @@ +/* + * Copyright 2021-2024 Aklivity Inc. + * + * Aklivity licenses this file to you 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 io.aklivity.zilla.runtime.engine.internal.metrics; + +import io.aklivity.zilla.runtime.engine.Configuration; +import io.aklivity.zilla.runtime.engine.metrics.MetricGroup; +import io.aklivity.zilla.runtime.engine.metrics.MetricGroupFactorySpi; + +public class EngineMetricGroupFactorySpi implements MetricGroupFactorySpi +{ + @Override + public String type() + { + return EngineMetricGroup.NAME; + } + + @Override + public MetricGroup create( + Configuration config) + { + return new EngineMetricGroup(config); + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/metrics/EngineWorkerCountMetric.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/metrics/EngineWorkerCountMetric.java new file mode 100644 index 0000000000..7aeefe269d --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/metrics/EngineWorkerCountMetric.java @@ -0,0 +1,59 @@ +/* + * Copyright 2021-2024 Aklivity Inc. + * + * Aklivity licenses this file to you 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 io.aklivity.zilla.runtime.engine.internal.metrics; + +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.metrics.Metric; +import io.aklivity.zilla.runtime.engine.metrics.MetricContext; + +public class EngineWorkerCountMetric implements Metric +{ + private static final String GROUP = EngineMetricGroup.NAME; + private static final String NAME = String.format("%s.%s", GROUP, "worker.count"); + private static final String DESCRIPTION = "Engine worker count"; + + @Override + public String name() + { + return NAME; + } + + @Override + public Kind kind() + { + return Kind.COUNTER; + } + + @Override + public Unit unit() + { + return Unit.COUNT; + } + + @Override + public String description() + { + return DESCRIPTION; + } + + @Override + public MetricContext supply( + EngineContext context) + { + //Unsupported metric context + return null; + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/metrics/EngineWorkerUtilizationMetric.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/metrics/EngineWorkerUtilizationMetric.java new file mode 100644 index 0000000000..186f0eb182 --- /dev/null +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/metrics/EngineWorkerUtilizationMetric.java @@ -0,0 +1,59 @@ +/* + * Copyright 2021-2024 Aklivity Inc. + * + * Aklivity licenses this file to you 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 io.aklivity.zilla.runtime.engine.internal.metrics; + +import io.aklivity.zilla.runtime.engine.EngineContext; +import io.aklivity.zilla.runtime.engine.metrics.Metric; +import io.aklivity.zilla.runtime.engine.metrics.MetricContext; + +public class EngineWorkerUtilizationMetric implements Metric +{ + private static final String GROUP = EngineMetricGroup.NAME; + private static final String NAME = String.format("%s.%s", GROUP, "worker.utilization"); + private static final String DESCRIPTION = "Engine worker utilization"; + + @Override + public String name() + { + return NAME; + } + + @Override + public Kind kind() + { + return Kind.GAUGE; + } + + @Override + public Unit unit() + { + return Unit.COUNT; + } + + @Override + public String description() + { + return DESCRIPTION; + } + + @Override + public MetricContext supply( + EngineContext context) + { + //Unsupported metric context + return null; + } +} diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/EngineWorker.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/EngineWorker.java index 20f8f14b40..a3bdaa39fe 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/EngineWorker.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/internal/registry/EngineWorker.java @@ -33,6 +33,7 @@ import static io.aklivity.zilla.runtime.engine.metrics.Metric.Kind.HISTOGRAM; import static io.aklivity.zilla.runtime.engine.metrics.MetricContext.Direction.RECEIVED; import static io.aklivity.zilla.runtime.engine.metrics.MetricContext.Direction.SENT; +import static io.aklivity.zilla.runtime.engine.namespace.NamespacedId.NO_NAMESPACED_ID; import static java.lang.System.currentTimeMillis; import static java.lang.ThreadLocal.withInitial; import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -297,6 +298,12 @@ public EngineWorker( metricWriterSuppliers.put(GAUGE, gaugesLayout::supplyWriter); metricWriterSuppliers.put(HISTOGRAM, histogramsLayout::supplyWriter); + if (!readonly) + { + final int metricId = labels.supplyLabelId("engine.worker.count"); + supplyMetricWriter(GAUGE, NO_NAMESPACED_ID, metricId).accept(1); + } + final StreamsLayout streamsLayout = new StreamsLayout.Builder() .path(config.directory().resolve(String.format("data%d", index))) .streamsCapacity(config.streamsBufferCapacity()) @@ -766,6 +773,14 @@ public ConverterHandler supplyWriteConverter( return model != null ? model.supplyWriteConverterHandler(config) : null; } + @Override + public LongConsumer supplyUtilizationMetric() + { + final int metricId = labels.supplyLabelId("engine.worker.utilization"); + + return supplyMetricWriter(GAUGE, NO_NAMESPACED_ID, metricId); + } + @Override public Path resolvePath( String location) diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/metrics/reader/ScalarRecord.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/metrics/reader/ScalarRecord.java index d54c8d66bc..b591a721fe 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/metrics/reader/ScalarRecord.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/metrics/reader/ScalarRecord.java @@ -22,6 +22,8 @@ import java.util.function.LongFunction; import java.util.function.LongSupplier; +import io.aklivity.zilla.runtime.engine.namespace.NamespacedId; + public class ScalarRecord implements MetricRecord { private final long bindingId; @@ -53,13 +55,13 @@ public long bindingId() public String namespace() { // implicit int -> long conversion, it's OK - return labelResolver.apply(namespaceId); + return namespaceId != NamespacedId.NO_NAMESPACE_ID ? labelResolver.apply(namespaceId) : null; } @Override public String binding() { - return labelResolver.apply(bindingId); + return bindingId != NamespacedId.NO_LOCAL_ID ? labelResolver.apply(bindingId) : null; } @Override diff --git a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/namespace/NamespacedId.java b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/namespace/NamespacedId.java index effc9d8836..766e79e127 100644 --- a/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/namespace/NamespacedId.java +++ b/runtime/engine/src/main/java/io/aklivity/zilla/runtime/engine/namespace/NamespacedId.java @@ -17,6 +17,10 @@ public final class NamespacedId { + public static final int NO_NAMESPACE_ID = -1; + public static final int NO_LOCAL_ID = -1; + public static final long NO_NAMESPACED_ID = id(NO_NAMESPACE_ID, NO_LOCAL_ID); + public static int namespaceId( long namespacedId) { diff --git a/runtime/engine/src/main/moditect/module-info.java b/runtime/engine/src/main/moditect/module-info.java index e9d7927615..eb866bdcfe 100644 --- a/runtime/engine/src/main/moditect/module-info.java +++ b/runtime/engine/src/main/moditect/module-info.java @@ -58,6 +58,8 @@ provides io.aklivity.zilla.runtime.engine.event.EventFormatterFactorySpi with io.aklivity.zilla.runtime.engine.internal.event.EngineEventFormatterFactory; + provides io.aklivity.zilla.runtime.engine.metrics.MetricGroupFactorySpi + with io.aklivity.zilla.runtime.engine.internal.metrics.EngineMetricGroupFactorySpi; uses io.aklivity.zilla.runtime.engine.config.ConditionConfigAdapterSpi; uses io.aklivity.zilla.runtime.engine.config.CompositeBindingAdapterSpi; diff --git a/runtime/engine/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.metrics.MetricGroupFactorySpi b/runtime/engine/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.metrics.MetricGroupFactorySpi new file mode 100644 index 0000000000..ddc7212652 --- /dev/null +++ b/runtime/engine/src/main/resources/META-INF/services/io.aklivity.zilla.runtime.engine.metrics.MetricGroupFactorySpi @@ -0,0 +1 @@ +io.aklivity.zilla.runtime.engine.internal.metrics.EngineMetricGroupFactorySpi diff --git a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/EngineMetricsIT.java b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/EngineMetricsIT.java index e1782cd668..3182ba67ff 100644 --- a/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/EngineMetricsIT.java +++ b/runtime/engine/src/test/java/io/aklivity/zilla/runtime/engine/internal/EngineMetricsIT.java @@ -105,7 +105,7 @@ public void shouldFetchGaugeIds() // THEN // gaugeIds[0] is coming from test.gauge in server.yaml - assertThat(gaugeIds[1], equalTo(new long[]{3L, 7L})); + assertThat(gaugeIds[2], equalTo(new long[]{3L, 7L})); } @Test diff --git a/runtime/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/serializer/OtlpMetricsSerializer.java b/runtime/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/serializer/OtlpMetricsSerializer.java index b20419d5c5..124e91edd7 100644 --- a/runtime/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/serializer/OtlpMetricsSerializer.java +++ b/runtime/exporter-otlp/src/main/java/io/aklivity/zilla/runtime/exporter/otlp/internal/serializer/OtlpMetricsSerializer.java @@ -15,6 +15,7 @@ package io.aklivity.zilla.runtime.exporter.otlp.internal.serializer; import static io.aklivity.zilla.runtime.engine.metrics.Metric.Kind.COUNTER; +import static io.aklivity.zilla.runtime.engine.namespace.NamespacedId.NO_NAMESPACED_ID; import java.util.Arrays; import java.util.LinkedList; @@ -174,16 +175,24 @@ private JsonArrayBuilder attributes( MetricRecord record) { List attributes = new LinkedList<>(); - attributes.add(AttributeConfig.builder() - .name("namespace") - .value(record.namespace()) - .build() - ); - attributes.add(AttributeConfig.builder() - .name("binding") - .value(record.binding()) - .build() - ); + + if (record.namespace() != null) + { + attributes.add(AttributeConfig.builder() + .name("namespace") + .value(record.namespace()) + .build() + ); + } + + if (record.binding() != null) + { + attributes.add(AttributeConfig.builder() + .name("binding") + .value(record.binding()) + .build() + ); + } if (serviceNameAttribute != null) { attributes.add(serviceNameAttribute); @@ -310,11 +319,14 @@ public String nameByBinding( long bindingId) { String result = null; - KindConfig kind = resolveKind.apply(bindingId); - Map externalNames = KIND_METRIC_NAMES.get(kind); - if (externalNames != null) + if (bindingId != NO_NAMESPACED_ID) { - result = externalNames.get(internalMetricName); + KindConfig kind = resolveKind.apply(bindingId); + Map externalNames = KIND_METRIC_NAMES.get(kind); + if (externalNames != null) + { + result = externalNames.get(internalMetricName); + } } return result != null ? result : internalMetricName; } diff --git a/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics.with.service.name/client.rpt b/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics.with.service.name/client.rpt index 928e3225d2..3e20588e28 100644 --- a/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics.with.service.name/client.rpt +++ b/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics.with.service.name/client.rpt @@ -19,107 +19,85 @@ connected write http:method "POST" write http:version "HTTP/1.1" write http:header "Host" "localhost:4318" -write http:header "Content-Length" "942" +write http:header "Content-Length" "1205" write '{' - '"resourceMetrics":[' - '{' - '"resource":{' - '"attributes":[' - '{' - '"key":"service.namespace",' - '"value":{' - '"stringValue":"example"' - '}' - '},' - '{' - '"key":"service.name",' - '"value":{' - '"stringValue":"zilla"' - '}' - '}' - ']' - '},' - '"scopeMetrics":[' - '{' - '"scope":{' - '"name":"OtlpMetricsSerializer",' - '"version":"1.0.0"' - '},' - '"metrics":[' - '{' - '"name":"test.counter",' - '"unit":"",' - '"description":"Description for test.counter",' - '"sum":{' - '"dataPoints":[' - '{' - '"asInt":77,' - '"timeUnixNano":0123456789123456789,' - '"attributes":[' - '{' - '"key":"namespace",' - '"value":{' - '"stringValue":"test"' - '}' - '},' - '{' - '"key":"binding",' - '"value":{' - '"stringValue":"net0"' - '}' - '},' - '{' - '"key":"service.name",' - '"value":{' - '"stringValue":"zilla"' - '}' - '}' - ']' - '}' - '],' - '"aggregationTemporality":2,' - '"isMonotonic":true' - '}' - '},' - '{' - '"name":"test.gauge",' - '"unit":"",' - '"description":"Description for test.gauge",' - '"gauge":{' - '"dataPoints":[' - '{' - '"asInt":66,' - '"timeUnixNano":0123456789123456789,' - '"attributes":[' - '{' - '"key":"namespace",' - '"value":{' - '"stringValue":"test"' - '}' - '},' - '{' - '"key":"binding",' - '"value":{' - '"stringValue":"net0"' - '}' - '},' - '{' - '"key":"service.name",' - '"value":{' - '"stringValue":"zilla"' - '}' - '}' - ']' - '}' - ']' - '}' - '}' - ']' - '}' - ']' + '"resourceMetrics":[{' + '"resource":{' + '"attributes":[{' + '"key":"service.namespace",' + '"value":{"stringValue":"example"}' + '},{' + '"key":"service.name",' + '"value":{"stringValue":"zilla"}' + '}]' + '},' + '"scopeMetrics":[{' + '"scope":{' + '"name":"OtlpMetricsSerializer",' + '"version":"1.0.0"' + '},' + '"metrics":[{' + '"name":"test.counter",' + '"unit":"",' + '"description":"Description for test.counter",' + '"sum":{' + '"dataPoints":[{' + '"asInt":77,' + '"timeUnixNano":0123456789123456789,' + '"attributes":[{' + '"key":"namespace",' + '"value":{"stringValue":"test"}' + '},{' + '"key":"binding",' + '"value":{"stringValue":"net0"}' + '},{' + '"key":"service.name",' + '"value":{"stringValue":"zilla"}' + '}]' + '}],' + '"aggregationTemporality":2,' + '"isMonotonic":true' '}' - ']' + '},{' + '"name":"engine.worker.count",' + '"unit":"",' + '"description":"Engine worker count",' + '"sum":{' + '"dataPoints":[{' + '"asInt":3,' + '"timeUnixNano":0123456789123456789,' + '"attributes":[{' + '"key":"service.name",' + '"value":{"stringValue":"zilla"}' + '}]' + '}],' + '"aggregationTemporality":2,' + '"isMonotonic":true' + '}' + '},{' + '"name":"test.gauge",' + '"unit":"",' + '"description":"Description for test.gauge",' + '"gauge":{' + '"dataPoints":[{' + '"asInt":66,' + '"timeUnixNano":0123456789123456789,' + '"attributes":[{' + '"key":"namespace",' + '"value":{"stringValue":"test"}' + '},{' + '"key":"binding",' + '"value":{"stringValue":"net0"}' + '},{' + '"key":"service.name",' + '"value":{"stringValue":"zilla"}' + '}]' + '}]' + '}' + '}]' + '}]' + '}]' '}' write close diff --git a/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics.with.service.name/server.rpt b/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics.with.service.name/server.rpt index c703e2f51b..ec4d08ea8b 100644 --- a/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics.with.service.name/server.rpt +++ b/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics.with.service.name/server.rpt @@ -20,107 +20,85 @@ connected read http:method "POST" read http:version "HTTP/1.1" read http:header "Host" "localhost:4318" -read http:header "Content-Length" "942" +read http:header "Content-Length" "1205" read '{' - '"resourceMetrics":[' - '{' - '"resource":{' - '"attributes":[' - '{' - '"key":"service.namespace",' - '"value":{' - '"stringValue":"example"' - '}' - '},' - '{' - '"key":"service.name",' - '"value":{' - '"stringValue":"zilla"' - '}' - '}' - ']' - '},' - '"scopeMetrics":[' - '{' - '"scope":{' - '"name":"OtlpMetricsSerializer",' - '"version":"1.0.0"' - '},' - '"metrics":[' - '{' - '"name":"test.counter",' - '"unit":"",' - '"description":"Description for test.counter",' - '"sum":{' - '"dataPoints":[' - '{' - '"asInt":77,' - '"timeUnixNano":' [0..19] ',' - '"attributes":[' - '{' - '"key":"namespace",' - '"value":{' - '"stringValue":"test"' - '}' - '},' - '{' - '"key":"binding",' - '"value":{' - '"stringValue":"net0"' - '}' - '},' - '{' - '"key":"service.name",' - '"value":{' - '"stringValue":"zilla"' - '}' - '}' - ']' - '}' - '],' - '"aggregationTemporality":2,' - '"isMonotonic":true' - '}' - '},' - '{' - '"name":"test.gauge",' - '"unit":"",' - '"description":"Description for test.gauge",' - '"gauge":{' - '"dataPoints":[' - '{' - '"asInt":66,' - '"timeUnixNano":' [0..19] ',' - '"attributes":[' - '{' - '"key":"namespace",' - '"value":{' - '"stringValue":"test"' - '}' - '},' - '{' - '"key":"binding",' - '"value":{' - '"stringValue":"net0"' - '}' - '},' - '{' - '"key":"service.name",' - '"value":{' - '"stringValue":"zilla"' - '}' - '}' - ']' - '}' - ']' - '}' - '}' - ']' - '}' - ']' + '"resourceMetrics":[{' + '"resource":{' + '"attributes":[{' + '"key":"service.namespace",' + '"value":{"stringValue":"example"}' + '},{' + '"key":"service.name",' + '"value":{"stringValue":"zilla"}' + '}]' + '},' + '"scopeMetrics":[{' + '"scope":{' + '"name":"OtlpMetricsSerializer",' + '"version":"1.0.0"' + '},' + '"metrics":[{' + '"name":"test.counter",' + '"unit":"",' + '"description":"Description for test.counter",' + '"sum":{' + '"dataPoints":[{' + '"asInt":77,' + '"timeUnixNano":' [0..19] ',' + '"attributes":[{' + '"key":"namespace",' + '"value":{"stringValue":"test"}' + '},{' + '"key":"binding",' + '"value":{"stringValue":"net0"}' + '},{' + '"key":"service.name",' + '"value":{"stringValue":"zilla"}' + '}]' + '}],' + '"aggregationTemporality":2,' + '"isMonotonic":true' '}' - ']' + '},{' + '"name":"engine.worker.count",' + '"unit":"",' + '"description":"Engine worker count",' + '"sum":{' + '"dataPoints":[{' + '"asInt":3,' + '"timeUnixNano":' [0..19] ',' + '"attributes":[{' + '"key":"service.name",' + '"value":{"stringValue":"zilla"}' + '}]' + '}],' + '"aggregationTemporality":2,' + '"isMonotonic":true' + '}' + '},{' + '"name":"test.gauge",' + '"unit":"",' + '"description":"Description for test.gauge",' + '"gauge":{' + '"dataPoints":[{' + '"asInt":66,' + '"timeUnixNano":' [0..19] ',' + '"attributes":[{' + '"key":"namespace",' + '"value":{"stringValue":"test"}' + '},{' + '"key":"binding",' + '"value":{"stringValue":"net0"}' + '},{' + '"key":"service.name",' + '"value":{"stringValue":"zilla"}' + '}]' + '}]' + '}' + '}]' + '}]' + '}]' '}' read closed diff --git a/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics/client.rpt b/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics/client.rpt index 049a21def6..7cd102e81d 100644 --- a/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics/client.rpt +++ b/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics/client.rpt @@ -19,249 +19,223 @@ connected write http:method "POST" write http:version "HTTP/1.1" write http:header "Host" "localhost:4318" -write http:header "Content-Length" "1953" +write http:header "Content-Length" "2162" write '{' - '"resourceMetrics":[' - '{' - '"resource":{' - '"attributes":[' - '{' - '"key":"service.namespace",' - '"value":{' - '"stringValue":"example"' - '}' - '}' - ']' - '},' - '"scopeMetrics":[' - '{' - '"scope":{' - '"name":"OtlpMetricsSerializer",' - '"version":"1.0.0"' - '},' - '"metrics":[' - '{' - '"name":"test.counter",' - '"unit":"",' - '"description":"Description for test.counter",' - '"sum":{' - '"dataPoints":[' - '{' - '"asInt":77,' - '"timeUnixNano":0123456789123456789,' - '"attributes":[' - '{' - '"key":"namespace",' - '"value":{' - '"stringValue":"test"' - '}' - '},' - '{' - '"key":"binding",' - '"value":{' - '"stringValue":"net0"' - '}' - '}' - ']' - '}' - '],' - '"aggregationTemporality":2,' - '"isMonotonic":true' - '}' - '},' - '{' - '"name":"test.gauge",' - '"unit":"",' - '"description":"Description for test.gauge",' - '"gauge":{' - '"dataPoints":[' - '{' - '"asInt":66,' - '"timeUnixNano":0123456789123456789,' - '"attributes":[' - '{' - '"key":"namespace",' - '"value":{' - '"stringValue":"test"' - '}' - '},' - '{' - '"key":"binding",' - '"value":{' - '"stringValue":"net0"' - '}' - '}' - ']' - '}' - ']' - '}' - '},' - '{' - '"name":"test.histogram",' - '"description":"Description for test.histogram",' - '"unit":"bytes",' - '"histogram":{' - '"aggregationTemporality":2,' - '"dataPoints":[' - '{' - '"timeUnixNano":0123456789123456789,' - '"attributes":[' - '{' - '"key":"namespace",' - '"value":{' - '"stringValue":"test"' - '}' - '},' - '{' - '"key":"binding",' - '"value":{' - '"stringValue":"net0"' - '}' - '}' - '],' - '"min":1,' - '"max":31,' - '"sum":63,' - '"count":3,' - '"explicitBounds":[' - '2,' - '4,' - '8,' - '16,' - '32,' - '64,' - '128,' - '256,' - '512,' - '1024,' - '2048,' - '4096,' - '8192,' - '16384,' - '32768,' - '65536,' - '131072,' - '262144,' - '524288,' - '1048576,' - '2097152,' - '4194304,' - '8388608,' - '16777216,' - '33554432,' - '67108864,' - '134217728,' - '268435456,' - '536870912,' - '1073741824,' - '2147483648,' - '4294967296,' - '8589934592,' - '17179869184,' - '34359738368,' - '68719476736,' - '137438953472,' - '274877906944,' - '549755813888,' - '1099511627776,' - '2199023255552,' - '4398046511104,' - '8796093022208,' - '17592186044416,' - '35184372088832,' - '70368744177664,' - '140737488355328,' - '281474976710656,' - '562949953421312,' - '1125899906842624,' - '2251799813685248,' - '4503599627370496,' - '9007199254740992,' - '18014398509481984,' - '36028797018963968,' - '72057594037927936,' - '144115188075855872,' - '288230376151711744,' - '576460752303423488,' - '1152921504606846976,' - '2305843009213693952,' - '4611686018427387904' - '],' - '"bucketCounts":[' - '1,' - '0,' - '0,' - '0,' - '2,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0' - ']' - '}' - ']' - '}' - '}' - ']' - '}' + '"resourceMetrics":[{' + '"resource":{' + '"attributes":[{' + '"key":"service.namespace",' + '"value":{"stringValue":"example"}' + '}]' + '},' + '"scopeMetrics":[{' + '"scope":{' + '"name":"OtlpMetricsSerializer",' + '"version":"1.0.0"' + '},' + '"metrics":[{' + '"name":"test.counter",' + '"unit":"",' + '"description":"Description for test.counter",' + '"sum":{' + '"dataPoints":[{' + '"asInt":77,' + '"timeUnixNano":0123456789123456789,' + '"attributes":[{' + '"key":"namespace",' + '"value":{"stringValue":"test"}' + '},{' + '"key":"binding",' + '"value":{"stringValue":"net0"}' + '}]' + '}],' + '"aggregationTemporality":2,' + '"isMonotonic":true' + '}' + '},{' + '"name":"engine.worker.count",' + '"unit":"",' + '"description":"Engine worker count",' + '"sum":{' + '"dataPoints":[{' + '"asInt":3,' + '"timeUnixNano":0123456789123456789,' + '"attributes":[]' + '}],' + '"aggregationTemporality":2,' + '"isMonotonic":true' + '}' + '},{' + '"name":"test.gauge",' + '"unit":"",' + '"description":"Description for test.gauge",' + '"gauge":{' + '"dataPoints":[{' + '"asInt":66,' + '"timeUnixNano":0123456789123456789,' + '"attributes":[{' + '"key":"namespace",' + '"value":{"stringValue":"test"}' + '},{' + '"key":"binding",' + '"value":{"stringValue":"net0"}' + '}]' + '}]' + '}' + '},{' + '"name":"test.histogram",' + '"description":"Description for test.histogram",' + '"unit":"bytes",' + '"histogram":{' + '"aggregationTemporality":2,' + '"dataPoints":[{' + '"timeUnixNano":0123456789123456789,' + '"attributes":[{' + '"key":"namespace",' + '"value":{"stringValue":"test"}' + '},{' + '"key":"binding",' + '"value":{"stringValue":"net0"}' + '}],' + '"min":1,' + '"max":31,' + '"sum":63,' + '"count":3,' + '"explicitBounds":[' + '2,' + '4,' + '8,' + '16,' + '32,' + '64,' + '128,' + '256,' + '512,' + '1024,' + '2048,' + '4096,' + '8192,' + '16384,' + '32768,' + '65536,' + '131072,' + '262144,' + '524288,' + '1048576,' + '2097152,' + '4194304,' + '8388608,' + '16777216,' + '33554432,' + '67108864,' + '134217728,' + '268435456,' + '536870912,' + '1073741824,' + '2147483648,' + '4294967296,' + '8589934592,' + '17179869184,' + '34359738368,' + '68719476736,' + '137438953472,' + '274877906944,' + '549755813888,' + '1099511627776,' + '2199023255552,' + '4398046511104,' + '8796093022208,' + '17592186044416,' + '35184372088832,' + '70368744177664,' + '140737488355328,' + '281474976710656,' + '562949953421312,' + '1125899906842624,' + '2251799813685248,' + '4503599627370496,' + '9007199254740992,' + '18014398509481984,' + '36028797018963968,' + '72057594037927936,' + '144115188075855872,' + '288230376151711744,' + '576460752303423488,' + '1152921504606846976,' + '2305843009213693952,' + '4611686018427387904' + '],' + '"bucketCounts":[' + '1,' + '0,' + '0,' + '0,' + '2,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0' ']' + '}]' '}' - ']' + '}]' + '}]' + '}]' '}' write close diff --git a/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics/server.rpt b/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics/server.rpt index 0b9e9dfeb4..9d7c1ba5a1 100644 --- a/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics/server.rpt +++ b/specs/exporter-otlp.spec/src/main/scripts/io/aklivity/zilla/specs/exporter/otlp/application/metrics/server.rpt @@ -20,249 +20,223 @@ connected read http:method "POST" read http:version "HTTP/1.1" read http:header "Host" "localhost:4318" -read http:header "Content-Length" "1953" +read http:header "Content-Length" "2162" read '{' - '"resourceMetrics":[' - '{' - '"resource":{' - '"attributes":[' - '{' - '"key":"service.namespace",' - '"value":{' - '"stringValue":"example"' - '}' - '}' - ']' - '},' - '"scopeMetrics":[' - '{' - '"scope":{' - '"name":"OtlpMetricsSerializer",' - '"version":"1.0.0"' - '},' - '"metrics":[' - '{' - '"name":"test.counter",' - '"unit":"",' - '"description":"Description for test.counter",' - '"sum":{' - '"dataPoints":[' - '{' - '"asInt":77,' - '"timeUnixNano":' [0..19] ',' - '"attributes":[' - '{' - '"key":"namespace",' - '"value":{' - '"stringValue":"test"' - '}' - '},' - '{' - '"key":"binding",' - '"value":{' - '"stringValue":"net0"' - '}' - '}' - ']' - '}' - '],' - '"aggregationTemporality":2,' - '"isMonotonic":true' - '}' - '},' - '{' - '"name":"test.gauge",' - '"unit":"",' - '"description":"Description for test.gauge",' - '"gauge":{' - '"dataPoints":[' - '{' - '"asInt":66,' - '"timeUnixNano":' [0..19] ',' - '"attributes":[' - '{' - '"key":"namespace",' - '"value":{' - '"stringValue":"test"' - '}' - '},' - '{' - '"key":"binding",' - '"value":{' - '"stringValue":"net0"' - '}' - '}' - ']' - '}' - ']' - '}' - '},' - '{' - '"name":"test.histogram",' - '"description":"Description for test.histogram",' - '"unit":"bytes",' - '"histogram":{' - '"aggregationTemporality":2,' - '"dataPoints":[' - '{' - '"timeUnixNano":' [0..19] ',' - '"attributes":[' - '{' - '"key":"namespace",' - '"value":{' - '"stringValue":"test"' - '}' - '},' - '{' - '"key":"binding",' - '"value":{' - '"stringValue":"net0"' - '}' - '}' - '],' - '"min":1,' - '"max":31,' - '"sum":63,' - '"count":3,' - '"explicitBounds":[' - '2,' - '4,' - '8,' - '16,' - '32,' - '64,' - '128,' - '256,' - '512,' - '1024,' - '2048,' - '4096,' - '8192,' - '16384,' - '32768,' - '65536,' - '131072,' - '262144,' - '524288,' - '1048576,' - '2097152,' - '4194304,' - '8388608,' - '16777216,' - '33554432,' - '67108864,' - '134217728,' - '268435456,' - '536870912,' - '1073741824,' - '2147483648,' - '4294967296,' - '8589934592,' - '17179869184,' - '34359738368,' - '68719476736,' - '137438953472,' - '274877906944,' - '549755813888,' - '1099511627776,' - '2199023255552,' - '4398046511104,' - '8796093022208,' - '17592186044416,' - '35184372088832,' - '70368744177664,' - '140737488355328,' - '281474976710656,' - '562949953421312,' - '1125899906842624,' - '2251799813685248,' - '4503599627370496,' - '9007199254740992,' - '18014398509481984,' - '36028797018963968,' - '72057594037927936,' - '144115188075855872,' - '288230376151711744,' - '576460752303423488,' - '1152921504606846976,' - '2305843009213693952,' - '4611686018427387904' - '],' - '"bucketCounts":[' - '1,' - '0,' - '0,' - '0,' - '2,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0,' - '0' - ']' - '}' - ']' - '}' - '}' - ']' - '}' + '"resourceMetrics":[{' + '"resource":{' + '"attributes":[{' + '"key":"service.namespace",' + '"value":{"stringValue":"example"}' + '}]' + '},' + '"scopeMetrics":[{' + '"scope":{' + '"name":"OtlpMetricsSerializer",' + '"version":"1.0.0"' + '},' + '"metrics":[{' + '"name":"test.counter",' + '"unit":"",' + '"description":"Description for test.counter",' + '"sum":{' + '"dataPoints":[{' + '"asInt":77,' + '"timeUnixNano":' [0..19] ',' + '"attributes":[{' + '"key":"namespace",' + '"value":{"stringValue":"test"}' + '},{' + '"key":"binding",' + '"value":{"stringValue":"net0"}' + '}]' + '}],' + '"aggregationTemporality":2,' + '"isMonotonic":true' + '}' + '},{' + '"name":"engine.worker.count",' + '"unit":"",' + '"description":"Engine worker count",' + '"sum":{' + '"dataPoints":[{' + '"asInt":3,' + '"timeUnixNano":' [0..19] ',' + '"attributes":[]' + '}],' + '"aggregationTemporality":2,' + '"isMonotonic":true' + '}' + '},{' + '"name":"test.gauge",' + '"unit":"",' + '"description":"Description for test.gauge",' + '"gauge":{' + '"dataPoints":[{' + '"asInt":66,' + '"timeUnixNano":' [0..19] ',' + '"attributes":[{' + '"key":"namespace",' + '"value":{"stringValue":"test"}' + '},{' + '"key":"binding",' + '"value":{"stringValue":"net0"}' + '}]' + '}]' + '}' + '},{' + '"name":"test.histogram",' + '"description":"Description for test.histogram",' + '"unit":"bytes",' + '"histogram":{' + '"aggregationTemporality":2,' + '"dataPoints":[{' + '"timeUnixNano":' [0..19] ',' + '"attributes":[{' + '"key":"namespace",' + '"value":{"stringValue":"test"}' + '},{' + '"key":"binding",' + '"value":{"stringValue":"net0"}' + '}],' + '"min":1,' + '"max":31,' + '"sum":63,' + '"count":3,' + '"explicitBounds":[' + '2,' + '4,' + '8,' + '16,' + '32,' + '64,' + '128,' + '256,' + '512,' + '1024,' + '2048,' + '4096,' + '8192,' + '16384,' + '32768,' + '65536,' + '131072,' + '262144,' + '524288,' + '1048576,' + '2097152,' + '4194304,' + '8388608,' + '16777216,' + '33554432,' + '67108864,' + '134217728,' + '268435456,' + '536870912,' + '1073741824,' + '2147483648,' + '4294967296,' + '8589934592,' + '17179869184,' + '34359738368,' + '68719476736,' + '137438953472,' + '274877906944,' + '549755813888,' + '1099511627776,' + '2199023255552,' + '4398046511104,' + '8796093022208,' + '17592186044416,' + '35184372088832,' + '70368744177664,' + '140737488355328,' + '281474976710656,' + '562949953421312,' + '1125899906842624,' + '2251799813685248,' + '4503599627370496,' + '9007199254740992,' + '18014398509481984,' + '36028797018963968,' + '72057594037927936,' + '144115188075855872,' + '288230376151711744,' + '576460752303423488,' + '1152921504606846976,' + '2305843009213693952,' + '4611686018427387904' + '],' + '"bucketCounts":[' + '1,' + '0,' + '0,' + '0,' + '2,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0,' + '0' ']' + '}]' '}' - ']' + '}]' + '}]' + '}]' '}' read closed