Browse code

Add extra prometheus metrics - buildsTriggered - buildsFailed - valid options: metricsDockerfileSyntaxError, metricsDockerfileEmptyError, metricsCommandNotSupportedError, metricsErrorProcessingCommandsError, metricsBuildTargetNotReachableError, metricsMissingOnbuildArgumentsError, metricsUnknownInstructionError, metricsBuildCanceled, - engineInfo

Signed-off-by: Roberto Gandolfo Hashioka <roberto_hashioka@hotmail.com>

Roberto Gandolfo Hashioka authored on 2017/04/24 20:32:01
Showing 5 changed files
... ...
@@ -49,6 +49,7 @@ func NewBuildManager(b builder.Backend) *BuildManager {
49 49
 
50 50
 // Build starts a new build from a BuildConfig
51 51
 func (bm *BuildManager) Build(ctx context.Context, config backend.BuildConfig) (*builder.Result, error) {
52
+	buildsTriggered.Inc()
52 53
 	if config.Options.Dockerfile == "" {
53 54
 		config.Options.Dockerfile = builder.DefaultDockerfileName
54 55
 	}
... ...
@@ -141,6 +142,7 @@ func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*buil
141 141
 	addNodesForLabelOption(dockerfile.AST, b.options.Labels)
142 142
 
143 143
 	if err := checkDispatchDockerfile(dockerfile.AST); err != nil {
144
+		buildsFailed.WithValues(metricsDockerfileSyntaxError).Inc()
144 145
 		return nil, err
145 146
 	}
146 147
 
... ...
@@ -150,12 +152,14 @@ func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*buil
150 150
 	}
151 151
 
152 152
 	if b.options.Target != "" && !dispatchState.isCurrentStage(b.options.Target) {
153
+		buildsFailed.WithValues(metricsBuildTargetNotReachableError).Inc()
153 154
 		return nil, errors.Errorf("failed to reach build target %s in Dockerfile", b.options.Target)
154 155
 	}
155 156
 
156 157
 	b.warnOnUnusedBuildArgs()
157 158
 
158 159
 	if dispatchState.imageID == "" {
160
+		buildsFailed.WithValues(metricsDockerfileEmptyError).Inc()
159 161
 		return nil, errors.New("No image was generated. Is your Dockerfile empty?")
160 162
 	}
161 163
 	return &builder.Result{ImageID: dispatchState.imageID, FromImage: dispatchState.baseImage}, nil
... ...
@@ -171,6 +175,7 @@ func (b *Builder) dispatchDockerfileWithCancellation(dockerfile *parser.Result)
171 171
 		case <-b.clientCtx.Done():
172 172
 			logrus.Debug("Builder: build cancelled!")
173 173
 			fmt.Fprint(b.Stdout, "Build cancelled")
174
+			buildsFailed.WithValues(metricsBuildCanceled).Inc()
174 175
 			return nil, errors.New("Build cancelled")
175 176
 		default:
176 177
 			// 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
+}
... ...
@@ -731,13 +731,15 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
731 731
 	// FIXME: this method never returns an error
732 732
 	info, _ := d.SystemInfo()
733 733
 
734
-	engineVersion.WithValues(
734
+	engineInfo.WithValues(
735 735
 		dockerversion.Version,
736 736
 		dockerversion.GitCommit,
737 737
 		info.Architecture,
738 738
 		info.Driver,
739 739
 		info.KernelVersion,
740 740
 		info.OperatingSystem,
741
+		info.OSType,
742
+		info.ID,
741 743
 	).Set(1)
742 744
 	engineCpus.Set(float64(info.NCPU))
743 745
 	engineMemory.Set(float64(info.MemTotal))
... ...
@@ -6,7 +6,7 @@ var (
6 6
 	containerActions          metrics.LabeledTimer
7 7
 	imageActions              metrics.LabeledTimer
8 8
 	networkActions            metrics.LabeledTimer
9
-	engineVersion             metrics.LabeledGauge
9
+	engineInfo                metrics.LabeledGauge
10 10
 	engineCpus                metrics.Gauge
11 11
 	engineMemory              metrics.Gauge
12 12
 	healthChecksCounter       metrics.Counter
... ...
@@ -26,12 +26,14 @@ func init() {
26 26
 		containerActions.WithValues(a).Update(0)
27 27
 	}
28 28
 	networkActions = ns.NewLabeledTimer("network_actions", "The number of seconds it takes to process each network action", "action")
29
-	engineVersion = ns.NewLabeledGauge("engine", "The version and commit information for the engine process", metrics.Unit("info"),
29
+	engineInfo = ns.NewLabeledGauge("engine", "The information related to the engine and the OS it is running on", metrics.Unit("info"),
30 30
 		"version",
31 31
 		"commit",
32 32
 		"architecture",
33
-		"graph_driver", "kernel",
34
-		"os",
33
+		"graphdriver",
34
+		"kernel", "os",
35
+		"os_type",
36
+		"daemon_id", // ID is a randomly generated unique identifier (e.g. UUID4)
35 37
 	)
36 38
 	engineCpus = ns.NewGauge("engine_cpus", "The number of cpus that the host system of the engine has", metrics.Unit("cpus"))
37 39
 	engineMemory = ns.NewGauge("engine_memory", "The number of bytes of memory that the host system of the engine has", metrics.Bytes)