Skip to content

Commit 4f2f14f

Browse files
authored
Merge pull request #51 from factorysh/features/logs-ui
Add logs text/html endpoint
2 parents 5a48046 + bbc84d6 commit 4f2f14f

File tree

8 files changed

+152
-46
lines changed

8 files changed

+152
-46
lines changed

application/application.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ func New(cfg *conf.Conf) (*Application, error) {
153153
r.Get("/", a.TaskHandler(false))
154154
r.Get("/volumes/*", a.VolumesHandler(6, false))
155155
r.Get("/logs", a.TaskLogsHandler(false))
156+
r.Get("/logz", a.TaskLogzHandler(false))
156157
})
157158
r.Group(func(r chi.Router) {
158159
r.Use(a.RefererMiddleware)
@@ -166,6 +167,7 @@ func New(cfg *conf.Conf) (*Application, error) {
166167
r.Get("/", a.TaskHandler(true))
167168
r.Get("/volumes/*", a.VolumesHandler(6, true))
168169
r.Get("/logs", a.TaskLogsHandler(true))
170+
r.Get("/logz", a.TaskLogzHandler(true))
169171
})
170172
r.Group(func(r chi.Router) {
171173
r.Use(a.RefererMiddleware)

application/logs.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package application
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"fmt"
7+
"html/template"
8+
"net/http"
9+
10+
"github.com/docker/docker/pkg/stdcopy"
11+
"github.com/factorysh/microdensity/html"
12+
"github.com/factorysh/microdensity/task"
13+
)
14+
15+
func (a *Application) renderLogsPageForTask(ctx context.Context, t *task.Task, w http.ResponseWriter) error {
16+
17+
reader, err := t.Logs(ctx, false)
18+
if err != nil {
19+
return err
20+
}
21+
22+
var buffer bytes.Buffer
23+
var dropped bytes.Buffer
24+
_, err = stdcopy.StdCopy(&buffer, &dropped, reader)
25+
if err != nil {
26+
return err
27+
}
28+
29+
data, err := NewTaskPage(t, template.HTML(fmt.Sprintf("<pre>%s</pre>", buffer.String())), a.GitlabURL, "Task Logs", "terminal")
30+
if err != nil {
31+
return err
32+
}
33+
34+
p := html.Page{
35+
Domain: a.Domain,
36+
Detail: fmt.Sprintf("%s / %s - logs", t.Service, t.Commit),
37+
Partial: html.Partial{
38+
Template: taskTemplate,
39+
Data: data,
40+
},
41+
}
42+
43+
w.WriteHeader(http.StatusOK)
44+
return p.Render(w)
45+
}

application/result.go

Lines changed: 0 additions & 38 deletions
This file was deleted.

application/task.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,39 @@ func (a *Application) TaskLogsHandler(latest bool) func(http.ResponseWriter, *ht
231231
}
232232

233233
}
234+
235+
// TaskLogzHandler get a logs for a task
236+
func (a *Application) TaskLogzHandler(latest bool) func(http.ResponseWriter, *http.Request) {
237+
238+
return func(w http.ResponseWriter, r *http.Request) {
239+
l := a.logger.With(
240+
zap.String("url", r.URL.String()),
241+
zap.String("service", chi.URLParam(r, "serviceID")),
242+
zap.String("project", chi.URLParam(r, "project")),
243+
zap.String("branch", chi.URLParam(r, "branch")),
244+
zap.String("commit", chi.URLParam(r, "commit")),
245+
)
246+
247+
t, err := a.storage.GetByCommit(
248+
chi.URLParam(r, "serviceID"),
249+
chi.URLParam(r, "project"),
250+
chi.URLParam(r, "branch"),
251+
chi.URLParam(r, "commit"),
252+
latest,
253+
)
254+
if err != nil {
255+
l.Warn("Task get error", zap.Error(err))
256+
w.WriteHeader(http.StatusNotFound)
257+
w.Write([]byte(http.StatusText(http.StatusNotFound)))
258+
return
259+
}
260+
261+
err = a.renderLogsPageForTask(r.Context(), t, w)
262+
if err != nil {
263+
l.Warn("when rendering a logs page", zap.Error(err))
264+
w.WriteHeader(http.StatusInternalServerError)
265+
w.Write([]byte(http.StatusText(http.StatusInternalServerError)))
266+
return
267+
}
268+
}
269+
}

application/task_page.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package application
2+
3+
import (
4+
"html/template"
5+
"net/url"
6+
7+
"github.com/factorysh/microdensity/task"
8+
)
9+
10+
// TaskPage present a page and an associated inner content
11+
type TaskPage struct {
12+
GitlabDomain string
13+
Domain string
14+
Project string
15+
Commit string
16+
Service string
17+
ID string
18+
CreatedAt string
19+
InnerDivClasses string
20+
InnerTitle string
21+
Inner template.HTML
22+
}
23+
24+
// NewTaskPage inits a result for a task
25+
func NewTaskPage(t *task.Task, inner template.HTML, gitlabDomain, InnerTitle, InnerDivClasses string) (*TaskPage, error) {
26+
prettyPath, err := url.PathUnescape(t.Project)
27+
if err != nil {
28+
return nil, err
29+
}
30+
31+
return &TaskPage{
32+
Project: prettyPath,
33+
GitlabDomain: gitlabDomain,
34+
Commit: t.Commit,
35+
Service: t.Service,
36+
ID: t.Id.String(),
37+
CreatedAt: t.Creation.Format("2006-01-02 15:04:05"),
38+
InnerTitle: InnerTitle,
39+
InnerDivClasses: InnerDivClasses,
40+
Inner: inner,
41+
}, nil
42+
}

application/templates/result.html renamed to application/templates/task.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ <h3>Task Description</h3>
88
<li>ID : {{ .ID }}</li>
99
</ul>
1010

11-
<h3>Task Result</h3>
11+
<h3>{{ .InnerTitle }}</h3>
1212

13-
<div class="container task-output">
13+
<div class="{{ .InnerDivClasses }}">
1414
{{ .Inner }}
1515
</div>

application/volume.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import (
1919
var (
2020
// used to ensure embed import
2121
_ embed.FS
22-
//go:embed templates/result.html
23-
resultTemplate string
22+
//go:embed templates/task.html
23+
taskTemplate string
2424
)
2525

2626
// VolumesHandler expose volumes of a task
@@ -65,7 +65,7 @@ func (a *Application) VolumesHandler(basePathLen int, latest bool) http.HandlerF
6565
if _, err := os.Stat(fullPath); os.IsNotExist(err) {
6666
l.Warn("Path not found", zap.Error(err))
6767

68-
data, err := NewResultFromTask(t, "No result for this task", a.GitlabURL)
68+
data, err := NewTaskPage(t, "No result for this task", a.GitlabURL, "Task Result", "container task-output")
6969
if err != nil {
7070
l.Error("when creating result from a task", zap.Error(err))
7171
w.WriteHeader(http.StatusInternalServerError)
@@ -76,7 +76,7 @@ func (a *Application) VolumesHandler(basePathLen int, latest bool) http.HandlerF
7676
Domain: a.Domain,
7777
Detail: fmt.Sprintf("%s / %s", t.Service, t.Commit),
7878
Partial: html.Partial{
79-
Template: resultTemplate,
79+
Template: taskTemplate,
8080
Data: data,
8181
}}
8282

@@ -128,13 +128,13 @@ func (a *Application) renderResultPageForTask(t *task.Task, filePath string, w h
128128
return err
129129
}
130130

131-
data, err := NewResultFromTask(t, template.HTML(content), a.GitlabURL)
131+
data, err := NewTaskPage(t, template.HTML(content), a.GitlabURL, "Task Result", "container task-output")
132132
// create the page
133133
p := html.Page{
134134
Domain: a.Domain,
135135
Detail: fmt.Sprintf("%s / %s", t.Service, t.Commit),
136136
Partial: html.Partial{
137-
Template: resultTemplate,
137+
Template: taskTemplate,
138138
Data: data,
139139
},
140140
}

html/templates/styles.css

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,22 @@ h6 {
6969
background-color: white;
7070
padding: 2rem;
7171
}
72+
73+
.terminal {
74+
min-height: 30%;
75+
padding: 2rem;
76+
background-color: black;
77+
color: white;
78+
border-radius: 1rem;
79+
font-family: monospace;
80+
text-align: left;
81+
}
82+
83+
.terminal pre {
84+
background-color: black;
85+
border-left: none;
86+
margin: 1rem;
87+
padding: 1rem;
88+
overflow-x: scroll;
89+
overflow-y: hidden;
90+
}

0 commit comments

Comments
 (0)