@atomist/sdm-pack-aspect
Version:
an Atomist SDM Extension Pack for visualizing drift across an organization
85 lines (77 loc) • 3.02 kB
text/typescript
/*
* Copyright © 2019 Atomist, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { FP } from "@atomist/sdm-pack-fingerprint";
import * as _ from "lodash";
import {
FingerprintKind,
ProjectAnalysisResultStore,
} from "../persist/ProjectAnalysisResultStore";
/**
* Retrieve all fingerprints, then compute and store fingerprint_analytics for the whole workspace
*/
export async function computeAnalytics(persister: ProjectAnalysisResultStore, workspaceId: string): Promise<void> {
const allFingerprints = await persister.fingerprintsInWorkspace(workspaceId, false);
const fingerprintKinds = await persister.distinctFingerprintKinds(workspaceId);
const persistThese = fingerprintKinds.map((kind: FingerprintKind) => {
const fingerprintsOfKind = allFingerprints.filter(f => f.type === kind.type && f.name === kind.name);
const cohortAnalysis = analyzeCohort(fingerprintsOfKind);
return { workspaceId, kind, cohortAnalysis };
});
await persister.persistAnalytics(persistThese);
}
/**
* Calculate and persist entropy for one fingerprint kind
*/
export async function computeAnalyticsForFingerprintKind(persister: ProjectAnalysisResultStore,
workspaceId: string,
type: string,
name: string): Promise<void> {
const fingerprints = await persister.fingerprintsInWorkspace(workspaceId, false, type, name);
if (fingerprints.length === 0) {
return;
}
const cohortAnalysis = analyzeCohort(fingerprints);
await persister.persistAnalytics([{ workspaceId, kind: { type, name }, cohortAnalysis }]);
}
/**
* Result of analyzing a cohort of fingerprints.
*/
export interface CohortAnalysis {
count: number;
variants: number;
entropy: number;
compliance: number;
}
/**
* Analyze a cohort of the same kind of fingerprints
*/
export function analyzeCohort(fps: FP[]): CohortAnalysis {
const groups: Record<string, FP[]> = _.groupBy(fps, fp => fp.sha);
const count: number = fps.length;
const entropy = -1 * Object.values(groups).reduce(
(agg, fp: FP[]) => {
const p: number = fp.length / count;
return agg + p * Math.log(p);
},
0,
);
return {
entropy,
variants: Object.values(groups).length,
count,
compliance: undefined,
};
}