Skip to content

Commit

Permalink
Add 'IdentifierRegistry' mechanism for debugging IDs
Browse files Browse the repository at this point in the history
Whenever an ID is generated, we will optionally log it to a file with the data
used to generate it.

This will help us debug generated identifiers on artefacts or runtime errors.

Test Plan: N/A

Pull Request: #333
  • Loading branch information
yamadapc committed Feb 11, 2025
1 parent 10a6f37 commit a55a54a
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 11 deletions.
5 changes: 4 additions & 1 deletion packages/core/core/src/Dependency.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
import {toInternalSourceLocation} from './utils';
import {toProjectPath} from './projectPath';
import assert from 'assert';
import {identifierRegistry} from './IdentifierRegistry';

type DependencyOpts = {|
id?: string,
Expand Down Expand Up @@ -80,7 +81,9 @@ export function createDependencyId({
priority: priority ? Priority[priority] : Priority.sync,
packageConditions,
};
return createDependencyIdRust(params);
const id = createDependencyIdRust(params);
identifierRegistry.addIdentifier('dependency', id, params);
return id;
}

export function createDependency(
Expand Down
8 changes: 6 additions & 2 deletions packages/core/core/src/Environment.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {createEnvironmentId} from '@atlaspack/rust';
import {toInternalSourceLocation} from './utils';
import PublicEnvironment from './public/Environment';
import {environmentToInternalEnvironment} from './public/Environment';
import {identifierRegistry} from './IdentifierRegistry';

const DEFAULT_ENGINES = {
browsers: ['> 0.25%'],
Expand Down Expand Up @@ -137,7 +138,7 @@ export function mergeEnvironments(
}

function getEnvironmentHash(env: Environment): string {
return createEnvironmentId({
const data = {
context: env.context,
engines: env.engines,
includeNodeModules: env.includeNodeModules,
Expand All @@ -147,5 +148,8 @@ function getEnvironmentHash(env: Environment): string {
shouldOptimize: env.shouldOptimize,
shouldScopeHoist: env.shouldScopeHoist,
sourceMap: env.sourceMap,
});
};
const id = createEnvironmentId(data);
identifierRegistry.addIdentifier('environment', id, data);
return id;
}
32 changes: 32 additions & 0 deletions packages/core/core/src/IdentifierRegistry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// @flow strict-local

import fs from 'fs';

export class IdentifierRegistry {
#enabled: boolean;
#createdDirectory: boolean = false;

constructor(enabled: boolean) {
this.#enabled = enabled;
}

addIdentifier(type: string, identifier: string, data: mixed) {
if (this.#enabled) {
if (!this.#createdDirectory) {
fs.mkdirSync('./.atlaspack', {recursive: true});
this.#createdDirectory = true;
}

fs.appendFile(
'./.atlaspack/atlaspack-identifiers.txt',
// $FlowFixMe
`${type} ${identifier} ${JSON.stringify(data)}\n`,
() => {},
);
}
}
}

export const identifierRegistry: IdentifierRegistry = new IdentifierRegistry(
process.env.ATLASPACK_IDENTIFIER_DEBUG === 'true',
);
8 changes: 6 additions & 2 deletions packages/core/core/src/assetUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
import {hashString, createAssetId as createAssetIdRust} from '@atlaspack/rust';
import {BundleBehavior as BundleBehaviorMap} from './types';
import {PluginTracer} from '@atlaspack/profiler';
import {identifierRegistry} from './IdentifierRegistry';

export type AssetOptions = {|
id?: string,
Expand Down Expand Up @@ -69,15 +70,18 @@ export type AssetOptions = {|
|};

export function createAssetIdFromOptions(options: AssetOptions): string {
return createAssetIdRust({
const data = {
environmentId: options.env.id,
filePath: options.filePath,
code: options.code,
pipeline: options.pipeline,
query: options.query,
uniqueKey: options.uniqueKey,
fileType: options.type,
});
};
const id = createAssetIdRust(data);
identifierRegistry.addIdentifier('asset', id, data);
return id;
}

export function createAsset(
Expand Down
30 changes: 24 additions & 6 deletions packages/core/core/src/public/MutableBundleGraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ import {HASH_REF_PREFIX} from '../constants';
import {fromProjectPathRelative} from '../projectPath';
import {BundleBehavior} from '../types';
import BundleGroup, {bundleGroupToInternalBundleGroup} from './BundleGroup';
import type {ProjectPath} from '../projectPath';
import {identifierRegistry} from '../IdentifierRegistry';

function createBundleId(data: {|
entryAssetId: string | null,
uniqueKey: string | null,
distDir: ProjectPath,
bundleBehavior: string | null,
|}): string {
const {entryAssetId, uniqueKey, distDir, bundleBehavior} = data;
const id = hashString(
`bundle:${String(
entryAssetId != null ? entryAssetId : uniqueKey,
)}${fromProjectPathRelative(distDir)}${bundleBehavior ?? ''}`,
);
identifierRegistry.addIdentifier('bundle', id, data);
return id;
}

export default class MutableBundleGraph
extends BundleGraph<IBundle>
Expand Down Expand Up @@ -181,12 +199,12 @@ export default class MutableBundleGraph
: null;

let target = targetToInternalTarget(opts.target);
let bundleId = hashString(
'bundle:' +
(opts.entryAsset ? opts.entryAsset.id : opts.uniqueKey) +
fromProjectPathRelative(target.distDir) +
(opts.bundleBehavior ?? ''),
);
let bundleId = createBundleId({
entryAssetId: entryAsset?.id ?? null,
uniqueKey: opts.uniqueKey ?? null,
distDir: target.distDir,
bundleBehavior: opts.bundleBehavior ?? null,
});

let existing = this.#graph._graph.getNodeByContentKey(bundleId);
if (existing != null) {
Expand Down
64 changes: 64 additions & 0 deletions packages/core/core/test/IdentifierRegistry.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// @flow strict-local

import assert from 'assert';
import fs from 'fs';
import sinon from 'sinon';
import {IdentifierRegistry} from '../src/IdentifierRegistry';

describe('IdentifierRegistry', () => {
let mkdirSyncStub;
let fsStub;

beforeEach(() => {
mkdirSyncStub = sinon.stub(fs, 'mkdirSync');
fsStub = sinon.stub(fs, 'appendFile');
});

afterEach(() => {
mkdirSyncStub.restore();
fsStub.restore();
});

it("does nothing if the identifers flag isn't set", () => {
const identifierRegistry = new IdentifierRegistry(false);
identifierRegistry.addIdentifier('type', 'identifier', 'data');
assert(!mkdirSyncStub.called);
assert(!fsStub.called);
});

it('appends the identifier to the file', () => {
const identifierRegistry = new IdentifierRegistry(true);
identifierRegistry.addIdentifier('type', 'identifier', 'data');
assert(
fsStub.calledWith(
'./.atlaspack/atlaspack-identifiers.txt',
'type identifier "data"\n',
sinon.match.func,
),
);
});

it('only creates the directory once', () => {
const identifierRegistry = new IdentifierRegistry(true);
identifierRegistry.addIdentifier('type', 'identifier', '1');
identifierRegistry.addIdentifier('type', 'identifier', '2');

assert(mkdirSyncStub.calledOnce);

assert(mkdirSyncStub.calledWith('./.atlaspack', {recursive: true}));
assert(
fsStub.calledWith(
'./.atlaspack/atlaspack-identifiers.txt',
'type identifier "1"\n',
sinon.match.func,
),
);
assert(
fsStub.calledWith(
'./.atlaspack/atlaspack-identifiers.txt',
'type identifier "2"\n',
sinon.match.func,
),
);
});
});

0 comments on commit a55a54a

Please sign in to comment.