Skip to content

Commit c36f363

Browse files
committed
Merge branch 'main' of https://github.com/coder/coder into bq/filter-by-user
2 parents d873e17 + 00502dc commit c36f363

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1183
-659
lines changed

cli/testdata/coder_list_--output_json.golden

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"workspace_id": "===========[workspace ID]===========",
2424
"workspace_name": "test-workspace",
2525
"workspace_owner_id": "==========[first user ID]===========",
26-
"workspace_owner_username": "testuser",
26+
"workspace_owner_name": "testuser",
2727
"template_version_id": "============[version ID]============",
2828
"template_version_name": "===========[version name]===========",
2929
"build_number": 1,

coderd/apidoc/docs.go

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/coderd.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ func New(options *Options) *API {
572572
TemplateScheduleStore: options.TemplateScheduleStore,
573573
UserQuietHoursScheduleStore: options.UserQuietHoursScheduleStore,
574574
AccessControlStore: options.AccessControlStore,
575-
FileCache: files.NewFromStore(options.Database),
575+
FileCache: files.NewFromStore(options.Database, options.PrometheusRegistry),
576576
Experiments: experiments,
577577
WebpushDispatcher: options.WebPushDispatcher,
578578
healthCheckGroup: &singleflight.Group[string, *healthsdk.HealthcheckReport]{},
@@ -860,7 +860,7 @@ func New(options *Options) *API {
860860
next.ServeHTTP(w, r)
861861
})
862862
},
863-
// httpmw.CSRF(options.DeploymentValues.HTTPCookies),
863+
httpmw.CSRF(options.DeploymentValues.HTTPCookies),
864864
)
865865

866866
// This incurs a performance hit from the middleware, but is required to make sure

coderd/database/dbmem/dbmem.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5131,7 +5131,9 @@ func (q *FakeQuerier) GetTelemetryItem(_ context.Context, key string) (database.
51315131
}
51325132

51335133
func (q *FakeQuerier) GetTelemetryItems(_ context.Context) ([]database.TelemetryItem, error) {
5134-
return q.telemetryItems, nil
5134+
q.mutex.RLock()
5135+
defer q.mutex.RUnlock()
5136+
return slices.Clone(q.telemetryItems), nil
51355137
}
51365138

