# Better Stack Cloudflare Workers logging

## Start logging in 5 minutes

Collect logs from your [Cloudflare Workers](https://workers.cloudflare.com).

### Create a new source

[Create a new JavaScript • Node.js source](https://telemetry.betterstack.com/team/0/sources/new?platform=javascript ";_blank") in Better Stack Logs.

[info]
#### Already created a Cloudflare Logpush or Cloudflare HTTP requests source?

Removing it and creating a new source instead will provide you much better experience with much more suitable default configuration.
[/info]

### Set up Cloudflare Worker

Either open your **existing project with Wrangler CLI** if you already have it set up, or initialize **new "Hello World" Worker**:

```bash
[label Initialize new "Hello World" Worker]
wrangler login
wrangler init better-stack-logging-example
cd better-stack-logging-example
```

### Install Better Stack logging library

Install Better Stack logging library for edge JS runtime `@logtail/edge`:

```bash
[label Install Better Stack logging library]
npm install --save @logtail/edge
```

### Create and use instance of logger

Import and instantiate `Logtail` class, **add the execution context** from the request, and use it for your application logs:

[code-tabs]
```ts
[label TypeScript (src/index.ts)]
import { Logtail } from "@logtail/edge"

export const baseLogger = new Logtail("$SOURCE_TOKEN", {
  endpoint: 'https://$INGESTING_HOST',
})

export interface Env {
  // ...
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const logger = baseLogger.withExecutionContext(ctx)

    logger.debug("I am using Better Stack!")
    logger.info("An interesting event occurred!")

    // Logging structured data
    logger.warn("Something is not quite right, better check on it.",{
      user:{
        username:"someuser",
        email:"someuser@example.com"
      },
      additional_info:{
        tried_accessing: "/url/of/error"
      }
    })

    // Logging application errors
    function callbackThatMightFail() {
      throw new Error("Example error")
    }
    try {
      callbackThatMightFail()
    } catch (err) {
      logger.error("Oops! An runtime ERROR occurred!", err)
    }

    return new Response('Hello world')
  },
}
```
```js
[label JavaScript (src/index.js)]
import { Logtail } from "@logtail/edge"

export const baseLogger = new Logtail("$SOURCE_TOKEN", {
  endpoint: "https://$INGESTING_HOST",
})

export default {
  async fetch(request, env, ctx) {
    const logger = baseLogger.withExecutionContext(ctx)

    logger.debug("I am using Better Stack!")
    logger.info("An interesting event occurred!")

    // Logging structured data
    logger.warn("Something is not quite right, better check on it.", {
      user: {
        username: "someuser",
        email: "someuser@example.com",
      },
      additional_info: {
        tried_accessing: "/url/of/error",
      },
    })

    // Logging application errors
    function callbackThatMightFail() {
      throw new Error("Example error")
    }

    try {
      callbackThatMightFail()
    } catch (err) {
      logger.error("Oops! A runtime ERROR occurred!", err)
    }

    return new Response("Hello world")
  },
}
```
[/code-tabs]

### Deploy your worker

Deploy your worker using Wrangler CLI

```sh
[label Deploy worker via Wrangler CLI]
wrangler deploy
```

Finally, **open the worker's URL** in your browser to run it.

You should see your logs in [Better Stack → Live tail](https://telemetry.betterstack.com/team/0/tail ";_blank").

## Additional information

- Instantiating the `Logtail` class outside of `fetch` handler method will allow different worker runs to share log queue.

- Providing the `ExecutionContext` instance (usually called `ctx`) will ensure all logs will be sent to Better Stack. To ensure best results, always use the returned logger instance from `Logtail::withExecutionContext()` method.

- Want to learn more about **log levels** and **middleware**?  
Continue to the [Advanced usage of Logtail JavaScript client](https://betterstack.com/docs/logs/javascript/logging/).

### Logging from environments without ExecutionContext?

Some environments — like Cloudflare Durable Objects — don’t expose the `ExecutionContext` to your log handler. When this happens, the logger can't schedule log syncing automatically, and you might see a warning like this:

[info]
ExecutionContext hasn't been passed to the `log` method, which means syncing logs cannot be guaranteed. To ensure your logs will reach Better Stack, use `logger.withExecutionContext(ctx)` to log in your handler function. See https://betterstack.com/docs/logs/js-edge-execution-context/ for details.
[/info]

To safely log in these environments:

```js
[label Safely logging in environments without ExecutionContext]
import { Logtail } from "@logtail/edge"

// Suppress the warning messages
export const logger = new Logtail("$SOURCE_TOKEN", {
  endpoint: 'https://$INGESTING_HOST',
  warnAboutMissingExecutionContext: false,
})

// Use logger as usual
logger.debug("I am using Better Stack!")
logger.info("An interesting event occurred!")

// Ensure logs are sent before the environment shuts down
await logger.flush();
```

## Need help?

Please let us know at hello@betterstack.com.  
We're happy to help! 🙏