@@ -3,7 +3,7 @@ import { AnalyticsEvent } from '@codebuff/common/constants/analytics-events'
33import db from '@codebuff/common/db'
44import * as schema from '@codebuff/common/db/schema'
55import { getNextQuotaReset } from '@codebuff/common/util/dates'
6- import { logger } from '@codebuff/common/util/logger '
6+ import { getErrorObject } from '@codebuff/common/util/error '
77import { eq } from 'drizzle-orm'
88
99import { calculateOrganizationUsageAndBalance } from './org-billing'
@@ -25,16 +25,6 @@ export interface OrganizationCreditAlert {
2525 metadata ?: Record < string , any >
2626}
2727
28- export interface OrganizationUsageMetrics {
29- organizationId : string
30- totalCreditsConsumed : number
31- uniqueUsers : number
32- repositoryCount : number
33- averageCreditsPerUser : number
34- topRepository : string
35- timeframe : 'daily' | 'weekly' | 'monthly'
36- }
37-
3828export interface OrganizationAlert {
3929 id : string
4030 type :
@@ -137,31 +127,44 @@ export async function getOrganizationAlerts(params: {
137127 * Sends alerts for organization credit issues
138128 */
139129export async function sendOrganizationAlert (
140- alert : OrganizationCreditAlert ,
130+ params : OrganizationCreditAlert & {
131+ logger : Logger
132+ } ,
141133) : Promise < void > {
134+ const {
135+ organizationId,
136+ alertType,
137+ currentBalance,
138+ threshold,
139+ usageAmount,
140+ error,
141+ metadata,
142+ logger,
143+ } = params
144+
142145 try {
143146 // Log the alert
144147 logger . warn (
145148 {
146- organizationId : alert . organizationId ,
147- alertType : alert . alertType ,
148- currentBalance : alert . currentBalance ,
149- threshold : alert . threshold ,
150- usageAmount : alert . usageAmount ,
151- error : alert . error ,
152- metadata : alert . metadata ,
149+ organizationId,
150+ alertType,
151+ currentBalance,
152+ threshold,
153+ usageAmount,
154+ error : error ,
155+ metadata : metadata ,
153156 } ,
154- `Organization alert: ${ alert . alertType } ` ,
157+ `Organization alert: ${ alertType } ` ,
155158 )
156159
157160 // Track analytics event
158161 trackEvent ( {
159162 event : AnalyticsEvent . CREDIT_GRANT ,
160- userId : alert . organizationId ,
163+ userId : organizationId ,
161164 properties : {
162- alertType : alert . alertType ,
163- currentBalance : alert . currentBalance ,
164- threshold : alert . threshold ,
165+ alertType,
166+ currentBalance,
167+ threshold,
165168 } ,
166169 logger,
167170 } )
@@ -172,18 +175,18 @@ export async function sendOrganizationAlert(
172175 // - Dashboard notifications
173176 // - SMS alerts for critical issues
174177
175- switch ( alert . alertType ) {
178+ switch ( alertType ) {
176179 case 'low_balance' :
177- await handleLowBalanceAlert ( alert )
180+ await handleLowBalanceAlert ( params )
178181 break
179182 case 'high_usage' :
180- await handleHighUsageAlert ( alert )
183+ await handleHighUsageAlert ( params )
181184 break
182185 case 'failed_consumption' :
183- await handleFailedConsumptionAlert ( alert )
186+ await handleFailedConsumptionAlert ( params )
184187 break
185188 case 'billing_setup_required' :
186- await handleBillingSetupAlert ( alert )
189+ await handleBillingSetupAlert ( params )
187190 break
188191 }
189192 } catch ( error ) {
@@ -192,67 +195,91 @@ export async function sendOrganizationAlert(
192195}
193196
194197async function handleLowBalanceAlert (
195- alert : OrganizationCreditAlert ,
198+ params : OrganizationCreditAlert & {
199+ logger : Logger
200+ } ,
196201) : Promise < void > {
202+ const { organizationId, currentBalance, logger } = params
203+
197204 // TODO: Send email to organization owners about low balance
198205 // TODO: Suggest auto-topup or manual credit purchase
199206 logger . info (
200- { organizationId : alert . organizationId , balance : alert . currentBalance } ,
207+ { organizationId, balance : currentBalance } ,
201208 'Low balance alert sent to organization owners' ,
202209 )
203210}
204211
205212async function handleHighUsageAlert (
206- alert : OrganizationCreditAlert ,
213+ params : OrganizationCreditAlert & {
214+ logger : Logger
215+ } ,
207216) : Promise < void > {
217+ const { organizationId, usageAmount, logger } = params
218+
208219 // TODO: Send usage spike notification
209220 // TODO: Provide usage breakdown and recommendations
210221 logger . info (
211- { organizationId : alert . organizationId , usage : alert . usageAmount } ,
222+ { organizationId, usage : usageAmount } ,
212223 'High usage alert sent to organization admins' ,
213224 )
214225}
215226
216227async function handleFailedConsumptionAlert (
217- alert : OrganizationCreditAlert ,
228+ params : OrganizationCreditAlert & {
229+ logger : Logger
230+ } ,
218231) : Promise < void > {
232+ const { organizationId, error, logger } = params
233+
219234 // TODO: Send immediate notification about failed credit consumption
220235 // TODO: Provide troubleshooting steps
221236 logger . error (
222- { organizationId : alert . organizationId , error : alert . error } ,
237+ { organizationId, error } ,
223238 'Failed consumption alert sent to organization owners' ,
224239 )
225240}
226241
227242async function handleBillingSetupAlert (
228- alert : OrganizationCreditAlert ,
243+ params : OrganizationCreditAlert & {
244+ logger : Logger
245+ } ,
229246) : Promise < void > {
247+ const { organizationId, logger } = params
248+
230249 // TODO: Send setup reminder to organization owners
231250 // TODO: Provide setup instructions and links
232251 logger . info (
233- { organizationId : alert . organizationId } ,
252+ { organizationId } ,
234253 'Billing setup reminder sent to organization owners' ,
235254 )
236255}
237256
238257/**
239258 * Monitors organization credit consumption and sends alerts when needed
240259 */
241- export async function monitorOrganizationCredits (
242- organizationId : string ,
243- currentBalance : number ,
244- recentUsage : number ,
245- organizationName ?: string ,
246- ) : Promise < void > {
260+ export async function monitorOrganizationCredits ( params : {
261+ organizationId : string
262+ currentBalance : number
263+ recentUsage : number
264+ organizationName ?: string
265+ logger : Logger
266+ } ) : Promise < void > {
267+ const {
268+ organizationId,
269+ currentBalance,
270+ recentUsage,
271+ organizationName,
272+ logger,
273+ } = params
274+
247275 const LOW_BALANCE_THRESHOLD = 100 // Credits
248276 const HIGH_USAGE_THRESHOLD = 1000 // Credits per day
249277
250278 try {
251279 // Check for low balance
252280 if ( currentBalance < LOW_BALANCE_THRESHOLD ) {
253281 await sendOrganizationAlert ( {
254- organizationId,
255- organizationName,
282+ ...params ,
256283 alertType : 'low_balance' ,
257284 currentBalance,
258285 threshold : LOW_BALANCE_THRESHOLD ,
@@ -262,8 +289,7 @@ export async function monitorOrganizationCredits(
262289 // Check for high usage
263290 if ( recentUsage > HIGH_USAGE_THRESHOLD ) {
264291 await sendOrganizationAlert ( {
265- organizationId,
266- organizationName,
292+ ...params ,
267293 alertType : 'high_usage' ,
268294 usageAmount : recentUsage ,
269295 threshold : HIGH_USAGE_THRESHOLD ,
@@ -273,8 +299,7 @@ export async function monitorOrganizationCredits(
273299 // Check for negative balance (debt)
274300 if ( currentBalance < 0 ) {
275301 await sendOrganizationAlert ( {
276- organizationId,
277- organizationName,
302+ ...params ,
278303 alertType : 'failed_consumption' ,
279304 currentBalance,
280305 error : 'Organization has negative credit balance' ,
@@ -291,33 +316,51 @@ export async function monitorOrganizationCredits(
291316/**
292317 * Tracks organization usage metrics for analytics
293318 */
294- export async function trackOrganizationUsageMetrics (
295- metrics : OrganizationUsageMetrics ,
296- ) : Promise < void > {
319+ export async function trackOrganizationUsageMetrics ( params : {
320+ organizationId : string
321+ totalCreditsConsumed : number
322+ uniqueUsers : number
323+ repositoryCount : number
324+ averageCreditsPerUser : number
325+ topRepository : string
326+ timeframe : 'daily' | 'weekly' | 'monthly'
327+ logger : Logger
328+ } ) : Promise < void > {
329+ const {
330+ organizationId,
331+ totalCreditsConsumed,
332+ uniqueUsers,
333+ repositoryCount,
334+ averageCreditsPerUser,
335+ topRepository,
336+ timeframe,
337+ logger,
338+ } = params
339+
297340 try {
298341 logger . info (
299342 {
300- organizationId : metrics . organizationId ,
301- totalCreditsConsumed : metrics . totalCreditsConsumed ,
302- uniqueUsers : metrics . uniqueUsers ,
303- repositoryCount : metrics . repositoryCount ,
304- averageCreditsPerUser : metrics . averageCreditsPerUser ,
305- topRepository : metrics . topRepository ,
306- timeframe : metrics . timeframe ,
343+ organizationId,
344+ totalCreditsConsumed,
345+ uniqueUsers,
346+ repositoryCount,
347+ averageCreditsPerUser,
348+ topRepository,
349+ timeframe,
307350 } ,
308351 'Organization usage metrics tracked' ,
309352 )
310353
311354 // Track analytics event
312355 trackEvent ( {
313356 event : AnalyticsEvent . CREDIT_GRANT ,
314- userId : metrics . organizationId ,
357+ userId : organizationId ,
315358 properties : {
316359 type : 'usage_metrics' ,
317- timeframe : metrics . timeframe ,
318- totalCreditsConsumed : metrics . totalCreditsConsumed ,
319- uniqueUsers : metrics . uniqueUsers ,
320- repositoryCount : metrics . repositoryCount ,
360+ timeframe,
361+ totalCreditsConsumed,
362+ uniqueUsers,
363+ repositoryCount,
321364 } ,
322365 logger,
323366 } )
@@ -326,23 +369,28 @@ export async function trackOrganizationUsageMetrics(
326369 // TODO: Generate usage reports
327370 // TODO: Identify usage patterns and optimization opportunities
328371 } catch ( error ) {
329- logger . error (
330- { metrics, error } ,
331- 'Failed to track organization usage metrics' ,
332- )
372+ const obj : any = {
373+ ...params ,
374+ error : getErrorObject ( error ) ,
375+ }
376+ delete obj . logger
377+ logger . error ( obj , 'Failed to track organization usage metrics' )
333378 }
334379}
335380
336381/**
337382 * Validates organization billing health
338383 */
339- export async function validateOrganizationBillingHealth (
340- organizationId : string ,
341- ) : Promise < {
384+ export async function validateOrganizationBillingHealth ( params : {
385+ organizationId : string
386+ logger : Logger
387+ } ) : Promise < {
342388 healthy : boolean
343389 issues : string [ ]
344390 recommendations : string [ ]
345391} > {
392+ const { organizationId, logger } = params
393+
346394 const issues : string [ ] = [ ]
347395 const recommendations : string [ ] = [ ]
348396
@@ -368,7 +416,7 @@ export async function validateOrganizationBillingHealth(
368416 return { healthy, issues, recommendations }
369417 } catch ( error ) {
370418 logger . error (
371- { organizationId, error } ,
419+ { organizationId, error : getErrorObject ( error ) } ,
372420 'Error validating organization billing health' ,
373421 )
374422 return {
0 commit comments