Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: analytics api #2740

Merged
merged 37 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
67e019f
wip
chronark Dec 11, 2024
9881dbf
Merge branch 'main' of https://github.com/unkeyed/unkey into analytic…
chronark Dec 11, 2024
26d7928
feat: write query
chronark Dec 11, 2024
4607502
Merge branch 'main' of https://github.com/unkeyed/unkey into analytic…
chronark Dec 12, 2024
89e2c8e
Merge branch 'main' of https://github.com/unkeyed/unkey into analytic…
chronark Dec 16, 2024
8ff01f2
feat: it sort of works
chronark Dec 16, 2024
f60b17e
wip
chronark Dec 18, 2024
7414e17
[autofix.ci] apply automated fixes
autofix-ci[bot] Dec 18, 2024
ccbfc78
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Dec 18, 2024
b3f122e
[autofix.ci] apply automated fixes (attempt 3/3)
autofix-ci[bot] Dec 18, 2024
66b90ba
chore: merge conflicts
chronark Jan 7, 2025
4ed7cc1
refactor: reduce api surface and clean up internal query generation
chronark Jan 8, 2025
39e855c
wip
chronark Jan 8, 2025
156bfb2
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 8, 2025
30c3cdd
Merge branch 'main' of https://github.com/unkeyed/unkey into analytic…
chronark Jan 9, 2025
e25a7c5
feat: grouping by tag and tags
chronark Jan 9, 2025
7b128a6
docs: explain what we track
chronark Jan 9, 2025
35f22c6
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 9, 2025
589e3cb
[autofix.ci] apply automated fixes (attempt 2/3)
autofix-ci[bot] Jan 9, 2025
55ec867
[autofix.ci] apply automated fixes (attempt 3/3)
autofix-ci[bot] Jan 9, 2025
30b2348
chore: hide unfinished docs
chronark Jan 10, 2025
7080b44
Merge branch 'analytics-api' of https://github.com/unkeyed/unkey into…
chronark Jan 10, 2025
85cce46
Merge branch 'main' of https://github.com/unkeyed/unkey into analytic…
chronark Jan 10, 2025
ba1b0e7
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 10, 2025
aeae54f
chore: remove console.logs and other artifacts
chronark Jan 10, 2025
d400384
chore: remove placeholder
chronark Jan 10, 2025
a2fb8e5
Merge branch 'analytics-api' of https://github.com/unkeyed/unkey into…
chronark Jan 10, 2025
308707e
fix: load identity
chronark Jan 10, 2025
12cc2aa
feat: filter by keys
chronark Jan 10, 2025
631e884
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 10, 2025
68ee365
fix: redact potentially sensitive error message
chronark Jan 10, 2025
ce0b91d
fix: redact potentially sensitive error message
chronark Jan 10, 2025
8a566f1
Merge branch 'analytics-api' of https://github.com/unkeyed/unkey into…
chronark Jan 10, 2025
9599d3c
docs: explain generate parameters
chronark Jan 10, 2025
acdd6f3
ci: migrate clickhouse tables
chronark Jan 10, 2025
1bf95a0
fix: require api
chronark Jan 10, 2025
9d05f32
[autofix.ci] apply automated fixes
autofix-ci[bot] Jan 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions apps/api/src/pkg/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,11 @@ export class Analytics {
public get getVerificationsDaily() {
return this.clickhouse.verifications.perDay;
}

/**
* Use this sparingly, mostly for quick iterations
*/
public get internalQuerier() {
return this.clickhouse.querier;
}
}
1 change: 1 addition & 0 deletions apps/api/src/pkg/cache/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export function initCache(c: Context<HonoEnv>, metrics: Metrics): C<CacheNamespa
c.executionCtx,
defaultOpts,
),
identityById: new Namespace<CacheNamespaces["identityById"]>(c.executionCtx, defaultOpts),
auditLogBucketByWorkspaceIdAndName: new Namespace<
CacheNamespaces["auditLogBucketByWorkspaceIdAndName"]
>(c.executionCtx, defaultOpts),
Expand Down
1 change: 1 addition & 0 deletions apps/api/src/pkg/cache/namespaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export type CacheNamespaces = {
total: number;
};
identityByExternalId: Identity | null;
identityById: Identity | null;
// uses a compound key of [workspaceId, name]
auditLogBucketByWorkspaceIdAndName: {
id: string;
Expand Down
1 change: 1 addition & 0 deletions apps/api/src/pkg/testutil/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const databaseEnv = z.object({
DATABASE_HOST: z.string().default("localhost:3900"),
DATABASE_USERNAME: z.string().default("unkey"),
DATABASE_PASSWORD: z.string().default("password"),
CLICKHOUSE_URL: z.string().default("http://default:password@localhost:8123"),
chronark marked this conversation as resolved.
Show resolved Hide resolved
});

export const integrationTestEnv = databaseEnv.merge(
Expand Down
13 changes: 11 additions & 2 deletions apps/api/src/pkg/testutil/harness.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Client } from "@planetscale/database";
import { ClickHouse } from "@unkey/clickhouse";
import { sha256 } from "@unkey/hash";
import { newId } from "@unkey/id";
import { KeyV1 } from "@unkey/keys";
Expand Down Expand Up @@ -27,10 +28,12 @@ export type Resources = {

export abstract class Harness {
public readonly db: { primary: Database; readonly: Database };
public readonly ch: ClickHouse;
public resources: Resources;

constructor(t: TaskContext) {
const { DATABASE_HOST, DATABASE_PASSWORD, DATABASE_USERNAME } = databaseEnv.parse(process.env);
const { DATABASE_HOST, DATABASE_PASSWORD, DATABASE_USERNAME, CLICKHOUSE_URL } =
databaseEnv.parse(process.env);

const db = drizzle(
new Client({
Expand All @@ -51,6 +54,7 @@ export abstract class Harness {
);

this.db = { primary: db, readonly: db };
this.ch = new ClickHouse({ url: CLICKHOUSE_URL });
this.resources = this.createResources();

t.onTestFinished(async () => {
Expand Down Expand Up @@ -131,7 +135,11 @@ export abstract class Harness {
name: string;
permissions?: string[];
}[];
}): Promise<{ keyId: string; key: string }> {
}): Promise<{
keyId: string;
key: string;
identityId?: string;
}> {
/**
* Prepare the key we'll use
*/
Expand Down Expand Up @@ -186,6 +194,7 @@ export abstract class Harness {
return {
keyId,
key,
identityId: opts?.identityId,
};
}

Expand Down
16 changes: 14 additions & 2 deletions apps/api/src/pkg/testutil/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export type StepRequest<TRequestBody> = {
url: string;
method: "POST" | "GET" | "PUT" | "DELETE";
headers?: Record<string, string>;
searchparams?: Record<string, string | string[]>;
body?: TRequestBody;
};
export type StepResponse<TBody = unknown> = {
Expand All @@ -14,7 +15,18 @@ export type StepResponse<TBody = unknown> = {
export async function step<TRequestBody = unknown, TResponseBody = unknown>(
req: StepRequest<TRequestBody>,
): Promise<StepResponse<TResponseBody>> {
const res = await fetch(req.url, {
const url = new URL(req.url);
for (const [k, vv] of Object.entries(req.searchparams ?? {})) {
if (Array.isArray(vv)) {
for (const v of vv) {
url.searchParams.append(k, v);
}
} else {
url.searchParams.append(k, vv);
}
}

const res = await fetch(url, {
method: req.method,
headers: req.headers,
body: JSON.stringify(req.body),
Expand All @@ -28,7 +40,7 @@ export async function step<TRequestBody = unknown, TResponseBody = unknown>(
body: JSON.parse(body),
};
} catch {
console.error(`${req.url} didn't return json, received: ${body}`);
console.error(`${url.toString()} didn't return json, received: ${body}`);
return {} as StepResponse<TResponseBody>;
}
}
Expand Down
Loading
Loading