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

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

Issue 2328023003: Fix Annotee stream name generation. (Closed)
Patch Set: Remove debugging junk. Created 4 years, 3 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 | logdog/client/annotee/annotation/annotation_test.go » ('j') | 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 annotation 5 package annotation
6 6
7 import ( 7 import (
8 "fmt" 8 "fmt"
9 "path"
10 "strconv" 9 "strconv"
11 "strings" 10 "strings"
12 "time" 11 "time"
13 12
14 "github.com/luci/luci-go/common/clock" 13 "github.com/luci/luci-go/common/clock"
15 "github.com/luci/luci-go/common/proto/google" 14 "github.com/luci/luci-go/common/proto/google"
16 "github.com/luci/luci-go/common/proto/milo" 15 "github.com/luci/luci-go/common/proto/milo"
17 "github.com/luci/luci-go/logdog/common/types" 16 "github.com/luci/luci-go/logdog/common/types"
18 ) 17 )
19 18
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 return 92 return
94 } 93 }
95 94
96 s.stepMap = map[string]*Step{} 95 s.stepMap = map[string]*Step{}
97 s.stepLookup = map[*milo.Step]*Step{} 96 s.stepLookup = map[*milo.Step]*Step{}
98 97
99 name := "steps" 98 name := "steps"
100 if s.Execution != nil { 99 if s.Execution != nil {
101 name = s.Execution.Name 100 name = s.Execution.Name
102 } 101 }
103 » s.rootStep.initializeStep(s, nil, name, 0, s.LogNameBase) 102 » s.rootStep.initializeStep(s, nil, name)
103 » s.rootStep.LogNameBase = s.LogNameBase
104 s.SetCurrentStep(nil) 104 s.SetCurrentStep(nil)
105 105
106 // Add our Command parameters, if applicable. 106 // Add our Command parameters, if applicable.
107 if exec := s.Execution; exec != nil { 107 if exec := s.Execution; exec != nil {
108 s.rootStep.Command = &milo.Step_Command{ 108 s.rootStep.Command = &milo.Step_Command{
109 CommandLine: exec.Command, 109 CommandLine: exec.Command,
110 Cwd: exec.Dir, 110 Cwd: exec.Dir,
111 Environ: exec.Env, 111 Environ: exec.Env,
112 } 112 }
113 } 113 }
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 // Both prevStep and nextStep are creation-ordered, and don't change eve n if 529 // Both prevStep and nextStep are creation-ordered, and don't change eve n if
530 // a Step is reparented. 530 // a Step is reparented.
531 prevStep *Step 531 prevStep *Step
532 // nextStep is the step that was created immediately after this step. It is 532 // nextStep is the step that was created immediately after this step. It is
533 // nil if this is the latest step. 533 // nil if this is the latest step.
534 // 534 //
535 // Both prevStep and nextStep are creation-ordered, and don't change eve n if 535 // Both prevStep and nextStep are creation-ordered, and don't change eve n if
536 // a Step is reparented. 536 // a Step is reparented.
537 nextStep *Step 537 nextStep *Step
538 538
539 index int
540 level int 539 level int
541 540
542 » stepIndex map[string]int 541 » // logPathIndex is a map of the number of log paths with the given base name.
542 » // Each time a log path is generated, it will register with this map and
543 » // increase the count.
544 » logPathIndex map[types.StreamName]int
543 545
544 // logLines is a map of log line labels to full log stream names. 546 // logLines is a map of log line labels to full log stream names.
545 logLines map[string]types.StreamName 547 logLines map[string]types.StreamName
546 // logLineCount is a map of log line label to the number of times that l og 548 // logLineCount is a map of log line label to the number of times that l og
547 // line has appeared. This is to prevent the case where multiple log lin es 549 // line has appeared. This is to prevent the case where multiple log lin es
548 // with the same label may be emitted, which would cause duplicate log s tream 550 // with the same label may be emitted, which would cause duplicate log s tream
549 // names. 551 // names.
550 logLineCount map[string]int 552 logLineCount map[string]int
551 553
552 » // LogNameBase is the LogDog stream name root for this step. 554 » // logNameBase is the LogDog stream name root for this step.
553 » logNameBase types.StreamName 555 » LogNameBase types.StreamName
554 // hasSummary, if true, means that this Step has summary text. The summa ry 556 // hasSummary, if true, means that this Step has summary text. The summa ry
555 // text is stored as the first line in its Step.Text slice. 557 // text is stored as the first line in its Step.Text slice.
556 hasSummary bool 558 hasSummary bool
557 // closed is true if the element is closed. 559 // closed is true if the element is closed.
558 closed bool 560 closed bool
559 } 561 }
560 562
561 func (as *Step) initializeStep(s *State, parent *Step, name string, index int, l ogNameBase types.StreamName) *Step { 563 func (as *Step) String() string { return string(as.LogNameBase) }
564
565 func (as *Step) initializeStep(s *State, parent *Step, name string) *Step {
562 t := milo.Status_RUNNING 566 t := milo.Status_RUNNING
563 as.Step = milo.Step{ 567 as.Step = milo.Step{
564 Name: name, 568 Name: name,
565 Status: t, 569 Status: t,
566 } 570 }
567 571
568 as.s = s 572 as.s = s
569 as.index = index
570 as.logNameBase = logNameBase
571 as.stepIndex = map[string]int{}
572 as.logLines = map[string]types.StreamName{} 573 as.logLines = map[string]types.StreamName{}
573 as.logLineCount = map[string]int{} 574 as.logLineCount = map[string]int{}
575 as.logPathIndex = map[types.StreamName]int{}
574 576
575 // Add this Step to our parent's Substep list. 577 // Add this Step to our parent's Substep list.
576 if parent != nil { 578 if parent != nil {
577 parent.appendSubstep(as) 579 parent.appendSubstep(as)
578 } 580 }
579 s.registerStep(as) 581 s.registerStep(as)
580 582
581 return as 583 return as
582 } 584 }
583 585
584 func (as *Step) appendSubstep(s *Step) { 586 func (as *Step) appendSubstep(s *Step) {
585 if s.parent == as { 587 if s.parent == as {
586 // Already parented to as, so do nothing. 588 // Already parented to as, so do nothing.
587 return 589 return
588 } 590 }
589 s.detachFromParent() 591 s.detachFromParent()
590 592
591 s.parent = as 593 s.parent = as
592 as.Substep = append(as.Substep, &milo.Step_Substep{ 594 as.Substep = append(as.Substep, &milo.Step_Substep{
593 Substep: &milo.Step_Substep_Step{ 595 Substep: &milo.Step_Substep_Step{
594 Step: &s.Step, 596 Step: &s.Step,
595 }, 597 },
596 }) 598 })
599 s.regenerateLogPath()
597 } 600 }
598 601
599 func (as *Step) detachFromParent() { 602 func (as *Step) detachFromParent() {
600 parent := as.parent 603 parent := as.parent
601 if parent == nil { 604 if parent == nil {
602 return 605 return
603 } 606 }
604 607
605 // Remove any instances of "as" from its current parent's Substeps. 608 // Remove any instances of "as" from its current parent's Substeps.
606 ssPtr := 0 609 ssPtr := 0
607 for _, ss := range parent.Substep { 610 for _, ss := range parent.Substep {
608 if ss.GetStep() != &as.Step { 611 if ss.GetStep() != &as.Step {
609 parent.Substep[ssPtr] = ss 612 parent.Substep[ssPtr] = ss
610 ssPtr++ 613 ssPtr++
611 } 614 }
612 } 615 }
613 parent.Substep = parent.Substep[:ssPtr] 616 parent.Substep = parent.Substep[:ssPtr]
614 as.parent = nil 617 as.parent = nil
615 } 618 }
616 619
617 // CanonicalName returns the canonical name of this Step. This name is
618 // guaranteed to be unique witin the State.
619 func (as *Step) CanonicalName() string {
620 parts := []string(nil)
621 if as.index == 0 {
622 parts = append(parts, as.Name())
623 } else {
624 parts = append(parts, fmt.Sprintf("%s_%d", as.Name(), as.index))
625 }
626 for p := as.parent; p != nil; p = p.parent {
627 parts = append(parts, p.Name())
628 }
629 for i := len(parts)/2 - 1; i >= 0; i-- {
630 opp := len(parts) - 1 - i
631 parts[i], parts[opp] = parts[opp], parts[i]
632 }
633 return path.Join(parts...)
634 }
635
636 // Name returns the step's component name. 620 // Name returns the step's component name.
637 func (as *Step) Name() string { 621 func (as *Step) Name() string {
638 return as.Step.Name 622 return as.Step.Name
639 } 623 }
640 624
641 // Proto returns the Milo protobuf associated with this Step. 625 // Proto returns the Milo protobuf associated with this Step.
642 func (as *Step) Proto() *milo.Step { 626 func (as *Step) Proto() *milo.Step {
643 return &as.Step 627 return &as.Step
644 } 628 }
645 629
646 // BaseStream returns the supplied name prepended with this Step's base 630 // BaseStream returns the supplied name prepended with this Step's base
647 // log name. 631 // log name.
648 // 632 //
649 // For example, if the base name is "foo/bar", BaseStream("baz") will return 633 // For example, if the base name is "foo/bar", BaseStream("baz") will return
650 // "foo/bar/baz". 634 // "foo/bar/baz".
651 func (as *Step) BaseStream(name types.StreamName) types.StreamName { 635 func (as *Step) BaseStream(name types.StreamName) types.StreamName {
652 » if as.logNameBase == "" { 636 » if as.LogNameBase == "" {
653 return name 637 return name
654 } 638 }
655 » return as.logNameBase.Concat(name) 639 » return as.LogNameBase.Concat(name)
656 } 640 }
657 641
658 // AddStep generates a new substep. 642 // AddStep generates a new substep.
659 func (as *Step) AddStep(name string) *Step { 643 func (as *Step) AddStep(name string) *Step {
660 » // Determine/advance step index. 644 » return (&Step{}).initializeStep(as.s, as, name)
661 » index := as.stepIndex[name] 645 }
662 » as.stepIndex[name]++
663 646
664 » logPath, err := types.MakeStreamName("s_", "steps", name, strconv.Itoa(i ndex)) 647 func (as *Step) regenerateLogPath() {
665 » if err != nil { 648 » if as.parent == nil {
666 » » panic(fmt.Errorf("failed to generate step name for [%s]: %s", na me, err)) 649 » » panic("log path regeneration cannot be called on root step")
667 } 650 }
668 651
669 » nas := (&Step{}).initializeStep(as.s, as, name, index, as.BaseStream(log Path)) 652 » // Recipe engine nests steps by prepending their parents' name, e.g.
670 » return nas 653 » // if "foo" has a nested child, it will be named "foo.bar". This is redu ndant
654 » // for our stream names, so strip that off.
655 » //
656 » // We throw the length conditional in just in case the child step happen s to
657 » // have the exact same name as the parent. This shouldn't happen natural ly,
658 » // but let's be robust.
659 » name := as.Name()
660 » if parentPrefix := (as.parent.Name() + "."); len(parentPrefix) < len(nam e) {
661 » » name = strings.TrimPrefix(name, parentPrefix)
662 » }
663
664 » logPath, err := types.MakeStreamName("s_", "steps", name)
665 » if err != nil {
666 » » panic(fmt.Errorf("failed to generate step name for [%s]: %s", as .Name(), err))
667 » }
668
669 » index := as.parent.logPathIndex[logPath]
670 » as.parent.logPathIndex[logPath] = (index + 1)
671
672 » // Append the index to the stream name.
673 » logPath = logPath.Concat(types.StreamName(strconv.Itoa(index)))
674 » if err := logPath.Validate(); err != nil {
675 » » panic(fmt.Errorf("generated invalid log stream path %q: %v", log Path, err))
676 » }
677
678 » as.LogNameBase = as.parent.BaseStream(logPath)
671 } 679 }
672 680
673 // Start marks the Step as started. 681 // Start marks the Step as started.
674 func (as *Step) Start(startTime *google.Timestamp) bool { 682 func (as *Step) Start(startTime *google.Timestamp) bool {
675 if as.Started != nil { 683 if as.Started != nil {
676 return false 684 return false
677 } 685 }
678 as.Started = startTime 686 as.Started = startTime
679 return true 687 return true
680 } 688 }
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 as.StderrStream, updated = as.maybeSetLogDogStream(as.StderrStream, st) 921 as.StderrStream, updated = as.maybeSetLogDogStream(as.StderrStream, st)
914 return 922 return
915 } 923 }
916 924
917 func (as *Step) maybeSetLogDogStream(target *milo.LogdogStream, st *milo.LogdogS tream) (*milo.LogdogStream, bool) { 925 func (as *Step) maybeSetLogDogStream(target *milo.LogdogStream, st *milo.LogdogS tream) (*milo.LogdogStream, bool) {
918 if (target == nil && st == nil) || (target != nil && st != nil && *targe t == *st) { 926 if (target == nil && st == nil) || (target != nil && st != nil && *targe t == *st) {
919 return target, false 927 return target, false
920 } 928 }
921 return st, true 929 return st, true
922 } 930 }
OLDNEW
« no previous file with comments | « no previous file | logdog/client/annotee/annotation/annotation_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698