| 260 | } |
| 261 | fmt.Fprintf(&sb, "$%d", base+col+1) |
| 262 | } |
| 263 | sb.WriteByte(')') |
| 264 | |
| 265 | args = append(args, queryLogEntryInsertArgs(e)...) |
| 266 | } |
| 267 | |
| 268 | if _, err := db.ExecContext(ctx, sb.String(), args...); err != nil { |
| 269 | return fmt.Errorf("insert query_log entries: %w", err) |
| 270 | } |
| 271 | return nil |
| 272 | } |
| 273 | |
| 274 | // truncateQuery truncates a query string to maxQueryLength. |
| 275 | func truncateQuery(q string) string { |
| 276 | if len(q) > maxQueryLength { |
| 277 | return q[:maxQueryLength] |
| 278 | } |
| 279 | return q |
| 280 | } |
| 281 | |
| 282 | // BoundQueryLogText is the shared 4096-byte UTF-8-safe cap used by the |
| 283 | // durable query log and the PostHog OTLP query-text handler. |
| 284 | func BoundQueryLogText(text string) string { |
| 285 | return boundQueryLogText(text) |
| 286 | } |
| 287 | |
| 288 | // boundQueryLogText caps control-plane query-log text before it reaches logs, |
| 289 | // in-memory queues, normalization, or RPC serialization. Clone the retained |
| 290 | // text so a bounded entry cannot keep a much larger query allocation alive. |
| 291 | func boundQueryLogText(text string) string { |
| 292 | if text == "" { |
| 293 | return "" |
| 294 | } |
| 295 | if len(text) > maxQueryLength { |
| 296 | end := maxQueryLength |
| 297 | for end > 0 && !utf8.RuneStart(text[end]) { |
| 298 | end-- |
| 299 | } |
| 300 | text = text[:end] |
| 301 | } |
| 302 | return strings.Clone(text) |
| 303 | } |
| 304 | |