-
Notifications
You must be signed in to change notification settings - Fork 3
/
demo.ts
executable file
·142 lines (120 loc) · 4.12 KB
/
demo.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#!/usr/bin/env -S deno run --watch --allow-read --allow-sys=hostname,osRelease --allow-env --allow-net --allow-run=uptime,sleep,ping,nonextant
import { metrics, trace, ValueType } from "./opentelemetry/api.js";
import { logs } from "./opentelemetry/api-logs.js";
import { SEMATTRS_HTTP_METHOD } from "./opentelemetry/semantic-conventions.js";
import { DenoTelemetrySdk } from './sdk.ts'
import { httpTracer } from "./instrumentation/http-server.ts";
new DenoTelemetrySdk({
resourceAttrs: {
'service.name': 'observability-demo',
'deployment.environment': 'local',
'service.version': 'adhoc',
},
});
// You could 'get' these APIs from the sdk instance fields,
// but it's better to decouple your application logic from your loading of the SDK
const logger = logs.getLogger('demo.ts');
logger.emit({
body: 'im alive',
});
const myMeter = metrics.getMeter('my-service-meter');
const test3 = myMeter.createCounter('test3', { valueType: ValueType.INT });
const test2 = myMeter.createHistogram('test2', { valueType: ValueType.DOUBLE });
async function handler(req: Request): Promise<Response> {
const url = new URL(req.url);
console.log(req.method, url.pathname);
test3.add(1, {[SEMATTRS_HTTP_METHOD]: req.method});
test2.record(50+Math.round(Math.random()*25), {[SEMATTRS_HTTP_METHOD]: req.method});
if (url.pathname == '/log') {
logger.emit({
body: 'hello world',
});
return new Response('logged hello world');
}
if (url.pathname == '/inner') {
await getData();
return new Response(JSON.stringify({
headers: Object.fromEntries(req.headers),
remote: await getData(),
}, null, 2));
}
if (url.pathname == '/uptime') {
const text = await new Promise<string>(ok => setTimeout(async () => {
const proc = await new Deno.Command('uptime', {
stdin: 'null',
stdout: 'piped',
stderr: 'inherit',
}).output();
const text = new TextDecoder().decode(proc.stdout);
ok(text);
}, 50));
return new Response(text);
}
if (url.pathname == '/failure') {
try {
await new Deno.Command('nonextant', {
stdin: 'null',
stdout: 'piped',
stderr: 'inherit',
}).output();
return new Response('No failure happened??');
} catch (thrown: unknown) {
const err = thrown as Error;
return new Response(`Failed as expected.\n${err.message}`);
}
}
if (url.pathname == '/sleep') {
// First, we spawn and gather the output as two chained steps.
await new Deno.Command('sleep', {
args: ['1'],
stdin: 'null',
}).spawn().output();
// Second, we spawn and gather the output as two different steps on the Command.
{
const sleepCmd = new Deno.Command('sleep', {
args: ['1'],
stdin: 'null',
});
sleepCmd.spawn();
await sleepCmd.output();
}
// Third, we run command in parallel, using the single-shot output() API.
await Promise.all([1,2,3,4,5].map(x =>
new Deno.Command('sleep', {
args: [`${x}`],
stdin: 'null',
}).output()));
// Fourth, we run the command with the synchronous single-shot API.
// This is not ideal in a server but we need to make sure our instrument works regardless.
new Deno.Command('sleep', {
args: ['1'],
stdin: 'null',
}).outputSync();
return new Response('done sleeping');
}
if (url.pathname == '/ping') {
const proc = new Deno.Command('ping', {
args: ['-c5', 'google.com'],
stdin: 'null',
stdout: 'piped',
stderr: 'inherit',
}).spawn();
return new Response(proc.stdout);
}
if (url.pathname == '/') {
const body1 = await getData();
const body2 = await fetch('http://localhost:8000/inner').then(x => x.json());
return new Response(JSON.stringify({
headers: Object.fromEntries(req.headers),
body1, body2,
}, null, 2));
}
return new Response('404', { status: 404 });
}
async function getData() {
const resp = await fetch("https://httpbin.org/get");
trace.getActiveSpan()?.addEvent('fetching-single-span-completed');
const body = await resp.json();
return body;
}
Deno.serve(httpTracer(handler));