(PUP-2747) Add support for multiple profilers

This commit makes a slight modification to the profiling system,
such that we can register multiple profilers at the same time.

This allows callers to register their own profiler without
worrying about collisions with profilers that might have
been registered by other parts of the code.
(PUP-2750) Add hierarchical metric ids to profiler

This commit modifies the signature of the
`Puppet::Util::Profiler.profile` method to accept a new argument,
which is basically a "metric id".  The argument takes the form
of an array of strings/symbols, allowing us to group specific sets of
profiling data into hierarchies and report aggregate profiling
statistics at any level of the hierarchy.

It also adds a new profiler, `Aggregate`, which extends the
existing `WallClock` profiler.  The new profiler tracks the
aggregate timing data based on the metric id hierarchy,
and logs a message containing the aggregate data
at the end of the run.