mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-08 22:48:14 -05:00
feat(audit): added audit log for billing line items (#2500)
* feat(audit): added audit log for billing line items * remove migration * reran migrations after resolving merge conflict * ack PR comment
This commit is contained in:
23
packages/db/migrations/0128_swift_terrax.sql
Normal file
23
packages/db/migrations/0128_swift_terrax.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
CREATE TYPE "public"."usage_log_category" AS ENUM('model', 'fixed');--> statement-breakpoint
|
||||
CREATE TYPE "public"."usage_log_source" AS ENUM('workflow', 'wand', 'copilot');--> statement-breakpoint
|
||||
CREATE TABLE "usage_log" (
|
||||
"id" text PRIMARY KEY NOT NULL,
|
||||
"user_id" text NOT NULL,
|
||||
"category" "usage_log_category" NOT NULL,
|
||||
"source" "usage_log_source" NOT NULL,
|
||||
"description" text NOT NULL,
|
||||
"metadata" jsonb,
|
||||
"cost" numeric NOT NULL,
|
||||
"workspace_id" text,
|
||||
"workflow_id" text,
|
||||
"execution_id" text,
|
||||
"created_at" timestamp DEFAULT now() NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
ALTER TABLE "usage_log" ADD CONSTRAINT "usage_log_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "usage_log" ADD CONSTRAINT "usage_log_workspace_id_workspace_id_fk" FOREIGN KEY ("workspace_id") REFERENCES "public"."workspace"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE "usage_log" ADD CONSTRAINT "usage_log_workflow_id_workflow_id_fk" FOREIGN KEY ("workflow_id") REFERENCES "public"."workflow"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
CREATE INDEX "usage_log_user_created_at_idx" ON "usage_log" USING btree ("user_id","created_at");--> statement-breakpoint
|
||||
CREATE INDEX "usage_log_source_idx" ON "usage_log" USING btree ("source");--> statement-breakpoint
|
||||
CREATE INDEX "usage_log_workspace_id_idx" ON "usage_log" USING btree ("workspace_id");--> statement-breakpoint
|
||||
CREATE INDEX "usage_log_workflow_id_idx" ON "usage_log" USING btree ("workflow_id");
|
||||
8444
packages/db/migrations/meta/0128_snapshot.json
Normal file
8444
packages/db/migrations/meta/0128_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -890,6 +890,13 @@
|
||||
"when": 1766209394504,
|
||||
"tag": "0127_flimsy_sister_grimm",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 128,
|
||||
"version": "7",
|
||||
"when": 1766266581373,
|
||||
"tag": "0128_swift_terrax",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1664,3 +1664,51 @@ export const ssoProvider = pgTable(
|
||||
organizationIdIdx: index('sso_provider_organization_id_idx').on(table.organizationId),
|
||||
})
|
||||
)
|
||||
|
||||
// Usage logging for tracking individual billable operations
|
||||
export const usageLogCategoryEnum = pgEnum('usage_log_category', ['model', 'fixed'])
|
||||
export const usageLogSourceEnum = pgEnum('usage_log_source', ['workflow', 'wand', 'copilot'])
|
||||
|
||||
export const usageLog = pgTable(
|
||||
'usage_log',
|
||||
{
|
||||
id: text('id').primaryKey(),
|
||||
userId: text('user_id')
|
||||
.notNull()
|
||||
.references(() => user.id, { onDelete: 'cascade' }),
|
||||
|
||||
// Charge category: 'model' (token-based) or 'fixed' (flat fee)
|
||||
category: usageLogCategoryEnum('category').notNull(),
|
||||
|
||||
// What generated this charge: 'workflow', 'wand', 'copilot'
|
||||
source: usageLogSourceEnum('source').notNull(),
|
||||
|
||||
// For model charges: model name (e.g., 'gpt-4o', 'claude-4.5-opus')
|
||||
// For fixed charges: charge type (e.g., 'execution_fee', 'search_query')
|
||||
description: text('description').notNull(),
|
||||
|
||||
// Category-specific metadata (e.g., tokens for 'model' category)
|
||||
metadata: jsonb('metadata'),
|
||||
|
||||
// Cost in USD
|
||||
cost: decimal('cost').notNull(),
|
||||
|
||||
// Optional context references
|
||||
workspaceId: text('workspace_id').references(() => workspace.id, { onDelete: 'set null' }),
|
||||
workflowId: text('workflow_id').references(() => workflow.id, { onDelete: 'set null' }),
|
||||
executionId: text('execution_id'),
|
||||
|
||||
// Timestamp
|
||||
createdAt: timestamp('created_at').notNull().defaultNow(),
|
||||
},
|
||||
(table) => ({
|
||||
// Index for querying user's usage history (most common query)
|
||||
userCreatedAtIdx: index('usage_log_user_created_at_idx').on(table.userId, table.createdAt),
|
||||
// Index for filtering by source
|
||||
sourceIdx: index('usage_log_source_idx').on(table.source),
|
||||
// Index for workspace-specific queries
|
||||
workspaceIdIdx: index('usage_log_workspace_id_idx').on(table.workspaceId),
|
||||
// Index for workflow-specific queries
|
||||
workflowIdIdx: index('usage_log_workflow_id_idx').on(table.workflowId),
|
||||
})
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user