• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / storage / 25738155938

12 May 2026 01:38PM UTC coverage: 39.251% (-35.1%) from 74.366%
25738155938

Pull #1094

github

web-flow
Merge 0f3efcca0 into defbbb616
Pull Request #1094: feat: embedded vector store

2188 of 6152 branches covered (35.57%)

Branch coverage included in aggregate %.

88 of 280 new or added lines in 6 files covered. (31.43%)

3689 existing lines in 165 files now uncovered.

4312 of 10408 relevant lines covered (41.43%)

34.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.11
/src/http/plugins/log-request.ts
1
import { logSchema, serializeReplyLog, serializeRequestLog } from '@internal/monitoring'
2
import type { FastifyReply, FastifyRequest } from 'fastify'
3
import fastifyPlugin from 'fastify-plugin'
4

5
interface RequestLoggerOptions {
6
  excludeUrls?: string[]
7
}
8

9
type BivariantHandler<Args extends unknown[], Return> = {
10
  bivarianceHack(...args: Args): Return
11
}['bivarianceHack']
12

13
declare module 'http' {
14
  interface IncomingMessage {
15
    executionError?: Error
16
    resources?: string[]
17
  }
18
}
19

20
declare module 'fastify' {
21
  interface FastifyRequest {
22
    executionError?: Error
23
    operation?: { type: string }
24
    resources?: string[]
25
    startTime: number
26
    executionTime?: number
27
  }
28

29
  interface FastifyContextConfig {
30
    operation?: { type: string }
31
    resources?: BivariantHandler<[req: FastifyRequest], string[]>
32
    logMetadata?: BivariantHandler<[req: FastifyRequest], Record<string, unknown>>
33
  }
34
}
35

36
/**
37
 * Request logger plugin
38
 * @param options
39
 */
40
export const logRequest = (options: RequestLoggerOptions) =>
9✔
41
  fastifyPlugin(
42
    async (fastify) => {
43
      fastify.addHook('onRequest', async (req, res) => {
9✔
44
        req.startTime = Date.now()
9✔
45

46
        res.raw.once('close', () => {
9✔
47
          if (req.raw.aborted) {
9!
UNCOV
48
            doRequestLog(req, {
×
49
              excludeUrls: options.excludeUrls,
50
              statusCode: 'ABORTED REQ',
51
              responseTime: (Date.now() - req.startTime) / 1000,
52
            })
UNCOV
53
            return
×
54
          }
55

56
          if (!res.raw.writableFinished) {
9!
57
            doRequestLog(req, {
9✔
58
              excludeUrls: options.excludeUrls,
59
              statusCode: 'ABORTED RES',
60
              responseTime: (Date.now() - req.startTime) / 1000,
61
            })
62
          }
63
        })
64
      })
65

66
      /**
67
       * Adds req.resources and req.operation to the request object
68
       */
69
      fastify.addHook('preHandler', async (req) => {
9✔
70
        let resources = req.resources
8✔
71

72
        if (resources === undefined) {
8✔
73
          resources = req.routeOptions.config.resources?.(req)
7✔
74
        }
75

76
        if (resources === undefined) {
8✔
77
          resources = req.raw.resources
6✔
78
        }
79

80
        if (resources === undefined) {
8✔
81
          const resourceFromParams = getResourceFromParams(req.params)
6✔
82
          resources = resourceFromParams ? [resourceFromParams] : []
6✔
83
        }
84

85
        if (resources && resources.length > 0) {
8✔
86
          for (let index = 0; index < resources.length; index++) {
4✔
87
            const resource = resources[index]
5✔
88
            if (!resource.startsWith('/')) {
5✔
89
              resources[index] = `/${resource}`
3✔
90
            }
91
          }
92
        }
93

94
        req.resources = resources
8✔
95
        req.operation = req.routeOptions.config.operation
8✔
96

97
        if (req.operation && typeof req.opentelemetry === 'function') {
8!
98
          req.opentelemetry()?.span?.setAttribute('http.operation', req.operation.type)
×
99
        }
100
      })
101

102
      fastify.addHook('onSend', async (req, _, payload) => {
9✔
103
        req.executionTime = Date.now() - req.startTime
9✔
104
        return payload
9✔
105
      })
106

107
      fastify.addHook('onResponse', async (req, reply) => {
9✔
108
        doRequestLog(req, {
9✔
109
          reply,
110
          excludeUrls: options.excludeUrls,
111
          statusCode: reply.statusCode,
112
          responseTime: reply.elapsedTime,
113
          executionTime: req.executionTime,
114
        })
115
      })
116
    },
117
    { name: 'log-request' }
118
  )
