@senad-d/observme 0.1.0

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 (111) hide show
  1. package/.env.example +57 -0
  2. package/CHANGELOG.md +52 -0
  3. package/LICENSE +21 -0
  4. package/ObservMe-Production-Docs/00-README.md +79 -0
  5. package/ObservMe-Production-Docs/01-requirements-and-scope.md +207 -0
  6. package/ObservMe-Production-Docs/02-reference-architecture.md +306 -0
  7. package/ObservMe-Production-Docs/03-pi-event-and-session-model.md +266 -0
  8. package/ObservMe-Production-Docs/04-telemetry-semantic-conventions.md +722 -0
  9. package/ObservMe-Production-Docs/05-otel-pipeline-and-collector.md +355 -0
  10. package/ObservMe-Production-Docs/06-security-privacy-redaction.md +294 -0
  11. package/ObservMe-Production-Docs/07-extension-implementation-blueprint.md +447 -0
  12. package/ObservMe-Production-Docs/08-query-grafana-integration.md +276 -0
  13. package/ObservMe-Production-Docs/09-dashboards-alerts-slos.md +640 -0
  14. package/ObservMe-Production-Docs/10-testing-release-operations.md +319 -0
  15. package/ObservMe-Production-Docs/11-deployment-runbooks.md +203 -0
  16. package/ObservMe-Production-Docs/12-configuration-reference.md +337 -0
  17. package/ObservMe-Production-Docs/13-source-notes.md +33 -0
  18. package/ObservMe-Production-Docs/pi-session-format.md +427 -0
  19. package/README.md +356 -0
  20. package/SECURITY.md +45 -0
  21. package/dashboards/observme-agent-node-graphs.json +250 -0
  22. package/dashboards/observme-agents.json +1880 -0
  23. package/dashboards/observme-alerts.yaml +113 -0
  24. package/dashboards/observme-branches-compactions.json +1042 -0
  25. package/dashboards/observme-cost.json +1254 -0
  26. package/dashboards/observme-errors.json +1659 -0
  27. package/dashboards/observme-export-health.json +1802 -0
  28. package/dashboards/observme-latency.json +1494 -0
  29. package/dashboards/observme-llm-conversations.json +730 -0
  30. package/dashboards/observme-logs-llm.json +644 -0
  31. package/dashboards/observme-models.json +933 -0
  32. package/dashboards/observme-overview.json +2129 -0
  33. package/dashboards/observme-slo-health.json +737 -0
  34. package/dashboards/observme-slos.yaml +56 -0
  35. package/dashboards/observme-tools.json +902 -0
  36. package/dashboards/observme-trace-journey.json +1793 -0
  37. package/docs/STRUCTURE.md +49 -0
  38. package/docs/agent-subagent-observability-requirements.md +997 -0
  39. package/docs/compatibility-matrix.md +39 -0
  40. package/docs/configuration-tui-design-standard.md +767 -0
  41. package/docs/configuration.md +38 -0
  42. package/docs/review-validation.md +115 -0
  43. package/docs/validation-flow.md +117 -0
  44. package/examples/collector.yaml +123 -0
  45. package/examples/observme.yaml +131 -0
  46. package/img/demo.gif +0 -0
  47. package/img/icon.svg +47 -0
  48. package/package.json +103 -0
  49. package/src/commands/obs-agents-runtime.ts +150 -0
  50. package/src/commands/obs-agents.ts +491 -0
  51. package/src/commands/obs-args.ts +63 -0
  52. package/src/commands/obs-backfill.ts +1334 -0
  53. package/src/commands/obs-command-support.ts +43 -0
  54. package/src/commands/obs-cost.ts +228 -0
  55. package/src/commands/obs-diagnostics.ts +22 -0
  56. package/src/commands/obs-errors.ts +156 -0
  57. package/src/commands/obs-health.ts +301 -0
  58. package/src/commands/obs-link.ts +90 -0
  59. package/src/commands/obs-logs.ts +194 -0
  60. package/src/commands/obs-loki-summary.ts +184 -0
  61. package/src/commands/obs-session.ts +259 -0
  62. package/src/commands/obs-status.ts +359 -0
  63. package/src/commands/obs-tools.ts +274 -0
  64. package/src/commands/obs-trace.ts +411 -0
  65. package/src/commands/obs.ts +211 -0
  66. package/src/config/bootstrap-project-config.ts +300 -0
  67. package/src/config/defaults.ts +143 -0
  68. package/src/config/load-config.ts +631 -0
  69. package/src/config/project-paths.ts +61 -0
  70. package/src/config/schema.ts +405 -0
  71. package/src/config/validate.ts +456 -0
  72. package/src/constants.ts +4 -0
  73. package/src/diagnostics/sanitize.ts +6 -0
  74. package/src/extension.ts +38 -0
  75. package/src/otel/logs.ts +160 -0
  76. package/src/otel/metrics.ts +165 -0
  77. package/src/otel/otlp-endpoint.ts +10 -0
  78. package/src/otel/sdk.ts +114 -0
  79. package/src/otel/shutdown.ts +102 -0
  80. package/src/otel/traces.ts +166 -0
  81. package/src/pi/agent-lineage.ts +378 -0
  82. package/src/pi/agent-tree-tracker.ts +258 -0
  83. package/src/pi/event-handlers/agent-turn.ts +155 -0
  84. package/src/pi/event-handlers/lifecycle.ts +642 -0
  85. package/src/pi/event-handlers/llm.ts +115 -0
  86. package/src/pi/event-handlers/session-events.ts +159 -0
  87. package/src/pi/event-handlers/tool-bash.ts +275 -0
  88. package/src/pi/handler-internals.ts +2154 -0
  89. package/src/pi/handler-runtime.ts +633 -0
  90. package/src/pi/handler-types.ts +261 -0
  91. package/src/pi/handlers.ts +75 -0
  92. package/src/pi/subagent-spawn.ts +975 -0
  93. package/src/pi/subagent-types.ts +29 -0
  94. package/src/privacy/content-capture.ts +104 -0
  95. package/src/privacy/hash.ts +93 -0
  96. package/src/privacy/redact.ts +619 -0
  97. package/src/privacy/secret-patterns.ts +185 -0
  98. package/src/privacy/truncate.ts +69 -0
  99. package/src/query/grafana-readiness.ts +164 -0
  100. package/src/query/grafana-transport.ts +481 -0
  101. package/src/query/grafana.ts +371 -0
  102. package/src/query/loki.ts +332 -0
  103. package/src/query/prometheus.ts +388 -0
  104. package/src/query/tempo.ts +332 -0
  105. package/src/safety/sensitive-input.ts +208 -0
  106. package/src/semconv/attributes.ts +279 -0
  107. package/src/semconv/metrics.ts +146 -0
  108. package/src/semconv/spans.ts +19 -0
  109. package/src/semconv/values.ts +13 -0
  110. package/src/util/bounded-map.ts +97 -0
  111. package/tsconfig.json +15 -0
