Split large events into multiple log entries. (#2092)

Just what it says on the tin. The splitting is implemented s.t.
colorization commands are never split across multiple log entries.
This commit is contained in:
Pat Gavlin 2018-10-23 14:59:30 -07:00 committed by GitHub
parent 052bc69a52
commit b14d259365
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 83 additions and 10 deletions

View file

@ -159,18 +159,28 @@ func (u *cloudUpdate) recordEvent(
// the user has a rich diff-log they can see when the look at their logs in the service.
opts.Color = colors.Raw
msg := display.RenderDiffEvent(action, event, seen, opts)
if msg == "" {
return nil
}
token, err := u.tokenSource.GetToken()
if err != nil {
return err
}
// If we have a message, upload it as <= 1MB chunks.
for msg != "" {
chunk := msg
const maxLen = 1 << 20 // 1 MB
if len(chunk) > maxLen {
chunk = colors.TrimPartialCommand(msg)
}
msg = msg[len(chunk):]
fields["text"] = msg
fields["colorize"] = colors.Always
return u.backend.client.AppendUpdateLogEntry(u.context, u.update, kind, fields, token)
token, err := u.tokenSource.GetToken()
if err != nil {
return err
}
fields["text"] = chunk
fields["colorize"] = colors.Always
if err = u.backend.client.AppendUpdateLogEntry(u.context, u.update, kind, fields, token); err != nil {
return err
}
}
return nil
}
func (u *cloudUpdate) RecordAndDisplayEvents(label string, action apitype.UpdateKind, stackRef backend.StackReference,

View file

@ -36,6 +36,38 @@ func Command(s string) string {
return colorLeft + s + colorRight
}
// TrimPartialCommand returns the input string with any partial colorization command trimmed off of the right end of
// the string.
func TrimPartialCommand(s string) string {
// First check for a partial left delimiter at the end of the string.
partialDelimLeft := colorLeft
if len(partialDelimLeft) > len(s) {
partialDelimLeft = partialDelimLeft[:len(s)]
}
for len(partialDelimLeft) > 0 {
trailer := s[len(s)-len(partialDelimLeft):]
if trailer == partialDelimLeft {
return s[:len(s)-len(partialDelimLeft)]
}
partialDelimLeft = partialDelimLeft[:len(partialDelimLeft)-1]
}
// Next check for a complete left delimiter. If there no complete left delimiter, just return the string as-is.
lastDelimLeft := strings.LastIndex(s, colorLeft)
if lastDelimLeft == -1 {
return s
}
// If there is a complete left delimiter, look for a matching complete right delimiter. If there is a match, return
// the string as-is.
if strings.Contains(s[lastDelimLeft:], colorRight) {
return s
}
// Otherwise, return the string up to but not including the incomplete left delimiter.
return s[:lastDelimLeft]
}
func Colorize(s fmt.Stringer) string {
txt := s.String()
return colorizeText(txt)

View file

@ -0,0 +1,31 @@
// Copyright 2016-2018, Pulumi Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package colors
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestTrimPartialCommand(t *testing.T) {
noPartial := Red + "foo" + Green + "bar" + Reset
assert.Equal(t, noPartial, TrimPartialCommand(noPartial))
expected := Red + "foo" + Green + "bar"
for partial := noPartial[:len(noPartial)-1]; partial[len(partial)-3:] != "bar"; partial = partial[:len(partial)-1] {
assert.Equal(t, expected, TrimPartialCommand(partial))
}
}