119

120
interface LogRequestOptions {
121
  reply?: FastifyReply
122
  excludeUrls?: string[]
123
  statusCode: number | 'ABORTED REQ' | 'ABORTED RES'
124
  responseTime: number
125
  executionTime?: number
126
}
127

128
function doRequestLog(req: FastifyRequest, options: LogRequestOptions) {
129
  if (options.excludeUrls?.includes(req.url)) {
18!
130
    return
×
131
  }
132

133
  const requestLog = serializeRequestLog(req)
18✔
134
  const replyLog = serializeReplyLog(options.reply)
18✔
135
  const rMeth = requestLog.method
18✔
136
  const rUrl = requestLog.url
18✔
137
  const uAgent = req.headers['user-agent']
18✔
138
  const rId = req.id
18✔
139
  const cIP = req.ip
18✔
140
  const statusCode = options.statusCode
18✔
141
  const error = req.raw.executionError || req.executionError
18✔
142
  const tenantId = req.tenantId
18✔
143

144
  let reqMetadata: Record<string, unknown> = {}
18✔
145

146
  if (req.routeOptions.config.logMetadata) {
18!
UNCOV
147
    try {
×
UNCOV
148
      reqMetadata = req.routeOptions.config.logMetadata(req)
×
149

UNCOV
150
      if (reqMetadata) {
×
UNCOV
151
        try {
×
UNCOV
152
          if (typeof req.opentelemetry === 'function') {
×
153
            req.opentelemetry()?.span?.setAttribute('http.metadata', JSON.stringify(reqMetadata))
×
154
          }
155
        } catch (e) {
156
          // do nothing
157
          logSchema.warning(req.log, 'Failed to serialize log metadata', {
×
158
            type: 'otel',
159
            tenantId,
160
            project: tenantId,
161
            reqId: rId,
162
            sbReqId: req.sbReqId,
163
            error: e,
164
          })
165
        }
166
      }
167
    } catch (e) {
168
      logSchema.error(req.log, 'Failed to get log metadata', {
×
169
        type: 'request',
170
        tenantId,
171
        project: tenantId,
172
        reqId: rId,
173
        sbReqId: req.sbReqId,
174
        error: e,
175
      })
176
    }
177
  }
178

179
  const buildLogMessage = `${tenantId} | ${rMeth} | ${statusCode} | ${cIP} | ${rId} | ${rUrl} | ${uAgent}`
18✔
180

181
  logSchema.request(req.log, buildLogMessage, {
18✔
182
    type: 'request',
183
    tenantId,
184
    project: tenantId,
185
    reqId: rId,
186
    sbReqId: req.sbReqId,
187
    req: requestLog,
188
    reqMetadata,
189
    res: replyLog,
190
    responseTime: options.responseTime,
191
    executionTime: options.executionTime,
192
    error,
193
    owner: req.owner,
194
    role: req.jwtPayload?.role,
195
    resources: req.resources,
196
    operation: req.operation?.type ?? req.routeOptions.config.operation?.type,
36✔
197
    serverTimes: req.serverTimings,
198
  })
199
}
200

201
function getResourceFromParams(params: unknown): string {
202
  if (!params || typeof params !== 'object') {
6!
203
    return ''
×
204
  }
205

206
  let resource = ''
6✔
207
  let first = true
6✔
208

209
  for (const key in params) {
6✔
210
    if (!Object.prototype.hasOwnProperty.call(params, key)) {
3!
211
      continue
×
212
    }
213

214
    if (!first) {
3✔
215
      resource += '/'
1✔
216
    }
217

218
    const value = (params as Record<string, unknown>)[key]
3✔
219
    resource += value == null ? '' : String(value)
3!
220
    first = false
3✔
221
  }
222

223
  return resource
6✔
224
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc