Skip to content

Commit a19f91a

Browse files
authored
improve logging: catalog http server, op-con resolver (#1564)
Signed-off-by: Joe Lanford <[email protected]>
1 parent f14e9d0 commit a19f91a

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

catalogd/internal/serverutil/serverutil.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ package serverutil
33
import (
44
"crypto/tls"
55
"fmt"
6+
"io"
67
"net"
78
"net/http"
89
"time"
910

11+
"github.com/go-logr/logr"
12+
"github.com/gorilla/handlers"
1013
ctrl "sigs.k8s.io/controller-runtime"
1114
"sigs.k8s.io/controller-runtime/pkg/certwatcher"
1215
"sigs.k8s.io/controller-runtime/pkg/manager"
@@ -40,12 +43,16 @@ func AddCatalogServerToManager(mgr ctrl.Manager, cfg CatalogServerConfig, tlsFil
4043

4144
shutdownTimeout := 30 * time.Second
4245

46+
l := mgr.GetLogger().WithName("catalogd-http-server")
47+
handler := catalogdmetrics.AddMetricsToHandler(cfg.LocalStorage.StorageServerHandler())
48+
handler = logrLoggingHandler(l, handler)
49+
4350
catalogServer := manager.Server{
4451
Name: "catalogs",
4552
OnlyServeWhenLeader: true,
4653
Server: &http.Server{
4754
Addr: cfg.CatalogAddr,
48-
Handler: catalogdmetrics.AddMetricsToHandler(cfg.LocalStorage.StorageServerHandler()),
55+
Handler: handler,
4956
ReadTimeout: 5 * time.Second,
5057
// TODO: Revert this to 10 seconds if/when the API
5158
// evolves to have significantly smaller responses
@@ -62,3 +69,31 @@ func AddCatalogServerToManager(mgr ctrl.Manager, cfg CatalogServerConfig, tlsFil
6269

6370
return nil
6471
}
72+
73+
func logrLoggingHandler(l logr.Logger, handler http.Handler) http.Handler {
74+
return handlers.CustomLoggingHandler(nil, handler, func(_ io.Writer, params handlers.LogFormatterParams) {
75+
// extract parameters used in apache common log format, but then log using `logr` to remain consistent
76+
// with other loggers used in this codebase.
77+
username := "-"
78+
if params.URL.User != nil {
79+
if name := params.URL.User.Username(); name != "" {
80+
username = name
81+
}
82+
}
83+
84+
host, _, err := net.SplitHostPort(params.Request.RemoteAddr)
85+
if err != nil {
86+
host = params.Request.RemoteAddr
87+
}
88+
89+
uri := params.Request.RequestURI
90+
if params.Request.ProtoMajor == 2 && params.Request.Method == http.MethodConnect {
91+
uri = params.Request.Host
92+
}
93+
if uri == "" {
94+
uri = params.URL.RequestURI()
95+
}
96+
97+
l.Info("handled request", "host", host, "username", username, "method", params.Request.Method, "uri", uri, "protocol", params.Request.Proto, "status", params.StatusCode, "size", params.Size)
98+
})
99+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ require (
1313
github.com/go-logr/logr v1.4.2
1414
github.com/google/go-cmp v0.6.0
1515
github.com/google/go-containerregistry v0.20.3
16+
github.com/gorilla/handlers v1.5.2
1617
github.com/klauspost/compress v1.17.11
1718
github.com/onsi/ginkgo/v2 v2.22.2
1819
github.com/onsi/gomega v1.36.2

internal/resolve/catalog.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type foundBundle struct {
3939

4040
// Resolve returns a Bundle from a catalog that needs to get installed on the cluster.
4141
func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtension, installedBundle *ocv1.BundleMetadata) (*declcfg.Bundle, *bsemver.Version, *declcfg.Deprecation, error) {
42+
l := log.FromContext(ctx)
4243
packageName := ext.Spec.Source.Catalog.PackageName
4344
versionRange := ext.Spec.Source.Catalog.Version
4445
channels := ext.Spec.Source.Catalog.Channels
@@ -65,6 +66,15 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio
6566
}
6667
}
6768

69+
type catStat struct {
70+
CatalogName string `json:"catalogName"`
71+
PackageFound bool `json:"packageFound"`
72+
TotalBundles int `json:"totalBundles"`
73+
MatchedBundles int `json:"matchedBundles"`
74+
}
75+
76+
var catStats []*catStat
77+
6878
resolvedBundles := []foundBundle{}
6979
var priorDeprecation *declcfg.Deprecation
7080

@@ -76,6 +86,16 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio
7686
return fmt.Errorf("error getting package %q from catalog %q: %w", packageName, cat.Name, err)
7787
}
7888

89+
cs := catStat{CatalogName: cat.Name}
90+
catStats = append(catStats, &cs)
91+
92+
if isFBCEmpty(packageFBC) {
93+
return nil
94+
}
95+
96+
cs.PackageFound = true
97+
cs.TotalBundles = len(packageFBC.Bundles)
98+
7999
var predicates []filter.Predicate[declcfg.Bundle]
80100
if len(channels) > 0 {
81101
channelSet := sets.New(channels...)
@@ -99,6 +119,7 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio
99119

100120
// Apply the predicates to get the candidate bundles
101121
packageFBC.Bundles = filter.Filter(packageFBC.Bundles, filter.And(predicates...))
122+
cs.MatchedBundles = len(packageFBC.Bundles)
102123
if len(packageFBC.Bundles) == 0 {
103124
return nil
104125
}
@@ -158,6 +179,7 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio
158179

159180
// Check for ambiguity
160181
if len(resolvedBundles) != 1 {
182+
l.Info("resolution failed", "stats", catStats)
161183
return nil, nil, nil, resolutionError{
162184
PackageName: packageName,
163185
Version: versionRange,
@@ -174,12 +196,15 @@ func (r *CatalogResolver) Resolve(ctx context.Context, ext *ocv1.ClusterExtensio
174196

175197
// Run validations against the resolved bundle to ensure only valid resolved bundles are being returned
176198
// Open Question: Should we grab the first valid bundle earlier?
199+
// Answer: No, that would be a hidden resolution input, which we should avoid at all costs; the query can be
200+
// constrained in order to eliminate the invalid bundle from the resolution.
177201
for _, validation := range r.Validations {
178202
if err := validation(resolvedBundle); err != nil {
179203
return nil, nil, nil, fmt.Errorf("validating bundle %q: %w", resolvedBundle.Name, err)
180204
}
181205
}
182206

207+
l.V(4).Info("resolution succeeded", "stats", catStats)
183208
return resolvedBundle, resolvedBundleVersion, priorDeprecation, nil
184209
}
185210

@@ -257,6 +282,9 @@ func CatalogWalker(
257282
return false
258283
})
259284

285+
availableCatalogNames := mapSlice(catalogs, func(c catalogd.ClusterCatalog) string { return c.Name })
286+
l.Info("using ClusterCatalogs for resolution", "catalogs", availableCatalogNames)
287+
260288
for i := range catalogs {
261289
cat := &catalogs[i]
262290

@@ -271,3 +299,18 @@ func CatalogWalker(
271299
return nil
272300
}
273301
}
302+
303+
func isFBCEmpty(fbc *declcfg.DeclarativeConfig) bool {
304+
if fbc == nil {
305+
return true
306+
}
307+
return len(fbc.Packages) == 0 && len(fbc.Channels) == 0 && len(fbc.Bundles) == 0 && len(fbc.Deprecations) == 0 && len(fbc.Others) == 0
308+
}
309+
310+
func mapSlice[I any, O any](in []I, f func(I) O) []O {
311+
out := make([]O, len(in))
312+
for i := range in {
313+
out[i] = f(in[i])
314+
}
315+
return out
316+
}

0 commit comments

Comments
 (0)