Skip to content

Commit d0a336d

Browse files
committed
reduce and improve log output for MfovPrealignTask runs, fix bug with Spark parallelism for MfovPrealignTask jobs
1 parent 96e7031 commit d0a336d

File tree

2 files changed

+64
-27
lines changed

2 files changed

+64
-27
lines changed

render-ws-spark-client/src/main/java/org/janelia/render/client/spark/multisem/MFOVASTileClient.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,13 +210,13 @@ private static void alignAndIntensityCorrectMfovAsTileStacks(final JavaSparkCont
210210

211211
if (! mfovTasks.isEmpty()) {
212212

213-
// Note: it takes about 1 minute to process 1 MFOV with 91 SFOV tiles
213+
// Note: it takes about 2 minutes to process 1 MFOV with 91 SFOV tiles
214214
final int parallelism = Math.min(MAX_PARTITIONS_FOR_ONE_WEB_SERVER, mfovTasks.size());
215215

216216
LOG.info("alignAndIntensityCorrectMfovAsTileStacks: distributing {} MFOV tasks across {} stacks with parallelism {} (defaultParallelism={})",
217217
mfovTasks.size(), prealignedStackIds.size(), parallelism, sparkContext.defaultParallelism());
218218

219-
final JavaRDD<MfovPrealignTask> rddMfovTasks = sparkContext.parallelize(mfovTasks);
219+
final JavaRDD<MfovPrealignTask> rddMfovTasks = sparkContext.parallelize(mfovTasks, parallelism);
220220
rddMfovTasks.foreach(MfovPrealignTask::run);
221221

222222
// Complete all prealigned stacks

render-ws-spark-client/src/main/java/org/janelia/render/client/spark/multisem/MfovPrealignTask.java

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,13 @@
4141
import org.janelia.alignment.util.ImageProcessorCache;
4242
import org.janelia.render.client.RenderDataClient;
4343
import org.janelia.render.client.spark.LogUtilities;
44+
import org.slf4j.ILoggerFactory;
4445
import org.slf4j.Logger;
4546
import org.slf4j.LoggerFactory;
4647

48+
import ch.qos.logback.classic.Level;
49+
import ch.qos.logback.classic.LoggerContext;
50+
4751
/**
4852
* Serializable task for aligning SFOVs within a single MFOV.
4953
* This task handles fetching tile specs, deriving matches, optimizing tiles, and saving results.
@@ -69,6 +73,10 @@ public MfovPrealignTask(
6973
this.layerMfov = layerMfov;
7074
}
7175

76+
public String toString() {
77+
return prealignedStackId.toDevString() + "::" + layerMfov;
78+
}
79+
7280
/**
7381
* Align and intensity correct all SFOVs within this MFOV and save the aligned tile specs to the prealigned stack.
7482
* Both alignment and intensity correction are performed by simple translation models.
@@ -79,15 +87,8 @@ public void run()
7987
throws IOException {
8088

8189
final long startTime = System.currentTimeMillis();
82-
83-
// Setup executor log4j for runs at Janelia which will place layerMfovDevString in the %X{context} element.
84-
// For Logs Explorer views of Google Dataproc runs, the context does not seem to be available/selectable
85-
// as a summary field. To work around this limitation, the layerMfovDevString is logged explicitly at
86-
// the entry and exit of this run method. You can then see which executorId maps to layerMfovDevString
87-
// and filter accordingly in Logs Explorer.
88-
final String layerMfovDevString = prealignedStackId.toDevString() + "::" + layerMfov;
89-
LogUtilities.setupExecutorLog4j(layerMfovDevString);
90-
LOG.info("run: entry, layerMfovDevString={}", layerMfovDevString);
90+
setupLogging();
91+
LOG.info("run: entry, {}", this);
9192

9293
final RenderDataClient dataClient = new RenderDataClient(baseDataUrl,
9394
rawSfovStackId.getOwner(),
@@ -97,14 +98,14 @@ public void run()
9798
final ResolvedTileSpecCollection mfovTiles = fetchMfovTileSpecs(dataClient);
9899

99100
if (mfovTiles.getTileCount() == 0) {
100-
throw new IOException("no tile specs found for " + layerMfovDevString);
101+
throw new IOException("no tile specs found for " + this);
101102
}
102103

103104
// 2. Generate tile pairs for matching
104105
final List<OrderedCanvasIdPair> tilePairs = generateTilePairs(mfovTiles);
105106

106107
if (tilePairs.isEmpty()) {
107-
LOG.info("[{}] run: exit, no tile pairs generated", layerMfovDevString);
108+
LOG.info("run: exit, {}, no tile pairs generated", this);
108109
return;
109110
}
110111

@@ -121,21 +122,56 @@ public void run()
121122
dataClient.saveResolvedTiles(alignedIcTiles, prealignedStackId.getStack(), layerMfov.getZ());
122123

123124
final long elapsedSeconds = (System.currentTimeMillis() - startTime) / 1000;
125+
LOG.info("run: exit, {}, elapsedSeconds={}", this, elapsedSeconds);
126+
}
127+
128+
private void setupLogging() {
129+
130+
// remove info messages for these classes to reduce messages logged per MFOV from ~3100 to ~30
131+
final String[] reducedLoggerNames = {
132+
CanvasFeatureExtractor.class.getName(),
133+
CanvasFeatureMatcher.class.getName(),
134+
MatchFilter.class.getName()
135+
};
136+
137+
final ILoggerFactory factory = LoggerFactory.getILoggerFactory();
138+
for (final String loggerName : reducedLoggerNames) {
139+
140+
if (factory instanceof LoggerContext) {
141+
142+
// Janelia Spark clusters use logback
143+
final LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
144+
final ch.qos.logback.classic.Logger logger = loggerContext.getLogger(loggerName);
145+
if (logger == null) {
146+
throw new IllegalArgumentException("logger with name '" + loggerName + "' not found");
147+
}
148+
logger.setLevel(Level.WARN);
149+
150+
} else if ("org.apache.logging.slf4j.Log4jLoggerFactory".equals(factory.getClass().getName())) {
151+
152+
// Google Dataproc Spark clusters use Log4j
153+
org.apache.logging.log4j.core.config.Configurator.setLevel(loggerName,
154+
org.apache.logging.log4j.Level.WARN);
155+
156+
}
157+
}
124158

125-
LOG.info("run: exit, layerMfovDevString={}, elapsedSeconds={}",
126-
layerMfovDevString, elapsedSeconds);
159+
// Setup executor log4j for runs at Janelia which will place layerMfovDevString in the %X{context} element.
160+
// For Logs Explorer views of Google Dataproc runs, the context does not seem to be available/selectable
161+
// as a summary field. To work around this limitation, the layerMfovDevString is logged explicitly
162+
// from methods in this class.
163+
// You can then see which executorId maps to layerMfovDevString and filter accordingly in Logs Explorer.
164+
LogUtilities.setupExecutorLog4j(this.toString());
127165
}
128166

129167
/**
130168
* Fetch tile specs for all SFOVs belonging to this MFOV at the specified z layer.
131169
*/
132170
private ResolvedTileSpecCollection fetchMfovTileSpecs(final RenderDataClient dataClient) throws IOException {
133171
final String matchPattern = "_" + layerMfov.getSimpleMfovName() + "_"; // limit to tiles in this MFOV
134-
final ResolvedTileSpecCollection resolvedTiles = dataClient.getResolvedTiles(rawSfovStackId.getStack(),
135-
layerMfov.getZ(),
136-
matchPattern);
137-
LOG.info("fetchMfovTileSpecs: exit, returning collection with {} tiles", resolvedTiles.getTileCount());
138-
return resolvedTiles;
172+
return dataClient.getResolvedTiles(rawSfovStackId.getStack(),
173+
layerMfov.getZ(),
174+
matchPattern);
139175
}
140176

141177
/**
@@ -162,8 +198,6 @@ private List<OrderedCanvasIdPair> generateTilePairs(final ResolvedTileSpecCollec
162198
}
163199
}
164200

165-
LOG.info("generateTilePairs: exit, returning {} pairs", pairs.size());
166-
167201
return pairs;
168202
}
169203

@@ -176,7 +210,8 @@ private ResolvedTileSpecCollection alignTiles(
176210
final ImageProcessorCache cache
177211
) {
178212

179-
LOG.info("alignTiles: entry");
213+
final long startTime = System.currentTimeMillis();
214+
LOG.info("alignTiles: entry, {}", this);
180215

181216
// Extract features from all mfov tiles
182217
final CanvasFeatureExtractor featureExtractor = CanvasFeatureExtractor.build(FEATURE_EXTRACTION_PARAMETERS);
@@ -218,7 +253,7 @@ private ResolvedTileSpecCollection alignTiles(
218253
}
219254
}
220255

221-
LOG.info("alignTiles: start optimization");
256+
LOG.info("alignTiles: start optimization, {}", this);
222257

223258
// Optimize the tiles
224259
final TileConfiguration tc = new TileConfiguration();
@@ -254,7 +289,9 @@ private ResolvedTileSpecCollection alignTiles(
254289
tiles.addTransformSpecToTile(tileId, newTransformSpec, ResolvedTileSpecCollection.TransformApplicationMethod.REPLACE_LAST);
255290
}
256291

257-
LOG.info("alignTiles: exit, returning collection with {} tiles", tiles.getTileCount());
292+
final long elapsedSeconds = (System.currentTimeMillis() - startTime) / 1000;
293+
LOG.info("alignTiles: exit, {}, returning collection with {} tiles, elapsedSeconds={}",
294+
this, tiles.getTileCount(), elapsedSeconds);
258295

259296
return tiles;
260297
}
@@ -344,7 +381,7 @@ private ResolvedTileSpecCollection intensityCorrectTiles(
344381
final List<OrderedCanvasIdPair> tilePairs,
345382
final ImageProcessorCache cache
346383
) {
347-
LOG.info("intensityCorrectTiles: entry, tile count={}", tiles.getTileCount());
384+
348385
final Map<String, Tile<TranslationModel1D>> modelTiles = new HashMap<>();
349386

350387
// Initialize models for each tile spec
@@ -419,7 +456,7 @@ private ResolvedTileSpecCollection intensityCorrectTiles(
419456
tileSpec.setFilterSpec(filterSpec);
420457
}
421458

422-
LOG.info("intensityCorrectTiles: exit");
459+
LOG.info("intensityCorrectTiles: exit, {}", this);
423460
return tiles;
424461
}
425462

0 commit comments

Comments
 (0)