Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(755)

Side by Side Diff: logdog/client/annotee/processor.go

Issue 2780673002: Include LogDog viewer links in message. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The LUCI Authors. All rights reserved. 1 // Copyright 2015 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package annotee 5 package annotee
6 6
7 import ( 7 import (
8 "bufio" 8 "bufio"
9 "bytes" 9 "bytes"
10 "fmt" 10 "fmt"
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 280
281 h, err := p.getStepHandler(step, true) 281 h, err := p.getStepHandler(step, true)
282 if err != nil { 282 if err != nil {
283 return err 283 return err
284 } 284 }
285 285
286 // Determine our injected annotations. 286 // Determine our injected annotations.
287 injectedAnnotations := h.flushInjectedAnnotations() 287 injectedAnnotations := h.flushInjectedAnnotations()
288 288
289 // Emit the "all" link if configured (at most once). 289 // Emit the "all" link if configured (at most once).
290 » if s.EmitAllLink { 290 » if lg := p.o.LinkGenerator; lg != nil && s.EmitAllLink {
291 » » if l := buildStreamLinkAnnotation(p.o.LinkGenerator, "all", "std io", "**/stdout", "**/stderr"); l != "" { 291 » » injectedAnnotations = append(injectedAnnotations,
292 » » » injectedAnnotations = append(injectedAnnotations, l) 292 » » » buildAliasAnnotation("all", "stdio", lg.GetLink("**/stdo ut", "**/stderr")))
293 » » } 293
294 s.EmitAllLink = false 294 s.EmitAllLink = false
295 } 295 }
296 296
297 // Get our root log stream handler. As an optimization, if "step" is 297 // Get our root log stream handler. As an optimization, if "step" is
298 // the root step, then "h" is already the root handler, so we don't need 298 // the root step, then "h" is already the root handler, so we don't need
299 // to duplicate the lookup. 299 // to duplicate the lookup.
300 // 300 //
301 // We only need the handler if we're going to emit annotations to the ro ot 301 // We only need the handler if we're going to emit annotations to the ro ot
302 // stream. 302 // stream.
303 var rootHandler *stepHandler 303 var rootHandler *stepHandler
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 if !s.StripAnnotations { 349 if !s.StripAnnotations {
350 if err := rootHandler.writeBaseStream(s, anno); err != n il { 350 if err := rootHandler.writeBaseStream(s, anno); err != n il {
351 log.WithError(err).Errorf(h, "Failed to send inj ected annotation line to LogDog.") 351 log.WithError(err).Errorf(h, "Failed to send inj ected annotation line to LogDog.")
352 return err 352 return err
353 } 353 }
354 } 354 }
355 } 355 }
356 356
357 // If we're stripping text, write a warning message noting that this str eam 357 // If we're stripping text, write a warning message noting that this str eam
358 // will not have text in it. 358 // will not have text in it.
359 » if !p.o.TeeText && s.Tee != nil && !h.textStrippedNote { 359 » if !p.o.TeeText && s.Tee != nil {
360 » » err := writeTextLine(s.Tee, "This build is configured to send lo g data exclusively to LogDog. "+ 360 » » if !h.textStrippedNote {
361 » » » "Please click the LogDog link on the build page to view this log stream.") 361 » » » err := writeTextLine(s.Tee, "This build is configured to send log data exclusively to LogDog. "+
362 » » if err != nil { 362 » » » » "Please use the LogDog link on the build page to view this log stream.")
hinoka 2017/03/27 22:21:05 This seems like a better place to inject the viewe
dnj 2017/03/27 22:24:14 We can't inject here, since the links aren't known
363 » » » log.WithError(err).Errorf(h, "Failed to write text strip ped notice.") 363 » » » if err != nil {
364 » » » return err 364 » » » » log.WithError(err).Errorf(h, "Failed to write te xt stripped notice.")
365 » » » » return err
366 » » » }
367
368 » » » h.textStrippedNote = true
365 } 369 }
366 370
367 » » h.textStrippedNote = true 371 » » // Add links to specific log streams as they are generated.
372 » » injectTextStreamLines := h.flushInjectedTextStreamLines()
373 » » if len(injectTextStreamLines) > 0 {
hinoka 2017/03/27 22:21:05 the if statement is redundant.
dnj 2017/03/27 22:24:13 Done.
374 » » » for _, line := range injectTextStreamLines {
375 » » » » if err := writeTextLine(s.Tee, line); err != nil {
376 » » » » » log.WithError(err).Errorf(h, "Failed to inject text stream line: %s", line)
377 » » » » » return err
378 » » » » }
379 » » » }
380 » » }
368 } 381 }
369 382
370 // If this is a text line, and we're teeing text, emit this line. 383 // If this is a text line, and we're teeing text, emit this line.
371 if a == "" { 384 if a == "" {
372 if s.Tee != nil && p.o.TeeText { 385 if s.Tee != nil && p.o.TeeText {
373 if err := writeTextLine(s.Tee, line); err != nil { 386 if err := writeTextLine(s.Tee, line); err != nil {
374 log.WithError(err).Errorf(h, "Failed to tee text line.") 387 log.WithError(err).Errorf(h, "Failed to tee text line.")
375 return err 388 return err
376 } 389 }
377 } 390 }
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 } 582 }
570 } 583 }
571 584
572 // stepHandler handles the steps associated with a specified stream. 585 // stepHandler handles the steps associated with a specified stream.
573 type stepHandler struct { 586 type stepHandler struct {
574 context.Context 587 context.Context
575 588
576 processor *Processor 589 processor *Processor
577 step *annotation.Step 590 step *annotation.Step
578 591
579 » client streamclient.Client 592 » client streamclient.Client
580 » injectedAnnotations []string 593 » injectedAnnotations []string
581 » streams map[types.StreamName]streamclient.Stream 594 » injectedTextStreamLines []string
582 » finished bool 595 » streams map[types.StreamName]streamclient.Stream
583 » allEmitted bool 596 » finished bool
584 » textStrippedNote bool 597 » allEmitted bool
598 » textStrippedNote bool
585 } 599 }
586 600
587 func newStepHandler(p *Processor, step *annotation.Step) (*stepHandler, error) { 601 func newStepHandler(p *Processor, step *annotation.Step) (*stepHandler, error) {
588 h := stepHandler{ 602 h := stepHandler{
589 Context: log.SetField(p.ctx, "step", step), 603 Context: log.SetField(p.ctx, "step", step),
590 processor: p, 604 processor: p,
591 step: step, 605 step: step,
592 606
593 client: p.o.Client, 607 client: p.o.Client,
594 streams: make(map[types.StreamName]streamclient.Stream), 608 streams: make(map[types.StreamName]streamclient.Stream),
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 704
691 func (h *stepHandler) closeStreamImpl(name types.StreamName, s streamclient.Stre am) { 705 func (h *stepHandler) closeStreamImpl(name types.StreamName, s streamclient.Stre am) {
692 if err := s.Close(); err != nil { 706 if err := s.Close(); err != nil {
693 log.Fields{ 707 log.Fields{
694 log.ErrorKey: err, 708 log.ErrorKey: err,
695 "stream": name, 709 "stream": name,
696 }.Errorf(h, "Failed to close step stream.") 710 }.Errorf(h, "Failed to close step stream.")
697 } 711 }
698 } 712 }
699 713
700 func (h *stepHandler) flushInjectedAnnotations() []string { 714 func (h *stepHandler) flushInjectedAnnotations() []string {
hinoka 2017/03/27 22:21:05 This method and the one below looks like they coul
dnj 2017/03/27 22:24:14 The method up there is huge enough. I'd like to ke
701 » if len(h.injectedAnnotations) == 0 { 715 » return flushStringSlice(&h.injectedAnnotations)
716 }
717
718 func (h *stepHandler) flushInjectedTextStreamLines() []string {
719 » return flushStringSlice(&h.injectedTextStreamLines)
720 }
721
722 func (h *stepHandler) maybeInjectLink(base, text string, names ...types.StreamNa me) {
723 » if lg := h.processor.o.LinkGenerator; lg != nil {
724 » » link := lg.GetLink(names...)
725
726 » » h.injectedAnnotations = append(h.injectedAnnotations, buildAlias Annotation(base, text, link))
727 » » h.injectedTextStreamLines = append(h.injectedTextStreamLines, fm t.Sprintf("LogDog Link [%s]: %s", base, link))
728 » }
729 }
730
731 func (h *stepHandler) maybeInjectTextStreamLink(name string, stream types.Stream Name) {
732 » if lg := h.processor.o.LinkGenerator; lg != nil {
733 » }
734 }
735
736 func buildAliasAnnotation(base, text, link string) string {
737 » return buildAnnotation("STEP_LINK", fmt.Sprintf("%s-->%s", text, base), link)
738 }
739
740 func flushStringSlice(sp *[]string) []string {
741 » if sp == nil {
702 return nil 742 return nil
703 } 743 }
704 744
705 » lines := make([]string, len(h.injectedAnnotations)) 745 » s := *sp
706 » copy(lines, h.injectedAnnotations) 746 » if len(s) == 0 {
707 » h.injectedAnnotations = h.injectedAnnotations[:0] 747 » » return nil
748 » }
749
750 » lines := make([]string, len(s))
751 » copy(lines, s)
752 » *sp = s[:0]
708 753
709 return lines 754 return lines
710 } 755 }
711 756
712 func (h *stepHandler) maybeInjectLink(base, text string, names ...types.StreamNa me) {
713 if l := buildStreamLinkAnnotation(h.processor.o.LinkGenerator, base, tex t, names...); l != "" {
714 h.injectedAnnotations = append(h.injectedAnnotations, l)
715 }
716 }
717
718 func buildStreamLinkAnnotation(lg LinkGenerator, base, text string, names ...typ es.StreamName) string {
719 if lg != nil {
720 if link := lg.GetLink(names...); link != "" {
721 return buildAnnotation("STEP_LINK", fmt.Sprintf("%s-->%s ", text, base), link)
722 }
723 }
724 return ""
725 }
726
727 // lineReader reads from an input stream and returns the data line-by-line. 757 // lineReader reads from an input stream and returns the data line-by-line.
728 // 758 //
729 // We don't use a Scanner because we want to be able to handle lines that may 759 // We don't use a Scanner because we want to be able to handle lines that may
730 // exceed the buffer length. We don't use ReadBytes here because we need to 760 // exceed the buffer length. We don't use ReadBytes here because we need to
731 // capture the last line in the stream, even if it doesn't end with a newline. 761 // capture the last line in the stream, even if it doesn't end with a newline.
732 type lineReader struct { 762 type lineReader struct {
733 r *bufio.Reader 763 r *bufio.Reader
734 buf bytes.Buffer 764 buf bytes.Buffer
735 } 765 }
736 766
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 return "@@@" + strings.Join(append(v, params...), "@") + "@@@" 804 return "@@@" + strings.Join(append(v, params...), "@") + "@@@"
775 } 805 }
776 806
777 func isContentAnnotation(a string) bool { 807 func isContentAnnotation(a string) bool {
778 // Strip out any annotation arguments. 808 // Strip out any annotation arguments.
779 if idx := strings.IndexRune(a, '@'); idx > 0 { 809 if idx := strings.IndexRune(a, '@'); idx > 0 {
780 a = a[:idx] 810 a = a[:idx]
781 } 811 }
782 return a == "STEP_LOG_LINE" 812 return a == "STEP_LOG_LINE"
783 } 813 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698