index_kibana.js (142 lines of code) (raw):

const crypto = require("crypto"); const glob = require("glob"); const execSync = require("child_process").execSync; const path = require("path"); const YAML = require("yaml"); const fs = require("fs"); const { Client } = require("@elastic/elasticsearch"); const client = new Client({ node: process.env.ES || "http://elastic:changeme@localhost:9200", }); const pluginName = (n) => /\/plugins\/(.*?)((\/common)|(\/public)|(\/server)).*/.exec(n)?.[1]; function getCommitData() { const stdout = execSync(`cd kibana && git log -1`, { encoding: "utf8" }); const [, hash, author, date] = /commit (\w+)\nAuthor: (.*)\nDate: (.*)/.exec( stdout ); return { hash, author: author.trim(), date: new Date(date.trim().toString()), }; } function groupBy(list, groupFn) { const map = new Map(); list.forEach((i) => { const group = groupFn(i); // exclude lens itself and invalid entries if (group === 'lens' || !i || !group ) return; if (!map.has(group)) { map.set(group, []); } map.get(group).push(i); }); return map; } function getUsage(commit, searchTerm, usage) { let srcFiles = []; try { srcFiles = execSync(`cd kibana && ag "${searchTerm}" -l ./src/plugins`) .toString("utf8") .split("\n"); } catch (e) {} let xpackFiles = []; try { xpackFiles = execSync(`cd kibana && ag "${searchTerm}" -l ./x-pack/plugins`) .toString("utf8") .split("\n"); } catch (e) {} const srcGroups = groupBy(srcFiles, pluginName); const xpackGroups = groupBy(xpackFiles, pluginName); const srcUsages = [...srcGroups.entries()].map(([id, files]) => ({ commit, usage, name: id, files, occurences: files.length, })); const xpackUsages = [...xpackGroups.entries()].map(([id, files]) => ({ commit, usage, name: `x-pack/${id}`, files, occurences: files.length, })); return [...srcUsages, ...xpackUsages]; } /* Document structure in usages index: Per crawling per pacakge/plugin { date: 2022-08-11..., usage: elastic/charts | lens-plugin | ExploratoryViewEmbeddable name: x-pack/lens | vis_types/timelion, files: [ kibana/src/..., kibana/src/...], occurences: files.length } elastic/charts: Something is imported from the elastic/charts package lens: Something is imported from the lens plugin exploratory_view: The ExploratoryViewEmbeddable component is used somewhere */ function collectUsages() { const commitData = getCommitData(); return [ ...getUsage(commitData, "elastic/charts", 'elastic-charts'), ...getUsage(commitData, "lens-plugin", 'lens'), ...getUsage(commitData, "/lens/", 'lens'), ...getUsage(commitData, "ExploratoryViewEmbeddable", 'exploratory-view'), ]; } (async function () { const usages = collectUsages(); if (fs.existsSync("./result.json")) { fs.rmSync("./result.json"); } fs.writeFileSync("./result.json", JSON.stringify(usages, null, 2)); console.log(`uploading ${usages.length} usages...`); const exists = await client.indices.exists({ index: "usages", }); if (!exists) { await client.indices.create({ index: "usages", mappings: { properties: { occurences: { type: "long", }, files: { type: "keyword", }, name: { type: "keyword", }, usage: { type: "keyword", }, commit: { properties: { hash: { type: "keyword", }, author: { type: "keyword", }, date: { type: "date", }, }, }, }, }, }); } const chunkSize = 250; for (let i = 0; i < usages.length; i += chunkSize) { console.log(`uploading #${i+1} out of ${Math.ceil(usages.length / chunkSize)}`); const chunk = usages.slice(i, i + chunkSize); const response = await client.bulk({ operations: chunk.flatMap((v) => [ { index: { _index: "usages", _id: crypto.randomBytes(16).toString("hex"), }, }, v, ]), }); if (response.errors) { console.log(JSON.stringify(response, null, 2)); throw new Error(); } } await client.indices.refresh({ index: "usages" }); console.log("done"); })();