Permalink
Browse files

Decouple the logsink handler from EntityDbLogger

We want to use this endpoint for migration log transfer as well - the
LoggingStrategy captures the authentication and selection of the type of
logger.
  • Loading branch information...
1 parent 0808eb5 commit eafd1f8286d4898907bf826af12c8512b1e76f8a @babbageclunk babbageclunk committed Nov 8, 2016
Showing with 61 additions and 11 deletions.
  1. +1 −1 apiserver/apiserver.go
  2. +60 −10 apiserver/logsink.go
View
@@ -355,7 +355,7 @@ func (srv *Server) endpoints() []apihttp.Endpoint {
strictCtxt.controllerModelOnly = true
mainAPIHandler := srv.trackRequests(http.HandlerFunc(srv.apiHandler))
- logSinkHandler := srv.trackRequests(newLogSinkHandler(httpCtxt, srv.logDir))
+ logSinkHandler := srv.trackRequests(newLogSinkHandler(httpCtxt, srv.logDir, newAgentLoggingStrategy))
logStreamHandler := srv.trackRequests(newLogStreamEndpointHandler(strictCtxt))
debugLogHandler := srv.trackRequests(newDebugLogDBHandler(httpCtxt))
View
@@ -16,14 +16,63 @@ import (
"github.com/juju/utils"
"github.com/juju/version"
"golang.org/x/net/websocket"
+ "gopkg.in/juju/names.v2"
"gopkg.in/natefinch/lumberjack.v2"
"github.com/juju/juju/apiserver/common"
"github.com/juju/juju/apiserver/params"
"github.com/juju/juju/state"
)
-func newLogSinkHandler(h httpContext, logDir string) http.Handler {
+type DbLogger interface {
+ Log(*params.LogRecord) error
+ Close()
+}
+
+type LoggingStrategy interface {
+ Authenticate(*http.Request) error
+ FilePrefix() string
+ MakeLogger(version.Number) DbLogger
+}
+
+type entityLogger struct {
+ *state.EntityDbLogger
+}
+
+func (l *entityLogger) Log(m *params.LogRecord) error {
+ level, _ := loggo.ParseLevel(m.Level)
+ return l.EntityDbLogger.Log(m.Time, m.Module, m.Location, level, m.Message)
+}
+
+type AgentLoggingStrategy struct {
+ ctxt httpContext
+ st *state.State
+ entity names.Tag
+}
+
+func (s *AgentLoggingStrategy) Authenticate(req *http.Request) error {
+ st, entity, err := s.ctxt.stateForRequestAuthenticatedAgent(req)
+ if err != nil {
+ return errors.Trace(err)
+ }
+ s.st = st
+ s.entity = entity.Tag()
+ return nil
+}
+
+func (s *AgentLoggingStrategy) FilePrefix() string {
+ return s.st.ModelUUID() + " " + s.entity.String() + ":"
+}
+
+func (s *AgentLoggingStrategy) MakeLogger(ver version.Number) DbLogger {
+ return &entityLogger{state.NewEntityDbLogger(s.st, s.entity, ver)}
+}
+
+func newAgentLoggingStrategy(ctxt httpContext) LoggingStrategy {
+ return &AgentLoggingStrategy{ctxt: ctxt}
+}
+
+func newLogSinkHandler(h httpContext, logDir string, newStrategy func(httpContext) LoggingStrategy) http.Handler {
logPath := filepath.Join(logDir, "logsink.log")
if err := primeLogFile(logPath); err != nil {
@@ -33,7 +82,8 @@ func newLogSinkHandler(h httpContext, logDir string) http.Handler {
}
return &logSinkHandler{
- ctxt: h,
+ ctxt: h,
+ newStrategy: newStrategy,
fileLogger: &lumberjack.Logger{
Filename: logPath,
MaxSize: 300, // MB
@@ -55,22 +105,23 @@ func primeLogFile(path string) error {
}
type logSinkHandler struct {
- ctxt httpContext
- fileLogger io.WriteCloser
+ ctxt httpContext
+ newStrategy func(httpContext) LoggingStrategy
+ fileLogger io.WriteCloser
}
// ServeHTTP implements the http.Handler interface.
func (h *logSinkHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+ strategy := h.newStrategy(h.ctxt)
server := websocket.Server{
Handler: func(socket *websocket.Conn) {
defer socket.Close()
- st, entity, err := h.ctxt.stateForRequestAuthenticatedAgent(req)
+ err := strategy.Authenticate(req)
if err != nil {
h.sendError(socket, req, err)
return
}
- tag := entity.Tag()
// Note that this endpoint is agent-only. Thus the only
// callers will necessarily provide their Juju version.
@@ -86,8 +137,8 @@ func (h *logSinkHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return
}
- filePrefix := st.ModelUUID() + " " + tag.String() + ":"
- dbLogger := state.NewEntityDbLogger(st, tag, ver)
+ filePrefix := strategy.FilePrefix()
+ dbLogger := strategy.MakeLogger(ver)
defer dbLogger.Close()
// If we get to here, no more errors to report, so we report a nil
@@ -105,8 +156,7 @@ func (h *logSinkHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if fileErr != nil {
logger.Errorf("logging to logsink.log failed: %v", fileErr)
}
- level, _ := loggo.ParseLevel(m.Level)
- dbErr := dbLogger.Log(m.Time, m.Module, m.Location, level, m.Message)
+ dbErr := dbLogger.Log(&m)
if dbErr != nil {
logger.Errorf("logging to DB failed: %v", err)
}

0 comments on commit eafd1f8

Please sign in to comment.