Skip to main content
Metrics allow you to collect and aggregate data while running codemods. This is useful for:
  • Codebase analysis: Count occurrences of patterns, prop usages, component instances
  • Migration tracking: Track what needs to be migrated before making changes
  • Read-only codemods: Gather insights without modifying code

Basic Usage

Import useMetricAtom from codemod:metrics to create a metric tracker:
import { useMetricAtom } from "codemod:metrics";

const metric = useMetricAtom("my-metric");

// Increment with cardinality dimensions
metric.increment({ category: "buttons", variant: "primary" });

// Increment by a specific amount
metric.increment({ category: "buttons" }, 5);

// Increment without cardinality (simple counter)
metric.increment();

Cardinality

Cardinality dimensions are key-value pairs that let you group and filter metrics. When you call increment(), you pass an object with string keys and values:
metric.increment({
  propName: "className",
  propValue: "container",
  component: "Button"
});
This creates a unique metric entry for each combination of cardinality values. You can later group by any dimension (e.g., all entries where component=Button).
Use cardinality to capture context about what you’re counting. For example, when counting prop usages, include both the prop name and the component it belongs to.

Example: Counting Prop Usage

This read-only codemod counts how many times each prop is used on Button components:
import type { Transform } from "codemod:ast-grep";
import type TSX from "codemod:ast-grep/langs/tsx";
import { useMetricAtom } from "codemod:metrics";

const propUsageMetric = useMetricAtom("prop-usage");

const codemod: Transform<TSX> = async (root) => {
  const rootNode = root.root();

  const jsxAttrs = rootNode.findAll({
    rule: {
      kind: "jsx_attribute",
      inside: {
        any: [
          { kind: "jsx_opening_element" },
          { kind: "jsx_self_closing_element" },
        ],
        has: {
          field: "name",
          kind: "identifier",
          regex: "^Button$"
        },
      },
    },
  });

  for (const attr of jsxAttrs) {
    const name = attr?.find({ rule: { kind: "property_identifier" } });
    const propName = name?.text();
    if (propName) {
      propUsageMetric.increment({ propName });
    }
  }

  return null;
};

export default codemod;
Running this codemod produces output like:
Metrics:
  prop-usage:
    propName=onClick: 42
    propName=className: 38
    propName=disabled: 15
    propName=variant: 12