Skip to content

Commit

Permalink
Allow log requests to specify a namespace filter
Browse files Browse the repository at this point in the history
**What**
- Add `Namespace` field to the log request and response so that users
  can specify the namespace of the function.  This is required to
  support the new multi-namespace support. Using this, a user can
  deploy a function with the same name to multiple namespaces. E.g. to
  `dev` and `prod` namespaces. The namespace field is required so that
  the user can target the specific deployment of the function.  It is
  expected the that the empty namespace will be treated as "in the
  default namespace"

  Note that this does not actually implement any filtering logic, it
  only allows the log providers to accept and return the information.
  faas-provider and log-provider implementation will need to update
  and handle the new field accordingly.

Signed-off-by: Lucas Roesler <[email protected]>
  • Loading branch information
LucasRoesler authored and alexellis committed Dec 15, 2019
1 parent 7677057 commit d6579bd
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 15 deletions.
1 change: 1 addition & 0 deletions logs/example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func (s staticLogRequestor) Query(ctx context.Context, r logs.Request) (<-chan l

resp <- logs.Message{
Name: r.Name,
Namespace: r.Namespace,
Instance: "fake",
Timestamp: time.Now(),
Text: m,
Expand Down
1 change: 1 addition & 0 deletions logs/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func NewLogHandlerFunc(requestor Requester, timeout time.Duration) http.HandlerF
func parseRequest(r *http.Request) (logRequest Request, err error) {
query := r.URL.Query()
logRequest.Name = getValue(query, "name")
logRequest.Namespace = getValue(query, "namespace")
logRequest.Instance = getValue(query, "instance")
tailStr := getValue(query, "tail")
if tailStr != "" {
Expand Down
21 changes: 8 additions & 13 deletions logs/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func Test_logsHandlerDoesNotLeakGoroutinesWhenProviderClosesStream(t *testing.T)
defer goleak.VerifyNoLeaks(t)

msgs := []Message{
Message{Name: "funcFoo", Text: "msg 0"},
Message{Name: "funcFoo", Text: "msg 0", Namespace: "default"},
Message{Name: "funcFoo", Text: "msg 1"},
}

Expand Down Expand Up @@ -54,7 +54,7 @@ func Test_logsHandlerDoesNotLeakGoroutinesWhenClientClosesConnection(t *testing.
defer goleak.VerifyNoLeaks(t)

msgs := []Message{
Message{Name: "funcFoo", Text: "msg 0"},
Message{Name: "funcFoo", Text: "msg 0", Namespace: "default"},
Message{Name: "funcFoo", Text: "msg 1"},
}

Expand Down Expand Up @@ -103,12 +103,6 @@ func Test_GETRequestParsing(t *testing.T) {
err: "",
expectedRequest: Request{Name: "foobar"},
},
{
name: "name only query",
rawQueryStr: "name=foobar",
err: "",
expectedRequest: Request{Name: "foobar"},
},
{
name: "multiple name values selects the last value",
rawQueryStr: "name=foobar&name=theactual name",
Expand All @@ -117,13 +111,14 @@ func Test_GETRequestParsing(t *testing.T) {
},
{
name: "valid request with every parameter",
rawQueryStr: "name=foobar&since=2019-02-16T09%3A10%3A06%2B00%3A00&tail=5&follow=true",
rawQueryStr: "name=foobar&since=2019-02-16T09%3A10%3A06%2B00%3A00&tail=5&follow=true&namespace=default",
err: "",
expectedRequest: Request{
Name: "foobar",
Since: &sinceTime,
Tail: 5,
Follow: true,
Name: "foobar",
Namespace: "default",
Since: &sinceTime,
Tail: 5,
Follow: true,
},
},
}
Expand Down
16 changes: 14 additions & 2 deletions logs/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import (
type Request struct {
// Name is the function name and is required
Name string `json:"name"`
// Namespace is the namespace the function is deployed to, how a namespace is defined
// is faas-provider specific
Namespace string `json:"namespace"`
// Instance is the optional container name, that allows you to request logs from a specific function instance
Instance string `json:"instance"`
// Since is the optional datetime value to start the logs from
Expand All @@ -29,13 +32,19 @@ type Request struct {
// String implements that Stringer interface and prints the log Request in a consistent way that
// allows you to safely compare if two requests have the same value.
func (r Request) String() string {
return fmt.Sprintf("name:%s instance:%s since:%v tail:%d follow:%v", r.Name, r.Instance, r.Since, r.Tail, r.Follow)
return fmt.Sprintf(
"name:%s namespace: %s instance:%s since:%v tail:%d follow:%v",
r.Name, r.Namespace, r.Instance, r.Since, r.Tail, r.Follow,
)
}

// Message is a specific log message from a function container log stream
type Message struct {
// Name is the function name
Name string `json:"name"`
// Namespace is the namespace the function is deployed to, how a namespace is defined
// is faas-provider specific
Namespace string `json:"namespace"`
// instance is the name/id of the specific function instance
Instance string `json:"instance"`
// Timestamp is the timestamp of when the log message was recorded
Expand All @@ -46,5 +55,8 @@ type Message struct {

// String implements the Stringer interface and allows for nice and simple string formatting of a log Message.
func (m Message) String() string {
return fmt.Sprintf("%s %s (%s) %s", m.Timestamp.String(), m.Name, m.Instance, m.Text)
return fmt.Sprintf(
"%s %s (%s %s) %s",
m.Timestamp.String(), m.Name, m.Namespace, m.Instance, m.Text,
)
}

0 comments on commit d6579bd

Please sign in to comment.