config = Map.of(
"maxIterations", 20,
"throwInCompute", true
diff --git a/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java b/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java
index 001f570242..0444c99bcc 100644
--- a/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java
+++ b/proc/test/src/main/java/org/neo4j/gds/ProcedureRunner.java
@@ -19,6 +19,8 @@
*/
package org.neo4j.gds;
+import org.neo4j.gds.algorithms.metrics.AlgorithmMetricsService;
+import org.neo4j.gds.algorithms.metrics.PassthroughAlgorithmMetricRegistrar;
import org.neo4j.gds.compat.GraphDatabaseApiProxy;
import org.neo4j.gds.core.Username;
import org.neo4j.gds.core.utils.progress.TaskRegistryFactory;
@@ -43,7 +45,8 @@ public static P instantiateProcedure(
TaskRegistryFactory taskRegistryFactory,
UserLogRegistryFactory userLogRegistryFactory,
Transaction tx,
- Username username
+ Username username,
+ AlgorithmMetricsService algorithmMetricsService
) {
P proc;
try {
@@ -61,6 +64,8 @@ public static
P instantiateProcedure(
proc.userLogRegistryFactory = userLogRegistryFactory;
proc.username = username;
+ proc.algorithmMetricsService = algorithmMetricsService;
+
return proc;
}
@@ -82,7 +87,8 @@ public static
P applyOnProcedure(
taskRegistryFactory,
EmptyUserLogRegistryFactory.INSTANCE,
tx,
- username
+ username,
+ new AlgorithmMetricsService(new PassthroughAlgorithmMetricRegistrar())
);
func.accept(proc);
return proc;
diff --git a/procedures/extension/build.gradle b/procedures/extension/build.gradle
index e3ed8a1c61..f51938d5e7 100644
--- a/procedures/extension/build.gradle
+++ b/procedures/extension/build.gradle
@@ -18,6 +18,7 @@ dependencies {
compileOnly(group: 'org.neo4j', name: 'neo4j-logging', version: ver.'neo4j') { transitive = false }
// the necessary GDS things for the extension to construct the application
+ implementation project(':algorithm-metrics-api')
implementation project(':config-api')
implementation project(':core')
implementation project(':core-utils')
diff --git a/procedures/extension/src/main/java/org/neo4j/gds/extension/OpenGraphDataScienceExtension.java b/procedures/extension/src/main/java/org/neo4j/gds/extension/OpenGraphDataScienceExtension.java
index befb41adc6..9d38c84ddd 100644
--- a/procedures/extension/src/main/java/org/neo4j/gds/extension/OpenGraphDataScienceExtension.java
+++ b/procedures/extension/src/main/java/org/neo4j/gds/extension/OpenGraphDataScienceExtension.java
@@ -21,6 +21,8 @@
import org.neo4j.annotations.service.ServiceProvider;
import org.neo4j.configuration.Config;
+import org.neo4j.gds.algorithms.metrics.AlgorithmMetricsService;
+import org.neo4j.gds.algorithms.metrics.PassthroughAlgorithmMetricRegistrar;
import org.neo4j.gds.applications.graphstorecatalog.CatalogBusinessFacade;
import org.neo4j.gds.core.write.NativeExportBuildersProvider;
import org.neo4j.gds.procedures.GraphDataScience;
@@ -54,7 +56,8 @@ public Lifecycle newInstance(ExtensionContext extensionContext, Dependencies dep
var log = new LogAccessor().getLog(dependencies.logService(), getClass());
var extensionBuilder = ExtensionBuilder.create(
- log, dependencies.config(),
+ log,
+ dependencies.config(),
dependencies.globalProcedures()
);
@@ -63,10 +66,20 @@ public Lifecycle newInstance(ExtensionContext extensionContext, Dependencies dep
// we have no extra checks to do in OpenGDS
Optional> businessFacadeDecorator = Optional.empty();
+ var algorithmMetricsService = new AlgorithmMetricsService(new PassthroughAlgorithmMetricRegistrar());
+
extensionBuilder
.withComponent(
GraphDataScience.class,
- () -> extensionBuilder.gdsProvider(exporterBuildersProviderService, businessFacadeDecorator)
+ () -> extensionBuilder.gdsProvider(
+ exporterBuildersProviderService,
+ businessFacadeDecorator,
+ algorithmMetricsService
+ )
+ )
+ .withComponent(
+ AlgorithmMetricsService.class,
+ () -> ctx -> algorithmMetricsService
)
.registerExtension();
diff --git a/procedures/integration/build.gradle b/procedures/integration/build.gradle
index fa589f7e20..532bc21ed0 100644
--- a/procedures/integration/build.gradle
+++ b/procedures/integration/build.gradle
@@ -13,6 +13,7 @@ dependencies {
testImplementation(group: 'org.neo4j', name: it, version: ver.'neo4j')
}
+ implementation project(':algorithm-metrics-api')
implementation project(':config-api')
implementation project(':core')
implementation project(':core-write')
diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/CommunityProcedureProvider.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/CommunityProcedureProvider.java
index a41be23797..d6a87f6573 100644
--- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/CommunityProcedureProvider.java
+++ b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/CommunityProcedureProvider.java
@@ -21,6 +21,7 @@
import org.neo4j.gds.ProcedureCallContextReturnColumns;
import org.neo4j.gds.algorithms.AlgorithmMemoryValidationService;
+import org.neo4j.gds.algorithms.community.BasicAlgorithmRunner;
import org.neo4j.gds.algorithms.community.CommunityAlgorithmsEstimateBusinessFacade;
import org.neo4j.gds.algorithms.community.CommunityAlgorithmsFacade;
import org.neo4j.gds.algorithms.community.CommunityAlgorithmsMutateBusinessFacade;
@@ -29,6 +30,7 @@
import org.neo4j.gds.algorithms.community.CommunityAlgorithmsWriteBusinessFacade;
import org.neo4j.gds.algorithms.community.MutateNodePropertyService;
import org.neo4j.gds.algorithms.community.WriteNodePropertyService;
+import org.neo4j.gds.algorithms.metrics.AlgorithmMetricsService;
import org.neo4j.gds.api.DatabaseId;
import org.neo4j.gds.api.GraphLoaderContext;
import org.neo4j.gds.api.ImmutableGraphLoaderContext;
@@ -72,6 +74,7 @@ public class CommunityProcedureProvider {
private final TerminationFlagService terminationFlagService;
private final UserLogServices userLogServices;
private final UserAccessor userAccessor;
+ private final AlgorithmMetricsService algorithmMetricsService;
public CommunityProcedureProvider(
Log log,
@@ -84,7 +87,8 @@ public CommunityProcedureProvider(
TaskRegistryFactoryService taskRegistryFactoryService,
TerminationFlagService terminationFlagService,
UserLogServices userLogServices,
- UserAccessor userAccessor
+ UserAccessor userAccessor,
+ AlgorithmMetricsService algorithmMetricsService
) {
this.log = log;
this.graphStoreCatalogService = graphStoreCatalogService;
@@ -98,6 +102,7 @@ public CommunityProcedureProvider(
this.terminationFlagService = terminationFlagService;
this.userLogServices = userLogServices;
this.userAccessor = userAccessor;
+ this.algorithmMetricsService = algorithmMetricsService;
}
public CommunityProcedureFacade createCommunityProcedureFacade(Context context) throws ProcedureException {
@@ -121,15 +126,18 @@ public CommunityProcedureFacade createCommunityProcedureFacade(Context context)
var exportBuildersProvider = exporterBuildersProviderService.identifyExportBuildersProvider(graphDatabaseService);
- // algorithm facade
- var communityAlgorithmsFacade = new CommunityAlgorithmsFacade(
+ var algorithmRunner = new BasicAlgorithmRunner(
graphStoreCatalogService,
taskRegistryFactory,
userLogRegistryFactory,
algorithmMemoryValidationService,
+ algorithmMetricsService,
log
);
+ // algorithm facade
+ var communityAlgorithmsFacade = new CommunityAlgorithmsFacade(algorithmRunner);
+
// moar services
var fictitiousGraphStoreEstimationService = new FictitiousGraphStoreEstimationService();
var graphLoaderContext = buildGraphLoaderContext(
diff --git a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/ExtensionBuilder.java b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/ExtensionBuilder.java
index 9e288c0752..1d65744e2e 100644
--- a/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/ExtensionBuilder.java
+++ b/procedures/integration/src/main/java/org/neo4j/gds/procedures/integration/ExtensionBuilder.java
@@ -20,6 +20,7 @@
package org.neo4j.gds.procedures.integration;
import org.neo4j.function.ThrowingFunction;
+import org.neo4j.gds.algorithms.metrics.AlgorithmMetricsService;
import org.neo4j.gds.applications.graphstorecatalog.CatalogBusinessFacade;
import org.neo4j.gds.core.loading.GraphStoreCatalogService;
import org.neo4j.gds.core.utils.progress.ProgressFeatureSettings;
@@ -187,17 +188,19 @@ public void registerExtension() {
*
* @param exporterBuildersProviderService The catalog of writers
* @param businessFacadeDecorator Any checks added across requests
+ * @param algorithmMetricsService
*/
public ThrowingFunction gdsProvider(
ExporterBuildersProviderService exporterBuildersProviderService,
- Optional> businessFacadeDecorator
+ Optional> businessFacadeDecorator,
+ AlgorithmMetricsService algorithmMetricsService
) {
var catalogFacadeProvider = createCatalogFacadeProvider(
exporterBuildersProviderService,
businessFacadeDecorator
);
- var communityProcedureProvider = createCommunityProcedureProvider(exporterBuildersProviderService);
+ var communityProcedureProvider = createCommunityProcedureProvider(exporterBuildersProviderService, algorithmMetricsService);
return new GraphDataScienceProvider(log, catalogFacadeProvider, communityProcedureProvider);
}
@@ -223,7 +226,9 @@ private CatalogFacadeProvider createCatalogFacadeProvider(
);
}
- private CommunityProcedureProvider createCommunityProcedureProvider(ExporterBuildersProviderService exporterBuildersProviderService) {
+ private CommunityProcedureProvider createCommunityProcedureProvider(ExporterBuildersProviderService exporterBuildersProviderService,
+ AlgorithmMetricsService algorithmMetricsService
+ ) {
var algorithmMetaDataSetterService = new AlgorithmMetaDataSetterService();
return new CommunityProcedureProvider(
@@ -237,7 +242,8 @@ private CommunityProcedureProvider createCommunityProcedureProvider(ExporterBuil
taskRegistryFactoryService,
terminationFlagService,
userLogServices,
- userAccessor
+ userAccessor,
+ algorithmMetricsService
);
}
}
diff --git a/settings.gradle b/settings.gradle
index a13a280bb0..2e5cbbf37c 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -19,6 +19,9 @@ project(':algo-common').projectDir = file('algo-common')
include('algo-test')
project(':algo-test').projectDir = file('algo-test')
+include('algorithm-metrics-api')
+project(':algorithm-metrics-api').projectDir = file('algorithm-metrics-api')
+
include('alpha-proc')
project(':alpha-proc').projectDir = file('alpha/alpha-proc')
diff --git a/test-utils/src/main/java/org/neo4j/gds/BaseTest.java b/test-utils/src/main/java/org/neo4j/gds/BaseTest.java
index afb596fb32..93baaf60b9 100644
--- a/test-utils/src/main/java/org/neo4j/gds/BaseTest.java
+++ b/test-utils/src/main/java/org/neo4j/gds/BaseTest.java
@@ -23,6 +23,8 @@
import org.assertj.core.api.Assertions;
import org.intellij.lang.annotations.Language;
import org.junit.jupiter.api.Timeout;
+import org.neo4j.gds.algorithms.metrics.AlgorithmMetricsService;
+import org.neo4j.gds.algorithms.metrics.PassthroughAlgorithmMetricRegistrar;
import org.neo4j.gds.compat.Neo4jProxy;
import org.neo4j.gds.compat.TestLog;
import org.neo4j.gds.core.Settings;
@@ -35,6 +37,11 @@
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Result;
import org.neo4j.graphdb.Transaction;
+import org.neo4j.kernel.api.procedure.GlobalProcedures;
+import org.neo4j.kernel.extension.ExtensionFactory;
+import org.neo4j.kernel.extension.context.ExtensionContext;
+import org.neo4j.kernel.lifecycle.Lifecycle;
+import org.neo4j.kernel.lifecycle.LifecycleAdapter;
import org.neo4j.test.TestDatabaseManagementServiceBuilder;
import org.neo4j.test.extension.ExtensionCallback;
import org.neo4j.test.extension.ImpermanentDbmsExtension;
@@ -86,6 +93,24 @@ protected void configuration(TestDatabaseManagementServiceBuilder builder) {
builder.setConfigRaw(Map.of("unsupported.dbms.debug.trace_cursors", "true"));
testLog = Neo4jProxy.testLog();
builder.setUserLogProvider(new TestLogProvider(testLog));
+
+ // Hacky as hell but will have to do until we make this BaseTest obsolete
+ builder.addExtension(new ExtensionFactory("AlgorithmMetricsServiceExtensionFactory") {
+ @Override
+ public Lifecycle newInstance(ExtensionContext context, Dependencies dependencies) {
+ dependencies.globalProcedures().registerComponent(
+ AlgorithmMetricsService.class,
+ ctx -> new AlgorithmMetricsService(new PassthroughAlgorithmMetricRegistrar()),
+ false
+ );
+ return new LifecycleAdapter();
+ }
+
+ });
+ }
+
+ interface Dependencies {
+ GlobalProcedures globalProcedures();
}
protected long clearDb() {