diff --git a/doc/source/admin/monitoring.rst b/doc/source/admin/monitoring.rst index 2a6c959abe..9c69960884 100644 --- a/doc/source/admin/monitoring.rst +++ b/doc/source/admin/monitoring.rst @@ -31,63 +31,101 @@ Your init script most probably loads a configuration file named Metrics ~~~~~~~ -The metrics are emitted by the Zuul scheduler (`zuul/scheduler.py`): +The metrics are emitted by the Zuul :ref:`scheduler`: -**gerrit.event. (counters)** - Gerrit emits different kind of message over its `stream-events` - interface. Zuul will report counters for each type of event it - receives from Gerrit. +.. stat:: gerrit.event. + :type: counter - Some of the events emitted are: + Gerrit emits different kind of message over its `stream-events` + interface. Zuul will report counters for each type of event it + receives from Gerrit. - * patchset-created - * draft-published - * change-abandonned - * change-restored - * change-merged - * merge-failed - * comment-added - * ref-updated - * reviewer-added + Refer to your Gerrit installation documentation for a complete + list of Gerrit event types. - Refer to your Gerrit installation documentation for an exhaustive list of - Gerrit event types. +.. stat:: zuul.pipeline -**zuul.pipeline.** - Holds metrics specific to jobs. The hierarchy is: + Holds metrics specific to jobs. This hierarchy includes: - #. **** as defined in your `layout.yaml` file (ex: `gate`, - `test`, `publish`). It contains: + .. stat:: - #. **all_jobs** counter of jobs triggered by the pipeline. - #. **current_changes** A gauge for the number of Gerrit changes being - processed by this pipeline. - #. **job** subtree detailing per jobs statistics: + A set of metrics for each pipeline named as defined in the Zuul + config. - #. **** The triggered job name. - #. **** Result as defined in your triggering system. For - Jenkins that would be SUCCESS, FAILURE, UNSTABLE, LOST. The - metrics holds both an increasing counter and a timing - reporting the duration of the build. Whenever the result is a - SUCCESS or FAILURE, Zuul will additionally report the duration - of the build as a timing event. + .. stat:: all_jobs + :type: counter - #. **resident_time** timing representing how long the Change has been - known by Zuul (which includes build time and Zuul overhead). - #. **total_changes** counter of the number of change proceeding since - Zuul started. - #. **wait_time** counter and timer of the wait time, with the difference - of the job start time and the execute time, in milliseconds. + Number of jobs triggered by the pipeline. - Additionally, the `zuul.pipeline.` hierarchy contains - `current_changes` (gauge), `resident_time` (timing) and `total_changes` - (counter) metrics for each projects. The slash separator used in Gerrit name - being replaced by dots. + .. stat:: current_changes + :type: gauge - As an example, given a job named `myjob` triggered by the `gate` pipeline - which took 40 seconds to build, the Zuul scheduler will emit the following - statsd events: + The number of items currently being processed by this + pipeline. - * `zuul.pipeline.gate.job.myjob.SUCCESS` +1 - * `zuul.pipeline.gate.job.myjob` 40 seconds - * `zuul.pipeline.gate.all_jobs` +1 + .. stat:: job + + Subtree detailing per jobs statistics: + + .. stat:: + + The triggered job name. + + .. stat:: + :type: counter, timer + + A counter for each type of result (e.g., ``SUCCESS`` or + ``FAILURE``, ``ERROR``, etc.) for the job. If the + result is ``SUCCESS`` or ``FAILURE``, Zuul will + additionally report the duration of the build as a + timer. + + .. stat:: resident_time + :type: timer + + A timer metric reporting how long each item has been in the + pipeline. + + .. stat:: total_changes + :type: counter + + The number of change processed by the pipeline since Zuul + started. + + .. stat:: wait_time + :type: timer + + How long each item spent in the pipeline before its first job + started. + + .. stat:: + + This hierarchy holds more specific metrics for each project + participating in the pipeline. If the project name contains + a ``/`` character, it will be replaced with a ``.``. + + .. stat:: current_changes + :type: gauge + + The number of items of this project currently being + processed by this pipeline. + + .. stat:: resident_time + :type: timer + + A timer metric reporting how long each item for this + project has been in the pipeline. + + .. stat:: total_changes + :type: counter + + The number of change for this project processed by the + pipeline since Zuul started. + +As an example, given a job named `myjob` triggered by the `gate` pipeline +which took 40 seconds to build, the Zuul scheduler will emit the following +statsd events: + + * ``zuul.pipeline.gate.job.myjob.SUCCESS`` +1 + * ``zuul.pipeline.gate.job.myjob`` 40 seconds + * ``zuul.pipeline.gate.all_jobs`` +1 diff --git a/zuul/sphinx/zuul.py b/zuul/sphinx/zuul.py index b6aca6cdac..bbd03e9051 100644 --- a/zuul/sphinx/zuul.py +++ b/zuul/sphinx/zuul.py @@ -166,6 +166,44 @@ class ZuulVarDirective(ZuulConfigObject): return sig +class ZuulStatDirective(ZuulConfigObject): + has_content = True + + option_spec = { + 'type': lambda x: x, + 'hidden': lambda x: x, + 'noindex': lambda x: x, + } + + def before_content(self): + path = self.env.ref_context.setdefault('zuul:attr_path', []) + element = self.names[-1] + path.append(element) + path = self.env.ref_context.setdefault('zuul:display_attr_path', []) + element = self.names[-1] + path.append(element) + + def after_content(self): + path = self.env.ref_context.get('zuul:attr_path') + if path: + path.pop() + path = self.env.ref_context.get('zuul:display_attr_path') + if path: + path.pop() + + def handle_signature(self, sig, signode): + if 'hidden' in self.options: + return sig + path = self.get_display_path() + for x in path: + signode += addnodes.desc_addname(x + '.', x + '.') + signode += addnodes.desc_name(sig, sig) + if 'type' in self.options: + t = ' (%s)' % self.options['type'] + signode += addnodes.desc_annotation(t, t) + return sig + + class ZuulDomain(Domain): name = 'zuul' label = 'Zuul' @@ -174,6 +212,7 @@ class ZuulDomain(Domain): 'attr': ZuulAttrDirective, 'value': ZuulValueDirective, 'var': ZuulVarDirective, + 'stat': ZuulStatDirective, } roles = { @@ -183,6 +222,8 @@ class ZuulDomain(Domain): warn_dangling=True), 'var': XRefRole(innernodeclass=nodes.inline, # type: ignore warn_dangling=True), + 'stat': XRefRole(innernodeclass=nodes.inline, # type: ignore + warn_dangling=True), } initial_data = {