30-second answer

One slice at a time, read only, into a folder. Start with --dry-run, which prints the command and reaches no tenant.

PowerShell
m365-governance collect sites \
  --client-id <id> \
  --tenant-url https://<tenant>-admin.sharepoint.com \
  --output ./evidence/ \
  --dry-run

Take the --dry-run off when the command reads the way you expect.

Pick the slice by the question you have

Ten of them, and each answers one question. sites is the one to run first: it is the only slice that walks the tenant rather than a single site, so it tells you what there is before you decide what to look at closely.

The full table, with what each one observes and what it cannot see, is in Collectors.

What comes back

One evidence document per resource. A slice that reads many resources writes many files, which is why --output is a directory for most of them.

Before reading any conclusion, read what the collector managed to see:

PowerShell
m365-governance stats ./evidence/site-contoso-marketing.json
Text
COVERAGE
  requested         2  items, permissions
  completed         2  items, permissions

requested against completed is the whole point. They are separate numbers because a collector that set out to read two things and finished one has produced evidence worth one thing, and a report over it is bounded rather than wrong. Where they differ, conclusions drawn across the gap come back unknown rather than being rounded up.

You can watch it happen

A collection reaches a network, and against a large tenant it takes minutes. Each line the collector writes appears as it is written, including the one that tells you how much there is:

Text
  connected as an application identity
  321 sites enumerated by this identity

Nothing is held back until the end, because the only thing separating a working collection from a hung one is what it has told you so far.

It ends in one of four words

And partial is not one of the failures.

StateMeansExit
completedEverything the slice asked for0
partialUsable evidence, incomplete coverage, with the reason0
failedNo usable artefact1
cancelledYou stopped it, and what was written is kept1
Text
2 evidence documents in 41.3s, and the collection is PARTIAL.
  contoso-marketing.json: owners not read (owners: permission-denied — the
  identity is not a site collection administrator)

Evaluating this is valid. Where the gap could change an answer, a rule returns
`unknown` rather than a pass.

A collection that reached part of an estate produced evidence worth exactly that part. Read the state, not the exit code.

It writes down what it did

Beside the evidence, collection-manifest.json, on every path, including the failure that produced no evidence at all, which is precisely the case you cannot reconstruct from an empty folder a month later.

A folder of evidence files is not a collection. It is what a collection left behind, and the two are the same thing only when nothing went wrong. See the collection manifest.

Nothing was written to your tenant

A collector has no write path. Not by policy: by construction, and CI proves it on every release by parsing every file in the collector tree and failing on any mutating verb. On every one of the four paths above, including the failures:

Text
collection failed after 12.4s. Nothing was written to the tenant;
a collector has no write path.

What the collection tells you to do next

It names the profile, rather than leaving the pairing to be guessed:

Text
Evaluate with:  m365-governance evaluate --profile profiles/capacity.yaml --evidence ./evidence/

That matters. Evaluating a collection against the wrong profile produces a wall of unknown for facts nobody asked to be collected, which reads like a broken tenant and is a mismatched pair.

Where to go deeper

  • Collectors: what each slice observes, the permissions it needs and its documented limits.
  • collect: every option, from the executable.
  • Coverage and bounds: what a number is allowed to claim when a collection did not finish.