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

174 generate social image of visualization when pasting link in slackxlinkedin #239

Conversation

roshan-gh
Copy link
Contributor

This pull request addresses the issue related to generating a social image for visualizations of the otel-col pipelines when pasting a configuration link in platforms such as Slack, X, and LinkedIn. The changes involve leveraging Next.js dynamic Open Graph features and incorporating Tailwind CSS for styling. Additionally, modifications have been made to the middleware in Next.js to enable the desired functionality.

@roshan-gh roshan-gh requested a review from bripkens December 7, 2023 15:50
@roshan-gh roshan-gh self-assigned this Dec 7, 2023
Copy link

vercel bot commented Dec 7, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
otelbin ✅ Ready (Inspect) Visit Preview 💬 Add feedback Dec 20, 2023 4:22pm

Roshan Ghojoghi added 3 commits December 8, 2023 15:22
…-link-in-slackxlinkedin' of github.com:dash0hq/otelbin into 174-generate-social-image-of-visualization-when-pasting-link-in-slackxlinkedin
…ocial-image-of-visualization-when-pasting-link-in-slackxlinkedin
@@ -18,6 +18,7 @@ const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "OTelBin – by Dash0",
description: "Edit, visualize and share OpenTelemetry Collector configurations",
metadataBase: new URL("https://otelbin.io/"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: While this is the the correct value for our production env, it will not be the correct value for others that are deploying OTelBin or for our preview envs.

Do we need this setting, or can we just remove it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct; we can remove it. In other fields, such as images, the full URL is used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upon further examination, the next server encounters an error without the presence of 'metadataBase.' This functionality is implemented in /social-preview/[id]/page.tsx, where metadata is utilized with the url.origin

import BarChart4 from "./svg/bar-chart-4.svg";
import ListTree from "./svg/list-tree.svg";

export const parentNodesConfig = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: This whole code block is duplicated.

Copy link
Contributor Author

@roshan-gh roshan-gh Dec 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed and the duplicates removed.

}
const urlHash = url.hash;
let parsedConfig = "";
if (urlHash != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: This code path is duplication the extraction logic for URL parameters, and it is fragile, e.g., #distro=otelcol-contrib&config=… would fail to parse.

Please consider using toUrlState(toParsedUrlStateParameters(new URLSearchParams(url.hash)), [configBinding]) instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed and toUrlState is implemented.


const edgeWidth = 80;

export async function GET(request: NextRequest) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: What do we need this route for? AFAICT this can be deleted?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just put it as a defualt og image, yes it can be deleted.

const redis = Redis.fromEnv();
const edgeWidth = 80;

export async function GET(request: NextRequest) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Move the route to social-preview/[id]/img/route.ts to put related logic closer together.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New route implemented.

>
{parentNodes?.map((parentNode, idx) => <ParentsNode key={idx} nodeData={parentNode} nodes={initNodes} />)}
</div>
</div>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: We are still missing the OTelBin logo in the response.

const mockNextRequest = new NextRequest(mockRequest, {});
const result = await handleShortLinkRequest(mockNextRequest);
expect(redirectSpy).toHaveBeenCalledTimes(0);
expect(rewriteSpy).toHaveBeenCalledTimes(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Test the arguments to rewriteSpy to ensure that the correct rewrite is executed.

if (isBotRequest(request)) {
return NextResponse.rewrite(new URL(`/social-preview/${shortLink}`, request.url));
} else {
return NextResponse.redirect(fullLink || "/", {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Use NextResponse.next(). That way, we don't have to re-implement the redirect logic here.

export async function handleShortLinkRequest(request: NextRequest) {
if (request.nextUrl.pathname.startsWith("/s") && !request.nextUrl.pathname.startsWith("/s/new")) {
const shortLink = request.url.split("/")[request.url.split("/").length - 1] ?? "";
const fullLink = await redis.get<string>(getShortLinkPersistenceKey(shortLink));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: We don't need to use Redis here. The call is something we can avoid. See suggestion below on NextResponse.next()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great suggestion! Implemented.


export async function handleShortLinkRequest(request: NextRequest) {
if (request.nextUrl.pathname.startsWith("/s") && !request.nextUrl.pathname.startsWith("/s/new")) {
const shortLink = request.url.split("/")[request.url.split("/").length - 1] ?? "";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Extract this from the URL via a regexp and capture groups. The way it is done right now looks like it could break below.

Example: /\/s\/([^\/]+)$/

@bripkens
Copy link
Member

Overall this seems to be going in the correct direction 👍 . It mostly requires a clean-up imo.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Why does this file need to exist under public?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed, base 64 data of svg image used in backgroud url.

Copy link
Member

@bripkens bripkens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just two small findings. Otherwise we are close to merge!

return NextResponse.rewrite(new URL(`/social-preview/${shortLink}`, request.url));
} else {
const newHeaders = new Headers(request.headers);
newHeaders.set("Cache-Control", "public, max-age=3600, stale-while-revalidate=3600, stale-if-error=3600");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Let the next handler take care of the caching headers. AFAICT we don't need to duplicate them here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

Comment on lines 58 to 59
const urlState = parseUrlState(hashSearchParams, binds);
return (urlState as never)[editorBinding.name];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: This function accepts binds, but then only returns the editor binding. That is imho unexpected, especially when compared to the behavior of useUrlState.

Why not return urlState here? Then the APIs should align.

@roshan-gh
Copy link
Contributor Author

@bripkens In the last commit, SVG icons for pipelines added, serverSide can not resolve React-Lucide icons.

Copy link

sonarqubecloud bot commented Dec 20, 2023

Quality Gate Passed Quality Gate passed

The SonarCloud Quality Gate passed, but some issues were introduced.

5 New issues
0 Security Hotspots
No data about Coverage
2.9% Duplication on New Code

See analysis details on SonarCloud

Copy link
Member

@bripkens bripkens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, let's get this merged @roshan-gh! 👍

In testing we did find some bugs. Let's try to iron them out with the production deployment.

@bripkens bripkens merged commit 2febc3c into main Dec 20, 2023
37 checks passed
@bripkens bripkens deleted the 174-generate-social-image-of-visualization-when-pasting-link-in-slackxlinkedin branch December 20, 2023 17:16
@github-actions github-actions bot locked and limited conversation to collaborators Dec 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Generate social image of visualization when pasting link in Slack/X/LinkedIn
3 participants