repos / pico

pico services - prose.sh, pastes.sh, imgs.sh, feeds.sh, pgs.sh
git clone https://github.com/picosh/pico.git

commit
1d2e979
parent
63a91e3
author
Eric Bower
date
2024-10-04 01:56:47 +0000 UTC
chore(pgs): better structured logging
1 files changed,  +44, -28
M pgs/api.go
+44, -28
  1@@ -166,7 +166,7 @@ func hasProtocol(url string) bool {
  2 	return isFullUrl
  3 }
  4 
  5-func (h *AssetHandler) handle(w http.ResponseWriter, r *http.Request) {
  6+func (h *AssetHandler) handle(logger *slog.Logger, w http.ResponseWriter, r *http.Request) {
  7 	var redirects []*RedirectRule
  8 	redirectFp, _, _, err := h.Storage.GetObject(h.Bucket, filepath.Join(h.ProjectDir, "_redirects"))
  9 	if err == nil {
 10@@ -174,14 +174,14 @@ func (h *AssetHandler) handle(w http.ResponseWriter, r *http.Request) {
 11 		buf := new(strings.Builder)
 12 		_, err := io.Copy(buf, redirectFp)
 13 		if err != nil {
 14-			h.Logger.Error("io copy", "err", err.Error())
 15+			logger.Error("io copy", "err", err.Error())
 16 			http.Error(w, "cannot read _redirects file", http.StatusInternalServerError)
 17 			return
 18 		}
 19 
 20 		redirects, err = parseRedirectText(buf.String())
 21 		if err != nil {
 22-			h.Logger.Error("could not parse redirect text", "err", err.Error())
 23+			logger.Error("could not parse redirect text", "err", err.Error())
 24 		}
 25 	}
 26 
 27@@ -203,19 +203,23 @@ func (h *AssetHandler) handle(w http.ResponseWriter, r *http.Request) {
 28 					continue
 29 				}
 30 			}
 31-			h.Logger.Info(
 32+			logger.Info(
 33 				"redirecting request",
 34-				"bucket", h.Bucket.Name,
 35-				"url", r.URL,
 36 				"destination", fp.Filepath,
 37 				"status", fp.Status,
 38 			)
 39 			http.Redirect(w, r, fp.Filepath, fp.Status)
 40 			return
 41 		} else if hasProtocol(fp.Filepath) {
 42+			logger.Info(
 43+				"fetching content from external service",
 44+				"destination", fp.Filepath,
 45+				"status", fp.Status,
 46+			)
 47 			// fetch content from url and serve it
 48 			resp, err := http.Get(fp.Filepath)
 49 			if err != nil {
 50+				logger.Error("external service not found", "err", err)
 51 				http.Error(w, "404 not found", http.StatusNotFound)
 52 				return
 53 			}
 54@@ -224,7 +228,7 @@ func (h *AssetHandler) handle(w http.ResponseWriter, r *http.Request) {
 55 			w.WriteHeader(status)
 56 			_, err = io.Copy(w, resp.Body)
 57 			if err != nil {
 58-				h.Logger.Error("io copy", "err", err.Error())
 59+				logger.Error("io copy", "err", err.Error())
 60 			}
 61 			return
 62 		}
 63@@ -251,9 +255,8 @@ func (h *AssetHandler) handle(w http.ResponseWriter, r *http.Request) {
 64 	}
 65 
 66 	if assetFilepath == "" {
 67-		h.Logger.Info(
 68+		logger.Info(
 69 			"asset not found in bucket",
 70-			"bucket", h.Bucket.Name,
 71 			"routes", strings.Join(attempts, ", "),
 72 		)
 73 		// track 404s
 74@@ -265,7 +268,7 @@ func (h *AssetHandler) handle(w http.ResponseWriter, r *http.Request) {
 75 			ch <- view
 76 		} else {
 77 			if !errors.Is(err, shared.ErrAnalyticsDisabled) {
 78-				h.Logger.Error("could not record analytics view", "err", err)
 79+				logger.Error("could not record analytics view", "err", err)
 80 			}
 81 		}
 82 		http.Error(w, "404 not found", http.StatusNotFound)
 83@@ -284,14 +287,14 @@ func (h *AssetHandler) handle(w http.ResponseWriter, r *http.Request) {
 84 		buf := new(strings.Builder)
 85 		_, err := io.Copy(buf, headersFp)
 86 		if err != nil {
 87-			h.Logger.Error("io copy", "err", err.Error())
 88+			logger.Error("io copy", "err", err.Error())
 89 			http.Error(w, "cannot read _headers file", http.StatusInternalServerError)
 90 			return
 91 		}
 92 
 93 		headers, err = parseHeaderText(buf.String())
 94 		if err != nil {
 95-			h.Logger.Error("could not parse header text", "err", err.Error())
 96+			logger.Error("could not parse header text", "err", err.Error())
 97 		}
 98 	}
 99 
100@@ -323,16 +326,13 @@ func (h *AssetHandler) handle(w http.ResponseWriter, r *http.Request) {
101 			ch <- view
102 		} else {
103 			if !errors.Is(err, shared.ErrAnalyticsDisabled) {
104-				h.Logger.Error("could not record analytics view", "err", err)
105+				logger.Error("could not record analytics view", "err", err)
106 			}
107 		}
108 	}
109 
110-	h.Logger.Info(
111+	logger.Info(
112 		"serving asset",
113-		"host", r.Host,
114-		"url", r.URL,
115-		"bucket", h.Bucket.Name,
116 		"asset", assetFilepath,
117 		"status", status,
118 		"contentType", finContentType,
119@@ -342,7 +342,7 @@ func (h *AssetHandler) handle(w http.ResponseWriter, r *http.Request) {
120 	_, err = io.Copy(w, contents)
121 
122 	if err != nil {
123-		h.Logger.Error("io copy", "err", err.Error())
124+		logger.Error("io copy", "err", err.Error())
125 	}
126 }
127 
128@@ -370,22 +370,41 @@ func ServeAsset(fname string, opts *storage.ImgProcessOpts, fromImgs bool, hasPe
129 	cfg := shared.GetCfg(r)
130 	dbpool := shared.GetDB(r)
131 	st := shared.GetStorage(r)
132-	logger := shared.GetLogger(r)
133+	ologger := shared.GetLogger(r)
134+
135+	logger := ologger.With(
136+		"subdomain", subdomain,
137+		"filename", fname,
138+		"url", r.URL,
139+		"host", r.Host,
140+	)
141 
142 	props, err := getProjectFromSubdomain(subdomain)
143 	if err != nil {
144-		logger.Info(err.Error(), "subdomain", subdomain, "filename", fname)
145+		logger.Info(
146+			"could parse project from subdomain",
147+			"err", err,
148+		)
149 		http.Error(w, err.Error(), http.StatusNotFound)
150 		return
151 	}
152 
153+	logger = logger.With(
154+		"project", props.ProjectName,
155+		"user", props.Username,
156+	)
157+
158 	user, err := dbpool.FindUserForName(props.Username)
159 	if err != nil {
160-		logger.Info("user not found", "user", props.Username)
161+		logger.Info("user not found")
162 		http.Error(w, "user not found", http.StatusNotFound)
163 		return
164 	}
165 
166+	logger = logger.With(
167+		"userId", user.ID,
168+	)
169+
170 	projectID := ""
171 	// TODO: this could probably be cleaned up more
172 	// imgs wont have a project directory
173@@ -398,10 +417,7 @@ func ServeAsset(fname string, opts *storage.ImgProcessOpts, fromImgs bool, hasPe
174 		bucket, err = st.GetBucket(shared.GetAssetBucketName(user.ID))
175 		project, err := dbpool.FindProjectByName(user.ID, props.ProjectName)
176 		if err != nil {
177-			logger.Info(
178-				"project not found",
179-				"projectName", props.ProjectName,
180-			)
181+			logger.Info("project not found")
182 			http.Error(w, "project not found", http.StatusNotFound)
183 			return
184 		}
185@@ -415,7 +431,7 @@ func ServeAsset(fname string, opts *storage.ImgProcessOpts, fromImgs bool, hasPe
186 	}
187 
188 	if err != nil {
189-		logger.Info("bucket not found", "user", props.Username)
190+		logger.Info("bucket not found")
191 		http.Error(w, "bucket not found", http.StatusNotFound)
192 		return
193 	}
194@@ -435,7 +451,7 @@ func ServeAsset(fname string, opts *storage.ImgProcessOpts, fromImgs bool, hasPe
195 		ProjectID:      projectID,
196 	}
197 
198-	asset.handle(w, r)
199+	asset.handle(logger, w, r)
200 }
201 
202 type HasPerm = func(proj *db.Project) bool
203@@ -526,7 +542,7 @@ func StartApiServer() {
204 
205 	portStr := fmt.Sprintf(":%s", cfg.Port)
206 	logger.Info(
207-		"Starting server on port",
208+		"starting server on port",
209 		"port", cfg.Port,
210 		"domain", cfg.Domain,
211 	)