docs/contributing/go/sql.md
SigNoz utilizes a relational database to store metadata including organization information, user data and other settings.
The database interface is defined in SQLStore. SigNoz leverages the Bun ORM to interact with the underlying database. To access the database instance, use the BunDBCtx function. For operations that require transactions across multiple database operations, use the RunInTxCtx function. This function embeds a transaction in the context, which propagates through various functions in the callback.
type Thing struct {
bun.BaseModel
ID types.Identifiable `bun:",embed"`
SomeColumn string `bun:"some_column"`
TimeAuditable types.TimeAuditable `bun:",embed"`
OrgID string `bun:"org_id"`
}
func GetThing(ctx context.Context, id string) (*Thing, error) {
thing := new(Thing)
err := sqlstore.
BunDBCtx(ctx).
NewSelect().
Model(thing).
Where("id = ?", id).
Scan(ctx)
return thing, err
}
func CreateThing(ctx context.Context, thing *Thing) error {
return sqlstore.
BunDBCtx(ctx).
NewInsert().
Model(thing).
Exec(ctx)
}
💡 Note: Always use line breaks while working with SQL queries to enhance code readability.
💡 Note: Always use the
newfunction to create new instances of structs.
Hooks are user-defined functions that execute before and/or after specific database operations. These hooks are particularly useful for generating telemetry data such as logs, traces, and metrics, providing visibility into database interactions. Hooks are defined in the SQLStoreHook interface.
SigNoz implements a star schema design with the organizations table as the central entity. All other tables link to the organizations table via foreign key constraints on the org_id column. This design ensures that every entity within the system is either directly or indirectly associated with an organization.
erDiagram
ORGANIZATIONS {
string id PK
timestamp created_at
timestamp updated_at
}
ENTITY_A {
string id PK
timestamp created_at
timestamp updated_at
string org_id FK
}
ENTITY_B {
string id PK
timestamp created_at
timestamp updated_at
string org_id FK
}
ORGANIZATIONS ||--o{ ENTITY_A : contains
ORGANIZATIONS ||--o{ ENTITY_B : contains
💡 Note: There are rare exceptions to the above star schema design. Consult with the maintainers before deviating from the above design.
All tables follow a consistent primary key pattern using a id column (referenced by the types.Identifiable struct) and include created_at and updated_at columns (referenced by the types.TimeAuditable struct) for audit purposes.
For schema migrations, use the SQLMigration interface and write the migration in the same package. When creating migrations, adhere to these guidelines:
ON CASCADE foreign key constraints. Deletion operations should be handled explicitly in application logic rather than delegated to the database.sqlmigration package. Instead, define the required types within the migration package itself. This practice ensures migration stability as the core types evolve over time.Down migrations. As the codebase matures, we may introduce this capability, but for now, the Down function should remain empty.BunDBCtx and RunInTxCtx to access the database instance and execute transactions respectively.id, created_at, updated_at and an org_id column with a foreign key constraint to the organizations table (unless the table serves as a transitive entity not directly associated with an organization but indirectly associated with one).