Skip to content

Commit 082bed2

Browse files
authored
perf: fixes an issue with too many containers (#3144)
1 parent 4aa315a commit 082bed2

File tree

16 files changed

+135
-172
lines changed

16 files changed

+135
-172
lines changed

assets/components/FuzzySearchModal.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ function createFuzzySearchModal() {
3131
initialState: {
3232
container: {
3333
containers: [
34-
new Container("123", new Date(), "image", "test", "command", "host", {}, "status", "running", []),
35-
new Container("345", new Date(), "image", "foo bar", "command", "host", {}, "status", "running", []),
36-
new Container("567", new Date(), "image", "baz", "command", "host", {}, "status", "running", []),
34+
new Container("123", new Date(), "image", "test", "command", "host", {}, "running", []),
35+
new Container("345", new Date(), "image", "foo bar", "command", "host", {}, "running", []),
36+
new Container("567", new Date(), "image", "baz", "command", "host", {}, "running", []),
3737
],
3838
},
3939
},

assets/components/LogViewer/EventSource.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ describe("<ContainerEventSource />", () => {
8888
},
8989
props: {
9090
streamSource: useContainerStream,
91-
entity: new Container("abc", new Date(), "image", "name", "command", "localhost", {}, "status", "created", []),
91+
entity: new Container("abc", new Date(), "image", "name", "command", "localhost", {}, "created", []),
9292
},
9393
});
9494
}

