Skip to content
Draft
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
2c0d424
Basic tracing hooks
Fryuni May 12, 2025
ce2de17
Merge branch 'main' into feat/tracing-hooks
Fryuni May 12, 2025
15fe631
Add extra trace points, data and make tracing platform independent
Fryuni May 12, 2025
f7ed4da
Run formatter
Fryuni May 12, 2025
741be1e
Rename trace event
Fryuni May 12, 2025
b1833ed
Merge branch 'main' into fryuni/tracing-hooks
Fryuni May 23, 2025
cb8fdcb
Merge branch 'main' into fryuni/tracing-hooks
Fryuni May 31, 2025
f116c3f
Merge remote-tracking branch 'origin/main' into fryuni/tracing-hooks
Fryuni Jul 21, 2025
ebac4ec
format
Fryuni Jul 21, 2025
e32b685
Merge remote-tracking branch 'origin/main' into fryuni/tracing-hooks
Fryuni Jul 21, 2025
628fcf1
Merge remote-tracking branch 'origin/main' into fryuni/tracing-hooks
Fryuni Aug 1, 2025
c46fa13
Make type future-proof
Fryuni Aug 2, 2025
2e1caaa
Add hook for async operation completion
Fryuni Aug 2, 2025
17d26db
Add function for integrations to add early initialization logic
Fryuni Aug 3, 2025
d4e29bc
Working exemple of tracing using OpenTelemetry
Fryuni Aug 3, 2025
cfe14a0
wip changeset for CI
Fryuni Aug 9, 2025
0eae15d
Merge branch 'main' into fryuni/tracing-hooks
Fryuni Aug 9, 2025
0cbc2d9
Preview unreleased package
Fryuni Aug 9, 2025
dc3a5f8
Refactor OpenTelemetry integration to be configurable and adaptable
Fryuni Aug 9, 2025
cfbe4bc
Add tracing to middlewares
Fryuni Aug 10, 2025
65601f7
Make logger export to console by default
Fryuni Aug 10, 2025
6979108
Allow integration to be wrapped
Fryuni Aug 10, 2025
c8f7291
Implement helper imports for each telemetry resource
Fryuni Aug 10, 2025
d804ded
Fix package.json
Fryuni Aug 11, 2025
aca5126
Merge remote-tracking branch 'origin/main' into fryuni/tracing-hooks
Fryuni Aug 11, 2025
06b4a5c
Format
Fryuni Aug 11, 2025
ddb6232
WIP
Fryuni Aug 13, 2025
2c970bc
Merge branch 'main' into fryuni/tracing-hooks
Fryuni Aug 15, 2025
fc5a126
Setup telemetry and initialization for dev server
Fryuni Aug 15, 2025
04d8081
API bash instructions
Fryuni Aug 15, 2025
202fc6f
WIP
Fryuni Aug 15, 2025
effa5e3
WIP
Fryuni Aug 15, 2025
3c624ac
Improve example
Fryuni Aug 24, 2025
b43d090
Merge remote-tracking branch 'origin/main' into fryuni/tracing-hooks
Fryuni Aug 29, 2025
b74a37a
Update packages/integrations/opentelemetry/src/initialization/dev.ts
Fryuni Sep 4, 2025
9410c07
Simplify tracing hooks and prevent consumers from breaking internal code
Fryuni Aug 29, 2025
4189a6d
WIP tests
Fryuni Aug 29, 2025
45da97e
Merge branch 'main' into fryuni/tracing-hooks
Fryuni Sep 10, 2025
0b62164
Put tracing behind an experimental flag
Fryuni Sep 10, 2025
268c593
Dedupe deps
Fryuni Sep 10, 2025
684dc12
Fix default env values for Node telemetry
Fryuni Sep 10, 2025
7042a1e
Docs and unit tests
Fryuni Sep 11, 2025
069ec6b
Adjust integration tests
Fryuni Sep 11, 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
6 changes: 6 additions & 0 deletions .changeset/great-chairs-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@astrojs/opentelemetry': minor
'astro': minor
---

Tracing hooks
20 changes: 20 additions & 0 deletions examples/with-telemetry/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// @ts-check

import node from '@astrojs/node';
import opentelemetry from '@astrojs/opentelemetry';
import svelte from '@astrojs/svelte';
import { defineConfig } from 'astro/config';

// https://astro.build/config
export default defineConfig({
output: 'server',
adapter: node({
mode: 'standalone',
}),
integrations: [svelte(), opentelemetry()],
vite: {
build: {
sourcemap: true,
},
},
});
31 changes: 31 additions & 0 deletions examples/with-telemetry/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
volumes:
developmentData:
driver: local
driver_opts:
type: none
device: ./data/development

services:
jaeger:
image: jaegertracing/all-in-one:1.71.0
ports:
- '6831:6831/udp'
- '16686:16686'

prometheus:
image: prom/prometheus
volumes:
- './prometheus.yaml:/etc/prometheus/prometheus.yml'
ports:
- '9090:9090'

otel:
image: otel/opentelemetry-collector-contrib:0.131.0
command: --config /config/otel.yaml
volumes:
- ./otel.yaml:/config/otel.yaml:ro
ports:
- '4317:4317'
- '4318:4318'
- '8888:8888'
- '8889:8889'
40 changes: 40 additions & 0 deletions examples/with-telemetry/otel.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318

processors:
batch:

exporters:
otlp/jaeger:
endpoint: 'jaeger:4317'
tls:
insecure: true

prometheus:
endpoint: '0.0.0.0:8889'

service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp/jaeger]

metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheus]

telemetry:
metrics:
readers:
- pull:
exporter:
prometheus:
host: '0.0.0.0'
port: 8888
20 changes: 20 additions & 0 deletions examples/with-telemetry/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@example/with-telemetry",
"type": "module",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro",
"server": "node dist/server/entry.mjs"
},
"dependencies": {
"@astrojs/node": "^9.3.3",
"@astrojs/opentelemetry": "0.0.1",
"@astrojs/svelte": "^7.1.0",
"astro": "^5.12.8",
"svelte": "^5.25.7"
}
}
11 changes: 11 additions & 0 deletions examples/with-telemetry/prometheus.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
global:
scrape_interval: 10s
scrape_configs:
- job_name: otel_collector
static_configs:
- targets:
- otel:8888
- job_name: app
static_configs:
- targets:
- otel:8889
9 changes: 9 additions & 0 deletions examples/with-telemetry/public/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 69 additions & 0 deletions examples/with-telemetry/src/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
export interface Product {
id: number;
name: string;
price: number;
image: string;
}

interface User {
id: number;
}

interface Cart {
items: Array<{
id: number;
name: string;
count: number;
}>;
}

async function getJson<T>(incomingReq: Request, endpoint: string): Promise<T> {
const origin = new URL(incomingReq.url).origin;
try {
const response = await fetch(`${origin}${endpoint}`, {
credentials: 'same-origin',
headers: incomingReq.headers,
});
if (!response.ok) {
throw new Error(`GET ${endpoint} failed: ${response.statusText}`);
}
return response.json() as Promise<T>;
} catch (error) {
if (error instanceof DOMException || error instanceof TypeError) {
throw new Error(`GET ${endpoint} failed: ${error.message}`);
}
throw error;
}
}

export async function getProducts(incomingReq: Request): Promise<Product[]> {
return getJson<Product[]>(incomingReq, '/api/products');
}

export async function getProduct(incomingReq: Request, id: number): Promise<Product> {
return getJson<Product>(incomingReq, `/api/products/${id}`);
}

export async function getUser(incomingReq: Request): Promise<User> {
return getJson<User>(incomingReq, `/api/user`);
}

export async function getCart(incomingReq: Request): Promise<Cart> {
return getJson<Cart>(incomingReq, `/api/cart`);
}

export async function addToUserCart(id: number | string, name: string): Promise<void> {
await fetch(`${location.origin}/api/cart`, {
credentials: 'same-origin',
method: 'POST',
mode: 'no-cors',
headers: {
'Content-Type': 'application/json',
Cache: 'no-cache',
},
body: JSON.stringify({
id,
name,
}),
});
}
54 changes: 54 additions & 0 deletions examples/with-telemetry/src/components/AddToCart.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<script>
import { addToUserCart } from '../api';

let { id, name } = $props()

function notifyCartItem(id) {
window.dispatchEvent(new CustomEvent('add-to-cart', {
detail: id
}));
}

async function addToCart() {
await addToUserCart(id, name);
notifyCartItem(id);
}
</script>
<style>
button {
display:block;
padding:0.5em 1em 0.5em 1em;
border-radius:100px;
border:none;
font-size: 1.4em;
position:relative;
background:#0652DD;
cursor:pointer;
height:2em;
width:10em;
overflow:hidden;
transition:transform 0.1s;
z-index:1;
}
button:hover {
transform:scale(1.1);
}

.pretext {
color:#fff;
background:#0652DD;
position:absolute;
top:0;
left:0;
height:100%;
width:100%;
display:flex;
justify-content:center;
align-items:center;
font-family: 'Quicksand', sans-serif;
text-transform: uppercase;
}
</style>
<button click={addToCart}>
<span class="pretext">Add to cart</span>
</button>
34 changes: 34 additions & 0 deletions examples/with-telemetry/src/components/Cart.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script>
let { count } = $props()
let items = new Set();

function onAddToCart(ev) {
const id = ev.detail;
items.add(id);
count++;
}
</script>
<style>
.cart {
display: flex;
align-items: center;
text-decoration: none;
color: inherit;
}
.cart :first-child {
margin-right: 5px;
}

.cart-icon {
font-size: 36px;
}

.count {
font-size: 24px;
}
</style>
<svelte:window onadd-to-cart={onAddToCart}/>
<a href="/cart" class="cart">
<span class="material-icons cart-icon">shopping_cart</span>
<span class="count">{count}</span>
</a>
13 changes: 13 additions & 0 deletions examples/with-telemetry/src/components/Container.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
const { tag = 'div' } = Astro.props;
const Tag = tag;
---

<style>
.container {
width: 1248px; /** TODO: responsive */
margin-left: auto;
margin-right: auto;
}
</style>
<Tag class="container"><slot /></Tag>
49 changes: 49 additions & 0 deletions examples/with-telemetry/src/components/Header.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
import { getCart } from '../api';
import Cart from './Cart.svelte';
import TextDecorationSkip from './TextDecorationSkip.astro';

const cart = await getCart(Astro.request);
const cartCount = cart.items.reduce((sum, item) => sum + item.count, 0);
---

<style>
@import url('https://fonts.googleapis.com/css2?family=Lobster&display=swap');

header {
margin: 1rem 2rem;
display: flex;
justify-content: space-between;
}

h1 {
margin: 0;
font-family: 'Lobster', cursive;
color: black;
}

a,
a:visited {
color: inherit;
text-decoration: none;
}

.right-pane {
display: flex;
}

.material-icons {
font-size: 36px;
margin-right: 1rem;
}
</style>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<header>
<h1><a href="/"><TextDecorationSkip text="Online Store" /></a></h1>
<div class="right-pane">
<a href="/login">
<span class="material-icons"> login</span>
</a>
<Cart client:idle count={cartCount} />
</div>
</header>
Loading
Loading