51375139
func (q *FakeQuerier) GetTemplateAppInsights(ctx context.Context, arg database.GetTemplateAppInsightsParams) ([]database.GetTemplateAppInsightsRow, error) {
@@ -9962,6 +9964,7 @@ func (q *FakeQuerier) InsertWorkspaceApp(_ context.Context, arg database.InsertW
99629964
Hidden: arg.Hidden,
99639965
DisplayOrder: arg.DisplayOrder,
99649966
OpenIn: arg.OpenIn,
9967+
DisplayGroup: arg.DisplayGroup,
99659968
}
99669969
q.workspaceApps = append(q.workspaceApps, workspaceApp)
99679970
return workspaceApp, nil

coderd/files/cache.go

Lines changed: 111 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"sync"
88

99
"github.com/google/uuid"
10+
"github.com/prometheus/client_golang/prometheus"
11+
"github.com/prometheus/client_golang/prometheus/promauto"
1012
"golang.org/x/xerrors"
1113

1214
archivefs "github.com/coder/coder/v2/archive/fs"
@@ -16,22 +18,78 @@ import (
1618

1719
// NewFromStore returns a file cache that will fetch files from the provided
1820
// database.
19-
func NewFromStore(store database.Store) *Cache {
20-
fetcher := func(ctx context.Context, fileID uuid.UUID) (fs.FS, error) {
21+
func NewFromStore(store database.Store, registerer prometheus.Registerer) *Cache {
22+
fetch := func(ctx context.Context, fileID uuid.UUID) (cacheEntryValue, error) {
2123
file, err := store.GetFileByID(ctx, fileID)
2224
if err != nil {
23-
return nil, xerrors.Errorf("failed to read file from database: %w", err)
25+
return cacheEntryValue{}, xerrors.Errorf("failed to read file from database: %w", err)
2426
}
2527

2628
content := bytes.NewBuffer(file.Data)
27-
return archivefs.FromTarReader(content), nil
29+
return cacheEntryValue{
30+
FS: archivefs.FromTarReader(content),
31+
size: int64(content.Len()),
32+
}, nil
2833
}
2934

30-
return &Cache{
35+
return New(fetch, registerer)
36+
}
37+
38+
func New(fetch fetcher, registerer prometheus.Registerer) *Cache {
39+
return (&Cache{
3140
lock: sync.Mutex{},
3241
data: make(map[uuid.UUID]*cacheEntry),
33-
fetcher: fetcher,
34-
}
42+
fetcher: fetch,
43+
}).registerMetrics(registerer)
44+
}
45+
46+
func (c *Cache) registerMetrics(registerer prometheus.Registerer) *Cache {
47+
subsystem := "file_cache"
48+
f := promauto.With(registerer)
49+
50+
c.currentCacheSize = f.NewGauge(prometheus.GaugeOpts{
51+
Namespace: "coderd",
52+
Subsystem: subsystem,
53+
Name: "open_files_size_bytes_current",
54+
Help: "The current amount of memory of all files currently open in the file cache.",
55+
})
56+
57+
c.totalCacheSize = f.NewCounter(prometheus.CounterOpts{
58+
Namespace: "coderd",
59+
Subsystem: subsystem,
60+
Name: "open_files_size_bytes_total",
61+
Help: "The total amount of memory ever opened in the file cache. This number never decrements.",
62+
})
63+
64+
c.currentOpenFiles = f.NewGauge(prometheus.GaugeOpts{
65+
Namespace: "coderd",
66+
Subsystem: subsystem,
67+
Name: "open_files_current",
68+
Help: "The count of unique files currently open in the file cache.",
69+
})
70+
71+
c.totalOpenedFiles = f.NewCounter(prometheus.CounterOpts{
72+
Namespace: "coderd",
73+
Subsystem: subsystem,
74+
Name: "open_files_total",
75+
Help: "The total count of unique files ever opened in the file cache.",
76+
})
77+
78+
c.currentOpenFileReferences = f.NewGauge(prometheus.GaugeOpts{
79+
Namespace: "coderd",
80+
Subsystem: subsystem,
81+
Name: "open_file_refs_current",
82+
Help: "The count of file references currently open in the file cache. Multiple references can be held for the same file.",
83+
})
84+
85+
c.totalOpenFileReferences = f.NewCounter(prometheus.CounterOpts{
86+
Namespace: "coderd",
87+
Subsystem: subsystem,
88+
Name: "open_file_refs_total",
89+
Help: "The total number of file references ever opened in the file cache.",
90+
})
91+
92+
return c
3593
}
3694

3795
// Cache persists the files for template versions, and is used by dynamic
@@ -43,15 +101,34 @@ type Cache struct {
43101
lock sync.Mutex
44102
data map[uuid.UUID]*cacheEntry
45103
fetcher
104+
105+
// metrics
106+
cacheMetrics
107+
}
108+
109+
type cacheMetrics struct {
110+
currentOpenFileReferences prometheus.Gauge
111+
totalOpenFileReferences prometheus.Counter
112+
113+
currentOpenFiles prometheus.Gauge
114+
totalOpenedFiles prometheus.Counter
115+
116+
currentCacheSize prometheus.Gauge
117+
totalCacheSize prometheus.Counter
118+
}
119+
120+
type cacheEntryValue struct {
121+
fs.FS
122+
size int64
46123
}
47124

48125
type cacheEntry struct {
49126
// refCount must only be accessed while the Cache lock is held.
50127
refCount int
51-
value *lazy.ValueWithError[fs.FS]
128+
value *lazy.ValueWithError[cacheEntryValue]
52129
}
53130

54-
type fetcher func(context.Context, uuid.UUID) (fs.FS, error)
131+
type fetcher func(context.Context, uuid.UUID) (cacheEntryValue, error)
55132

56133
// Acquire will load the fs.FS for the given file. It guarantees that parallel
57134
// calls for the same fileID will only result in one fetch, and that parallel
@@ -66,27 +143,40 @@ func (c *Cache) Acquire(ctx context.Context, fileID uuid.UUID) (fs.FS, error) {
66143
it, err := c.prepare(ctx, fileID).Load()
67144
if err != nil {
68145
c.Release(fileID)
146+
return nil, err
69147
}
70-
return it, err
148+
return it.FS, err
71149
}
72150

73-
func (c *Cache) prepare(ctx context.Context, fileID uuid.UUID) *lazy.ValueWithError[fs.FS] {
151+
func (c *Cache) prepare(ctx context.Context, fileID uuid.UUID) *lazy.ValueWithError[cacheEntryValue] {
74152
c.lock.Lock()
75153
defer c.lock.Unlock()
76154

77155
entry, ok := c.data[fileID]
78156
if !ok {
79-
value := lazy.NewWithError(func() (fs.FS, error) {
80-
return c.fetcher(ctx, fileID)
157+
value := lazy.NewWithError(func() (cacheEntryValue, error) {
158+
val, err := c.fetcher(ctx, fileID)
159+
160+
// Always add to the cache size the bytes of the file loaded.
161+
if err == nil {
162+
c.currentCacheSize.Add(float64(val.size))
163+
c.totalCacheSize.Add(float64(val.size))
164+
}
165+
166+
return val, err
81167
})
82168

83169
entry = &cacheEntry{
84170
value: value,
85171
refCount: 0,
86172
}
87173
c.data[fileID] = entry
174+
c.currentOpenFiles.Inc()
175+
c.totalOpenedFiles.Inc()
88176
}
89177

178+
c.currentOpenFileReferences.Inc()
179+
c.totalOpenFileReferences.Inc()
90180
entry.refCount++
91181
return entry.value
92182
}
@@ -105,11 +195,19 @@ func (c *Cache) Release(fileID uuid.UUID) {
105195
return
106196
}
107197

198+
c.currentOpenFileReferences.Dec()
108199
entry.refCount--
109200
if entry.refCount > 0 {
110201
return
111202
}
112203

204+
c.currentOpenFiles.Dec()
205+
206+
ev, err := entry.value.Load()
207+
if err == nil {
208+
c.currentCacheSize.Add(-1 * float64(ev.size))
209+
}
210+
113211
delete(c.data, fileID)
114212
}
115213

0 commit comments

Comments
 (0)