Master OpenTelemetry observability for Google Antigravity IDE production applications
# OpenTelemetry Observability Patterns for Google Antigravity IDE
Implement comprehensive observability with OpenTelemetry using Google Antigravity IDE. This guide covers tracing, metrics, logging, and instrumentation patterns for debugging and monitoring production applications.
## Core Setup
```typescript
// src/lib/telemetry.ts
import { NodeSDK } from "@opentelemetry/sdk-node";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
import { Resource } from "@opentelemetry/resources";
import { SEMRESATTRS_SERVICE_NAME, SEMRESATTRS_SERVICE_VERSION } from "@opentelemetry/semantic-conventions";
const resource = new Resource({
[SEMRESATTRS_SERVICE_NAME]: process.env.SERVICE_NAME ?? "my-app",
[SEMRESATTRS_SERVICE_VERSION]: process.env.SERVICE_VERSION ?? "1.0.0",
environment: process.env.NODE_ENV ?? "development",
});
const traceExporter = new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://localhost:4318/v1/traces",
headers: {
Authorization: `Bearer ${process.env.OTEL_API_KEY}`,
},
});
const metricExporter = new OTLPMetricExporter({
url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://localhost:4318/v1/metrics",
headers: {
Authorization: `Bearer ${process.env.OTEL_API_KEY}`,
},
});
export const sdk = new NodeSDK({
resource,
traceExporter,
metricReader: new PeriodicExportingMetricReader({
exporter: metricExporter,
exportIntervalMillis: 60000, // Export every minute
}),
instrumentations: [
getNodeAutoInstrumentations({
"@opentelemetry/instrumentation-fs": { enabled: false },
"@opentelemetry/instrumentation-http": {
ignoreIncomingRequestHook: (req) => {
return req.url?.includes("/health") ?? false;
},
},
}),
],
});
// Start the SDK
sdk.start();
// Graceful shutdown
process.on("SIGTERM", () => {
sdk.shutdown()
.then(() => console.log("Telemetry shut down"))
.catch((err) => console.error("Error shutting down telemetry", err))
.finally(() => process.exit(0));
});
```
## Custom Tracing
```typescript
// src/lib/tracing.ts
import { trace, SpanKind, SpanStatusCode, context } from "@opentelemetry/api";
import type { Span, Tracer } from "@opentelemetry/api";
const tracer: Tracer = trace.getTracer("my-app", "1.0.0");
// Decorator for tracing async functions
export function traced(
spanName: string,
options?: { kind?: SpanKind; attributes?: Record<string, string | number | boolean> }
) {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
return tracer.startActiveSpan(
spanName,
{ kind: options?.kind ?? SpanKind.INTERNAL, attributes: options?.attributes },
async (span: Span) => {
try {
const result = await originalMethod.apply(this, args);
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: error instanceof Error ? error.message : "Unknown error",
});
span.recordException(error as Error);
throw error;
} finally {
span.end();
}
}
);
};
return descriptor;
};
}
// Manual tracing helper
export async function withSpan<T>(
name: string,
fn: (span: Span) => Promise<T>,
options?: { kind?: SpanKind; attributes?: Record<string, string | number | boolean> }
): Promise<T> {
return tracer.startActiveSpan(
name,
{ kind: options?.kind ?? SpanKind.INTERNAL, attributes: options?.attributes },
async (span) => {
try {
const result = await fn(span);
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error) {
span.setStatus({
code: SpanStatusCode.ERROR,
message: error instanceof Error ? error.message : "Unknown error",
});
span.recordException(error as Error);
throw error;
} finally {
span.end();
}
}
);
}
// Example usage
class OrderService {
@traced("OrderService.createOrder", { kind: SpanKind.INTERNAL })
async createOrder(userId: string, items: OrderItem[]) {
return withSpan("validate-items", async (span) => {
span.setAttribute("user.id", userId);
span.setAttribute("items.count", items.length);
const validated = await this.validateItems(items);
span.addEvent("items-validated", { validCount: validated.length });
return await this.saveOrder(userId, validated);
});
}
}
```
## Custom Metrics
```typescript
// src/lib/metrics.ts
import { metrics } from "@opentelemetry/api";
import type { Counter, Histogram, UpDownCounter } from "@opentelemetry/api";
const meter = metrics.getMeter("my-app", "1.0.0");
// Define application metrics
export const appMetrics = {
// Counters
requestTotal: meter.createCounter("http_requests_total", {
description: "Total number of HTTP requests",
}),
errorTotal: meter.createCounter("errors_total", {
description: "Total number of errors",
}),
// Histograms for latency
requestDuration: meter.createHistogram("http_request_duration_seconds", {
description: "HTTP request duration in seconds",
unit: "s",
}),
dbQueryDuration: meter.createHistogram("db_query_duration_seconds", {
description: "Database query duration in seconds",
unit: "s",
}),
// Gauges for current state
activeConnections: meter.createUpDownCounter("active_connections", {
description: "Number of active connections",
}),
queueSize: meter.createObservableGauge("queue_size", {
description: "Current queue size",
}),
};
// Middleware for HTTP metrics
export function metricsMiddleware(req: Request, res: Response, next: NextFunction) {
const startTime = performance.now();
res.on("finish", () => {
const duration = (performance.now() - startTime) / 1000;
const attributes = {
method: req.method,
path: req.route?.path ?? req.path,
status_code: res.statusCode.toString(),
};
appMetrics.requestTotal.add(1, attributes);
appMetrics.requestDuration.record(duration, attributes);
if (res.statusCode >= 400) {
appMetrics.errorTotal.add(1, {
...attributes,
error_type: res.statusCode >= 500 ? "server" : "client",
});
}
});
next();
}
```
## Best Practices for Google Antigravity IDE
When implementing OpenTelemetry with Google Antigravity, configure auto-instrumentation for common libraries. Create custom spans for business operations. Define meaningful metrics for KPIs. Use structured logging with trace context. Set up proper resource attributes for service identification. Let Gemini 3 generate instrumentation for your application flows.
Google Antigravity excels at adding observability to existing codebases without major refactoring.This OpenTelemetry prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their opentelemetry implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For OpenTelemetry projects, consider mentioning your framework version, coding style, and any specific libraries you're using.