docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    Analytics

    The Editor server reports how the pipeline is used through Unity's editor analytics (EditorAnalytics.SendAnalytic). The data answers questions the package has no other way to answer: whether sessions are interactive or automated, which commands clients actually reach for, how often they fail, how long they take, and how much traffic is raw script eval rather than a concrete command.

    Three things bound what is collected:

    • Editor only. A server running in a development Player reports nothing — EditorAnalytics does not exist there.
    • The editor's own opt-out applies. With analytics disabled in Unity preferences, SendAnalytic does nothing and no event leaves the machine. There is no separate pipeline switch to turn off.
    • Nothing about a command's content is collected. Not its parameters, not the code passed to script eval, not paths, not results.
    • Nothing a project declared about its own commands is collected. Only commands shipped in the package report their name and tags; anything a project declared itself reports <customUserCommand> and no tags — see What is and is not collected.

    Events

    Pipeline_SessionStarted

    Sent once when a client executes its first command, which is the moment the pipeline actually started handling work — not when the Editor launched or the server bound its port.

    Field Meaning
    batchmode The Editor was launched with -batchmode.
    automated The Editor was launched with -automated.
    browserAllowed The server accepts sandboxed browser clients (the limited-CORS path). Off unless enabled in the Pipeline settings.
    dynamicPortAssignation The port was auto-assigned from the server's range rather than pinned in the editor settings.
    hotReloadWatcherEnabled The .cs change watcher is running.

    A session spans a Unity process. The latch lives in SessionState, which survives domain reloads, so a script recompile does not open a second session.

    Pipeline_CommandExecuted

    Sent once per command a client executes.

    Field Meaning
    commandName The command's full name (group name, e.g. asset delete) — but only for commands that ship with the package. A project-declared command reports the literal <customUserCommand> instead.
    commandTags The command's tags, in declaration order — but only for commands that ship with the package. Empty for an untagged command, and always empty for a project-declared one.
    commandSuccess Whether the command succeeded. False both when it threw and when it returned a result carrying its own failure — script eval, script.methodreload reload, script run and test run all report failure the second way.
    commandDuration Milliseconds spent inside the command, excluding the wait for the one-command-at-a-time gate.
    isUserDefinedCommand The command was declared by the project rather than shipped in the package.
    isEval The command is a code evaluation: it carries the scripts/eval tag, as script eval, script eval_file and script run do.
    isEvalWithExistingCommandAvailable Whether the evaluated snippet touches an API that a shipped command already covers — the "you did not need eval for this" signal. Same judgement diagnostics report_evals makes, applied to one invocation: see How the eval-coverage flag is decided.
    commandId The calling client's invocation id, which matches the pipeline_command_id on the unity CLI's own command executed event. One CLI invocation can send several commands, so several events can share an id. 0 when the caller sent none.
    clientSource Who drove the client: human, agent, ci or unknown. Empty when the caller sent none.
    clientName Which AI client family drove the client (claude, cursor, …), or none. Empty when the caller sent none.

    See Caller context for how a client supplies these.

    What counts as one execution:

    • One event per /api/exec call, including a job: true submission — reported when the job actually finishes, not when its job handle is returned.
    • A job batch reports one event, for job batch itself. Its sub-operations are not reported individually.
    • A request rejected before anything ran (oversized body, malformed JSON, unknown command, settling host, full job queue) reports nothing: no command executed.
    • The internal executions behind /api/editor_status and /api/test-status report nothing. Clients poll those endpoints, and the polling would swamp everything else.

    Pipeline_SessionStopped

    Sent when the Editor quits, and only if Pipeline_SessionStarted was sent — an Editor that never served a command closes no session.

    Field Meaning
    sessionDuration Milliseconds between the session starting and the Editor quitting.

    How the eval-coverage flag is decided

    isEvalWithExistingCommandAvailable reuses the eval instrumentation from AUTHAPI-29 rather than inventing a second opinion. Per invocation:

    1. EvalUsageFingerprinter.Analyze turns the snippet into API fingerprints — dotted member-access paths, with no literals or raw source in them.
    2. Each fingerprint is looked up in EvalCoverageMap.Default, a small curated hint map from API to the command that would cover it.
    3. The flag is true only if a mapped command is actually in the live catalog. A mapping to a command that does not exist yet (AssetDatabase.Refresh → asset.refresh) is a gap for diagnostics report_evals to surface, not an avoidable eval.

    This is deliberately the same rule as diagnostics report_evals' covered list, so the two can never disagree. Two consequences worth knowing when reading the data:

    • It is a floor, not a measure. The map has a handful of entries and matching is on the whole fingerprint, so PlayerSettings.GetScriptingBackend(...) matches while UnityEditor.PlayerSettings.GetScriptingBackend(...) and PlayerSettings.GetScriptingBackend(...).ToString() do not — they fingerprint as different paths. A false means "no mapped-and-present command matched", never "no command could cover this".
    • script run always reports false. It runs a project file through a named entry point rather than a snippet, and the fingerprinter parses script-kind bodies, so it is not fingerprinted. script eval (inline body) and script eval_file (body read back from its file) are judged.

    What is and is not collected

    A command's name (its group and name) and tags are text the project's own authors wrote, so either can name an unannounced feature or an internal system. Tags are constrained in shape (^[a-z0-9_]+(/[a-z0-9_]+)*$) and shipped commands must use the documented taxonomy, but nothing holds a project to it, so a tag carries a project-chosen word exactly as a name does.

    So both are withheld. commandName and commandTags describe only commands that ship in the package (Unity.Pipeline, Unity.Pipeline.Editor); every other [CliGroupCommand] reports the literal <customUserCommand> and an empty tag array. The remaining fields — success, duration, isEval — are facts about the execution, not about what the project called it, so they are reported for every command.

    What this costs: project-declared traffic is countable but not breakable down by area. That is the deliberate trade — isUserDefinedCommand answers how much of the surface is project-declared, which is the question worth asking, and nothing identifying is needed to answer it.

    Command arguments are never collected. Neither is anything a command reads or writes.

    Adding post-command work

    Analytics is one consumer of a single seam rather than a special case. When a command that ran ends, synchronous or a detached job, the executor's OnCommandEnded receives a CommandExecutionInfo describing the execution. It runs on whatever thread the command ended on, so EditorCommandExecutor hands it to the server dispatcher with Dispatcher.Post, which runs it in ReportOnMainThread on the next main-thread pump. The raw transaction goes to the HTTP transport instead: BasePipelineServer.OnCommandDone receives it on the HTTP thread, and EditorPipelineServer appends it to the transaction log there (thread-safe file I/O by design).

    New post-command work goes in ReportOnMainThread when it needs Unity APIs, in OnCommandEnded when it doesn't, and in OnCommandDone only when it is about the HTTP transaction. Post is the general fire-and-forget counterpart to Dispatcher.Invoke: it returns immediately instead of parking the request thread until the next pump, and swallows-and-logs failures because there is no caller left to throw to. Work still queued when the server stops is dropped, so a report can be lost in the frame the Editor quits or reloads its domain.

    See also

    • Creating commands — where a command's name and tags come from.
    • Connectivity — the port and CORS settings the session event reports.
    • Method reload — the watcher whose state the session event reports.
    In This Article
    Back to top
    Copyright © 2026 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)