blob: 1ded9ca4681bc8d24cbfa1f4a58d6d3c739d286f [file] [log] [blame]
Dan Willemsenb82471a2018-05-17 16:37:09 -07001// Copyright 2018 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package status
16
17import (
Dan Willemsenb82471a2018-05-17 16:37:09 -070018 "compress/gzip"
Patrice Arruda297ceba2019-06-06 16:44:37 -070019 "errors"
Dan Willemsenb82471a2018-05-17 16:37:09 -070020 "fmt"
21 "io"
Patrice Arruda297ceba2019-06-06 16:44:37 -070022 "io/ioutil"
Patrice Arruda36b5e312020-03-11 12:41:47 -070023 "os"
Dan Willemsenb82471a2018-05-17 16:37:09 -070024 "strings"
Patrice Arruda297ceba2019-06-06 16:44:37 -070025
26 "github.com/golang/protobuf/proto"
27
28 "android/soong/ui/logger"
29 "android/soong/ui/status/build_error_proto"
Dan Willemsenb82471a2018-05-17 16:37:09 -070030)
31
32type verboseLog struct {
33 w io.WriteCloser
34}
35
36func NewVerboseLog(log logger.Logger, filename string) StatusOutput {
37 if !strings.HasSuffix(filename, ".gz") {
38 filename += ".gz"
39 }
40
41 f, err := logger.CreateFileWithRotation(filename, 5)
42 if err != nil {
43 log.Println("Failed to create verbose log file:", err)
44 return nil
45 }
46
47 w := gzip.NewWriter(f)
48
49 return &verboseLog{
50 w: w,
51 }
52}
53
54func (v *verboseLog) StartAction(action *Action, counts Counts) {}
55
56func (v *verboseLog) FinishAction(result ActionResult, counts Counts) {
57 cmd := result.Command
58 if cmd == "" {
59 cmd = result.Description
60 }
61
62 fmt.Fprintf(v.w, "[%d/%d] %s\n", counts.FinishedActions, counts.TotalActions, cmd)
63
64 if result.Error != nil {
65 fmt.Fprintf(v.w, "FAILED: %s\n", strings.Join(result.Outputs, " "))
66 }
67
68 if result.Output != "" {
69 fmt.Fprintln(v.w, result.Output)
70 }
71}
72
73func (v *verboseLog) Flush() {
74 v.w.Close()
75}
76
77func (v *verboseLog) Message(level MsgLevel, message string) {
78 fmt.Fprintf(v.w, "%s%s\n", level.Prefix(), message)
79}
80
Colin Crosse0df1a32019-06-09 19:40:08 -070081func (v *verboseLog) Write(p []byte) (int, error) {
82 fmt.Fprint(v.w, string(p))
83 return len(p), nil
84}
85
Dan Willemsenb82471a2018-05-17 16:37:09 -070086type errorLog struct {
Patrice Arruda297ceba2019-06-06 16:44:37 -070087 w io.WriteCloser
Dan Willemsenb82471a2018-05-17 16:37:09 -070088 empty bool
89}
90
91func NewErrorLog(log logger.Logger, filename string) StatusOutput {
92 f, err := logger.CreateFileWithRotation(filename, 5)
93 if err != nil {
94 log.Println("Failed to create error log file:", err)
95 return nil
96 }
97
98 return &errorLog{
99 w: f,
100 empty: true,
101 }
102}
103
104func (e *errorLog) StartAction(action *Action, counts Counts) {}
105
106func (e *errorLog) FinishAction(result ActionResult, counts Counts) {
107 if result.Error == nil {
108 return
109 }
110
Dan Willemsenb82471a2018-05-17 16:37:09 -0700111 if !e.empty {
112 fmt.Fprintf(e.w, "\n\n")
113 }
114 e.empty = false
115
116 fmt.Fprintf(e.w, "FAILED: %s\n", result.Description)
Patrice Arruda297ceba2019-06-06 16:44:37 -0700117
Dan Willemsenb82471a2018-05-17 16:37:09 -0700118 if len(result.Outputs) > 0 {
119 fmt.Fprintf(e.w, "Outputs: %s\n", strings.Join(result.Outputs, " "))
120 }
Patrice Arruda297ceba2019-06-06 16:44:37 -0700121
Dan Willemsenb82471a2018-05-17 16:37:09 -0700122 fmt.Fprintf(e.w, "Error: %s\n", result.Error)
123 if result.Command != "" {
124 fmt.Fprintf(e.w, "Command: %s\n", result.Command)
125 }
126 fmt.Fprintf(e.w, "Output:\n%s\n", result.Output)
127}
128
129func (e *errorLog) Flush() {
130 e.w.Close()
131}
132
133func (e *errorLog) Message(level MsgLevel, message string) {
134 if level < ErrorLvl {
135 return
136 }
137
138 if !e.empty {
139 fmt.Fprintf(e.w, "\n\n")
140 }
141 e.empty = false
142
143 fmt.Fprintf(e.w, "error: %s\n", message)
144}
Colin Crosse0df1a32019-06-09 19:40:08 -0700145
146func (e *errorLog) Write(p []byte) (int, error) {
147 fmt.Fprint(e.w, string(p))
148 return len(p), nil
149}
Patrice Arruda297ceba2019-06-06 16:44:37 -0700150
151type errorProtoLog struct {
152 errorProto soong_build_error_proto.BuildError
153 filename string
154 log logger.Logger
155}
156
157func NewProtoErrorLog(log logger.Logger, filename string) StatusOutput {
Patrice Arruda36b5e312020-03-11 12:41:47 -0700158 os.Remove(filename)
Patrice Arruda297ceba2019-06-06 16:44:37 -0700159 return &errorProtoLog{
160 errorProto: soong_build_error_proto.BuildError{},
161 filename: filename,
162 log: log,
163 }
164}
165
166func (e *errorProtoLog) StartAction(action *Action, counts Counts) {}
167
168func (e *errorProtoLog) FinishAction(result ActionResult, counts Counts) {
169 if result.Error == nil {
170 return
171 }
172
173 e.errorProto.ActionErrors = append(e.errorProto.ActionErrors, &soong_build_error_proto.BuildActionError{
174 Description: proto.String(result.Description),
175 Command: proto.String(result.Command),
176 Output: proto.String(result.Output),
177 Artifacts: result.Outputs,
178 Error: proto.String(result.Error.Error()),
179 })
180}
181
182func (e *errorProtoLog) Flush() {
Patrice Arruda36b5e312020-03-11 12:41:47 -0700183 // Don't create the build error proto file if there is action errors.
184 if len(e.errorProto.ActionErrors) == 0 {
185 return
186 }
187
Patrice Arruda297ceba2019-06-06 16:44:37 -0700188 data, err := proto.Marshal(&e.errorProto)
189 if err != nil {
Colin Crossff27ce42019-11-26 16:20:03 -0800190 e.log.Printf("Failed to marshal build status proto: %v\n", err)
Patrice Arruda297ceba2019-06-06 16:44:37 -0700191 return
192 }
Patrice Arruda36b5e312020-03-11 12:41:47 -0700193
Patrice Arruda297ceba2019-06-06 16:44:37 -0700194 err = ioutil.WriteFile(e.filename, []byte(data), 0644)
195 if err != nil {
Colin Crossff27ce42019-11-26 16:20:03 -0800196 e.log.Printf("Failed to write file %s: %v\n", e.filename, err)
Patrice Arruda297ceba2019-06-06 16:44:37 -0700197 }
198}
199
200func (e *errorProtoLog) Message(level MsgLevel, message string) {
201 if level > ErrorLvl {
202 e.errorProto.ErrorMessages = append(e.errorProto.ErrorMessages, message)
203 }
204}
205
206func (e *errorProtoLog) Write(p []byte) (int, error) {
207 return 0, errors.New("not supported")
208}