Signed-off-by: Roberto Gandolfo Hashioka <roberto_hashioka@hotmail.com>
| ... | ... |
@@ -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)
|