container-superposition 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/README.md +843 -0
  2. package/dist/scripts/init.d.ts +3 -0
  3. package/dist/scripts/init.d.ts.map +1 -0
  4. package/dist/scripts/init.js +1190 -0
  5. package/dist/scripts/init.js.map +1 -0
  6. package/dist/scripts/migrate-to-manifests.d.ts +12 -0
  7. package/dist/scripts/migrate-to-manifests.d.ts.map +1 -0
  8. package/dist/scripts/migrate-to-manifests.js +230 -0
  9. package/dist/scripts/migrate-to-manifests.js.map +1 -0
  10. package/dist/tool/questionnaire/composer.d.ts +6 -0
  11. package/dist/tool/questionnaire/composer.d.ts.map +1 -0
  12. package/dist/tool/questionnaire/composer.js +1232 -0
  13. package/dist/tool/questionnaire/composer.js.map +1 -0
  14. package/dist/tool/readme/markdown-parser.d.ts +30 -0
  15. package/dist/tool/readme/markdown-parser.d.ts.map +1 -0
  16. package/dist/tool/readme/markdown-parser.js +139 -0
  17. package/dist/tool/readme/markdown-parser.js.map +1 -0
  18. package/dist/tool/readme/readme-generator.d.ts +9 -0
  19. package/dist/tool/readme/readme-generator.d.ts.map +1 -0
  20. package/dist/tool/readme/readme-generator.js +422 -0
  21. package/dist/tool/readme/readme-generator.js.map +1 -0
  22. package/dist/tool/schema/custom-loader.d.ts +17 -0
  23. package/dist/tool/schema/custom-loader.d.ts.map +1 -0
  24. package/dist/tool/schema/custom-loader.js +149 -0
  25. package/dist/tool/schema/custom-loader.js.map +1 -0
  26. package/dist/tool/schema/overlay-loader.d.ts +47 -0
  27. package/dist/tool/schema/overlay-loader.d.ts.map +1 -0
  28. package/dist/tool/schema/overlay-loader.js +252 -0
  29. package/dist/tool/schema/overlay-loader.js.map +1 -0
  30. package/dist/tool/schema/types.d.ts +212 -0
  31. package/dist/tool/schema/types.d.ts.map +1 -0
  32. package/dist/tool/schema/types.js +5 -0
  33. package/dist/tool/schema/types.js.map +1 -0
  34. package/docs/README.md +308 -0
  35. package/docs/architecture.md +233 -0
  36. package/docs/creating-overlays.md +549 -0
  37. package/docs/custom-patches.md +540 -0
  38. package/docs/dependencies.md +279 -0
  39. package/docs/examples/custom-patches-example.md +85 -0
  40. package/docs/examples.md +576 -0
  41. package/docs/messaging-comparison.md +265 -0
  42. package/docs/messaging-quick-start.md +385 -0
  43. package/docs/observability-workflow.md +537 -0
  44. package/docs/overlay-manifest-refactoring.md +214 -0
  45. package/docs/overlay-metadata-archive.md +54 -0
  46. package/docs/overlays.md +523 -0
  47. package/docs/presets-architecture.md +498 -0
  48. package/docs/presets.md +366 -0
  49. package/docs/publishing.md +476 -0
  50. package/docs/quick-reference.md +326 -0
  51. package/docs/ux.md +170 -0
  52. package/features/README.md +85 -0
  53. package/features/cross-distro-packages/README.md +146 -0
  54. package/features/cross-distro-packages/devcontainer-feature.json +20 -0
  55. package/features/cross-distro-packages/install.sh +58 -0
  56. package/features/local-secrets-manager/devcontainer-feature.json +18 -0
  57. package/features/local-secrets-manager/install.sh +127 -0
  58. package/features/project-scaffolder/devcontainer-feature.json +24 -0
  59. package/features/project-scaffolder/install.sh +100 -0
  60. package/features/team-conventions/devcontainer-feature.json +24 -0
  61. package/features/team-conventions/install.sh +93 -0
  62. package/overlays/.registry/README.md +14 -0
  63. package/overlays/.registry/base-images.yml +26 -0
  64. package/overlays/.registry/base-templates.yml +7 -0
  65. package/overlays/README.md +155 -0
  66. package/overlays/alertmanager/.env.example +5 -0
  67. package/overlays/alertmanager/README.md +465 -0
  68. package/overlays/alertmanager/alert-rules.yml +56 -0
  69. package/overlays/alertmanager/alertmanager.yml +42 -0
  70. package/overlays/alertmanager/devcontainer.patch.json +12 -0
  71. package/overlays/alertmanager/docker-compose.yml +20 -0
  72. package/overlays/alertmanager/overlay.yml +17 -0
  73. package/overlays/alertmanager/setup.sh +53 -0
  74. package/overlays/alertmanager/verify.sh +31 -0
  75. package/overlays/aws-cli/README.md +473 -0
  76. package/overlays/aws-cli/devcontainer.patch.json +13 -0
  77. package/overlays/aws-cli/overlay.yml +13 -0
  78. package/overlays/azure-cli/README.md +551 -0
  79. package/overlays/azure-cli/devcontainer.patch.json +8 -0
  80. package/overlays/azure-cli/overlay.yml +13 -0
  81. package/overlays/bun/README.md +312 -0
  82. package/overlays/bun/devcontainer.patch.json +41 -0
  83. package/overlays/bun/overlay.yml +16 -0
  84. package/overlays/bun/setup.sh +79 -0
  85. package/overlays/bun/verify.sh +30 -0
  86. package/overlays/codex/README.md +128 -0
  87. package/overlays/codex/devcontainer.patch.json +3 -0
  88. package/overlays/codex/overlay.yml +14 -0
  89. package/overlays/codex/setup.sh +24 -0
  90. package/overlays/codex/verify.sh +30 -0
  91. package/overlays/commitlint/README.md +333 -0
  92. package/overlays/commitlint/devcontainer.patch.json +8 -0
  93. package/overlays/commitlint/overlay.yml +16 -0
  94. package/overlays/commitlint/setup.sh +234 -0
  95. package/overlays/direnv/README.md +504 -0
  96. package/overlays/direnv/devcontainer.patch.json +6 -0
  97. package/overlays/direnv/overlay.yml +13 -0
  98. package/overlays/direnv/setup.sh +139 -0
  99. package/overlays/docker-in-docker/README.md +534 -0
  100. package/overlays/docker-in-docker/devcontainer.patch.json +10 -0
  101. package/overlays/docker-in-docker/overlay.yml +13 -0
  102. package/overlays/docker-sock/README.md +256 -0
  103. package/overlays/docker-sock/devcontainer.patch.json +9 -0
  104. package/overlays/docker-sock/docker-compose.yml +8 -0
  105. package/overlays/docker-sock/overlay.yml +13 -0
  106. package/overlays/dotnet/README.md +147 -0
  107. package/overlays/dotnet/devcontainer.patch.json +51 -0
  108. package/overlays/dotnet/global-tools.txt +24 -0
  109. package/overlays/dotnet/overlay.yml +13 -0
  110. package/overlays/dotnet/setup.sh +51 -0
  111. package/overlays/dotnet/verify.sh +26 -0
  112. package/overlays/gcloud/README.md +269 -0
  113. package/overlays/gcloud/devcontainer.patch.json +14 -0
  114. package/overlays/gcloud/overlay.yml +14 -0
  115. package/overlays/gcloud/verify.sh +52 -0
  116. package/overlays/git-helpers/README.md +168 -0
  117. package/overlays/git-helpers/devcontainer.patch.json +33 -0
  118. package/overlays/git-helpers/overlay.yml +15 -0
  119. package/overlays/git-helpers/setup.sh +91 -0
  120. package/overlays/go/README.md +293 -0
  121. package/overlays/go/devcontainer.patch.json +43 -0
  122. package/overlays/go/overlay.yml +15 -0
  123. package/overlays/go/setup.sh +33 -0
  124. package/overlays/go/verify.sh +40 -0
  125. package/overlays/grafana/.env.example +9 -0
  126. package/overlays/grafana/README.md +462 -0
  127. package/overlays/grafana/dashboard-provider.yml +11 -0
  128. package/overlays/grafana/dashboards/observability-overview.json +263 -0
  129. package/overlays/grafana/devcontainer.patch.json +12 -0
  130. package/overlays/grafana/docker-compose.yml +27 -0
  131. package/overlays/grafana/grafana-datasources.yml +57 -0
  132. package/overlays/grafana/overlay.yml +21 -0
  133. package/overlays/grafana/verify.sh +34 -0
  134. package/overlays/jaeger/.env.example +7 -0
  135. package/overlays/jaeger/README.md +867 -0
  136. package/overlays/jaeger/devcontainer.patch.json +12 -0
  137. package/overlays/jaeger/docker-compose.yml +17 -0
  138. package/overlays/jaeger/overlay.yml +19 -0
  139. package/overlays/java/README.md +267 -0
  140. package/overlays/java/devcontainer.patch.json +44 -0
  141. package/overlays/java/overlay.yml +16 -0
  142. package/overlays/java/setup.sh +41 -0
  143. package/overlays/java/verify.sh +42 -0
  144. package/overlays/just/README.md +443 -0
  145. package/overlays/just/devcontainer.patch.json +3 -0
  146. package/overlays/just/overlay.yml +13 -0
  147. package/overlays/just/setup.sh +182 -0
  148. package/overlays/kubectl-helm/README.md +660 -0
  149. package/overlays/kubectl-helm/devcontainer.patch.json +10 -0
  150. package/overlays/kubectl-helm/overlay.yml +13 -0
  151. package/overlays/loki/.env.example +5 -0
  152. package/overlays/loki/README.md +1156 -0
  153. package/overlays/loki/devcontainer.patch.json +12 -0
  154. package/overlays/loki/docker-compose.yml +18 -0
  155. package/overlays/loki/loki-config.yaml +45 -0
  156. package/overlays/loki/overlay.yml +17 -0
  157. package/overlays/minio/.env.example +9 -0
  158. package/overlays/minio/README.md +639 -0
  159. package/overlays/minio/devcontainer.patch.json +30 -0
  160. package/overlays/minio/docker-compose.yml +28 -0
  161. package/overlays/minio/overlay.yml +18 -0
  162. package/overlays/minio/setup.sh +61 -0
  163. package/overlays/minio/verify.sh +64 -0
  164. package/overlays/mkdocs/README.md +309 -0
  165. package/overlays/mkdocs/devcontainer.patch.json +24 -0
  166. package/overlays/mkdocs/overlay.yml +15 -0
  167. package/overlays/modern-cli-tools/README.md +556 -0
  168. package/overlays/modern-cli-tools/devcontainer.patch.json +3 -0
  169. package/overlays/modern-cli-tools/overlay.yml +13 -0
  170. package/overlays/modern-cli-tools/setup.sh +153 -0
  171. package/overlays/mongodb/.env.example +9 -0
  172. package/overlays/mongodb/README.md +481 -0
  173. package/overlays/mongodb/devcontainer.patch.json +32 -0
  174. package/overlays/mongodb/docker-compose.yml +44 -0
  175. package/overlays/mongodb/overlay.yml +17 -0
  176. package/overlays/mongodb/verify.sh +48 -0
  177. package/overlays/mysql/.env.example +11 -0
  178. package/overlays/mysql/README.md +542 -0
  179. package/overlays/mysql/devcontainer.patch.json +34 -0
  180. package/overlays/mysql/docker-compose.yml +55 -0
  181. package/overlays/mysql/overlay.yml +16 -0
  182. package/overlays/mysql/verify.sh +48 -0
  183. package/overlays/nats/.env.example +5 -0
  184. package/overlays/nats/README.md +762 -0
  185. package/overlays/nats/devcontainer.patch.json +24 -0
  186. package/overlays/nats/docker-compose.yml +31 -0
  187. package/overlays/nats/overlay.yml +18 -0
  188. package/overlays/nats/verify.sh +50 -0
  189. package/overlays/ngrok/README.md +503 -0
  190. package/overlays/ngrok/devcontainer.patch.json +3 -0
  191. package/overlays/ngrok/overlay.yml +14 -0
  192. package/overlays/ngrok/setup.sh +125 -0
  193. package/overlays/nodejs/README.md +192 -0
  194. package/overlays/nodejs/devcontainer.patch.json +49 -0
  195. package/overlays/nodejs/global-packages.txt +16 -0
  196. package/overlays/nodejs/overlay.yml +14 -0
  197. package/overlays/nodejs/setup.sh +46 -0
  198. package/overlays/nodejs/verify.sh +32 -0
  199. package/overlays/otel-collector/.env.example +9 -0
  200. package/overlays/otel-collector/README.md +1257 -0
  201. package/overlays/otel-collector/devcontainer.patch.json +28 -0
  202. package/overlays/otel-collector/docker-compose.yml +22 -0
  203. package/overlays/otel-collector/otel-collector-config.yaml +68 -0
  204. package/overlays/otel-collector/overlay.yml +21 -0
  205. package/overlays/otel-collector/setup.sh +49 -0
  206. package/overlays/otel-demo-nodejs/.env.example +2 -0
  207. package/overlays/otel-demo-nodejs/Dockerfile-otel-demo-nodejs +17 -0
  208. package/overlays/otel-demo-nodejs/README.md +409 -0
  209. package/overlays/otel-demo-nodejs/devcontainer.patch.json +12 -0
  210. package/overlays/otel-demo-nodejs/docker-compose.yml +19 -0
  211. package/overlays/otel-demo-nodejs/overlay.yml +23 -0
  212. package/overlays/otel-demo-nodejs/package-otel-demo-nodejs.json +20 -0
  213. package/overlays/otel-demo-nodejs/server-otel-demo-nodejs.js +259 -0
  214. package/overlays/otel-demo-nodejs/tracing-otel-demo-nodejs.js +57 -0
  215. package/overlays/otel-demo-nodejs/verify.sh +31 -0
  216. package/overlays/otel-demo-python/.env.example +2 -0
  217. package/overlays/otel-demo-python/Dockerfile-otel-demo-python +16 -0
  218. package/overlays/otel-demo-python/README.md +82 -0
  219. package/overlays/otel-demo-python/app-otel-demo-python.py +208 -0
  220. package/overlays/otel-demo-python/devcontainer.patch.json +12 -0
  221. package/overlays/otel-demo-python/docker-compose.yml +19 -0
  222. package/overlays/otel-demo-python/overlay.yml +23 -0
  223. package/overlays/otel-demo-python/requirements-otel-demo-python.txt +4 -0
  224. package/overlays/otel-demo-python/verify.sh +31 -0
  225. package/overlays/playwright/README.md +629 -0
  226. package/overlays/playwright/devcontainer.patch.json +9 -0
  227. package/overlays/playwright/overlay.yml +13 -0
  228. package/overlays/postgres/.env.example +6 -0
  229. package/overlays/postgres/README.md +602 -0
  230. package/overlays/postgres/devcontainer.patch.json +21 -0
  231. package/overlays/postgres/docker-compose.yml +22 -0
  232. package/overlays/postgres/overlay.yml +15 -0
  233. package/overlays/postgres/verify.sh +45 -0
  234. package/overlays/powershell/README.md +314 -0
  235. package/overlays/powershell/devcontainer.patch.json +22 -0
  236. package/overlays/powershell/overlay.yml +13 -0
  237. package/overlays/powershell/setup.sh +29 -0
  238. package/overlays/powershell/verify.sh +38 -0
  239. package/overlays/pre-commit/README.md +263 -0
  240. package/overlays/pre-commit/devcontainer.patch.json +9 -0
  241. package/overlays/pre-commit/overlay.yml +16 -0
  242. package/overlays/pre-commit/setup.sh +129 -0
  243. package/overlays/presets/docs-site.yml +118 -0
  244. package/overlays/presets/fullstack.yml +181 -0
  245. package/overlays/presets/microservice.yml +118 -0
  246. package/overlays/presets/web-api.yml +109 -0
  247. package/overlays/prometheus/.env.example +5 -0
  248. package/overlays/prometheus/README.md +1246 -0
  249. package/overlays/prometheus/devcontainer.patch.json +12 -0
  250. package/overlays/prometheus/docker-compose.yml +22 -0
  251. package/overlays/prometheus/overlay.yml +17 -0
  252. package/overlays/prometheus/prometheus.yml +12 -0
  253. package/overlays/prometheus/verify.sh +34 -0
  254. package/overlays/promtail/.env.example +2 -0
  255. package/overlays/promtail/README.md +357 -0
  256. package/overlays/promtail/devcontainer.patch.json +5 -0
  257. package/overlays/promtail/docker-compose.yml +16 -0
  258. package/overlays/promtail/overlay.yml +17 -0
  259. package/overlays/promtail/promtail-config.yaml +60 -0
  260. package/overlays/promtail/verify.sh +31 -0
  261. package/overlays/pulumi/README.md +472 -0
  262. package/overlays/pulumi/devcontainer.patch.json +13 -0
  263. package/overlays/pulumi/overlay.yml +14 -0
  264. package/overlays/pulumi/verify.sh +31 -0
  265. package/overlays/python/README.md +919 -0
  266. package/overlays/python/devcontainer.patch.json +41 -0
  267. package/overlays/python/overlay.yml +12 -0
  268. package/overlays/python/requirements-overlay.txt +13 -0
  269. package/overlays/python/setup.sh +47 -0
  270. package/overlays/python/verify.sh +32 -0
  271. package/overlays/rabbitmq/.env.example +7 -0
  272. package/overlays/rabbitmq/README.md +680 -0
  273. package/overlays/rabbitmq/devcontainer.patch.json +28 -0
  274. package/overlays/rabbitmq/docker-compose.yml +30 -0
  275. package/overlays/rabbitmq/overlay.yml +18 -0
  276. package/overlays/rabbitmq/verify.sh +41 -0
  277. package/overlays/redis/.env.example +4 -0
  278. package/overlays/redis/README.md +776 -0
  279. package/overlays/redis/devcontainer.patch.json +21 -0
  280. package/overlays/redis/docker-compose.yml +21 -0
  281. package/overlays/redis/overlay.yml +15 -0
  282. package/overlays/redis/verify.sh +41 -0
  283. package/overlays/redpanda/.env.example +10 -0
  284. package/overlays/redpanda/README.md +703 -0
  285. package/overlays/redpanda/devcontainer.patch.json +37 -0
  286. package/overlays/redpanda/docker-compose.yml +67 -0
  287. package/overlays/redpanda/overlay.yml +21 -0
  288. package/overlays/redpanda/verify.sh +48 -0
  289. package/overlays/rust/README.md +299 -0
  290. package/overlays/rust/devcontainer.patch.json +39 -0
  291. package/overlays/rust/overlay.yml +15 -0
  292. package/overlays/rust/setup.sh +36 -0
  293. package/overlays/rust/verify.sh +51 -0
  294. package/overlays/sqlite/README.md +584 -0
  295. package/overlays/sqlite/devcontainer.patch.json +14 -0
  296. package/overlays/sqlite/overlay.yml +15 -0
  297. package/overlays/sqlite/setup.sh +27 -0
  298. package/overlays/sqlite/verify.sh +43 -0
  299. package/overlays/sqlserver/.env.example +6 -0
  300. package/overlays/sqlserver/README.md +592 -0
  301. package/overlays/sqlserver/devcontainer.patch.json +22 -0
  302. package/overlays/sqlserver/docker-compose.yml +32 -0
  303. package/overlays/sqlserver/overlay.yml +17 -0
  304. package/overlays/sqlserver/verify.sh +30 -0
  305. package/overlays/tempo/.env.example +5 -0
  306. package/overlays/tempo/README.md +273 -0
  307. package/overlays/tempo/devcontainer.patch.json +12 -0
  308. package/overlays/tempo/docker-compose.yml +20 -0
  309. package/overlays/tempo/overlay.yml +20 -0
  310. package/overlays/tempo/tempo-config.yaml +32 -0
  311. package/overlays/tempo/verify.sh +31 -0
  312. package/overlays/terraform/README.md +389 -0
  313. package/overlays/terraform/devcontainer.patch.json +15 -0
  314. package/overlays/terraform/overlay.yml +14 -0
  315. package/overlays/terraform/verify.sh +63 -0
  316. package/package.json +74 -0
  317. package/templates/README.md +285 -0
  318. package/templates/compose/.devcontainer/devcontainer.json +46 -0
  319. package/templates/compose/.devcontainer/docker-compose.yml +12 -0
  320. package/templates/compose/README.md +20 -0
  321. package/templates/plain/.devcontainer/devcontainer.json +35 -0
  322. package/templates/plain/README.md +21 -0
  323. package/tool/README.md +281 -0
  324. package/tool/schema/base-images.schema.json +43 -0
  325. package/tool/schema/base-templates.schema.json +34 -0
  326. package/tool/schema/config.schema.json +71 -0
  327. package/tool/schema/overlay-manifest.schema.json +86 -0
