Skip to main content

Command Palette

Search for a command to run...

Enabling Chrome Extension Logging with Datadog: A Journey of Trial and Error

A Deep Dive into Chrome Extensions and Datadog Integration: Challenges and Solutions

Updated
6 min read
Enabling Chrome Extension Logging with Datadog: A Journey of Trial and Error

Logging is a critical aspect of developing and maintaining software applications, providing valuable insights into their behavior and aiding in troubleshooting. When it comes to Chrome extensions, enabling comprehensive logging from various components, such as content scripts, pop-ups, and background scripts, can present unique challenges. Additionally, streaming these logs to a centralized monitoring platform, like Datadog, adds another layer of complexity. In this blog post, we will delve into the intricacies of logging from different parts of a Chrome extension and explore effective strategies for streaming those logs to Datadog for comprehensive monitoring and analysis.

🕸️ Chrome Extension Logging: Architecture

Our journey began with the challenge of understanding how to enable logging across all parts of a Chrome extension effectively. Since our goal is to stream all of the logs to a centralized location, we've started exploring different techniques to capture and consolidate logs from content scripts, pop-ups, and background scripts. By understanding the logging capabilities and limitations of each component, our goal was to create a unified and comprehensive logging solution.

One challenge we encountered during our journey was that content scripts in Chrome extensions may face restrictions imposed by Content Security Policies (CSPs), which can block HTTP requests required for logging purposes. To overcome this limitation, we found it necessary to centralize the logging mechanism within the service worker. By leveraging the capabilities of the service worker, we were able to capture and consolidate the logs from content scripts and other components, ensuring uninterrupted logging even in the presence of CSP restrictions.

🎥 Streaming Extension Logs to Datadog

Now that we've got all of the logs in one centralized location (our service worker), we want to start streaming them to Datadog. We assumed that it would be very simple and straightforward to use the Datadog Browser Log Collection. This assumption was a major mistake.

🫥 The Challenge - Missing document and window

We've finished implementing the entire architecture as described. There was only one thing left and it was using @datadog/browser-logs to stream the logs to Datadog.

We've implemented the basic functionality and were disappointed to discover the following error:

It seems like the Datadog logging library for the web requires document and window configured in the global context. Since we are running inside a service worker, both of these variables don't exist in our context.

A short Google search raised the following open Github issues in the Datadog logging library

Despite this setback, we saw the issue as surmountable. We began implementing minor polyfills for document and window to get the library working. Although the library stopped raising exceptions after implementing the necessary polyfills, it didn't send the logs to Datadog.

At this point, we've come to the understanding that we need to rethink our process and find new ways to achieve the same goal.

After some brainstorming, we've come up with the following options:

  • ❌ Stream the logs from one of the content scripts instead of the service worker

    • CSP constraints on content scripts are very limiting

    • Many content scripts can be loaded at the same time to multiple tabs - which requires a complex architecture

  • ❌ Find another logging library and platform that supports Chrome extensions

    • There's absolutely no logging library for Chrome extensions - All existing logging libraries are either for regular websites or for Node.JS
  • ❓ Upload the logs to our backend which in turn will stream the logs to Datadog

    • This will dramatically increase the load on our servers
  • ❓ Implement the same API requests as Datadog's logging SDK performs

    • This is an "undocumented" browser-intake API. It may break or change at any moment without us knowing.
  • ❓ Check out if there's an official Datadog API we can call directly instead of using a logging library using @datadog/datadog-api-client

    • There is an official API for logging - Datadog Logs API reference

    • According to the documentation, the API requires an API key and not a client token.

      • Datadog API keys are private, we can't use them in our extension since they will be accessible to everyone

        For security reasons, API keys cannot be used to send data from a browser, as they would be exposed client-side in the JavaScript code. Instead, web browsers and other clients use client tokens to send data to Datadog.

✅ The Solution - Using Datadog API

During the research process, we discovered an interesting insight. Datadog client tokens and API keys are very similar to each other.

API key264f471f058cda49a768715edadca33a
Client tokenpubcea7edf6c6492736768cbaddb7354ee

We can see that the client token structure is identical to the API key (32-byte hex encoded string). The only difference is that the client token starts with pub which probably stands for "public".

Based on these findings, we decided to try using the official Datadog logging API with the client token instead of the API key.

import { client, v2 } from "@datadog/datadog-api-client";

const configuration = client.createConfiguration({
  authMethods: {
    apiKeyAuth: "pub**********", // Our client token
  },
});

const apiInstance = new v2.LogsApi(configuration);

const params: v2.LogsApiSubmitLogRequest = {
  body: [
    {
      ddsource: "grip",
      ddtags: "env:staging,version:1.33.7",
      message: "Hello World",
      service: "guyg",
    },
  ],
};

await apiInstance.submitLog(params);
Snippet Notes
This snippet is based on Datadog's Typescript API example. The basic example didn't work out of the box because of the use of Content-Encoding. The Content-Encoding in Datadog's example causes the datadog/datadog-api-client library bufferFrom which is implemented for Node.JS and not for the web. After reading some of the library source code, we've identified that we can remove the default Content-Encoding from the example, and by that the entire flow works for the web.

And it worked! 🎉

🔄 Future Considerations

Given our success with this approach, we'll likely keep using it in the future. However, it's important to remember that our workaround relies on a certain similarity between client tokens and API keys. If Datadog changes how client tokens or API keys are structured, our approach may need to be revised.

Moreover, since our workaround employs an 'undocumented' method - using the client token in place of the API key - there could be hidden limitations or restrictions we haven't yet encountered. As a result, we must continuously monitor our logging system and remain prepared for potential troubleshooting and adjustments.

🧩 Final Thoughts

Logging in Chrome extensions and integrating with Datadog presented unique challenges because of specific architecture and platform issues. But, with some creative thinking and technical know-how, we managed to build a solution that works for us.

Our experience shows that problem-solving, understanding your tools, and determination can help overcome tough challenges. Our unique solution for Chrome extension logging is proof that it's possible to find new ways to tackle problems when we're willing to think differently.

We hope our story can help others facing similar challenges in their work. With the right mindset and a willingness to try new approaches, you can solve any problem that comes your way!

📚 References

A

This doesn't seem to work anymore

B

We offer 100% secure and fully verified personal and business Cash App accounts at the best prices.If you want a secure, stable, and fully verified personal and business Cash App account, you can place your order at seosmmbiz

J

In March 2024, I found myself facing a bad scenario that many in the cryptocurrency space dread – falling victim to a phishing scam and losing a substantial amount of Bitcoin, totaling around $300,000. It was a devastating blow, one that left me feeling helpless and betrayed by the very technology I had come to trust. However, amidst the despair, a glimmer of hope emerged in the form of Digital Hack Recovery. In the attack, I was determined to learn from my mistake and take proactive measures to prevent such incidents from happening again. I delved into the world of cryptocurrency security, absorbing every piece of information I could find to arm myself against future threats. It was during this research phase that I came across Digital Hack Recovery, a name that would soon become synonymous with salvation. What struck me initially about Digital Hack Recovery was their emphasis on education and awareness. They understood that ignorance was often the greatest vulnerability in the crypto space and sought to empower their clients with the knowledge to mitigate risks effectively. Their website was a treasure trove of resources, offering comprehensive guides on security best practices, common scams to watch out for, and steps to take in the event of a breach. It was evident that they were not just a recovery service but a beacon of guidance in a sea of uncertainty. Upon reaching out to Digital Hack Recovery, I was met with a level of expertise that immediately put me at ease. Unlike other recovery platforms I had encountered, they took the time to assess my case thoroughly before committing to any action. Their transparency was refreshing – they made it clear from the outset what the likelihood of success was and what steps would be involved in the recovery process. This level of honesty instilled confidence in their capabilities and gave me hope that all was not lost. Throughout the recovery journey, Digital Hack Recovery maintained clear and open communication, providing regular updates on their progress and patiently answering any questions or concerns I had along the way. Their dedication to customer satisfaction was evident in every interaction, and it was clear that they genuinely cared about restoring not just my funds but also my peace of mind. In the end, Digital Hack Recovery delivered on its promise, managing to recover approximately 80% of the funds I had lost to the scam. While the financial aspect was certainly significant, it was the sense of closure and justice that proved to be the most valuable takeaway. Thanks to their expertise and perseverance, I was able to reclaim a portion of what was rightfully mine and move forward with renewed confidence in the crypto landscape. I cannot recommend Digital Hack Recovery highly enough to anyone who finds themselves in a similar predicament. Their commitment to education, transparency, and customer satisfaction sets them apart as a beacon of hope in an otherwise tumultuous industry. While the scars of my ordeal may never fully heal, knowing that there are professionals like Digital Hack Recovery standing ready to assist brings a sense of comfort and reassurance that is truly priceless. Trusting them with my recovery was undoubtedly one of the best decisions I have ever made, and I am eternally grateful for their unwavering support. Their contact;

WhatsApp +19152151930

Email; digital hack recovery @ techie . com

7
7892y ago

Sicbo 789Club – Chơi là mê, đổi thưởng uy tín

Chơi Sicbo tại 789Club - Một trải nghiệm đầy thú vị và kịch tính, với đảm bảo về tính minh bạch và sự đổi thưởng đáng tin cậy.

Chi Tiết: https://chembargains.com/sicbo-789club/

J

Just in case other people run into this:

I was getting 403's when I implemented the solution in this blog. It turns out that my company uses a different datadog enpoint than the default. So if you're using a different one, here's how to configure it:

const configuration = client.createConfiguration({
  authMethods: {
    apiKeyAuth: "pub...",
  },
});

configuration.setServerVariables({
  site: "us5.datadoghq.com"
});

const apiInstance = new v2.LogsApi(configuration);
A

Hi John, I would appreciate if you can elaborate on how did you find you have a different endpoint from the default.

S

Hi Guy! Thank you very much for sharing your experience. Did you face a CORS error while sending logs to DD from the extension? I have a problem: all requests, either from background or content are rejected by Datadog with the error:

Access to fetch at 'http-intake.logs.datadoghq.eu/api/v2/logs' from origin 'chrome-extension://*********' has been blocked by CORS policy: Request header field dd-api-key is not allowed by Access-Control-Allow-Headers in preflight response.

Postman's exact (absolutely the same) request passed successfully (code 202 and entry in Datadog).

3
G

Interesting! Generally, since the API should be accessible and must receive this header, I suspect this might be related to the endpoint you are trying to send the logs to.

I see that you are using http-intake.logs.datadoghq.eu/api/v2/logs

It's worth trying to send the requests to https://http-intake.logs.datadoghq.com/api/v2/logs (.com instead of .eu)

Let me know if it works :)

Y

Hi. I'm facing a similar error as well. I think this behavior might be because the API is not designed to be called from a browser. I would be grateful if you could let me know if you find any workarounds.

S
Sargis1y ago

Guy Goldenberg

Unfortunately, I am also facing same issue. Works in postman, getting CORs issue from background script:

Access to fetch at 'https://http-intake.logs.us5.datadoghq.com/api/v2/logs' from origin 'chrome-extension://obdlkagmmgblbmgmflmkeopiennejpph' has been blocked by CORS policy: Request header field dd-api-key is not allowed by Access-Control-Allow-Headers in preflight response.
Y

This blog just saved me. I had the document is not defied error for so long. Great blog, I’m sure it’s going to serve me in the future and a lot of other developers.

1