-
Notifications
You must be signed in to change notification settings - Fork 1
Capture per-entity metrics on Repository and EventStore #155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/af5-model-inspection
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /* | ||
| * Copyright (c) 2022-2025. AxonIQ B.V. | ||
| * | ||
| * 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 io.axoniq.platform.framework.api.metrics | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty | ||
|
|
||
| data class EntityStatisticIdentifier( | ||
| @JsonProperty("n") | ||
| val entityName: String, | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| /* | ||
| * Copyright (c) 2022-2025. AxonIQ B.V. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same, copyright issue
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please check the entire PR before merging |
||
| * | ||
| * 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 io.axoniq.platform.framework.api.metrics | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty | ||
|
|
||
| data class EntityStatistics( | ||
| @JsonProperty("c") | ||
| val count: Double, | ||
| @JsonProperty("f") | ||
| val failed: Double, | ||
| @JsonProperty("t") | ||
| val timer: StatisticDistribution?, | ||
| @JsonProperty("m") | ||
| val metrics: Map<String, StatisticDistribution>, | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| /* | ||
| * Copyright (c) 2022-2025. AxonIQ B.V. | ||
| * | ||
| * 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 io.axoniq.platform.framework.api.metrics | ||
|
|
||
| import com.fasterxml.jackson.annotation.JsonProperty | ||
|
|
||
| data class EntityStatisticsWithIdentifier( | ||
| @JsonProperty("e") | ||
| val entity: EntityStatisticIdentifier, | ||
| @JsonProperty("s") | ||
| val statistics: EntityStatistics, | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| /* | ||
| * Copyright (c) 2022-2026. AxonIQ B.V. | ||
| * | ||
| * 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 io.axoniq.platform.framework.eventsourcing | ||
|
|
||
| import io.axoniq.platform.framework.api.metrics.PreconfiguredMetric | ||
| import io.axoniq.platform.framework.messaging.HandlerMeasurement | ||
| import io.axoniq.platform.framework.messaging.HandlerMeasurement.Companion.RESOURCE_KEY | ||
| import io.axoniq.platform.framework.messaging.HandlerMetricsRegistry | ||
| import io.axoniq.platform.framework.messaging.toInformation | ||
| import io.axoniq.platform.framework.modelling.CurrentEntityContext | ||
| import io.axoniq.platform.framework.modelling.EntityMetricsRegistry | ||
| import org.axonframework.common.infra.ComponentDescriptor | ||
| import org.axonframework.eventsourcing.eventstore.AppendCondition | ||
| import org.axonframework.eventsourcing.eventstore.EventStorageEngine | ||
| import org.axonframework.eventsourcing.eventstore.SourcingCondition | ||
| import org.axonframework.eventsourcing.eventstore.TaggedEventMessage | ||
| import org.axonframework.messaging.core.MessageStream | ||
| import org.axonframework.messaging.core.unitofwork.ProcessingContext | ||
| import org.axonframework.messaging.eventhandling.EventMessage | ||
| import org.axonframework.messaging.eventhandling.processing.streaming.token.TrackingToken | ||
| import org.axonframework.messaging.eventstreaming.StreamingCondition | ||
| import java.time.Instant | ||
| import java.util.concurrent.CompletableFuture | ||
| import java.util.concurrent.TimeUnit | ||
|
|
||
| class AxoniqPlatformEventStorageEngine( | ||
| private val delegate: EventStorageEngine, | ||
| private val registry: HandlerMetricsRegistry, | ||
| private val entityMetricsRegistry: EntityMetricsRegistry, | ||
| ) : EventStorageEngine { | ||
|
|
||
| override fun appendEvents(condition: AppendCondition, context: ProcessingContext?, events: List<TaggedEventMessage<*>>): CompletableFuture<EventStorageEngine.AppendTransaction<*>> { | ||
| // First, report dispatches | ||
| val container = context?.getResource(RESOURCE_KEY) | ||
| if (container == null) { | ||
| events.forEach { tm -> | ||
| val event: EventMessage = tm.event() | ||
| registry.registerMessageDispatchedWithoutHandling(event.toInformation()) | ||
| } | ||
| } else { | ||
| events.forEach { tm -> | ||
| val event: EventMessage = tm.event() | ||
| container.reportMessageDispatched(event.toInformation()) | ||
| } | ||
| } | ||
| if (context == null) { | ||
| return delegate.appendEvents(condition, context, events) | ||
| } | ||
| // Second, measure commit time if measurement is ongoing | ||
| val startTime = System.nanoTime() | ||
| val currentEntity = context.getResource(CurrentEntityContext.RESOURCE_KEY) | ||
| return delegate.appendEvents(condition, context, events) | ||
| .whenComplete { _, _ -> | ||
| val endTime = System.nanoTime() | ||
| HandlerMeasurement.onContext(context) { | ||
| it.registerMetricValue(PreconfiguredMetric.EVENT_COMMIT_TIME, endTime - startTime) | ||
| } | ||
| currentEntity?.let { | ||
| entityMetricsRegistry.registerAdditionalTimer( | ||
| it, | ||
| EntityMetricsRegistry.METRIC_EVENT_COMMIT_TIME, | ||
| endTime - startTime, | ||
| TimeUnit.NANOSECONDS, | ||
| ) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| override fun appendEvents(condition: AppendCondition, context: ProcessingContext?, vararg events: TaggedEventMessage<*>): CompletableFuture<EventStorageEngine.AppendTransaction<*>> { | ||
| return appendEvents(condition, context, events.toList()) | ||
| } | ||
|
|
||
| override fun source(condition: SourcingCondition): MessageStream<EventMessage> { | ||
|
Check warning on line 87 in framework-client/src/main/java/io/axoniq/platform/framework/eventsourcing/AxoniqPlatformEventStorageEngine.kt
|
||
| return delegate.source(condition) | ||
| } | ||
|
|
||
| override fun stream(condition: StreamingCondition): MessageStream<EventMessage> { | ||
|
Check warning on line 91 in framework-client/src/main/java/io/axoniq/platform/framework/eventsourcing/AxoniqPlatformEventStorageEngine.kt
|
||
| return delegate.stream(condition) | ||
| } | ||
|
|
||
| override fun firstToken(): CompletableFuture<TrackingToken> = delegate.firstToken() | ||
|
Check warning on line 95 in framework-client/src/main/java/io/axoniq/platform/framework/eventsourcing/AxoniqPlatformEventStorageEngine.kt
|
||
|
|
||
| override fun latestToken(): CompletableFuture<TrackingToken> = delegate.latestToken() | ||
|
Check warning on line 97 in framework-client/src/main/java/io/axoniq/platform/framework/eventsourcing/AxoniqPlatformEventStorageEngine.kt
|
||
|
|
||
| override fun tokenAt(at: Instant): CompletableFuture<TrackingToken> = delegate.tokenAt(at) | ||
|
Check warning on line 99 in framework-client/src/main/java/io/axoniq/platform/framework/eventsourcing/AxoniqPlatformEventStorageEngine.kt
|
||
|
|
||
| override fun describeTo(descriptor: ComponentDescriptor) { | ||
| descriptor.describeWrapperOf(delegate) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The copyright notice is outdated. Should be 2026. Are you using the copyright plugin with the templte?