Add extra prometheus metrics
| ... | ... |
@@ -50,6 +50,7 @@ func NewBuildManager(b builder.Backend) *BuildManager {
|
| 50 | 50 |
|
| 51 | 51 |
// Build starts a new build from a BuildConfig |
| 52 | 52 |
func (bm *BuildManager) Build(ctx context.Context, config backend.BuildConfig) (*builder.Result, error) {
|
| 53 |
+ buildsTriggered.Inc() |
|
| 53 | 54 |
if config.Options.Dockerfile == "" {
|
| 54 | 55 |
config.Options.Dockerfile = builder.DefaultDockerfileName |
| 55 | 56 |
} |
| ... | ... |
@@ -144,6 +145,7 @@ func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*buil |
| 144 | 144 |
addNodesForLabelOption(dockerfile.AST, b.options.Labels) |
| 145 | 145 |
|
| 146 | 146 |
if err := checkDispatchDockerfile(dockerfile.AST); err != nil {
|
| 147 |
+ buildsFailed.WithValues(metricsDockerfileSyntaxError).Inc() |
|
| 147 | 148 |
return nil, err |
| 148 | 149 |
} |
| 149 | 150 |
|
| ... | ... |
@@ -153,12 +155,14 @@ func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*buil |
| 153 | 153 |
} |
| 154 | 154 |
|
| 155 | 155 |
if b.options.Target != "" && !dispatchState.isCurrentStage(b.options.Target) {
|
| 156 |
+ buildsFailed.WithValues(metricsBuildTargetNotReachableError).Inc() |
|
| 156 | 157 |
return nil, errors.Errorf("failed to reach build target %s in Dockerfile", b.options.Target)
|
| 157 | 158 |
} |
| 158 | 159 |
|
| 159 | 160 |
b.warnOnUnusedBuildArgs() |
| 160 | 161 |
|
| 161 | 162 |
if dispatchState.imageID == "" {
|
| 163 |
+ buildsFailed.WithValues(metricsDockerfileEmptyError).Inc() |
|
| 162 | 164 |
return nil, errors.New("No image was generated. Is your Dockerfile empty?")
|
| 163 | 165 |
} |
| 164 | 166 |
return &builder.Result{ImageID: dispatchState.imageID, FromImage: dispatchState.baseImage}, nil
|
| ... | ... |
@@ -181,6 +185,7 @@ func (b *Builder) dispatchDockerfileWithCancellation(dockerfile *parser.Result) |
| 181 | 181 |
case <-b.clientCtx.Done(): |
| 182 | 182 |
logrus.Debug("Builder: build cancelled!")
|
| 183 | 183 |
fmt.Fprint(b.Stdout, "Build cancelled") |
| 184 |
+ buildsFailed.WithValues(metricsBuildCanceled).Inc() |
|
| 184 | 185 |
return nil, errors.New("Build cancelled")
|
| 185 | 186 |
default: |
| 186 | 187 |
// Not cancelled yet, keep going... |
| ... | ... |
@@ -134,6 +134,7 @@ func (b *Builder) dispatch(options dispatchOptions) (*dispatchState, error) {
|
| 134 | 134 |
// To ensure the user is given a decent error message if the platform |
| 135 | 135 |
// on which the daemon is running does not support a builder command. |
| 136 | 136 |
if err := platformSupports(strings.ToLower(cmd)); err != nil {
|
| 137 |
+ buildsFailed.WithValues(metricsCommandNotSupportedError).Inc() |
|
| 137 | 138 |
return nil, err |
| 138 | 139 |
} |
| 139 | 140 |
|
| ... | ... |
@@ -155,6 +156,7 @@ func (b *Builder) dispatch(options dispatchOptions) (*dispatchState, error) {
|
| 155 | 155 |
processFunc := createProcessWordFunc(options.shlex, cmd, envs) |
| 156 | 156 |
words, err := getDispatchArgsFromNode(ast, processFunc, msg) |
| 157 | 157 |
if err != nil {
|
| 158 |
+ buildsFailed.WithValues(metricsErrorProcessingCommandsError).Inc() |
|
| 158 | 159 |
return nil, err |
| 159 | 160 |
} |
| 160 | 161 |
args = append(args, words...) |
| ... | ... |
@@ -163,6 +165,7 @@ func (b *Builder) dispatch(options dispatchOptions) (*dispatchState, error) {
|
| 163 | 163 |
|
| 164 | 164 |
f, ok := evaluateTable[cmd] |
| 165 | 165 |
if !ok {
|
| 166 |
+ buildsFailed.WithValues(metricsUnknownInstructionError).Inc() |
|
| 166 | 167 |
return nil, fmt.Errorf("unknown instruction: %s", upperCasedCmd)
|
| 167 | 168 |
} |
| 168 | 169 |
if err := f(newDispatchRequestFromOptions(options, b, args)); err != nil {
|
| ... | ... |
@@ -283,6 +286,7 @@ func checkDispatch(ast *parser.Node) error {
|
| 283 | 283 |
// least one argument |
| 284 | 284 |
if upperCasedCmd == "ONBUILD" {
|
| 285 | 285 |
if ast.Next == nil {
|
| 286 |
+ buildsFailed.WithValues(metricsMissingOnbuildArgumentsError).Inc() |
|
| 286 | 287 |
return errors.New("ONBUILD requires at least one argument")
|
| 287 | 288 |
} |
| 288 | 289 |
} |
| ... | ... |
@@ -290,6 +294,6 @@ func checkDispatch(ast *parser.Node) error {
|
| 290 | 290 |
if _, ok := evaluateTable[cmd]; ok {
|
| 291 | 291 |
return nil |
| 292 | 292 |
} |
| 293 |
- |
|
| 293 |
+ buildsFailed.WithValues(metricsUnknownInstructionError).Inc() |
|
| 294 | 294 |
return errors.Errorf("unknown instruction: %s", upperCasedCmd)
|
| 295 | 295 |
} |
| 296 | 296 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,44 @@ |
| 0 |
+package dockerfile |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "github.com/docker/go-metrics" |
|
| 4 |
+) |
|
| 5 |
+ |
|
| 6 |
+var ( |
|
| 7 |
+ buildsTriggered metrics.Counter |
|
| 8 |
+ buildsFailed metrics.LabeledCounter |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+// Build metrics prometheus messages, these values must be initialized before |
|
| 12 |
+// using them. See the example below in the "builds_failed" metric definition. |
|
| 13 |
+const ( |
|
| 14 |
+ metricsDockerfileSyntaxError = "dockerfile_syntax_error" |
|
| 15 |
+ metricsDockerfileEmptyError = "dockerfile_empty_error" |
|
| 16 |
+ metricsCommandNotSupportedError = "command_not_supported_error" |
|
| 17 |
+ metricsErrorProcessingCommandsError = "error_processing_commands_error" |
|
| 18 |
+ metricsBuildTargetNotReachableError = "build_target_not_reachable_error" |
|
| 19 |
+ metricsMissingOnbuildArgumentsError = "missing_onbuild_arguments_error" |
|
| 20 |
+ metricsUnknownInstructionError = "unknown_instruction_error" |
|
| 21 |
+ metricsBuildCanceled = "build_canceled" |
|
| 22 |
+) |
|
| 23 |
+ |
|
| 24 |
+func init() {
|
|
| 25 |
+ buildMetrics := metrics.NewNamespace("builder", "", nil)
|
|
| 26 |
+ |
|
| 27 |
+ buildsTriggered = buildMetrics.NewCounter("builds_triggered", "Number of triggered image builds")
|
|
| 28 |
+ buildsFailed = buildMetrics.NewLabeledCounter("builds_failed", "Number of failed image builds", "reason")
|
|
| 29 |
+ for _, r := range []string{
|
|
| 30 |
+ metricsDockerfileSyntaxError, |
|
| 31 |
+ metricsDockerfileEmptyError, |
|
| 32 |
+ metricsCommandNotSupportedError, |
|
| 33 |
+ metricsErrorProcessingCommandsError, |
|
| 34 |
+ metricsBuildTargetNotReachableError, |
|
| 35 |
+ metricsMissingOnbuildArgumentsError, |
|
| 36 |
+ metricsUnknownInstructionError, |
|
| 37 |
+ metricsBuildCanceled, |
|
| 38 |
+ } {
|
|
| 39 |
+ buildsFailed.WithValues(r) |
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ metrics.Register(buildMetrics) |
|
| 43 |
+} |
| ... | ... |
@@ -732,13 +732,15 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe |
| 732 | 732 |
// FIXME: this method never returns an error |
| 733 | 733 |
info, _ := d.SystemInfo() |
| 734 | 734 |
|
| 735 |
- engineVersion.WithValues( |
|
| 735 |
+ engineInfo.WithValues( |
|
| 736 | 736 |
dockerversion.Version, |
| 737 | 737 |
dockerversion.GitCommit, |
| 738 | 738 |
info.Architecture, |
| 739 | 739 |
info.Driver, |
| 740 | 740 |
info.KernelVersion, |
| 741 | 741 |
info.OperatingSystem, |
| 742 |
+ info.OSType, |
|
| 743 |
+ info.ID, |
|
| 742 | 744 |
).Set(1) |
| 743 | 745 |
engineCpus.Set(float64(info.NCPU)) |
| 744 | 746 |
engineMemory.Set(float64(info.MemTotal)) |
| ... | ... |
@@ -12,7 +12,7 @@ var ( |
| 12 | 12 |
containerStates metrics.LabeledGauge |
| 13 | 13 |
imageActions metrics.LabeledTimer |
| 14 | 14 |
networkActions metrics.LabeledTimer |
| 15 |
- engineVersion metrics.LabeledGauge |
|
| 15 |
+ engineInfo metrics.LabeledGauge |
|
| 16 | 16 |
engineCpus metrics.Gauge |
| 17 | 17 |
engineMemory metrics.Gauge |
| 18 | 18 |
healthChecksCounter metrics.Counter |
| ... | ... |
@@ -35,12 +35,14 @@ func init() {
|
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 | 37 |
networkActions = ns.NewLabeledTimer("network_actions", "The number of seconds it takes to process each network action", "action")
|
| 38 |
- engineVersion = ns.NewLabeledGauge("engine", "The version and commit information for the engine process", metrics.Unit("info"),
|
|
| 38 |
+ engineInfo = ns.NewLabeledGauge("engine", "The information related to the engine and the OS it is running on", metrics.Unit("info"),
|
|
| 39 | 39 |
"version", |
| 40 | 40 |
"commit", |
| 41 | 41 |
"architecture", |
| 42 |
- "graph_driver", "kernel", |
|
| 43 |
- "os", |
|
| 42 |
+ "graphdriver", |
|
| 43 |
+ "kernel", "os", |
|
| 44 |
+ "os_type", |
|
| 45 |
+ "daemon_id", // ID is a randomly generated unique identifier (e.g. UUID4) |
|
| 44 | 46 |
) |
| 45 | 47 |
engineCpus = ns.NewGauge("engine_cpus", "The number of cpus that the host system of the engine has", metrics.Unit("cpus"))
|
| 46 | 48 |
engineMemory = ns.NewGauge("engine_memory", "The number of bytes of memory that the host system of the engine has", metrics.Bytes)
|