Skip to content

Commit

Permalink
feat: add custom spans
Browse files Browse the repository at this point in the history
  • Loading branch information
simonknittel committed Jan 25, 2025
1 parent 1ad2c7f commit f5cefba
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 80 deletions.
31 changes: 20 additions & 11 deletions app/src/auth/authenticateAndAuthorize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
requireConfirmedEmailForPage,
} from "@/auth/utils/emailConfirmation";
import { log } from "@/logging";
import { trace } from "@opentelemetry/api";
import { getServerSession, type Session } from "next-auth";
import { cookies } from "next/headers";
import { forbidden, redirect } from "next/navigation";
Expand All @@ -13,17 +14,25 @@ import { type PermissionSet } from "./PermissionSet";
import comparePermissionSets from "./comparePermissionSets";

export const authenticate = cache(async () => {
const session = await getServerSession(authOptions);
if (!session) return false;

return {
session,
authorize: (
resource: PermissionSet["resource"],
operation: PermissionSet["operation"],
attributes?: PermissionSet["attributes"],
) => authorize(session, resource, operation, attributes),
};
return await trace
.getTracer("sam")
.startActiveSpan("authenticate", async (span) => {
try {
const session = await getServerSession(authOptions);
if (!session) return false;

return {
session,
authorize: (
resource: PermissionSet["resource"],
operation: PermissionSet["operation"],
attributes?: PermissionSet["attributes"],
) => authorize(session, resource, operation, attributes),
};
} finally {
span.end();
}
});
});

export async function authenticatePage(requestPath?: string) {
Expand Down
25 changes: 17 additions & 8 deletions app/src/auth/queries.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import { prisma } from "@/db";
import { trace } from "@opentelemetry/api";
import type { EmailConfirmationToken } from "@prisma/client";

export const getEmailConfirmationToken = async (
token: EmailConfirmationToken["token"],
) => {
return prisma.emailConfirmationToken.findUnique({
where: {
token,
expires: {
gt: new Date(),
},
},
});
return await trace
.getTracer("sam")
.startActiveSpan("getEmailConfirmationToken", async (span) => {
try {
return prisma.emailConfirmationToken.findUnique({
where: {
token,
expires: {
gt: new Date(),
},
},
});
} finally {
span.end();
}
});
};
43 changes: 27 additions & 16 deletions app/src/common/utils/getUnleashFlag.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { authenticate } from "@/auth/server";
import { log } from "@/logging";
import { trace } from "@opentelemetry/api";
import { evaluateFlags, flagsClient, getDefinitions } from "@unleash/nextjs";
import { cache } from "react";
import { serializeError } from "serialize-error";
Expand All @@ -15,26 +16,36 @@ export const getUnleashFlag = cache(
| "EnableOperations"
| "EnableNotifications",
) => {
try {
const authentication = await authenticate();
return await trace
.getTracer("sam")
.startActiveSpan("getUnleashFlag", async (span) => {
try {
try {
const authentication = await authenticate();

const definitions = await getDefinitions({
fetchOptions: {
next: { revalidate: 30 },
},
});
const definitions = await getDefinitions({
fetchOptions: {
next: { revalidate: 30 },
},
});

const { toggles } = evaluateFlags(definitions, {
userId: authentication ? authentication.session.user.id : undefined,
});
const { toggles } = evaluateFlags(definitions, {
userId: authentication
? authentication.session.user.id
: undefined,
});

const flags = flagsClient(toggles);
const flags = flagsClient(toggles);

return flags.isEnabled(name);
} catch (error) {
void log.error("Error fetching feature flag", {
error: serializeError(error),
return flags.isEnabled(name);
} catch (error) {
void log.error("Error fetching feature flag", {
error: serializeError(error),
});
}
} finally {
span.end();
}
});
}
},
);
41 changes: 25 additions & 16 deletions app/src/discord/utils/getEventUsers.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
import { env } from "@/env";
import { trace } from "@opentelemetry/api";
import { cache } from "react";
import { z } from "zod";
import { checkResponseForError } from "./checkResponseForError";
import { memberSchema, userSchema } from "./schemas";

export const getEventUsers = cache(async (id: string) => {
// https://discord.com/developers/docs/resources/guild-scheduled-event#get-guild-scheduled-event-users
const response = await fetch(
`https://discord.com/api/v10/guilds/${env.DISCORD_GUILD_ID}/scheduled-events/${id}/users?with_member=true`,
{
headers: new Headers({
Authorization: `Bot ${env.DISCORD_TOKEN}`,
}),
next: {
revalidate: 30,
},
},
);
return await trace
.getTracer("sam")
.startActiveSpan("getEventUsers", async (span) => {
try {
// https://discord.com/developers/docs/resources/guild-scheduled-event#get-guild-scheduled-event-users
const response = await fetch(
`https://discord.com/api/v10/guilds/${env.DISCORD_GUILD_ID}/scheduled-events/${id}/users?with_member=true`,
{
headers: new Headers({
Authorization: `Bot ${env.DISCORD_TOKEN}`,
}),
next: {
revalidate: 30,
},
},
);

const body: unknown = await response.json();
const data = schema.parse(body);
const body: unknown = await response.json();
const data = schema.parse(body);

checkResponseForError(data);
checkResponseForError(data);

return data as z.infer<typeof successSchema>;
return data as z.infer<typeof successSchema>;
} finally {
span.end();
}
});
});

const successSchema = z.array(
Expand Down
75 changes: 46 additions & 29 deletions app/src/users/queries.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,59 @@
import { prisma } from "@/db";
import { trace } from "@opentelemetry/api";
import type { User } from "@prisma/client";

export const getUsersWithEntities = async () => {
const [users, entities] = await Promise.all([
prisma.user.findMany({
include: {
accounts: true,
},
}),
return await trace
.getTracer("sam")
.startActiveSpan("getUsersWithEntities", async (span) => {
try {
const [users, entities] = await Promise.all([
prisma.user.findMany({
include: {
accounts: true,
},
}),

prisma.entity.findMany(),
]);
prisma.entity.findMany(),
]);

const enrichedUsers = users.map((user) => {
const entity = entities.find(
(entity) => entity.discordId === user.accounts[0].providerAccountId,
);
const enrichedUsers = users.map((user) => {
const entity = entities.find(
(entity) => entity.discordId === user.accounts[0].providerAccountId,
);

if (!entity)
return {
user,
discordId: user.accounts[0].providerAccountId,
};
if (!entity)
return {
user,
discordId: user.accounts[0].providerAccountId,
};

return {
user,
discordId: user.accounts[0].providerAccountId,
entity,
};
});
return {
user,
discordId: user.accounts[0].providerAccountId,
entity,
};
});

return enrichedUsers;
return enrichedUsers;
} finally {
span.end();
}
});
};

export const getUserById = async (id: User["id"]) => {
return prisma.user.findUnique({
where: {
id,
},
});
return await trace
.getTracer("sam")
.startActiveSpan("getUserById", async (span) => {
try {
return prisma.user.findUnique({
where: {
id,
},
});
} finally {
span.end();
}
});
};

0 comments on commit f5cefba

Please sign in to comment.