blob: 9090f4995db88b0458cca31aa547625b6eb58ef3 [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"
Dan Willemsenb82471a2018-05-17 16:37:09 -070023 "strings"
Patrice Arruda297ceba2019-06-06 16:44:37 -070024
25 "github.com/golang/protobuf/proto"
26
27 "android/soong/ui/logger"
28 "android/soong/ui/status/build_error_proto"
Dan Willemsenb82471a2018-05-17 16:37:09 -070029)
30
31type verboseLog struct {
32 w io.WriteCloser
33}
34
35func NewVerboseLog(log logger.Logger, filename string) StatusOutput {
36 if !strings.HasSuffix(filename, ".gz") {
37 filename += ".gz"
38 }
39
40 f, err := logger.CreateFileWithRotation(filename, 5)
41 if err != nil {
42 log.Println("Failed to create verbose log file:", err)
43 return nil
44 }
45
46 w := gzip.NewWriter(f)
47
48 return &verboseLog{
49 w: w,
50 }
51}
52
53func (v *verboseLog) StartAction(action *Action, counts Counts) {}
54
55func (v *verboseLog) FinishAction(result ActionResult, counts Counts) {
56 cmd := result.Command
57 if cmd == "" {
58 cmd = result.Description
59 }
60
61 fmt.Fprintf(v.w, "[%d/%d] %s\n", counts.FinishedActions, counts.TotalActions, cmd)
62
63 if result.Error != nil {
64 fmt.Fprintf(v.w, "FAILED: %s\n", strings.Join(result.Outputs, " "))
65 }
66
67 if result.Output != "" {
68 fmt.Fprintln(v.w, result.Output)
69 }
70}
71
72func (v *verboseLog) Flush() {
73 v.w.Close()
74}
75
76func (v *verboseLog) Message(level MsgLevel, message string) {
77 fmt.Fprintf(v.w, "%s%s\n", level.Prefix(), message)
78}
79
Colin Crosse0df1a32019-06-09 19:40:08 -070080func (v *verboseLog) Write(p []byte) (int, error) {
81 fmt.Fprint(v.w, string(p))
82 return len(p), nil
83}
84
Dan Willemsenb82471a2018-05-17 16:37:09 -070085type errorLog struct {
Patrice Arruda297ceba2019-06-06 16:44:37 -070086 w io.WriteCloser
Dan Willemsenb82471a2018-05-17 16:37:09 -070087 empty bool
88}
89
90func NewErrorLog(log logger.Logger, filename string) StatusOutput {
91 f, err := logger.CreateFileWithRotation(filename, 5)
92 if err != nil {
93 log.Println("Failed to create error log file:", err)
94 return nil
95 }
96
97 return &errorLog{
98 w: f,
99 empty: true,
100 }
101}
102
103func (e *errorLog) StartAction(action *Action, counts Counts) {}
104
105func (e *errorLog) FinishAction(result ActionResult, counts Counts) {
106 if result.Error == nil {
107 return
108 }
109
Dan Willemsenb82471a2018-05-17 16:37:09 -0700110 if !e.empty {
111 fmt.Fprintf(e.w, "\n\n")
112 }
113 e.empty = false
114
115 fmt.Fprintf(e.w, "FAILED: %s\n", result.Description)
Patrice Arruda297ceba2019-06-06 16:44:37 -0700116
Dan Willemsenb82471a2018-05-17 16:37:09 -0700117 if len(result.Outputs) > 0 {
118 fmt.Fprintf(e.w, "Outputs: %s\n", strings.Join(result.Outputs, " "))
119 }
Patrice Arruda297ceba2019-06-06 16:44:37 -0700120
Dan Willemsenb82471a2018-05-17 16:37:09 -0700121 fmt.Fprintf(e.w, "Error: %s\n", result.Error)
122 if result.Command != "" {
123 fmt.Fprintf(e.w, "Command: %s\n", result.Command)
124 }
125 fmt.Fprintf(e.w, "Output:\n%s\n", result.Output)
126}
127
128func (e *errorLog) Flush() {
129 e.w.Close()
130}
131
132func (e *errorLog) Message(level MsgLevel, message string) {
133 if level < ErrorLvl {
134 return
135 }
136
137 if !e.empty {
138 fmt.Fprintf(e.w, "\n\n")
139 }
140 e.empty = false
141
142 fmt.Fprintf(e.w, "error: %s\n", message)
143}
Colin Crosse0df1a32019-06-09 19:40:08 -0700144
145func (e *errorLog) Write(p []byte) (int, error) {
146 fmt.Fprint(e.w, string(p))
147 return len(p), nil
148}
Patrice Arruda297ceba2019-06-06 16:44:37 -0700149
150type errorProtoLog struct {
151 errorProto soong_build_error_proto.BuildError
152 filename string
153 log logger.Logger
154}
155
156func NewProtoErrorLog(log logger.Logger, filename string) StatusOutput {
157 return &errorProtoLog{
158 errorProto: soong_build_error_proto.BuildError{},
159 filename: filename,
160 log: log,
161 }
162}
163
164func (e *errorProtoLog) StartAction(action *Action, counts Counts) {}
165
166func (e *errorProtoLog) FinishAction(result ActionResult, counts Counts) {
167 if result.Error == nil {
168 return
169 }
170
171 e.errorProto.ActionErrors = append(e.errorProto.ActionErrors, &soong_build_error_proto.BuildActionError{
172 Description: proto.String(result.Description),
173 Command: proto.String(result.Command),
174 Output: proto.String(result.Output),
175 Artifacts: result.Outputs,
176 Error: proto.String(result.Error.Error()),
177 })
178}
179
180func (e *errorProtoLog) Flush() {
181 data, err := proto.Marshal(&e.errorProto)
182 if err != nil {
183 e.log.Println("Failed to marshal build status proto: %v", err)
184 return
185 }
186 err = ioutil.WriteFile(e.filename, []byte(data), 0644)
187 if err != nil {
188 e.log.Println("Failed to write file %s: %v", e.errorProto, err)
189 }
190}
191
192func (e *errorProtoLog) Message(level MsgLevel, message string) {
193 if level > ErrorLvl {
194 e.errorProto.ErrorMessages = append(e.errorProto.ErrorMessages, message)
195 }
196}
197
198func (e *errorProtoLog) Write(p []byte) (int, error) {
199 return 0, errors.New("not supported")
200}