assets/models/Container.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ export class Container {
3535
public readonly command: string,
3636
public readonly host: string,
3737
public readonly labels = {} as Record<string, string>,
38-
public status: string,
3938
public state: ContainerState,
4039
stats: Stat[],
4140
public readonly group?: string,

assets/stores/container.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ export const useContainerStore = defineStore("container", () => {
121121

122122
existingContainers.forEach((c) => {
123123
const existing = allContainersById.value[c.id];
124-
existing.status = c.status;
125124
existing.state = c.state;
126125
existing.health = c.health;
127126
});
@@ -137,7 +136,6 @@ export const useContainerStore = defineStore("container", () => {
137136
c.command,
138137
c.host,
139138
c.labels,
140-
c.status,
141139
c.state,
142140
c.stats,
143141
c.group,

internal/agent/client.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,6 @@ func (c *Client) StreamNewContainers(ctx context.Context, containers chan<- dock
263263
ImageID: resp.Container.ImageId,
264264
Created: resp.Container.Created.AsTime(),
265265
State: resp.Container.State,
266-
Status: resp.Container.Status,
267266
Health: resp.Container.Health,
268267
Host: resp.Container.Host,
269268
Tty: resp.Container.Tty,
@@ -305,7 +304,6 @@ func (c *Client) FindContainer(containerID string) (docker.Container, error) {
305304
ImageID: response.Container.ImageId,
306305
Created: response.Container.Created.AsTime(),
307306
State: response.Container.State,
308-
Status: response.Container.Status,
309307
Health: response.Container.Health,
310308
Host: response.Container.Host,
311309
Tty: response.Container.Tty,
@@ -348,7 +346,6 @@ func (c *Client) ListContainers() ([]docker.Container, error) {
348346
ImageID: container.ImageId,
349347
Created: container.Created.AsTime(),
350348
State: container.State,
351-
Status: container.Status,
352349
Health: container.Health,
353350
Host: container.Host,
354351
Tty: container.Tty,

internal/agent/client_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,19 @@ func init() {
9494
client = &MockedClient{}
9595
client.On("ListContainers").Return([]docker.Container{
9696
{
97-
ID: "123456",
98-
Name: "test",
99-
Host: "localhost",
97+
ID: "123456",
98+
Name: "test",
99+
Host: "localhost",
100+
State: "running",
100101
},
101102
}, nil)
103+
102104
client.On("Host").Return(docker.Host{
103105
ID: "localhost",
104106
Endpoint: "local",
105107
Name: "local",
106108
})
109+
107110
client.On("ContainerEvents", mock.Anything, mock.AnythingOfType("chan<- docker.ContainerEvent")).Return(nil).Run(func(args mock.Arguments) {
108111
time.Sleep(5 * time.Second)
109112
})
@@ -116,7 +119,6 @@ func init() {
116119
ImageID: "test",
117120
StartedAt: &time.Time{},
118121
State: "running",
119-
Status: "running",
120122
Health: "healthy",
121123
Group: "test",
122124
Command: "test",
@@ -151,7 +153,6 @@ func TestFindContainer(t *testing.T) {
151153
ImageID: "test",
152154
StartedAt: &time.Time{},
153155
State: "running",
154-
Status: "running",
155156
Health: "healthy",
156157
Group: "test",
157158
Command: "test",
@@ -181,7 +182,6 @@ func TestListContainers(t *testing.T) {
181182
ImageID: "test",
182183
StartedAt: &time.Time{},
183184
State: "running",
184-
Status: "running",
185185
Health: "healthy",
186186
Group: "test",
187187
Command: "test",

internal/agent/server.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ func (s *server) FindContainer(ctx context.Context, in *pb.FindContainerRequest)
182182
Command: container.Command,
183183
Created: timestamppb.New(container.Created),
184184
State: container.State,
185-
Status: container.Status,
186185
Health: container.Health,
187186
Host: container.Host,
188187
Tty: container.Tty,
@@ -224,7 +223,6 @@ func (s *server) ListContainers(ctx context.Context, in *pb.ListContainersReques
224223
ImageId: container.ImageID,
225224
Created: timestamppb.New(container.Created),
226225
State: container.State,
227-
Status: container.Status,
228226
Health: container.Health,
229227
Host: container.Host,
230228
Tty: container.Tty,
@@ -269,7 +267,6 @@ func (s *server) StreamContainerStarted(in *pb.StreamContainerStartedRequest, ou
269267
ImageId: container.ImageID,
270268
Created: timestamppb.New(container.Created),
271269
State: container.State,
272-
Status: container.Status,
273270
Health: container.Health,
274271
Host: container.Host,
275272
Tty: container.Tty,

internal/docker/client.go

Lines changed: 69 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"fmt"
66
"io"
77
"path/filepath"
8-
"regexp"
98
"sort"
109
"strconv"
1110
"strings"
@@ -176,37 +175,15 @@ func NewRemoteClient(f map[string][]string, host Host) (Client, error) {
176175
return NewClient(cli, filterArgs, host), nil
177176
}
178177

178+
// Finds a container by id, skipping the filters
179179
func (d *httpClient) FindContainer(id string) (Container, error) {
180180
log.Debugf("finding container with id: %s", id)
181-
var container Container
182-
containers, err := d.ListContainers()
183-
if err != nil {
184-
return container, err
185-
}
186-
187-
found := false
188-
for _, c := range containers {
189-
if c.ID == id {
190-
container = c
191-
found = true
192-
break
193-
}
194-
}
195-
if !found {
196-
return container, fmt.Errorf("unable to find container with id: %s", id)
197-
}
198-
199-
if json, err := d.cli.ContainerInspect(context.Background(), container.ID); err == nil {
200-
container.Tty = json.Config.Tty
201-
if startedAt, err := time.Parse(time.RFC3339Nano, json.State.StartedAt); err == nil {
202-
utc := startedAt.UTC()
203-
container.StartedAt = &utc
204-
}
181+
if json, err := d.cli.ContainerInspect(context.Background(), id); err == nil {
182+
return newContainerFromJSON(json, d.host.ID), nil
205183
} else {
206-
return container, err
184+
return Container{}, err
207185
}
208186

209-
return container, nil
210187
}
211188

212189
func (d *httpClient) ContainerActions(action ContainerAction, containerID string) error {
@@ -223,6 +200,7 @@ func (d *httpClient) ContainerActions(action ContainerAction, containerID string
223200
}
224201

225202
func (d *httpClient) ListContainers() ([]Container, error) {
203+
log.Debugf("listing containers with filters: %v", d.filters)
226204
containerListOptions := container.ListOptions{
227205
Filters: d.filters,
228206
All: true,
@@ -234,33 +212,7 @@ func (d *httpClient) ListContainers() ([]Container, error) {
234212

235213
var containers = make([]Container, 0, len(list))
236214
for _, c := range list {
237-
name := "no name"
238-
if len(c.Names) > 0 {
239-
name = strings.TrimPrefix(c.Names[0], "/")
240-
}
241-
242-
group := ""
243-
if c.Labels["dev.dozzle.group"] != "" {
244-
group = c.Labels["dev.dozzle.group"]
245-
}
246-
247-
container := Container{
248-
ID: c.ID[:12],
249-
Names: c.Names,
250-
Name: name,
251-
Image: c.Image,
252-
ImageID: c.ImageID,
253-
Command: c.Command,
254-
Created: time.Unix(c.Created, 0),
255-
State: c.State,
256-
Status: c.Status,
257-
Host: d.host.ID,
258-
Health: findBetweenParentheses(c.Status),
259-
Labels: c.Labels,
260-
Stats: utils.NewRingBuffer[ContainerStat](300), // 300 seconds of stats
261-
Group: group,
262-
}
263-
containers = append(containers, container)
215+
containers = append(containers, newContainer(c, d.host.ID))
264216
}
265217

266218
sort.Slice(containers, func(i, j int) bool {
@@ -398,11 +350,69 @@ func (d *httpClient) SystemInfo() system.Info {
398350
return d.info
399351
}
400352

401-
var PARENTHESIS_RE = regexp.MustCompile(`\(([a-zA-Z]+)\)`)
353+
func newContainer(c types.Container, host string) Container {
354+
name := "no name"
355+
if len(c.Names) > 0 {
356+
name = strings.TrimPrefix(c.Names[0], "/")
357+
}
402358

403-
func findBetweenParentheses(s string) string {
404-
if results := PARENTHESIS_RE.FindStringSubmatch(s); results != nil {
405-
return results[1]
359+
group := ""
360+
if c.Labels["dev.dozzle.group"] != "" {
361+
group = c.Labels["dev.dozzle.group"]
362+
}
363+
return Container{
364+
ID: c.ID[:12],
365+
Name: name,
366+
Image: c.Image,
367+
ImageID: c.ImageID,
368+
Command: c.Command,
369+
Created: time.Unix(c.Created, 0),
370+
State: c.State,
371+
Host: host,
372+
Labels: c.Labels,
373+
Stats: utils.NewRingBuffer[ContainerStat](300), // 300 seconds of stats
374+
Group: group,
406375
}
407-
return ""
376+
}
377+
378+
func newContainerFromJSON(c types.ContainerJSON, host string) Container {
379+
name := "no name"
380+
if len(c.Name) > 0 {
381+
name = strings.TrimPrefix(c.Name, "/")
382+
}
383+
384+
group := ""
385+
if c.Config.Labels["dev.dozzle.group"] != "" {
386+
group = c.Config.Labels["dev.dozzle.group"]
387+
}
388+
389+
container := Container{
390+
ID: c.ID[:12],
391+
Name: name,
392+
Image: c.Image,
393+
ImageID: c.Image,
394+
Command: strings.Join(c.Config.Entrypoint, " ") + " " + strings.Join(c.Config.Cmd, " "),
395+
State: c.State.Status,
396+
Host: host,
397+
Labels: c.Config.Labels,
398+
Stats: utils.NewRingBuffer[ContainerStat](300), // 300 seconds of stats
399+
Group: group,
400+
Tty: c.Config.Tty,
401+
}
402+
403+
if startedAt, err := time.Parse(time.RFC3339Nano, c.State.StartedAt); err == nil {
404+
utc := startedAt.UTC()
405+
container.StartedAt = &utc
406+
}
407+
408+
if createdAt, err := time.Parse(time.RFC3339Nano, c.Created); err == nil {
409+
utc := createdAt.UTC()
410+
container.Created = utc
411+
}
412+
413+
if c.State.Health != nil {
414+
container.Health = strings.ToLower(c.State.Health.Status)
415+
}
416+
417+
return container
408418
}

0 commit comments

Comments
 (0)