@@ -0,0 +1,300 @@
1
+ import { CONFIG_DIR_NAME, withFileMutationQueue } from "@earendil-works/pi-coding-agent";
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
+ import { dirname } from "node:path";
4
+ import { readDiagnosticMessage, sanitizeDiagnosticText } from "../diagnostics/sanitize.ts";
5
+ import { RESOURCE_ATTRIBUTES } from "../semconv/attributes.ts";
6
+ import { resolveProjectLocalFilePath } from "./project-paths.ts";
7
+
8
+ export type ProjectConfigBootstrapStatus = "created" | "exists" | "skipped_untrusted";
9
+ export type ProjectConfigNotifyLevel = "info" | "warning" | "error";
10
+
11
+ export interface ProjectConfigBootstrapResult {
12
+ readonly path: string;
13
+ readonly status: ProjectConfigBootstrapStatus;
14
+ }
15
+
16
+ export interface ProjectConfigBootstrapContext {
17
+ readonly cwd?: string;
18
+ readonly isProjectTrusted?: () => boolean | Promise<boolean>;
19
+ readonly ui?: {
20
+ notify?: (message: string, level?: ProjectConfigNotifyLevel) => Promise<void> | void;
21
+ };
22
+ }
23
+
24
+ export interface RegisterProjectConfigBootstrapOptions {
25
+ readonly configDirName?: string;
26
+ readonly ensureProjectConfig?: EnsureProjectConfig;
27
+ }
28
+
29
+ export interface EnsureProjectConfigOptions {
30
+ readonly configDirName?: string;
31
+ readonly cwd?: string;
32
+ readonly isProjectTrusted?: boolean | (() => boolean | Promise<boolean>);
33
+ }
34
+
35
+ export type EnsureProjectConfig = (options: EnsureProjectConfigOptions) => Promise<ProjectConfigBootstrapResult>;
36
+
37
+ type ProjectConfigBootstrapHandler = (event: unknown, ctx: ProjectConfigBootstrapContext) => Promise<void> | void;
38
+
39
+ interface ProjectConfigBootstrapPiApi {
40
+ on: (eventName: string, handler: ProjectConfigBootstrapHandler) => void;
41
+ }
42
+
43
+ const observmeYamlFileName = "observme.yaml";
44
+
45
+ export const PROJECT_OBSERVME_YAML_TEMPLATE = `observme:
46
+ enabled: true
47
+ environment: development
48
+ tenant: local-dev
49
+ replayOnStart: false
50
+
51
+ otlp:
52
+ endpoint: http://localhost:4318
53
+ protocol: http/protobuf
54
+ timeoutMs: 3000
55
+ headers: {}
56
+ tls:
57
+ enabled: false
58
+ insecureSkipVerify: false
59
+ signalEndpoints:
60
+ traces: http://localhost:4318/v1/traces
61
+ metrics: http://localhost:4318/v1/metrics
62
+ logs: http://localhost:4318/v1/logs
63
+
64
+ resource:
65
+ attributes:
66
+ ${RESOURCE_ATTRIBUTES.SERVICE_NAME}: observme-pi-extension
67
+ ${RESOURCE_ATTRIBUTES.OBSERVME_TENANT_ID}: local-dev
68
+ ${RESOURCE_ATTRIBUTES.PI_PROJECT_NAME}: local-project
69
+ ${RESOURCE_ATTRIBUTES.DEPLOYMENT_ENVIRONMENT_NAME}: development
70
+
71
+ workflow:
72
+ idEnv: OBSERVME_WORKFLOW_ID
73
+ enabled: true
74
+ maxDepthWarning: 5
75
+ maxFanoutWarning: 20
76
+
77
+ agent:
78
+ idEnv: OBSERVME_AGENT_ID
79
+ parentIdEnv: OBSERVME_PARENT_AGENT_ID
80
+ rootIdEnv: OBSERVME_ROOT_AGENT_ID
81
+ parentSessionIdEnv: OBSERVME_PARENT_SESSION_ID
82
+ parentTraceIdEnv: OBSERVME_PARENT_TRACE_ID
83
+ parentSpanIdEnv: OBSERVME_PARENT_SPAN_ID
84
+ depthEnv: OBSERVME_AGENT_DEPTH
85
+ spawnIdEnv: OBSERVME_SPAWN_ID
86
+ propagateTraceContext: true
87
+ propagateToSubagents: true
88
+ capabilityEnv: OBSERVME_AGENT_CAPABILITY
89
+ writeCorrelationEntry: false
90
+
91
+ traces:
92
+ enabled: true
93
+ sampleRatio: 1.0
94
+ batch:
95
+ maxQueueSize: 2048
96
+ maxExportBatchSize: 512
97
+ scheduledDelayMillis: 1000
98
+ exportTimeoutMillis: 3000
99
+
100
+ metrics:
101
+ enabled: true
102
+ exportIntervalMillis: 15000
103
+ exportTimeoutMillis: 3000
104
+
105
+ logs:
106
+ enabled: true
107
+ batch:
108
+ maxQueueSize: 2048
109
+ maxExportBatchSize: 512
110
+ scheduledDelayMillis: 1000
111
+
112
+ capture:
113
+ # Content capture is opt-in. To export redacted local debug content,
114
+ # set only the specific capture flags you need to true and keep
115
+ # privacy.redactionEnabled enabled.
116
+ prompts: false
117
+ responses: false
118
+ thinking: false
119
+ toolArguments: false
120
+ toolResults: false
121
+ bashCommands: false
122
+ bashOutput: false
123
+ filePaths: false
124
+
125
+ privacy:
126
+ redactionEnabled: true
127
+ # Set this to true only when you intentionally accept unredacted
128
+ # sensitive-content export from this trusted project.
129
+ allowUnsafeCapture: false
130
+ allowInsecureTransport: true
131
+ tenantSaltEnv: OBSERVME_HASH_SALT
132
+ pathMode: hash
133
+ customRedactionPatterns: []
134
+
135
+ limits:
136
+ maxPromptChars: 12000
137
+ maxResponseChars: 12000
138
+ maxToolArgumentChars: 8000
139
+ maxToolResultChars: 16000
140
+ maxBashOutputChars: 16000
141
+ maxLogBodyChars: 32000
142
+ maxActiveAgentRuns: 16
143
+ maxActiveTurns: 128
144
+ maxActiveToolCalls: 1024
145
+ maxActiveLlmRequests: 128
146
+ maxActiveSubagentSpawns: 128
147
+ maxActiveAgentWaits: 128
148
+ maxActiveAgentJoins: 128
149
+
150
+ query:
151
+ enabled: true
152
+ timeoutMs: 5000
153
+ maxLogs: 50
154
+ maxTraces: 20
155
+ maxMetricSeries: 20
156
+ maxAgents: 20
157
+ links:
158
+ # Uses the supported bundled-stack Grafana Explore fallback.
159
+ traceUrlTemplate: https://observability.local/explore?left=...
160
+ grafana:
161
+ # Supported local command path: Grafana behind nginx HTTPS.
162
+ url: https://observability.local
163
+ # Preferred: set a Grafana service-account token in this env var.
164
+ token: \${OBSERVME_GRAFANA_TOKEN}
165
+ # Local fallback: set OBSERVME_GRAFANA_PASSWORD from observability-stack/secrets/grafana_admin_password.
166
+ username: "admin"
167
+ password: \${OBSERVME_GRAFANA_PASSWORD}
168
+ datasourceUids:
169
+ tempo: tempo
170
+ loki: loki
171
+ prometheus: prometheus
172
+ tls:
173
+ # Local self-signed certificate only; keep false for production CAs.
174
+ insecureSkipVerify: true
175
+ transport:
176
+ # Avoid observability.local resolving to an unreachable IPv6 loopback first.
177
+ preferIPv4: true
178
+
179
+ shutdown:
180
+ flushTimeoutMs: 3000
181
+ `;
182
+
183
+ export function registerProjectConfigBootstrap(
184
+ pi: unknown,
185
+ options: RegisterProjectConfigBootstrapOptions = {},
186
+ ): void {
187
+ const api = pi as ProjectConfigBootstrapPiApi;
188
+ api.on("session_start", createProjectConfigBootstrapHandler(options));
189
+ }
190
+
191
+ export async function ensureProjectObservMeConfig(
192
+ options: EnsureProjectConfigOptions = {},
193
+ ): Promise<ProjectConfigBootstrapResult> {
194
+ const configPath = resolveProjectObservMeConfigPath(options);
195
+ const projectTrusted = await resolveBootstrapProjectTrust(options.isProjectTrusted);
196
+
197
+ if (!projectTrusted) return { path: configPath, status: "skipped_untrusted" };
198
+ return createProjectObservMeConfigFile(configPath);
199
+ }
200
+
201
+ function createProjectConfigBootstrapHandler(
202
+ options: RegisterProjectConfigBootstrapOptions,
203
+ ): ProjectConfigBootstrapHandler {
204
+ return async (_event, ctx) => {
205
+ await bootstrapProjectObservMeConfig(ctx, options);
206
+ };
207
+ }
208
+
209
+ /**
210
+ * Single startup source of truth for trusted-project ObservMe config creation and user notification.
211
+ */
212
+ export async function bootstrapProjectObservMeConfig(
213
+ ctx: ProjectConfigBootstrapContext,
214
+ options: RegisterProjectConfigBootstrapOptions = {},
215
+ ): Promise<ProjectConfigBootstrapResult | undefined> {
216
+ if (!hasProjectCwd(ctx)) return undefined;
217
+
218
+ try {
219
+ const result = await resolveProjectConfigBootstrapResult(ctx, options);
220
+ await notifyProjectConfigCreated(ctx, result);
221
+ return result;
222
+ } catch (error) {
223
+ await notifyProjectConfigBootstrapFailed(ctx, error);
224
+ return undefined;
225
+ }
226
+ }
227
+
228
+ function hasProjectCwd(ctx: ProjectConfigBootstrapContext): boolean {
229
+ return typeof ctx.cwd === "string" && ctx.cwd.trim().length > 0;
230
+ }
231
+
232
+ function resolveProjectConfigBootstrapResult(
233
+ ctx: ProjectConfigBootstrapContext,
234
+ options: RegisterProjectConfigBootstrapOptions,
235
+ ): Promise<ProjectConfigBootstrapResult> {
236
+ const ensureProjectConfig = options.ensureProjectConfig ?? ensureProjectObservMeConfig;
237
+ return ensureProjectConfig({
238
+ configDirName: options.configDirName,
239
+ cwd: ctx.cwd,
240
+ isProjectTrusted: ctx.isProjectTrusted,
241
+ });
242
+ }
243
+
244
+ async function notifyProjectConfigCreated(
245
+ ctx: ProjectConfigBootstrapContext,
246
+ result: ProjectConfigBootstrapResult,
247
+ ): Promise<void> {
248
+ if (result.status !== "created") return;
249
+ await ctx.ui?.notify?.(`ObservMe created ${result.path}. Edit this file for custom setup.`, "info");
250
+ }
251
+
252
+ async function notifyProjectConfigBootstrapFailed(ctx: ProjectConfigBootstrapContext, error: unknown): Promise<void> {
253
+ await ctx.ui?.notify?.(`ObservMe could not create the project config file: ${formatError(error)}`, "warning");
254
+ }
255
+
256
+ async function createProjectObservMeConfigFile(configPath: string): Promise<ProjectConfigBootstrapResult> {
257
+ return withFileMutationQueue(configPath, createProjectObservMeConfigFileInQueue.bind(undefined, configPath));
258
+ }
259
+
260
+ async function createProjectObservMeConfigFileInQueue(configPath: string): Promise<ProjectConfigBootstrapResult> {
261
+ await mkdir(dirname(configPath), { recursive: true });
262
+
263
+ try {
264
+ await writeFile(configPath, PROJECT_OBSERVME_YAML_TEMPLATE, { encoding: "utf8", flag: "wx" });
265
+ return { path: configPath, status: "created" };
266
+ } catch (error) {
267
+ if (isFileAlreadyExistsError(error)) return { path: configPath, status: "exists" };
268
+ throw error;
269
+ }
270
+ }
271
+
272
+ function resolveProjectObservMeConfigPath(options: EnsureProjectConfigOptions): string {
273
+ return resolveProjectLocalFilePath({
274
+ cwd: options.cwd,
275
+ configDirName: options.configDirName,
276
+ defaultConfigDirName: CONFIG_DIR_NAME,
277
+ fileName: observmeYamlFileName,
278
+ inputLabel: "project config path",
279
+ });
280
+ }
281
+
282
+ async function resolveBootstrapProjectTrust(
283
+ isProjectTrusted: EnsureProjectConfigOptions["isProjectTrusted"],
284
+ ): Promise<boolean> {
285
+ if (typeof isProjectTrusted === "boolean") return isProjectTrusted;
286
+ if (typeof isProjectTrusted === "function") return isProjectTrusted();
287
+ return false;
288
+ }
289
+
290
+ function isFileAlreadyExistsError(error: unknown): boolean {
291
+ return isErrorWithCode(error) && error.code === "EEXIST";
292
+ }
293
+
294
+ function isErrorWithCode(error: unknown): error is NodeJS.ErrnoException {
295
+ return typeof error === "object" && error !== null && "code" in error;
296
+ }
297
+
298
+ function formatError(error: unknown): string {
299
+ return sanitizeDiagnosticText(readDiagnosticMessage(error));
300
+ }
@@ -0,0 +1,143 @@
1
+ import { RESOURCE_ATTRIBUTES } from "../semconv/attributes.ts";
2
+ import type { ObservMeConfig } from "./schema.ts";
3
+
4
+ export const defaultObservMeConfig = {
5
+ enabled: true,
6
+ environment: "production",
7
+ tenant: "platform",
8
+ replayOnStart: false,
9
+ otlp: {
10
+ endpoint: "https://otel-collector.example.com:4318",
11
+ protocol: "http/protobuf",
12
+ timeoutMs: 3000,
13
+ headers: {
14
+ Authorization: "Bearer ${OBSERVME_OTLP_TOKEN}",
15
+ },
16
+ tls: {
17
+ enabled: true,
18
+ insecureSkipVerify: false,
19
+ },
20
+ },
21
+ resource: {
22
+ attributes: {
23
+ [RESOURCE_ATTRIBUTES.SERVICE_NAME]: "observme-pi-extension",
24
+ [RESOURCE_ATTRIBUTES.OBSERVME_TENANT_ID]: "platform",
25
+ [RESOURCE_ATTRIBUTES.PI_PROJECT_NAME]: "my-project",
26
+ [RESOURCE_ATTRIBUTES.DEPLOYMENT_ENVIRONMENT_NAME]: "production",
27
+ },
28
+ },
29
+ workflow: {
30
+ idEnv: "OBSERVME_WORKFLOW_ID",
31
+ enabled: true,
32
+ maxDepthWarning: 5,
33
+ maxFanoutWarning: 20,
34
+ },
35
+ agent: {
36
+ idEnv: "OBSERVME_AGENT_ID",
37
+ parentIdEnv: "OBSERVME_PARENT_AGENT_ID",
38
+ rootIdEnv: "OBSERVME_ROOT_AGENT_ID",
39
+ parentSessionIdEnv: "OBSERVME_PARENT_SESSION_ID",
40
+ parentTraceIdEnv: "OBSERVME_PARENT_TRACE_ID",
41
+ parentSpanIdEnv: "OBSERVME_PARENT_SPAN_ID",
42
+ depthEnv: "OBSERVME_AGENT_DEPTH",
43
+ spawnIdEnv: "OBSERVME_SPAWN_ID",
44
+ propagateTraceContext: true,
45
+ propagateToSubagents: true,
46
+ capabilityEnv: "OBSERVME_AGENT_CAPABILITY",
47
+ writeCorrelationEntry: false,
48
+ },
49
+ traces: {
50
+ enabled: true,
51
+ sampleRatio: 1.0,
52
+ batch: {
53
+ maxQueueSize: 2048,
54
+ maxExportBatchSize: 512,
55
+ scheduledDelayMillis: 1000,
56
+ exportTimeoutMillis: 3000,
57
+ },
58
+ },
59
+ metrics: {
60
+ enabled: true,
61
+ exportIntervalMillis: 15000,
62
+ exportTimeoutMillis: 3000,
63
+ },
64
+ logs: {
65
+ enabled: true,
66
+ batch: {
67
+ maxQueueSize: 2048,
68
+ maxExportBatchSize: 512,
69
+ scheduledDelayMillis: 1000,
70
+ },
71
+ },
72
+ capture: {
73
+ prompts: false,
74
+ responses: false,
75
+ thinking: false,
76
+ toolArguments: false,
77
+ toolResults: false,
78
+ bashCommands: false,
79
+ bashOutput: false,
80
+ filePaths: false,
81
+ },
82
+ privacy: {
83
+ redactionEnabled: true,
84
+ allowUnsafeCapture: false,
85
+ allowInsecureTransport: false,
86
+ tenantSaltEnv: "OBSERVME_HASH_SALT",
87
+ pathMode: "hash",
88
+ customRedactionPatterns: [
89
+ {
90
+ name: "internal-token",
91
+ pattern: "(?i)internal_token=[a-z0-9-]+",
92
+ },
93
+ ],
94
+ },
95
+ limits: {
96
+ maxPromptChars: 12000,
97
+ maxResponseChars: 12000,
98
+ maxToolArgumentChars: 8000,
99
+ maxToolResultChars: 16000,
100
+ maxBashOutputChars: 16000,
101
+ maxLogBodyChars: 32000,
102
+ maxActiveAgentRuns: 16,
103
+ maxActiveTurns: 128,
104
+ maxActiveToolCalls: 1024,
105
+ maxActiveLlmRequests: 128,
106
+ maxActiveSubagentSpawns: 128,
107
+ maxActiveAgentWaits: 128,
108
+ maxActiveAgentJoins: 128,
109
+ },
110
+ query: {
111
+ enabled: true,
112
+ timeoutMs: 5000,
113
+ maxLogs: 50,
114
+ maxTraces: 20,
115
+ maxMetricSeries: 20,
116
+ maxAgents: 20,
117
+ links: {
118
+ traceUrlTemplate: "https://grafana.example.com/explore?left=...",
119
+ },
120
+ grafana: {
121
+ url: "https://grafana.example.com",
122
+ token: "${OBSERVME_GRAFANA_TOKEN}",
123
+ username: "",
124
+ password: "",
125
+ datasourceUids: {
126
+ tempo: "tempo",
127
+ loki: "loki",
128
+ prometheus: "mimir",
129
+ },
130
+ tls: {
131
+ insecureSkipVerify: false,
132
+ },
133
+ transport: {
134
+ preferIPv4: false,
135
+ },
136
+ },
137
+ },
138
+ shutdown: {
139
+ flushTimeoutMs: 3000,
140
+ },
141
+ } satisfies ObservMeConfig;
142
+
143
+ export const DEFAULT_OBSERVME_CONFIG = defaultObservMeConfig;