@@ -0,0 +1,259 @@
1
+ const http = require('http');
2
+ const pino = require('pino');
3
+ const { trace, metrics, context } = require('@opentelemetry/api');
4
+
5
+ // Create JSON logger
6
+ const logger = pino({
7
+ level: 'info',
8
+ formatters: {
9
+ level: (label) => {
10
+ return { level: label };
11
+ },
12
+ },
13
+ });
14
+
15
+ // Get tracer and meter
16
+ const tracer = trace.getTracer('otel-demo-nodejs', '1.0.0');
17
+ const meter = metrics.getMeter('otel-demo-nodejs', '1.0.0');
18
+
19
+ // Create custom metrics
20
+ const requestCounter = meter.createCounter('http_requests_total', {
21
+ description: 'Total number of HTTP requests',
22
+ });
23
+
24
+ const requestDuration = meter.createHistogram('http_request_duration_seconds', {
25
+ description: 'HTTP request duration in seconds',
26
+ });
27
+
28
+ const activeRequests = meter.createUpDownCounter('http_requests_active', {
29
+ description: 'Number of active HTTP requests',
30
+ });
31
+
32
+ // Request handler
33
+ function handleRequest(req, res) {
34
+ const startTime = Date.now();
35
+
36
+ // Increment active requests
37
+ activeRequests.add(1, { method: req.method, route: req.url });
38
+
39
+ // Create span for request
40
+ const span = tracer.startSpan(`${req.method} ${req.url}`, {
41
+ kind: 1, // SERVER
42
+ attributes: {
43
+ 'http.method': req.method,
44
+ 'http.url': req.url,
45
+ 'http.target': req.url,
46
+ },
47
+ });
48
+
49
+ context.with(trace.setSpan(context.active(), span), () => {
50
+ // Log request
51
+ logger.info({
52
+ msg: 'HTTP request received',
53
+ method: req.method,
54
+ url: req.url,
55
+ 'trace.id': span.spanContext().traceId,
56
+ 'span.id': span.spanContext().spanId,
57
+ });
58
+
59
+ // Route handling
60
+ if (req.url === '/') {
61
+ handleHome(req, res, span);
62
+ } else if (req.url === '/api/data') {
63
+ handleData(req, res, span);
64
+ } else if (req.url === '/api/slow') {
65
+ handleSlow(req, res, span);
66
+ } else if (req.url === '/api/error') {
67
+ handleError(req, res, span);
68
+ } else if (req.url === '/health') {
69
+ handleHealth(req, res, span);
70
+ } else {
71
+ handleNotFound(req, res, span);
72
+ }
73
+
74
+ // Record metrics
75
+ const duration = (Date.now() - startTime) / 1000;
76
+ requestCounter.add(1, {
77
+ method: req.method,
78
+ route: req.url,
79
+ status: res.statusCode,
80
+ });
81
+ requestDuration.record(duration, {
82
+ method: req.method,
83
+ route: req.url,
84
+ status: res.statusCode,
85
+ });
86
+ activeRequests.add(-1, { method: req.method, route: req.url });
87
+
88
+ // Set span status and end
89
+ span.setAttribute('http.status_code', res.statusCode);
90
+ if (res.statusCode >= 400) {
91
+ span.setStatus({ code: 2, message: 'Error' }); // ERROR
92
+ } else {
93
+ span.setStatus({ code: 1 }); // OK
94
+ }
95
+ span.end();
96
+ });
97
+ }
98
+
99
+ function handleHome(req, res, span) {
100
+ span.addEvent('Rendering home page');
101
+ res.writeHead(200, { 'Content-Type': 'text/html' });
102
+ res.end(`
103
+ <!DOCTYPE html>
104
+ <html>
105
+ <head>
106
+ <title>OpenTelemetry Demo - Node.js</title>
107
+ <style>
108
+ body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
109
+ h1 { color: #333; }
110
+ .endpoint { background: #f4f4f4; padding: 10px; margin: 10px 0; border-left: 4px solid #007acc; }
111
+ .endpoint code { background: #e0e0e0; padding: 2px 6px; border-radius: 3px; }
112
+ .success { color: #28a745; }
113
+ .warning { color: #ffc107; }
114
+ .error { color: #dc3545; }
115
+ </style>
116
+ </head>
117
+ <body>
118
+ <h1>🔭 OpenTelemetry Demo - Node.js</h1>
119
+ <p>This is a sample application instrumented with OpenTelemetry.</p>
120
+
121
+ <h2>Available Endpoints:</h2>
122
+
123
+ <div class="endpoint">
124
+ <strong class="success">GET /</strong><br>
125
+ This page - application home
126
+ </div>
127
+
128
+ <div class="endpoint">
129
+ <strong class="success">GET /api/data</strong><br>
130
+ Returns sample JSON data with nested spans
131
+ </div>
132
+
133
+ <div class="endpoint">
134
+ <strong class="warning">GET /api/slow</strong><br>
135
+ Simulates slow request (2 second delay)
136
+ </div>
137
+
138
+ <div class="endpoint">
139
+ <strong class="error">GET /api/error</strong><br>
140
+ Simulates an error (500 status)
141
+ </div>
142
+
143
+ <div class="endpoint">
144
+ <strong class="success">GET /health</strong><br>
145
+ Health check endpoint
146
+ </div>
147
+
148
+ <h2>Observability Data:</h2>
149
+ <ul>
150
+ <li><strong>Traces:</strong> Sent to OTLP endpoint (view in Jaeger/Tempo via Grafana)</li>
151
+ <li><strong>Metrics:</strong> Exported every 5 seconds (view in Prometheus/Grafana)</li>
152
+ <li><strong>Logs:</strong> JSON formatted to stdout (view in Loki via Grafana)</li>
153
+ </ul>
154
+
155
+ <h2>Try It:</h2>
156
+ <ul>
157
+ <li><a href="/api/data">Call /api/data</a></li>
158
+ <li><a href="/api/slow">Call /api/slow (slow)</a></li>
159
+ <li><a href="/api/error">Call /api/error (error)</a></li>
160
+ <li><a href="/health">Call /health</a></li>
161
+ </ul>
162
+ </body>
163
+ </html>
164
+ `);
165
+ }
166
+
167
+ function handleData(req, res, span) {
168
+ // Create child span for data processing
169
+ const childSpan = tracer.startSpan('process_data', {
170
+ parent: span,
171
+ });
172
+
173
+ childSpan.addEvent('Fetching data');
174
+
175
+ // Simulate data processing
176
+ const data = {
177
+ timestamp: new Date().toISOString(),
178
+ items: [
179
+ { id: 1, name: 'Item 1', value: Math.random() * 100 },
180
+ { id: 2, name: 'Item 2', value: Math.random() * 100 },
181
+ { id: 3, name: 'Item 3', value: Math.random() * 100 },
182
+ ],
183
+ trace: {
184
+ traceId: span.spanContext().traceId,
185
+ spanId: span.spanContext().spanId,
186
+ },
187
+ };
188
+
189
+ childSpan.setAttribute('data.items', data.items.length);
190
+ childSpan.end();
191
+
192
+ logger.info({ msg: 'Data fetched successfully', itemCount: data.items.length });
193
+
194
+ res.writeHead(200, { 'Content-Type': 'application/json' });
195
+ res.end(JSON.stringify(data, null, 2));
196
+ }
197
+
198
+ function handleSlow(req, res, span) {
199
+ span.addEvent('Simulating slow operation');
200
+ logger.warn({ msg: 'Slow endpoint called', expectedDelay: '2s' });
201
+
202
+ // Simulate slow operation
203
+ setTimeout(() => {
204
+ res.writeHead(200, { 'Content-Type': 'application/json' });
205
+ res.end(
206
+ JSON.stringify({
207
+ message: 'This was a slow request',
208
+ duration: '2 seconds',
209
+ })
210
+ );
211
+ }, 2000);
212
+ }
213
+
214
+ function handleError(req, res, span) {
215
+ span.addEvent('Error occurred');
216
+ logger.error({ msg: 'Error endpoint called', error: 'Simulated error' });
217
+
218
+ span.recordException(new Error('Simulated error'));
219
+
220
+ res.writeHead(500, { 'Content-Type': 'application/json' });
221
+ res.end(
222
+ JSON.stringify({
223
+ error: 'Internal Server Error',
224
+ message: 'This is a simulated error',
225
+ })
226
+ );
227
+ }
228
+
229
+ function handleHealth(req, res, span) {
230
+ res.writeHead(200, { 'Content-Type': 'application/json' });
231
+ res.end(
232
+ JSON.stringify({
233
+ status: 'healthy',
234
+ timestamp: new Date().toISOString(),
235
+ })
236
+ );
237
+ }
238
+
239
+ function handleNotFound(req, res, span) {
240
+ logger.warn({ msg: 'Not found', url: req.url });
241
+
242
+ res.writeHead(404, { 'Content-Type': 'application/json' });
243
+ res.end(
244
+ JSON.stringify({
245
+ error: 'Not Found',
246
+ path: req.url,
247
+ })
248
+ );
249
+ }
250
+
251
+ // Create HTTP server
252
+ const server = http.createServer(handleRequest);
253
+
254
+ const PORT = process.env.PORT || 8080;
255
+
256
+ server.listen(PORT, () => {
257
+ logger.info({ msg: 'Server started', port: PORT });
258
+ console.log(`🚀 Server running on http://localhost:${PORT}`);
259
+ });
@@ -0,0 +1,57 @@
1
+ const { NodeSDK } = require('@opentelemetry/sdk-node');
2
+ const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
3
+ const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');
4
+ const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-grpc');
5
+ const { PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics');
6
+ const { Resource } = require('@opentelemetry/resources');
7
+ const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
8
+
9
+ // Configure resource with service information
10
+ const resource = Resource.default().merge(
11
+ new Resource({
12
+ [SemanticResourceAttributes.SERVICE_NAME]:
13
+ process.env.OTEL_SERVICE_NAME || 'otel-demo-nodejs',
14
+ [SemanticResourceAttributes.SERVICE_VERSION]: process.env.OTEL_SERVICE_VERSION || '1.0.0',
15
+ [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]:
16
+ process.env.OTEL_DEPLOYMENT_ENVIRONMENT || 'dev',
17
+ })
18
+ );
19
+
20
+ // Configure trace exporter
21
+ const traceExporter = new OTLPTraceExporter({
22
+ url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://otel-collector:4317',
23
+ });
24
+
25
+ // Configure metrics exporter
26
+ const metricReader = new PeriodicExportingMetricReader({
27
+ exporter: new OTLPMetricExporter({
28
+ url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://otel-collector:4317',
29
+ }),
30
+ exportIntervalMillis: 5000, // Export every 5 seconds
31
+ });
32
+
33
+ // Initialize OpenTelemetry SDK
34
+ const sdk = new NodeSDK({
35
+ resource: resource,
36
+ traceExporter: traceExporter,
37
+ metricReader: metricReader,
38
+ instrumentations: [
39
+ getNodeAutoInstrumentations({
40
+ '@opentelemetry/instrumentation-fs': {
41
+ enabled: false, // Disable filesystem instrumentation (noisy)
42
+ },
43
+ }),
44
+ ],
45
+ });
46
+
47
+ // Start the SDK
48
+ sdk.start();
49
+ console.log('OpenTelemetry instrumentation initialized');
50
+
51
+ // Gracefully shutdown on exit
52
+ process.on('SIGTERM', () => {
53
+ sdk.shutdown()
54
+ .then(() => console.log('OpenTelemetry SDK shut down successfully'))
55
+ .catch((error) => console.log('Error shutting down OpenTelemetry SDK', error))
56
+ .finally(() => process.exit(0));
57
+ });
@@ -0,0 +1,31 @@
1
+ #!/bin/bash
2
+ # OTel Demo Node.js verification script
3
+
4
+ echo "🔍 Verifying OTel Demo (Node.js) installation..."
5
+
6
+ # Track overall success
7
+ ALL_CHECKS_PASSED=true
8
+
9
+ # Check if service is running
10
+ if docker ps --format '{{.Names}}' | grep -q otel-demo-nodejs; then
11
+ echo "✓ OTel Demo (Node.js) service is running"
12
+ else
13
+ echo "✗ OTel Demo (Node.js) service is not running"
14
+ ALL_CHECKS_PASSED=false
15
+ fi
16
+
17
+ # Check if HTTP endpoint is accessible
18
+ if curl -s -o /dev/null -w "%{http_code}" http://otel-demo-nodejs:8080/health 2>/dev/null | grep -q "200"; then
19
+ echo "✓ Demo app HTTP endpoint is accessible"
20
+ else
21
+ echo "⚠️ Demo app HTTP endpoint not responding yet (may still be starting)"
22
+ fi
23
+
24
+ # Final result
25
+ if [ "$ALL_CHECKS_PASSED" = true ]; then
26
+ echo "✓ All critical checks passed"
27
+ exit 0
28
+ else
29
+ echo "✗ Some checks failed"
30
+ exit 1
31
+ fi
@@ -0,0 +1,2 @@
1
+ # OTel Demo Python port
2
+ OTEL_DEMO_PYTHON_PORT=8081
@@ -0,0 +1,16 @@
1
+ FROM python:3.12-slim
2
+
3
+ WORKDIR /app
4
+
5
+ # Copy requirements and app files
6
+ COPY ./requirements-otel-demo-python.txt requirements.txt
7
+ COPY ./app-otel-demo-python.py app.py
8
+
9
+ # Install dependencies
10
+ RUN pip install --no-cache-dir -r requirements.txt
11
+
12
+ # Expose port
13
+ EXPOSE 8081
14
+
15
+ # Run with auto-instrumentation
16
+ CMD ["opentelemetry-instrument", "python", "app.py"]
@@ -0,0 +1,82 @@
1
+ # OpenTelemetry Demo - Python
2
+
3
+ Sample Python Flask application fully instrumented with OpenTelemetry to demonstrate distributed tracing, metrics, and logging.
4
+
5
+ ## Features
6
+
7
+ - **Auto-instrumentation** - Automatic Flask request tracing
8
+ - **Custom metrics** - Request counters and duration histograms
9
+ - **Structured logs** - JSON formatted logs with trace context
10
+ - **Multiple endpoints** - Various scenarios (normal, slow, error)
11
+ - **OTLP export** - Sends traces and metrics to OpenTelemetry Collector
12
+ - **Zero-config** - Works out-of-box with the observability stack
13
+
14
+ ## How It Works
15
+
16
+ This Flask application demonstrates the three pillars of observability using OpenTelemetry's Python SDK with auto-instrumentation.
17
+
18
+ **Key Components:**
19
+
20
+ - `opentelemetry-instrument` - Auto-instruments Flask
21
+ - Flask application - HTTP server with sample endpoints
22
+ - JSON logging - Structured logs with trace correlation
23
+ - Custom spans and metrics - Business logic instrumentation
24
+
25
+ ## Configuration
26
+
27
+ ### Ports
28
+
29
+ - `8081` - HTTP API (web interface and endpoints)
30
+
31
+ ### Environment Variables
32
+
33
+ ```bash
34
+ # OTLP endpoint (OpenTelemetry Collector)
35
+ OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
36
+
37
+ # Service identification
38
+ OTEL_SERVICE_NAME=otel-demo-python
39
+ OTEL_RESOURCE_ATTRIBUTES=service.version=1.0.0,deployment.environment=dev
40
+ ```
41
+
42
+ ### Dependencies
43
+
44
+ Requires:
45
+
46
+ - **otel-collector** - Required to receive and route telemetry
47
+ - **jaeger** or **tempo** - Recommended for trace visualization
48
+ - **prometheus** - Recommended for metrics visualization
49
+ - **loki** - Recommended for log aggregation
50
+ - **grafana** - Recommended for unified visualization
51
+
52
+ ## Available Endpoints
53
+
54
+ Same as Node.js demo:
55
+
56
+ - `GET /` - Home page with documentation
57
+ - `GET /api/data` - Returns JSON data with trace context
58
+ - `GET /api/slow` - Simulates 2-second delay
59
+ - `GET /api/error` - Returns 500 error
60
+ - `GET /health` - Health check
61
+
62
+ ## Use Cases
63
+
64
+ - **Learning OpenTelemetry** - Python/Flask implementation
65
+ - **Testing observability stack** - Verify traces, metrics, and logs work
66
+ - **Multi-language tracing** - See trace correlation across services
67
+ - **Dashboard development** - Real data for creating Grafana dashboards
68
+
69
+ ## References
70
+
71
+ - [OpenTelemetry Python](https://opentelemetry.io/docs/instrumentation/python/)
72
+ - [Flask Instrumentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/flask/flask.html)
73
+ - [Auto-instrumentation](https://opentelemetry.io/docs/instrumentation/python/automatic/)
74
+
75
+ **Related Overlays:**
76
+
77
+ - `otel-collector` - Required for receiving telemetry
78
+ - `otel-demo-nodejs` - Node.js demo app for multi-language testing
79
+ - `jaeger` or `tempo` - Trace visualization
80
+ - `prometheus` - Metrics storage
81
+ - `loki` - Log aggregation
82
+ - `grafana` - Unified observability UI
@@ -0,0 +1,208 @@
1
+ import time
2
+ import random
3
+ import logging
4
+ import json
5
+ from flask import Flask, jsonify, request
6
+ from opentelemetry import trace, metrics
7
+ from opentelemetry.trace import Status, StatusCode
8
+
9
+ # Configure JSON logging
10
+ class JSONFormatter(logging.Formatter):
11
+ def format(self, record):
12
+ log_data = {
13
+ 'timestamp': self.formatTime(record),
14
+ 'level': record.levelname.lower(),
15
+ 'message': record.getMessage(),
16
+ 'logger': record.name,
17
+ }
18
+
19
+ # Add trace context if available
20
+ span = trace.get_current_span()
21
+ if span and span.get_span_context().is_valid:
22
+ ctx = span.get_span_context()
23
+ log_data['trace.id'] = format(ctx.trace_id, '032x')
24
+ log_data['span.id'] = format(ctx.span_id, '016x')
25
+
26
+ return json.dumps(log_data)
27
+
28
+ # Setup logging
29
+ handler = logging.StreamHandler()
30
+ handler.setFormatter(JSONFormatter())
31
+ logger = logging.getLogger(__name__)
32
+ logger.addHandler(handler)
33
+ logger.setLevel(logging.INFO)
34
+
35
+ # Create Flask app
36
+ app = Flask(__name__)
37
+
38
+ # Get tracer and meter
39
+ tracer = trace.get_tracer(__name__)
40
+ meter = metrics.get_meter(__name__)
41
+
42
+ # Create custom metrics
43
+ request_counter = meter.create_counter(
44
+ name="http_requests_total",
45
+ description="Total number of HTTP requests",
46
+ )
47
+
48
+ request_duration = meter.create_histogram(
49
+ name="http_request_duration_seconds",
50
+ description="HTTP request duration in seconds",
51
+ )
52
+
53
+ @app.route('/')
54
+ def home():
55
+ """Home page with documentation"""
56
+ span = trace.get_current_span()
57
+ span.add_event("Rendering home page")
58
+
59
+ logger.info("Home page requested")
60
+
61
+ return """
62
+ <!DOCTYPE html>
63
+ <html>
64
+ <head>
65
+ <title>OpenTelemetry Demo - Python</title>
66
+ <style>
67
+ body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; padding: 20px; }
68
+ h1 { color: #333; }
69
+ .endpoint { background: #f4f4f4; padding: 10px; margin: 10px 0; border-left: 4px solid #007acc; }
70
+ .success { color: #28a745; }
71
+ .warning { color: #ffc107; }
72
+ .error { color: #dc3545; }
73
+ </style>
74
+ </head>
75
+ <body>
76
+ <h1>🐍 OpenTelemetry Demo - Python</h1>
77
+ <p>Flask application instrumented with OpenTelemetry.</p>
78
+
79
+ <h2>Available Endpoints:</h2>
80
+
81
+ <div class="endpoint">
82
+ <strong class="success">GET /</strong><br>
83
+ This page - application home
84
+ </div>
85
+
86
+ <div class="endpoint">
87
+ <strong class="success">GET /api/data</strong><br>
88
+ Returns sample JSON data with nested spans
89
+ </div>
90
+
91
+ <div class="endpoint">
92
+ <strong class="warning">GET /api/slow</strong><br>
93
+ Simulates slow request (2 second delay)
94
+ </div>
95
+
96
+ <div class="endpoint">
97
+ <strong class="error">GET /api/error</strong><br>
98
+ Simulates an error (500 status)
99
+ </div>
100
+
101
+ <div class="endpoint">
102
+ <strong class="success">GET /health</strong><br>
103
+ Health check endpoint
104
+ </div>
105
+
106
+ <h2>Try It:</h2>
107
+ <ul>
108
+ <li><a href="/api/data">Call /api/data</a></li>
109
+ <li><a href="/api/slow">Call /api/slow (slow)</a></li>
110
+ <li><a href="/api/error">Call /api/error (error)</a></li>
111
+ <li><a href="/health">Call /health</a></li>
112
+ </ul>
113
+ </body>
114
+ </html>
115
+ """
116
+
117
+ @app.route('/api/data')
118
+ def get_data():
119
+ """Returns sample data with child span"""
120
+ with tracer.start_as_current_span("process_data") as span:
121
+ span.add_event("Fetching data")
122
+
123
+ # Simulate data processing
124
+ data = {
125
+ 'timestamp': time.time(),
126
+ 'items': [
127
+ {'id': i, 'name': f'Item {i}', 'value': random.random() * 100}
128
+ for i in range(1, 4)
129
+ ],
130
+ 'trace': {
131
+ 'traceId': format(span.get_span_context().trace_id, '032x'),
132
+ 'spanId': format(span.get_span_context().span_id, '016x'),
133
+ }
134
+ }
135
+
136
+ span.set_attribute("data.items", len(data['items']))
137
+ logger.info(f"Data fetched successfully, itemCount={len(data['items'])}")
138
+
139
+ return jsonify(data)
140
+
141
+ @app.route('/api/slow')
142
+ def slow_endpoint():
143
+ """Simulates slow request"""
144
+ span = trace.get_current_span()
145
+ span.add_event("Simulating slow operation")
146
+ logger.warning("Slow endpoint called, expectedDelay=2s")
147
+
148
+ time.sleep(2)
149
+
150
+ return jsonify({
151
+ 'message': 'This was a slow request',
152
+ 'duration': '2 seconds'
153
+ })
154
+
155
+ @app.route('/api/error')
156
+ def error_endpoint():
157
+ """Simulates error"""
158
+ span = trace.get_current_span()
159
+ span.add_event("Error occurred")
160
+ logger.error("Error endpoint called")
161
+
162
+ # Record exception in span
163
+ try:
164
+ raise ValueError("Simulated error")
165
+ except ValueError as e:
166
+ span.record_exception(e)
167
+ span.set_status(Status(StatusCode.ERROR, "Simulated error"))
168
+
169
+ return jsonify({
170
+ 'error': 'Internal Server Error',
171
+ 'message': 'This is a simulated error'
172
+ }), 500
173
+
174
+ @app.route('/health')
175
+ def health():
176
+ """Health check"""
177
+ return jsonify({
178
+ 'status': 'healthy',
179
+ 'timestamp': time.time()
180
+ })
181
+
182
+ # Middleware to record metrics
183
+ @app.before_request
184
+ def before_request():
185
+ request.start_time = time.time()
186
+
187
+ @app.after_request
188
+ def after_request(response):
189
+ duration = time.time() - request.start_time
190
+
191
+ # Record metrics
192
+ request_counter.add(1, {
193
+ 'method': request.method,
194
+ 'route': request.path,
195
+ 'status': response.status_code,
196
+ })
197
+
198
+ request_duration.record(duration, {
199
+ 'method': request.method,
200
+ 'route': request.path,
201
+ 'status': response.status_code,
202
+ })
203
+
204
+ return response
205
+
206
+ if __name__ == '__main__':
207
+ logger.info("Server starting on port 8081")
208
+ app.run(host='0.0.0.0', port=8081, debug=False)
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.base.schema.json",
3
+ "runServices": ["otel-demo-python"],
4
+ "_serviceOrder": 3,
5
+ "forwardPorts": [8081],
6
+ "portsAttributes": {
7
+ "8081": {
8
+ "label": "OTel Demo (Python)",
9
+ "onAutoForward": "openBrowser"
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,19 @@
1
+ version: '3.8'
2
+ services:
3
+ otel-demo-python:
4
+ build:
5
+ context: .
6
+ dockerfile: ./Dockerfile-otel-demo-python
7
+ environment:
8
+ - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
9
+ - OTEL_SERVICE_NAME=otel-demo-python
10
+ - OTEL_RESOURCE_ATTRIBUTES=service.version=1.0.0,deployment.environment=dev
11
+ ports:
12
+ - '${OTEL_DEMO_PYTHON_PORT:-8081}:8081'
13
+ depends_on:
14
+ - otel-collector
15
+ networks:
16
+ - devnet
17
+
18
+ networks:
19
+ devnet: