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

Unified Diff: milo/appengine/logdog/build.go

Issue 2674603002: milo: Export LogDog annotation stream, remove host (Closed)
Patch Set: Comments Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « milo/appengine/frontend/milo.go ('k') | milo/appengine/logdog/http.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: milo/appengine/logdog/build.go
diff --git a/milo/appengine/logdog/build.go b/milo/appengine/logdog/build.go
index fba82c954f3828062260cad5360bda4304e8304d..724517105ceb7dd154282858e47baed64ffbc3fa 100644
--- a/milo/appengine/logdog/build.go
+++ b/milo/appengine/logdog/build.go
@@ -5,11 +5,8 @@
package logdog
import (
- "errors"
"fmt"
"net/http"
- "net/url"
- "strings"
"time"
log "github.com/luci/luci-go/common/logging"
@@ -19,6 +16,7 @@ import (
"github.com/luci/luci-go/logdog/api/logpb"
"github.com/luci/luci-go/logdog/client/coordinator"
"github.com/luci/luci-go/logdog/common/types"
+ "github.com/luci/luci-go/logdog/common/viewer"
"github.com/luci/luci-go/luci_config/common/cfgtypes"
"github.com/luci/luci-go/milo/api/resp"
"github.com/luci/luci-go/milo/appengine/logdog/internal"
@@ -41,55 +39,44 @@ const (
defaultLogDogHost = "luci-logdog.appspot.com"
)
-type annotationStreamRequest struct {
- *AnnotationStream
-
- // host is the name of the LogDog host.
- host string
-
- project cfgtypes.ProjectName
- path types.StreamPath
+// AnnotationStream represents a LogDog annotation protobuf stream.
+type AnnotationStream struct {
+ Project cfgtypes.ProjectName
+ Path types.StreamPath
// logDogClient is the HTTP client to use for LogDog communication.
- logDogClient *coordinator.Client
+ Client *coordinator.Client
// cs is the unmarshalled annotation stream Step and associated data.
cs internal.CachedStep
}
-func (as *annotationStreamRequest) normalize() error {
- if err := as.project.Validate(); err != nil {
- return &miloerror.Error{
- Message: "Invalid project name",
- Code: http.StatusBadRequest,
- }
- }
-
- if err := as.path.Validate(); err != nil {
- return &miloerror.Error{
- Message: fmt.Sprintf("Invalid log stream path %q: %s", as.path, err),
- Code: http.StatusBadRequest,
- }
+// Normalize validates and normalizes the stream's parameters.
+func (as *AnnotationStream) Normalize() error {
+ if err := as.Project.Validate(); err != nil {
+ return fmt.Errorf("Invalid project name: %s", as.Project)
}
- // Get the host. We normalize it to lowercase and trim spaces since we use
- // it as a memcache key.
- as.host = strings.ToLower(strings.TrimSpace(as.host))
- if as.host == "" {
- as.host = defaultLogDogHost
- }
- if strings.ContainsRune(as.host, '/') {
- return errors.New("invalid host name")
+ if err := as.Path.Validate(); err != nil {
+ return fmt.Errorf("Invalid log stream path %q: %s", as.Path, err)
}
return nil
}
-func (as *annotationStreamRequest) memcacheKey() string {
- return fmt.Sprintf("logdog/%s/%s/%s", as.host, as.project, as.path)
-}
+// Load loads the annotation stream from LogDog.
+//
+// If the stream does not exist, or is invalid, Load will return a Milo error.
+// Otherwise, it will return the Step that was loaded.
+//
+// Load caches the step, so multiple calls to Load will return the same Step
+// value.
+func (as *AnnotationStream) Load(c context.Context) (*miloProto.Step, error) {
+ // Cached?
+ if as.cs.Step != nil {
+ return as.cs.Step, nil
+ }
-func (as *annotationStreamRequest) load(c context.Context) error {
// Load from memcache, if possible. If an error occurs, we will proceed as if
// no CachedStep was available.
mcKey := as.memcacheKey()
@@ -97,7 +84,7 @@ func (as *annotationStreamRequest) load(c context.Context) error {
switch err {
case nil:
if err := proto.Unmarshal(mcItem.Value(), &as.cs); err == nil {
- return nil
+ return as.cs.Step, nil
}
// We could not unmarshal the cached value. Try and delete it from
@@ -122,14 +109,14 @@ func (as *annotationStreamRequest) load(c context.Context) error {
// Load from LogDog directly.
log.Fields{
- "project": as.project,
- "path": as.path,
- "host": as.host,
+ "host": as.Client.Host,
+ "project": as.Project,
+ "path": as.Path,
}.Infof(c, "Making tail request to LogDog to fetch annotation stream.")
var (
state coordinator.LogStream
- stream = as.logDogClient.Stream(as.project, as.path)
+ stream = as.Client.Stream(as.Project, as.Path)
)
le, err := stream.Tail(c, coordinator.WithState(&state), coordinator.Complete())
switch code := grpcutil.Code(err); code {
@@ -137,7 +124,7 @@ func (as *annotationStreamRequest) load(c context.Context) error {
break
case codes.NotFound:
- return &miloerror.Error{
+ return nil, &miloerror.Error{
Message: "Stream not found",
Code: http.StatusNotFound,
}
@@ -149,7 +136,7 @@ func (as *annotationStreamRequest) load(c context.Context) error {
log.ErrorKey: err,
"code": code,
}.Errorf(c, "Failed to load LogDog annotation stream.")
- return &miloerror.Error{
+ return nil, &miloerror.Error{
Message: "Failed to load stream",
Code: http.StatusInternalServerError,
}
@@ -158,20 +145,23 @@ func (as *annotationStreamRequest) load(c context.Context) error {
// Make sure that this is an annotation stream.
switch {
case state.Desc.ContentType != miloProto.ContentTypeAnnotations:
- return &miloerror.Error{
+ return nil, &miloerror.Error{
Message: "Requested stream is not a Milo annotation protobuf",
Code: http.StatusBadRequest,
}
case state.Desc.StreamType != logpb.StreamType_DATAGRAM:
- return &miloerror.Error{
+ return nil, &miloerror.Error{
Message: "Requested stream is not a datagram stream",
Code: http.StatusBadRequest,
}
case le == nil:
// No annotation stream data, so render a minimal page.
- return nil
+ return nil, &miloerror.Error{
+ Message: "Log stream has no annotation entries",
+ Code: http.StatusNotFound,
+ }
}
// Get the last log entry in the stream. In reality, this will be index 0,
@@ -181,7 +171,7 @@ func (as *annotationStreamRequest) load(c context.Context) error {
// will be complete even if its source datagram(s) are fragments.
dg := le.GetDatagram()
if dg == nil {
- return &miloerror.Error{
+ return nil, &miloerror.Error{
Message: "Datagram stream does not have datagram data",
Code: http.StatusInternalServerError,
}
@@ -190,7 +180,7 @@ func (as *annotationStreamRequest) load(c context.Context) error {
// Attempt to decode the Step protobuf.
var step miloProto.Step
if err := proto.Unmarshal(dg.Data, &step); err != nil {
- return &miloerror.Error{
+ return nil, &miloerror.Error{
Message: "Failed to unmarshal annotation protobuf",
Code: http.StatusInternalServerError,
}
@@ -246,16 +236,20 @@ func (as *annotationStreamRequest) load(c context.Context) error {
log.WithError(err).Warningf(c, "Failed to marshal annotation protobuf CachedStep.")
}
- return nil
+ return as.cs.Step, nil
+}
+
+func (as *AnnotationStream) memcacheKey() string {
+ return fmt.Sprintf("logdog/%s/%s/%s", as.Client.Host, as.Project, as.Path)
}
-func (as *annotationStreamRequest) toMiloBuild(c context.Context) *resp.MiloBuild {
- prefix, name := as.path.Split()
+func (as *AnnotationStream) toMiloBuild(c context.Context) *resp.MiloBuild {
+ prefix, name := as.Path.Split()
// Prepare a Streams object with only one stream.
streams := Streams{
MainStream: &Stream{
- Server: as.host,
+ Server: as.Client.Host,
Prefix: string(prefix),
Path: string(name),
IsDatagram: true,
@@ -267,8 +261,8 @@ func (as *annotationStreamRequest) toMiloBuild(c context.Context) *resp.MiloBuil
var (
build resp.MiloBuild
ub = logDogURLBuilder{
- project: as.project,
- host: as.host,
+ host: as.Client.Host,
+ project: as.Project,
prefix: prefix,
}
)
@@ -297,19 +291,10 @@ func (b *logDogURLBuilder) BuildLink(l *miloProto.Link) *resp.Link {
prefix = b.prefix
}
- path := fmt.Sprintf("%s/%s", b.project, prefix.Join(types.StreamName(ls.Name)))
- u := url.URL{
- Scheme: "https",
- Host: server,
- Path: "v/",
- RawQuery: url.Values{
- "s": []string{string(path)},
- }.Encode(),
- }
-
+ u := viewer.GetURL(server, b.project, prefix.Join(types.StreamName(ls.Name)))
link := resp.Link{
Label: l.Label,
- URL: u.String(),
+ URL: u,
}
if link.Label == "" {
link.Label = ls.Name
« no previous file with comments | « milo/appengine/frontend/milo.go ('k') | milo/appengine/logdog/http.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698