diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/Planetiler.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/Planetiler.java index ba9ba66e..2551c1a6 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/Planetiler.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/Planetiler.java @@ -15,6 +15,7 @@ import com.onthegomap.planetiler.reader.osm.OsmReader; import com.onthegomap.planetiler.stats.ProcessInfo; import com.onthegomap.planetiler.stats.Stats; import com.onthegomap.planetiler.stats.Timers; +import com.onthegomap.planetiler.util.BuildInfo; import com.onthegomap.planetiler.util.ByteBufferUtil; import com.onthegomap.planetiler.util.Downloader; import com.onthegomap.planetiler.util.FileUtils; @@ -25,14 +26,11 @@ import com.onthegomap.planetiler.util.ResourceUsage; import com.onthegomap.planetiler.util.Translations; import com.onthegomap.planetiler.util.Wikidata; import com.onthegomap.planetiler.worker.RunnableThatThrows; -import java.io.IOException; import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; -import java.time.Instant; import java.util.ArrayList; import java.util.List; -import java.util.Properties; import java.util.function.Function; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -95,6 +93,7 @@ public class Planetiler { private boolean useWikidata = false; private boolean onlyFetchWikidata = false; private boolean fetchWikidata = false; + private MbtilesMetadata mbtilesMetadata; private Planetiler(Arguments arguments) { this.arguments = arguments; @@ -175,6 +174,10 @@ public class Planetiler { name + "_pass2: Process OpenStreetMap nodes, ways, then relations" ), ifSourceUsed(name, () -> { + var header = osmInputFile.getHeader(); + mbtilesMetadata.set("planetiler:" + name + ":osmosisreplicationtime", header.instant()); + mbtilesMetadata.set("planetiler:" + name + ":osmosisreplicationseq", header.osmosisReplicationSequenceNumber()); + mbtilesMetadata.set("planetiler:" + name + ":osmosisreplicationurl", header.osmosisReplicationBaseUrl()); try ( var nodeLocations = LongLongMap.from(config.nodeMapType(), config.nodeMapStorage(), nodeDbPath, config.nodeMapMadvise()); @@ -499,7 +502,12 @@ public class Planetiler { */ public void run() throws Exception { var showVersion = arguments.getBoolean("version", "show version then exit", false); - printVersionInfoFromManifest(); + var buildInfo = BuildInfo.get(); + if (buildInfo != null && LOGGER.isInfoEnabled()) { + LOGGER.info("Planetiler build git hash: {}", buildInfo.githash()); + LOGGER.info("Planetiler build version: {}", buildInfo.version()); + LOGGER.info("Planetiler build timestamp: {}", buildInfo.buildTimeString()); + } if (showVersion) { System.exit(0); } @@ -516,7 +524,7 @@ public class Planetiler { throw new IllegalArgumentException("Can only run once"); } ran = true; - MbtilesMetadata mbtilesMetadata = new MbtilesMetadata(profile, config.arguments()); + mbtilesMetadata = new MbtilesMetadata(profile, config.arguments()); if (arguments.getBoolean("help", "show arguments then exit", false)) { System.exit(0); @@ -607,22 +615,6 @@ public class Planetiler { stats.close(); } - public static void printVersionInfoFromManifest() { - try (var properties = Planetiler.class.getResourceAsStream("/buildinfo.properties")) { - var parsed = new Properties(); - parsed.load(properties); - LOGGER.info("Planetiler build git hash: {}", parsed.getProperty("githash")); - LOGGER.info("Planetiler build version: {}", parsed.getProperty("version")); - var epochMs = parsed.getProperty("timestamp"); - if (epochMs != null && !epochMs.isBlank() && epochMs.matches("^\\d+$")) { - var time = Instant.ofEpochMilli(Long.parseLong(epochMs)); - LOGGER.info("Planetiler build timestamp: {}", time); - } - } catch (IOException e) { - LOGGER.error("Error getting build properties"); - } - } - private void checkDiskSpace() { ResourceUsage readPhase = new ResourceUsage("read phase disk"); ResourceUsage writePhase = new ResourceUsage("write phase disk"); diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/config/MbtilesMetadata.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/config/MbtilesMetadata.java index 0954a8b8..56fde04b 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/config/MbtilesMetadata.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/config/MbtilesMetadata.java @@ -2,6 +2,9 @@ package com.onthegomap.planetiler.config; import com.onthegomap.planetiler.Profile; import com.onthegomap.planetiler.mbtiles.MbtilesWriter; +import com.onthegomap.planetiler.util.BuildInfo; +import java.util.LinkedHashMap; +import java.util.Map; /** Controls information that {@link MbtilesWriter} will write to the mbtiles metadata table. */ public record MbtilesMetadata( @@ -9,7 +12,8 @@ public record MbtilesMetadata( String description, String attribution, String version, - String type + String type, + Map planetilerSpecific ) { public MbtilesMetadata(Profile profile) { @@ -18,7 +22,8 @@ public record MbtilesMetadata( profile.description(), profile.attribution(), profile.version(), - profile.isOverlay() ? "overlay" : "baselayer" + profile.isOverlay() ? "overlay" : "baselayer", + mapWithBuildInfo() ); } @@ -29,7 +34,32 @@ public record MbtilesMetadata( args.getString("mbtiles_attribution", "'attribution' attribute for mbtiles metadata", profile.attribution()), args.getString("mbtiles_version", "'version' attribute for mbtiles metadata", profile.version()), args.getString("mbtiles_type", "'type' attribute for mbtiles metadata", - profile.isOverlay() ? "overlay" : "baselayer") + profile.isOverlay() ? "overlay" : "baselayer"), + mapWithBuildInfo() ); } + + private static Map mapWithBuildInfo() { + Map result = new LinkedHashMap<>(); + var buildInfo = BuildInfo.get(); + if (buildInfo != null) { + if (buildInfo.version() != null) { + result.put("planetiler:version", buildInfo.version()); + } + if (buildInfo.githash() != null) { + result.put("planetiler:githash", buildInfo.githash()); + } + if (buildInfo.buildTimeString() != null) { + result.put("planetiler:buildtime", buildInfo.buildTimeString()); + } + } + return result; + } + + public MbtilesMetadata set(String key, Object value) { + if (key != null && value != null) { + planetilerSpecific.put(key, value.toString()); + } + return this; + } } diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/mbtiles/MbtilesWriter.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/mbtiles/MbtilesWriter.java index 4f9ccc28..61dbca8c 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/mbtiles/MbtilesWriter.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/mbtiles/MbtilesWriter.java @@ -326,7 +326,7 @@ public class MbtilesWriter { db.createTablesWithIndexes(); } - db.metadata() + var metadata = db.metadata() .setName(mbtilesMetadata.name()) .setFormat("pbf") .setDescription(mbtilesMetadata.description()) @@ -338,6 +338,10 @@ public class MbtilesWriter { .setMaxzoom(config.maxzoom()) .setJson(layerStats.getTileStats()); + for (var entry : mbtilesMetadata.planetilerSpecific().entrySet()) { + metadata.setMetadata(entry.getKey(), entry.getValue()); + } + TileCoord lastTile = null; Timer time = null; int currentZ = Integer.MIN_VALUE; diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/util/BuildInfo.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/util/BuildInfo.java new file mode 100644 index 00000000..e277fcdd --- /dev/null +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/util/BuildInfo.java @@ -0,0 +1,45 @@ +package com.onthegomap.planetiler.util; + +import com.onthegomap.planetiler.Planetiler; +import java.io.IOException; +import java.time.Instant; +import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** Accessor for the build info inserted by maven into the {@code buildinfo.properties} file. */ +public record BuildInfo(String githash, String version, Long buildTime) { + + private static final Logger LOGGER = LoggerFactory.getLogger(BuildInfo.class); + + private static final BuildInfo instance; + static { + BuildInfo result = null; + try (var properties = Planetiler.class.getResourceAsStream("/buildinfo.properties")) { + var parsed = new Properties(); + parsed.load(properties); + String githash = parsed.getProperty("githash"); + String version = parsed.getProperty("version"); + String epochMs = parsed.getProperty("timestamp"); + Long buildTime = null; + + if (epochMs != null && !epochMs.isBlank() && epochMs.matches("^\\d+$")) { + buildTime = Long.parseLong(epochMs); + } + result = new BuildInfo(githash, version, buildTime); + } catch (IOException e) { + LOGGER.error("Error getting build properties"); + } + instance = result; + } + + public String buildTimeString() { + return buildTime == null ? null : Instant.ofEpochMilli(buildTime).toString(); + } + + /** Returns info inserted by maven at build-time into the {@code buildinfo.properties} file. */ + public static BuildInfo get() { + return instance; + } +} diff --git a/planetiler-core/src/test/java/com/onthegomap/planetiler/PlanetilerTests.java b/planetiler-core/src/test/java/com/onthegomap/planetiler/PlanetilerTests.java index faf435b7..87b977bf 100644 --- a/planetiler-core/src/test/java/com/onthegomap/planetiler/PlanetilerTests.java +++ b/planetiler-core/src/test/java/com/onthegomap/planetiler/PlanetilerTests.java @@ -23,6 +23,7 @@ import com.onthegomap.planetiler.reader.osm.OsmElement; import com.onthegomap.planetiler.reader.osm.OsmReader; import com.onthegomap.planetiler.reader.osm.OsmRelationInfo; import com.onthegomap.planetiler.stats.Stats; +import com.onthegomap.planetiler.util.BuildInfo; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -248,6 +249,9 @@ class PlanetilerTests { "center", "0,0,0", "bounds", "-180,-85.05113,180,85.05113" ), results.metadata); + assertSubmap(Map.of( + "planetiler:version", BuildInfo.get().version() + ), results.metadata); assertSameJson( """ { @@ -1683,6 +1687,12 @@ class PlanetilerTests { assertEquals(11, tileMap.size(), "num tiles"); assertEquals(2146, features, "num buildings"); + assertSubmap(Map.of( + "planetiler:version", BuildInfo.get().version(), + "planetiler:osm:osmosisreplicationtime", "2021-04-21T20:21:46Z", + "planetiler:osm:osmosisreplicationseq", "2947", + "planetiler:osm:osmosisreplicationurl", "http://download.geofabrik.de/europe/monaco-updates" + ), db.metadata().getAll()); } }