diff --git a/packages/cli/package.json b/packages/cli/package.json index 8763d0aa2..d6173a24b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -26,6 +26,7 @@ "@rushstack/ts-command-line": "^4.3.13", "@turf/turf": "^5.1.6", "chalk": "^4.0.0", + "git-rev-sync": "^2.0.0", "p-limit": "^2.2.1", "pretty-json-log": "^0.3.1", "proj4": "^2.6.0" diff --git a/packages/cli/src/cli/base.cli.ts b/packages/cli/src/cli/base.cli.ts index 688284b0f..2f8c00b38 100644 --- a/packages/cli/src/cli/base.cli.ts +++ b/packages/cli/src/cli/base.cli.ts @@ -1,8 +1,23 @@ #!/usr/bin/env node import { LogConfig } from '@basemaps/lambda-shared'; import { CommandLineParser } from '@rushstack/ts-command-line'; +import * as gitRev from 'git-rev-sync'; import { PrettyTransform } from 'pretty-json-log'; import 'source-map-support/register'; +import * as ulid from 'ulid'; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const packageJson = require('../../package.json'); + +/** Useful traceability information */ +export const CliInfo: { package: string; version: string; hash: string } = { + package: packageJson.name as string, + version: packageJson.version as string, + hash: packageJson.hash ?? `${gitRev.branch()}@${gitRev.short()}`, +}; + +/** Unique Id for this instance of the cli being run */ +export const CliId = ulid.ulid(); export abstract class BaseCommandLine extends CommandLineParser { verbose = this.defineFlagParameter({ @@ -30,6 +45,10 @@ export abstract class BaseCommandLine extends CommandLineParser { LogConfig.get().level = 'info'; } + const logger = LogConfig.get().child({ id: CliId }); + logger.info(CliInfo, 'CliStart'); + LogConfig.set(logger); + return super.onExecute(); } protected onDefineParameters(): void { diff --git a/packages/cli/src/cli/basemaps/tileset.action.ts b/packages/cli/src/cli/basemaps/tileset.action.ts index 5c7a1cf76..049a9a6e7 100644 --- a/packages/cli/src/cli/basemaps/tileset.action.ts +++ b/packages/cli/src/cli/basemaps/tileset.action.ts @@ -1,8 +1,6 @@ import { CommandLineAction, CommandLineStringParameter, CommandLineIntegerParameter } from '@rushstack/ts-command-line'; -import * as ulid from 'ulid'; export abstract class TileSetBaseAction extends CommandLineAction { - id = ulid.ulid(); tileSet: CommandLineStringParameter; projection: CommandLineIntegerParameter; diff --git a/packages/cli/src/cli/basemaps/tileset.util.ts b/packages/cli/src/cli/basemaps/tileset.util.ts index 9c0c9434a..4e420b4ec 100644 --- a/packages/cli/src/cli/basemaps/tileset.util.ts +++ b/packages/cli/src/cli/basemaps/tileset.util.ts @@ -1,16 +1,16 @@ +import { EPSG } from '@basemaps/geo'; import { Aws, + LogConfig, TileMetadataImageRule, TileMetadataImageryRecord, TileMetadataSetRecord, TileSetTag, - LogConfig, } from '@basemaps/lambda-shared'; +import * as AWS from 'aws-sdk'; import * as c from 'chalk'; +import { CliId } from '../base.cli'; import { CliTable } from '../cli.table'; -import { EPSG } from '@basemaps/geo'; -import * as AWS from 'aws-sdk'; -import * as ulid from 'ulid'; export const TileSetTable = new CliTable<{ rule: TileMetadataImageRule; img: TileMetadataImageryRecord }>(); TileSetTable.field('#', 4, (obj) => String(obj.rule.priority)); @@ -74,7 +74,7 @@ export async function invalidateCache(name: string, projection: EPSG, tag: TileS await cloudFront .createInvalidation({ DistributionId: cf.Id, - InvalidationBatch: { Paths: { Quantity: 1, Items: [path] }, CallerReference: ulid.ulid() }, + InvalidationBatch: { Paths: { Quantity: 1, Items: [path] }, CallerReference: CliId }, }) .promise(); } diff --git a/packages/cli/src/cli/cogify/action.batch.ts b/packages/cli/src/cli/cogify/action.batch.ts index 60e232a7e..9601a3123 100644 --- a/packages/cli/src/cli/cogify/action.batch.ts +++ b/packages/cli/src/cli/cogify/action.batch.ts @@ -11,7 +11,6 @@ import { } from '@basemaps/lambda-shared'; import { CommandLineAction, CommandLineFlagParameter, CommandLineStringParameter } from '@rushstack/ts-command-line'; import * as aws from 'aws-sdk'; -import * as ulid from 'ulid'; import { CogJob } from '../../cog/types'; import { getJobPath } from '../folder'; import { EPSG } from '@basemaps/geo'; @@ -148,10 +147,8 @@ export class ActionBatchJob extends CommandLineAction { if (this.job?.value == null) { throw new Error('Failed to read parameters'); } - const processId = ulid.ulid(); - const logger = LogConfig.get().child({ id: processId }); - await ActionBatchJob.batchJob(this.job.value, this.commit?.value, logger); + await ActionBatchJob.batchJob(this.job.value, this.commit?.value, LogConfig.get()); } static async batchJob(jobPath: string, commit = false, logger: LogType): Promise { diff --git a/packages/cli/src/cli/cogify/action.cog.ts b/packages/cli/src/cli/cogify/action.cog.ts index 2d02d86c7..6246632bd 100644 --- a/packages/cli/src/cli/cogify/action.cog.ts +++ b/packages/cli/src/cli/cogify/action.cog.ts @@ -7,12 +7,12 @@ import { } from '@rushstack/ts-command-line'; import { createReadStream, promises as fs } from 'fs'; import { FeatureCollection } from 'geojson'; -import * as ulid from 'ulid'; import { buildCogForQuadKey } from '../../cog/cog'; import { buildWarpedVrt } from '../../cog/cog.vrt'; import { Cutline } from '../../cog/cutline'; import { QuadKeyVrt } from '../../cog/quadkey.vrt'; import { CogJob } from '../../cog/types'; +import { CliId } from '../base.cli'; import { getJobPath, makeTempFolder } from '../folder'; export class ActionCogCreate extends CommandLineAction { @@ -68,11 +68,10 @@ export class ActionCogCreate extends CommandLineAction { const inFp = FileOperator.create(jobFn); const job = (await inFp.readJson(jobFn)) as CogJob; - const processId = ulid.ulid(); const isCommit = this.commit?.value ?? false; - const logger = LogConfig.get().child({ id: processId, correlationId: job.id, imageryName: job.name }); + const logger = LogConfig.get().child({ correlationId: job.id, imageryName: job.name }); LogConfig.set(logger); const quadKey = this.getQuadKey(job, logger); @@ -90,7 +89,7 @@ export class ActionCogCreate extends CommandLineAction { return; } - const tmpFolder = await makeTempFolder(`basemaps-${job.id}-${processId}`); + const tmpFolder = await makeTempFolder(`basemaps-${job.id}-${CliId}`); try { const sourceGeo = (await inFp.readJson(getJobPath(job, 'source.geojson'))) as FeatureCollection; diff --git a/packages/cli/src/cli/cogify/action.job.ts b/packages/cli/src/cli/cogify/action.job.ts index 7a1b9e33d..8963e917a 100644 --- a/packages/cli/src/cli/cogify/action.job.ts +++ b/packages/cli/src/cli/cogify/action.job.ts @@ -5,9 +5,9 @@ import { CommandLineIntegerParameter, CommandLineStringParameter, } from '@rushstack/ts-command-line'; -import * as ulid from 'ulid'; import { CogJobFactory, JobCreationContext, MaxConcurrencyDefault } from '../../cog/job'; import { GdalCogBuilderDefaults, GdalResamplingOptions } from '../../gdal/gdal.config'; +import { CliId } from '../base.cli'; export class CLiInputData { path: CommandLineStringParameter; @@ -97,7 +97,7 @@ export class ActionJobCreate extends CommandLineAction { override: { concurrency: this.maxConcurrency?.value ?? MaxConcurrencyDefault, quality: this.quality?.value ?? GdalCogBuilderDefaults.quality, - id: this.overrideId?.value ?? ulid.ulid(), + id: this.overrideId?.value ?? CliId, projection: this.sourceProjection?.value, resampling, }, diff --git a/packages/cli/src/cog/job.ts b/packages/cli/src/cog/job.ts index 8d043fece..6ae4be7c7 100644 --- a/packages/cli/src/cog/job.ts +++ b/packages/cli/src/cog/job.ts @@ -14,6 +14,7 @@ import { getTileSize } from './cog'; import { buildVrtForTiffs, VrtOptions } from './cog.vrt'; import { Cutline } from './cutline'; import { CogJob } from './types'; +import { CliInfo } from '../cli/base.cli'; export const MaxConcurrencyDefault = 50; @@ -173,6 +174,10 @@ export const CogJobFactory = { options: { maxConcurrency }, }, quadkeys, + generated: { + ...CliInfo, + date: new Date().toISOString(), + }, }; const tmpFolder = await makeTempFolder(`basemaps-${job.id}`); diff --git a/packages/cli/src/cog/types.ts b/packages/cli/src/cog/types.ts index 00b22ac25..1f4062a27 100644 --- a/packages/cli/src/cog/types.ts +++ b/packages/cli/src/cog/types.ts @@ -54,6 +54,18 @@ export interface CogJob { /** List of quadkeys to generate */ quadkeys: string[]; + + /** How and when this job file was generated */ + generated: { + /** ISO date string */ + date: string; + /** Package name of the generator */ + package: string; + /* Version of the generator */ + version: string; + /** Commit hash of the generator */ + hash: string | undefined; + }; } export interface SourceMetadata {