You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2016/05/13 18:14:15 UTC
[33/50] [abbrv] isis git commit: ISIS-1399: new MetricsService to
capture metrics (objects loaded etc),
capture within the Interaction.Execution.
ISIS-1399: new MetricsService to capture metrics (objects loaded etc), capture within the Interaction.Execution.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/4ce54bcf
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/4ce54bcf
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/4ce54bcf
Branch: refs/heads/master
Commit: 4ce54bcf6f52d2905d2e618dc68cfaca50a78428
Parents: d50731c
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Sat May 7 15:58:21 2016 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Sat May 7 15:58:21 2016 +0100
----------------------------------------------------------------------
.../src/main/asciidoc/schema/ixn/ixn-1.0.xsd | 4 +-
.../isis/applib/services/iactn/Interaction.java | 170 +++++++++++++------
.../applib/services/metrics/MetricsService.java | 80 +++++++++
.../isis/schema/utils/InteractionDtoUtils.java | 10 --
.../schema/utils/MemberExecutionDtoUtils.java | 55 ++++++
...onInvocationFacetForDomainEventAbstract.java | 14 +-
...etterOrClearFacetForDomainEventAbstract.java | 23 ++-
.../enlist/EnlistedObjectsServiceInternal.java | 9 +-
.../services/metrics/MetricsServiceDefault.java | 67 ++++++++
.../system/persistence/PersistenceSession.java | 8 +-
.../transaction/IsisTransactionManager.java | 6 +-
.../apache/isis/schema/common/common-1.0.xsd | 21 +++
.../org/apache/isis/schema/ixn/ixn-1.0.xsd | 48 +++++-
13 files changed, 436 insertions(+), 79 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/adocs/documentation/src/main/asciidoc/schema/ixn/ixn-1.0.xsd
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/schema/ixn/ixn-1.0.xsd b/adocs/documentation/src/main/asciidoc/schema/ixn/ixn-1.0.xsd
index 116d9ab..072825d 100644
--- a/adocs/documentation/src/main/asciidoc/schema/ixn/ixn-1.0.xsd
+++ b/adocs/documentation/src/main/asciidoc/schema/ixn/ixn-1.0.xsd
@@ -147,7 +147,7 @@
</xs:element>
<xs:element name="returned" type="returnDto" minOccurs="0" maxOccurs="1">
<xs:annotation>
- <xs:documentation>The value returned by this action (including the type of that returned value). Either the 'returned' or the 'threw' element (from 'memberInteractionDto') will be populated.
+ <xs:documentation>The value returned by this action (including the type of that returned value). Either the 'returned' or the 'threw' element (from 'memberExecutionDto') will be populated.
</xs:documentation>
</xs:annotation>
</xs:element>
@@ -156,7 +156,7 @@
</xs:complexContent>
</xs:complexType>
- <xs:complexType name="propertyModificationDto">
+ <xs:complexType name="propertyEditDto">
<xs:complexContent>
<xs:extension base="interactionExecutionDto">
<xs:sequence>
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java b/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
index dc59c2f..584bbb1 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/iactn/Interaction.java
@@ -27,6 +27,8 @@ import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
+import javax.inject.Inject;
+
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -38,12 +40,17 @@ import org.apache.isis.applib.services.eventbus.AbstractDomainEvent;
import org.apache.isis.applib.services.eventbus.ActionDomainEvent;
import org.apache.isis.applib.services.eventbus.EventBusService;
import org.apache.isis.applib.services.eventbus.PropertyDomainEvent;
+import org.apache.isis.applib.services.metrics.MetricsService;
import org.apache.isis.applib.services.wrapper.WrapperFactory;
+import org.apache.isis.schema.common.v1.DifferenceDto;
import org.apache.isis.schema.common.v1.InteractionType;
import org.apache.isis.schema.common.v1.PeriodDto;
import org.apache.isis.schema.ixn.v1.ActionInvocationDto;
import org.apache.isis.schema.ixn.v1.MemberExecutionDto;
+import org.apache.isis.schema.ixn.v1.MetricsDto;
+import org.apache.isis.schema.ixn.v1.ObjectCountsDto;
import org.apache.isis.schema.ixn.v1.PropertyEditDto;
+import org.apache.isis.schema.utils.MemberExecutionDtoUtils;
import org.apache.isis.schema.utils.jaxbadapters.JavaSqlTimestampXmlGregorianCalendarAdapter;
/**
@@ -112,48 +119,27 @@ public class Interaction implements HasTransactionId {
}
-
public Object execute(
final MemberExecutor<ActionInvocation> memberExecutor,
- final ActionInvocation actionInvocation,
- final ClockService clockService,
- final Command command) {
+ final ActionInvocation actionInvocation) {
- pushAndUpdateCommand(actionInvocation, clockService, command);
+ push(actionInvocation);
- return execute(memberExecutor, actionInvocation, clockService);
+ return executeInternal(memberExecutor, actionInvocation);
}
public Object execute(
- final MemberExecutor<PropertyModification> memberExecutor,
- final PropertyModification propertyModification,
- final ClockService clockService,
- final Command command) {
-
- pushAndUpdateCommand(propertyModification, clockService, command);
- return execute(memberExecutor, propertyModification, clockService);
- }
-
+ final MemberExecutor<PropertyEdit> memberExecutor,
+ final PropertyEdit propertyEdit) {
- private Execution pushAndUpdateCommand(
- final Execution execution,
- final ClockService clockService,
- final Command command) {
+ push(propertyEdit);
- final Timestamp startedAt = clockService.nowAsJavaSqlTimestamp();
- push(startedAt, execution);
-
- if(command.getStartedAt() == null) {
- command.setStartedAt(startedAt);
- }
- return execution;
+ return executeInternal(memberExecutor, propertyEdit);
}
-
- private <T extends Execution> Object execute(
+ private <T extends Execution> Object executeInternal(
final MemberExecutor<T> memberExecutor,
- final T execution,
- final ClockService clockService) {
+ final T execution) {
// as a convenience, since in all cases we want the command to start when the first interaction executes,
// we populate the command here.
@@ -203,7 +189,7 @@ public class Interaction implements HasTransactionId {
* </p>
*/
@Programmatic
- private Execution push(final Timestamp startedAt, final Execution execution) {
+ private Execution push(final Execution execution) {
if(currentExecution == null) {
// new top-level execution
@@ -214,7 +200,6 @@ public class Interaction implements HasTransactionId {
execution.setParent(currentExecution);
}
- execution.setStartedAt(startedAt);
// update this.currentExecution and this.previousExecution
moveCurrentTo(execution);
@@ -265,7 +250,7 @@ public class Interaction implements HasTransactionId {
/**
* <b>NOT API</b>: intended to be called only by the framework.
*
- * Clears the set of {@link Execution}s that may have been {@link #push(Timestamp, Execution)}ed.
+ * Clears the set of {@link Execution}s that may have been {@link #push(Execution)}ed.
*/
@Programmatic
public void clear() {
@@ -432,8 +417,7 @@ public class Interaction implements HasTransactionId {
}
public void setStartedAt(final Timestamp startedAt) {
- this.startedAt = startedAt;
- syncMetrics();
+ syncMetrics(When.BEFORE, startedAt);
}
@@ -448,8 +432,7 @@ public class Interaction implements HasTransactionId {
* <b>NOT API</b>: intended to be called only by the framework.
*/
void setCompletedAt(final Timestamp completedAt) {
- this.completedAt = completedAt;
- syncMetrics();
+ syncMetrics(When.AFTER, completedAt);
}
//endregion
@@ -517,28 +500,103 @@ public class Interaction implements HasTransactionId {
*/
public void setDto(final T executionDto) {
this.dto = executionDto;
- syncMetrics();
}
//endregion
//region > helpers (syncMetrics)
- private void syncMetrics() {
- if (this.dto == null) {
- return;
+
+ enum When {
+ BEFORE {
+ @Override
+ public void syncMetrics(
+ final Execution<?, ?> execution,
+ final Timestamp timestamp,
+ final int numberObjectsLoaded,
+ final int numberObjectsDirtied,
+ final int numberObjectPropertiesModified) {
+
+ execution.startedAt = timestamp;
+
+ final MetricsDto metricsDto = metricsFor(execution);
+
+ final PeriodDto periodDto = timingsFor(metricsDto);
+ periodDto.setStartedAt(JavaSqlTimestampXmlGregorianCalendarAdapter.print(timestamp));
+
+ final ObjectCountsDto objectCountsDto = objectCountsFor(metricsDto);
+ numberObjectsLoadedFor(objectCountsDto).setBefore(numberObjectsLoaded);
+ numberObjectsDirtiedFor(objectCountsDto).setBefore(numberObjectsDirtied);
+ numberObjectPropertiesModifiedFor(objectCountsDto).setBefore(numberObjectPropertiesModified);
+ }
+
+ },
+ AFTER {
+ @Override public void syncMetrics(
+ final Execution<?, ?> execution,
+ final Timestamp timestamp,
+ final int numberObjectsLoaded,
+ final int numberObjectsDirtied,
+ final int numberObjectPropertiesModified) {
+
+ execution.completedAt = timestamp;
+
+ final MetricsDto metricsDto = metricsFor(execution);
+
+ final PeriodDto periodDto = timingsFor(metricsDto);
+ periodDto.setCompletedAt(JavaSqlTimestampXmlGregorianCalendarAdapter.print(timestamp));
+
+ final ObjectCountsDto objectCountsDto = objectCountsFor(metricsDto);
+ numberObjectsLoadedFor(objectCountsDto).setAfter(numberObjectsLoaded);
+ numberObjectsDirtiedFor(objectCountsDto).setAfter(numberObjectsDirtied);
+ numberObjectPropertiesModifiedFor(objectCountsDto).setAfter(numberObjectPropertiesModified);
+
+ }
+
+ };
+
+ //region > helpers
+ private static DifferenceDto numberObjectPropertiesModifiedFor(final ObjectCountsDto objectCountsDto) {
+ return MemberExecutionDtoUtils.numberObjectPropertiesModifiedFor(objectCountsDto);
+ }
+
+ private static DifferenceDto numberObjectsDirtiedFor(final ObjectCountsDto objectCountsDto) {
+ return MemberExecutionDtoUtils.numberObjectsDirtiedFor(objectCountsDto);
+ }
+
+ private static DifferenceDto numberObjectsLoadedFor(final ObjectCountsDto objectCountsDto) {
+ return MemberExecutionDtoUtils.numberObjectsLoadedFor(objectCountsDto);
+ }
+
+ private static ObjectCountsDto objectCountsFor(final MetricsDto metricsDto) {
+ return MemberExecutionDtoUtils.objectCountsFor(metricsDto);
+ }
+
+ private static MetricsDto metricsFor(final Execution<?, ?> execution) {
+ return MemberExecutionDtoUtils.metricsFor(execution.dto);
}
- final PeriodDto periodDto = periodDtoFor(this.dto);
- periodDto.setStartedAt(JavaSqlTimestampXmlGregorianCalendarAdapter.print(getStartedAt()));
- periodDto.setCompletedAt(JavaSqlTimestampXmlGregorianCalendarAdapter.print(getCompletedAt()));
- }
- private static PeriodDto periodDtoFor(final MemberExecutionDto executionDto) {
- PeriodDto timings = executionDto.getTimings();
- if(timings == null) {
- timings = new PeriodDto();
+ private static PeriodDto timingsFor(final MetricsDto metricsDto) {
+ return MemberExecutionDtoUtils.timingsFor(metricsDto);
}
- return timings;
+ //endregion
+
+ public abstract void syncMetrics(
+ final Execution<?,?> teExecution,
+ final Timestamp timestamp,
+ final int numberObjectsLoaded,
+ final int numberObjectsDirtied,
+ final int numberObjectPropertiesModified);
+ }
+ private void syncMetrics(final When when, final Timestamp timestamp) {
+ final MetricsService metricsService = interaction.metricsService;
+
+ final int numberObjectsLoaded = metricsService.numberObjectsLoaded();
+ final int numberObjectsDirtied = metricsService.numberObjectsDirtied();
+ final int numberObjectPropertiesModified = metricsService.numberObjectPropertiesModified();
+
+ when.syncMetrics(this, timestamp, numberObjectsLoaded, numberObjectsDirtied, numberObjectPropertiesModified);
}
+
//endregion
}
@@ -561,11 +619,11 @@ public class Interaction implements HasTransactionId {
}
}
- public static class PropertyModification extends Execution<PropertyEditDto, PropertyDomainEvent<?,?>> {
+ public static class PropertyEdit extends Execution<PropertyEditDto, PropertyDomainEvent<?,?>> {
private final Object newValue;
- public PropertyModification(
+ public PropertyEdit(
final Interaction interaction,
final String memberId,
final Object target,
@@ -578,4 +636,12 @@ public class Interaction implements HasTransactionId {
return newValue;
}
}
+
+
+ @Inject
+ MetricsService metricsService;
+
+ @Inject
+ ClockService clockService;
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/core/applib/src/main/java/org/apache/isis/applib/services/metrics/MetricsService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/metrics/MetricsService.java b/core/applib/src/main/java/org/apache/isis/applib/services/metrics/MetricsService.java
new file mode 100644
index 0000000..4404418
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/metrics/MetricsService.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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 org.apache.isis.applib.services.metrics;
+
+import java.sql.Timestamp;
+import java.util.UUID;
+
+import javax.enterprise.context.RequestScoped;
+import javax.jdo.listener.InstanceLifecycleEvent;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.iactn.InteractionContext;
+import org.apache.isis.schema.ixn.v1.MemberExecutionDto;
+
+@RequestScoped
+public interface MetricsService {
+
+ /**
+ * The number of objects that have, so far in this request, been loaded from the database.
+ *
+ * <p>
+ * Corresponds to the number of times that {@link javax.jdo.listener.LoadLifecycleListener#postLoad(InstanceLifecycleEvent)} is fired.
+ * </p>
+ *
+ * <p>
+ * Is captured within {@link MemberExecutionDto#getMetrics()} (accessible from {@link InteractionContext#getInteraction()}).
+ * </p>
+ */
+ @Programmatic
+ int numberObjectsLoaded();
+
+ /**
+ * The number of objects that have, so far in this request, been dirtied/will need updating in the database); a
+ * good measure of the footprint of the interaction.
+ *
+ * <p>
+ * Corresponds to the number of times that {@link javax.jdo.listener.DirtyLifecycleListener#preDirty(InstanceLifecycleEvent)} callback is fired.
+ * </p>
+ *
+ * <p>
+ * Is captured within {@link MemberExecutionDto#getMetrics()} (accessible from {@link InteractionContext#getInteraction()}).
+ * </p>
+ */
+ @Programmatic
+ int numberObjectsDirtied();
+
+ /**
+ * The number of individual properties of objects that were modified; a good measure of the amount of work being done in the interaction.
+ *
+ * <p>
+ * Related to {@link #numberObjectsDirtied()}, corresponds to the number of times that {@link org.apache.isis.applib.services.audit.AuditingService3#audit(UUID, String, Bookmark, String, String, String, String, String, Timestamp)} would be called if the transaction were to complete.
+ * </p>
+ *
+ * <p>
+ * Is captured within {@link MemberExecutionDto#getMetrics()} (accessible from {@link InteractionContext#getInteraction()}).
+ * </p>
+ */
+ @Programmatic
+ int numberObjectPropertiesModified();
+
+}
+
+
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/core/applib/src/main/java/org/apache/isis/schema/utils/InteractionDtoUtils.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/schema/utils/InteractionDtoUtils.java b/core/applib/src/main/java/org/apache/isis/schema/utils/InteractionDtoUtils.java
index 2ed9448..deaf447 100644
--- a/core/applib/src/main/java/org/apache/isis/schema/utils/InteractionDtoUtils.java
+++ b/core/applib/src/main/java/org/apache/isis/schema/utils/InteractionDtoUtils.java
@@ -45,7 +45,6 @@ import org.apache.isis.schema.cmd.v1.ParamDto;
import org.apache.isis.schema.cmd.v1.ParamsDto;
import org.apache.isis.schema.common.v1.InteractionType;
import org.apache.isis.schema.common.v1.OidDto;
-import org.apache.isis.schema.common.v1.PeriodDto;
import org.apache.isis.schema.common.v1.ValueDto;
import org.apache.isis.schema.common.v1.ValueType;
import org.apache.isis.schema.common.v1.ValueWithTypeDto;
@@ -334,15 +333,6 @@ public final class InteractionDtoUtils {
return parametersFor(invocationDto).getParameter();
}
- private static PeriodDto timingsFor(final MemberExecutionDto executionDto) {
- PeriodDto timings = executionDto.getTimings();
- if(timings == null) {
- timings = new PeriodDto();
- executionDto.setTimings(timings);
- }
- return timings;
- }
-
//endregion
//region > addParamArg
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/core/applib/src/main/java/org/apache/isis/schema/utils/MemberExecutionDtoUtils.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/schema/utils/MemberExecutionDtoUtils.java b/core/applib/src/main/java/org/apache/isis/schema/utils/MemberExecutionDtoUtils.java
index f70c2b8..844d468 100644
--- a/core/applib/src/main/java/org/apache/isis/schema/utils/MemberExecutionDtoUtils.java
+++ b/core/applib/src/main/java/org/apache/isis/schema/utils/MemberExecutionDtoUtils.java
@@ -29,7 +29,11 @@ import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;
+import org.apache.isis.schema.common.v1.DifferenceDto;
+import org.apache.isis.schema.common.v1.PeriodDto;
import org.apache.isis.schema.ixn.v1.MemberExecutionDto;
+import org.apache.isis.schema.ixn.v1.MetricsDto;
+import org.apache.isis.schema.ixn.v1.ObjectCountsDto;
public final class MemberExecutionDtoUtils {
@@ -63,4 +67,55 @@ public final class MemberExecutionDtoUtils {
}
}
+ public static MetricsDto metricsFor(final MemberExecutionDto executionDto) {
+ MetricsDto metrics = executionDto.getMetrics();
+ if(metrics == null) {
+ metrics = new MetricsDto();
+ executionDto.setMetrics(metrics);
+ }
+ return metrics;
+ }
+
+ public static PeriodDto timingsFor(final MetricsDto metricsDto) {
+ PeriodDto timings = metricsDto.getTimings();
+ if(timings == null) {
+ timings = new PeriodDto();
+ metricsDto.setTimings(timings);
+ }
+ return timings;
+ }
+
+ public static ObjectCountsDto objectCountsFor(final MetricsDto metricsDto) {
+ ObjectCountsDto objectCounts = metricsDto.getObjectCounts();
+ if(objectCounts == null) {
+ objectCounts = new ObjectCountsDto();
+ metricsDto.setObjectCounts(objectCounts);
+ }
+ return objectCounts;
+ }
+
+ public static DifferenceDto numberObjectsLoadedFor(final ObjectCountsDto objectCountsDto) {
+ DifferenceDto differenceDto = objectCountsDto.getNumberObjectsLoaded();
+ if(differenceDto == null) {
+ differenceDto = new DifferenceDto();
+ objectCountsDto.setNumberObjectsLoaded(differenceDto);
+ }
+ return differenceDto;
+ }
+ public static DifferenceDto numberObjectsDirtiedFor(final ObjectCountsDto objectCountsDto) {
+ DifferenceDto differenceDto = objectCountsDto.getNumberObjectsDirtied();
+ if(differenceDto == null) {
+ differenceDto = new DifferenceDto();
+ objectCountsDto.setNumberObjectsDirtied(differenceDto);
+ }
+ return differenceDto;
+ }
+ public static DifferenceDto numberObjectPropertiesModifiedFor(final ObjectCountsDto objectCountsDto) {
+ DifferenceDto differenceDto = objectCountsDto.getNumberObjectPropertiesModified();
+ if(differenceDto == null) {
+ differenceDto = new DifferenceDto();
+ objectCountsDto.setNumberObjectPropertiesModified(differenceDto);
+ }
+ return differenceDto;
+ }
}
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
index bdaeb92..c900f17 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
@@ -21,6 +21,7 @@ package org.apache.isis.core.metamodel.facets.actions.action.invocation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -211,6 +212,17 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
owningAction, targetAdapter, argumentAdapterList);
currentExecution.setDto(invocationDto);
+
+ // set the startedAt (and update command if this is the top-most member execution)
+ // (this isn't done within Interaction#execute(...) because it requires the DTO
+ // to have been set on the current execution).
+ final Timestamp startedAt = getClockService().nowAsJavaSqlTimestamp();
+ execution.setStartedAt(startedAt);
+ if(command.getStartedAt() == null) {
+ command.setStartedAt(startedAt);
+ }
+
+
// ... post the executing event
final ActionDomainEvent<?> event =
domainEventHelper.postEventForAction(
@@ -274,7 +286,7 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
};
// sets up startedAt and completedAt on the execution, also manages the execution call graph
- interaction.execute(callable, execution, getClockService(), command);
+ interaction.execute(callable, execution);
// handle any exceptions
final Interaction.Execution<ActionInvocationDto, ?> priorExecution = interaction.getPriorExecution();
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
index d6a3fbf..4661cfc 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
@@ -19,6 +19,8 @@
package org.apache.isis.core.metamodel.facets.properties.property.modify;
+import java.sql.Timestamp;
+
import com.google.common.base.Objects;
import org.apache.isis.applib.services.clock.ClockService;
@@ -184,12 +186,12 @@ public abstract class PropertySetterOrClearFacetForDomainEventAbstract
final Object target = ObjectAdapter.Util.unwrap(targetAdapter);
final Object argValue = ObjectAdapter.Util.unwrap(newValueAdapter);
- final Interaction.PropertyModification execution =
- new Interaction.PropertyModification(interaction, propertyId, target, argValue);
- final Interaction.MemberExecutor<Interaction.PropertyModification> executor =
- new Interaction.MemberExecutor<Interaction.PropertyModification>() {
+ final Interaction.PropertyEdit execution =
+ new Interaction.PropertyEdit(interaction, propertyId, target, argValue);
+ final Interaction.MemberExecutor<Interaction.PropertyEdit> executor =
+ new Interaction.MemberExecutor<Interaction.PropertyEdit>() {
@Override
- public Object execute(final Interaction.PropertyModification currentExecution) {
+ public Object execute(final Interaction.PropertyEdit currentExecution) {
try {
@@ -200,6 +202,15 @@ public abstract class PropertySetterOrClearFacetForDomainEventAbstract
currentExecution.setDto(editDto);
+ // set the startedAt (and update command if this is the top-most member execution)
+ // (this isn't done within Interaction#execute(...) because it requires the DTO
+ // to have been set on the current execution).
+ final Timestamp startedAt = getClockService().nowAsJavaSqlTimestamp();
+ execution.setStartedAt(startedAt);
+ if(command.getStartedAt() == null) {
+ command.setStartedAt(startedAt);
+ }
+
// ... post the executing event
final Object oldValue = getterFacet.getProperty(targetAdapter, interactionInitiatedBy);
final Object newValue = ObjectAdapter.Util.unwrap(newValueAdapter);
@@ -247,7 +258,7 @@ public abstract class PropertySetterOrClearFacetForDomainEventAbstract
};
// sets up startedAt and completedAt on the execution, also manages the execution call graph
- interaction.execute(executor, execution, getClockService(), command);
+ interaction.execute(executor, execution);
// handle any exceptions
final Interaction.Execution priorExecution = interaction.getPriorExecution();
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/EnlistedObjectsServiceInternal.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/EnlistedObjectsServiceInternal.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/EnlistedObjectsServiceInternal.java
index 1839b6e..053dc86 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/EnlistedObjectsServiceInternal.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/enlist/EnlistedObjectsServiceInternal.java
@@ -251,6 +251,13 @@ public class EnlistedObjectsServiceInternal {
return object != null? object.toString(): null;
}
+ @Programmatic
+ public int numberObjectsDirtied() {
+ return changedObjectProperties.size();
+ }
-
+ @Programmatic
+ public int numberObjectPropertiesModified() {
+ return changedObjectProperties.size();
+ }
}
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/core/runtime/src/main/java/org/apache/isis/core/runtime/services/metrics/MetricsServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/metrics/MetricsServiceDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/metrics/MetricsServiceDefault.java
new file mode 100644
index 0000000..889b887
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/metrics/MetricsServiceDefault.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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 org.apache.isis.core.runtime.services.metrics;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.jdo.listener.InstanceLifecycleEvent;
+import javax.jdo.listener.InstanceLifecycleListener;
+import javax.jdo.listener.LoadLifecycleListener;
+
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.metrics.MetricsService;
+import org.apache.isis.core.runtime.services.enlist.EnlistedObjectsServiceInternal;
+
+@RequestScoped
+@DomainService(nature = NatureOfService.DOMAIN)
+public class MetricsServiceDefault implements MetricsService, InstanceLifecycleListener, LoadLifecycleListener {
+
+ private AtomicInteger numberLoaded = new AtomicInteger(0);
+
+ @Override
+ public int numberObjectsLoaded() {
+ return numberLoaded.get();
+ }
+
+ @Override
+ public int numberObjectsDirtied() {
+ return enlistedObjectsServiceInternal.numberObjectsDirtied();
+ }
+
+ @Override
+ public int numberObjectPropertiesModified() {
+ return enlistedObjectsServiceInternal.numberObjectPropertiesModified();
+ }
+
+ @Programmatic
+ @Override
+ public void postLoad(final InstanceLifecycleEvent event) {
+ numberLoaded.incrementAndGet();
+ }
+
+
+ @Inject
+ EnlistedObjectsServiceInternal enlistedObjectsServiceInternal;
+
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
index 7fe16c1..d1c1058 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
@@ -123,6 +123,7 @@ import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindAllIns
import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindUsingApplibQueryDefault;
import org.apache.isis.core.runtime.runner.opts.OptionHandlerFixtureAbstract;
import org.apache.isis.core.runtime.services.enlist.EnlistedObjectsServiceInternal;
+import org.apache.isis.core.runtime.services.metrics.MetricsServiceDefault;
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.core.runtime.system.persistence.adaptermanager.OidAdapterHashMap;
import org.apache.isis.core.runtime.system.persistence.adaptermanager.PojoAdapterHashMap;
@@ -301,6 +302,9 @@ public class PersistenceSession implements
initServices();
+ final MetricsServiceDefault metricsServiceDefault = servicesInjector.lookupService(MetricsServiceDefault.class);
+ persistenceManager.addInstanceLifecycleListener(metricsServiceDefault, (Class[])null);
+
setState(State.OPEN);
}
@@ -396,8 +400,6 @@ public class PersistenceSession implements
//endregion
//region > Injectable
- //endregion
-
@Override
public void injectInto(final Object candidate) {
if (AdapterManagerAware.class.isAssignableFrom(candidate.getClass())) {
@@ -417,6 +419,7 @@ public class PersistenceSession implements
cast.setConfigurationService(this);
}
}
+ //endregion
//region > QuerySubmitter impl, findInstancesInTransaction
@@ -510,6 +513,7 @@ public class PersistenceSession implements
return oidMarshaller;
}
+
//endregion
//region > State
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
index 23d759c..18be7e1 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
@@ -31,6 +31,7 @@ import org.apache.isis.applib.services.clock.ClockService;
import org.apache.isis.applib.services.command.Command;
import org.apache.isis.applib.services.command.CommandContext;
import org.apache.isis.applib.services.command.spi.CommandService;
+import org.apache.isis.applib.services.factory.FactoryService;
import org.apache.isis.applib.services.iactn.Interaction;
import org.apache.isis.applib.services.iactn.InteractionContext;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
@@ -68,6 +69,7 @@ public class IsisTransactionManager implements SessionScopedComponent {
private final ServicesInjector servicesInjector;
+ private final FactoryService factoryService;
private final CommandContext commandContext;
private final CommandService commandService;
@@ -101,6 +103,7 @@ public class IsisTransactionManager implements SessionScopedComponent {
this.persistenceSession = persistenceSession;
this.servicesInjector = servicesInjector;
+ this.factoryService = lookupService(FactoryService.class);
this.commandContext = lookupService(CommandContext.class);
this.commandService = lookupService(CommandService.class);
@@ -288,14 +291,13 @@ public class IsisTransactionManager implements SessionScopedComponent {
command = createCommand();
transactionId = UUID.randomUUID();
}
- final Interaction interaction = new Interaction();
+ final Interaction interaction = factoryService.instantiate(Interaction.class);
initCommandAndInteraction(transactionId, command, interaction);
commandContext.setCommand(command);
interactionContext.setInteraction(interaction);
-
initOtherApplibServicesIfConfigured();
final MessageBroker messageBroker = MessageBroker.acquire(getAuthenticationSession());
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.0.xsd
----------------------------------------------------------------------
diff --git a/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.0.xsd b/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.0.xsd
index ac55c8e..f38a9d4 100644
--- a/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.0.xsd
+++ b/core/schema/src/main/resources/org/apache/isis/schema/common/common-1.0.xsd
@@ -129,6 +129,27 @@
</xs:sequence>
</xs:complexType>
+ <xs:complexType name="differenceDto">
+ <xs:annotation>
+ <xs:documentation>Captures a pair of numbers representing a difference. Used for example to capture metrics (number objects modified before and after).
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ </xs:sequence>
+ <xs:attribute name="before" type="xs:int">
+ <xs:annotation>
+ <xs:documentation>The initial quantity.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="after" type="xs:int">
+ <xs:annotation>
+ <xs:documentation>The final quantity, once known. The difference is therefore the computation of (after - before).
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+
<xs:complexType name="valueWithTypeDto">
<xs:annotation>
<xs:documentation>Captures both a value and its corresponding type. Used for the return value of action invocations, and for the new value in property edits.
http://git-wip-us.apache.org/repos/asf/isis/blob/4ce54bcf/core/schema/src/main/resources/org/apache/isis/schema/ixn/ixn-1.0.xsd
----------------------------------------------------------------------
diff --git a/core/schema/src/main/resources/org/apache/isis/schema/ixn/ixn-1.0.xsd b/core/schema/src/main/resources/org/apache/isis/schema/ixn/ixn-1.0.xsd
index 32349de..024d349 100644
--- a/core/schema/src/main/resources/org/apache/isis/schema/ixn/ixn-1.0.xsd
+++ b/core/schema/src/main/resources/org/apache/isis/schema/ixn/ixn-1.0.xsd
@@ -101,9 +101,9 @@
</xs:documentation>
</xs:annotation>
</xs:element>
- <xs:element name="timings" type="common:periodDto">
+ <xs:element name="metrics" type="metricsDto">
<xs:annotation>
- <xs:documentation>Captures the time taken to perform the member interaction (invoke the action, or edit the property).
+ <xs:documentation>Profiling metrics capturng the this time/number of objects affected as a result of performing this member interaction (invoke the action, or edit the property).
</xs:documentation>
</xs:annotation>
</xs:element>
@@ -146,7 +146,7 @@
</xs:element>
<xs:element name="returned" type="common:valueWithTypeDto" minOccurs="0" maxOccurs="1">
<xs:annotation>
- <xs:documentation>The value returned by this action (including the type of that returned value). Either the 'returned' or the 'threw' element (from 'memberInteractionDto') will be populated.
+ <xs:documentation>The value returned by this action (including the type of that returned value). Either the 'returned' or the 'threw' element (from 'memberExecutionDto') will be populated.
</xs:documentation>
</xs:annotation>
</xs:element>
@@ -165,6 +165,48 @@
</xs:complexContent>
</xs:complexType>
+ <xs:complexType name="metricsDto">
+ <xs:sequence>
+ <xs:element name="timings" type="common:periodDto">
+ <xs:annotation>
+ <xs:documentation>The time taken to perform the member interaction (invoke the action, or edit the property).
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="objectCounts" type="objectCountsDto">
+ <xs:annotation>
+ <xs:documentation>How many objets were affected by the member interaction.
+ </xs:documentation>
+ </xs:annotation>
+
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="objectCountsDto">
+ <xs:sequence>
+ <xs:element name="numberObjectsLoaded" type="common:differenceDto">
+ <xs:annotation>
+ <xs:documentation>The number of objects loaded.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="numberObjectsDirtied" type="common:differenceDto">
+ <xs:annotation>
+ <xs:documentation>The number of objects dirtied (ie updated).
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="numberObjectPropertiesModified" type="common:differenceDto">
+ <xs:annotation>
+ <xs:documentation>The number of individual properties of objects that were modified (eg as per individual calls to AuditingService).
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+
+ </xs:complexType>
+
<xs:complexType name="exceptionDto">
<xs:annotation>
<xs:documentation>Captures any exception thrown by an action invocation. Use as the xsd:type of the 'threw' element.