Skip to content
Closed
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,43 @@ protected AbstractCompositeJsonFormatter<ILoggingEvent> createFormatter() {
return formatter;
}

private static final String OTEL_GCP_PROJECT_ID_ATTRIBUTE = "gcp.project_id";

/**
* Resolves the GCP project that traces are stored in, so it can be embedded in the
* 'projects/{projectId}/traces/{traceId}' value written to the log entry.
*
* On Kubernetes, traces are exported to the cluster's host project (ent-kub-<env>),
* which differs from the workload's own project. That destination project is carried in the
* 'gcp.project_id' OpenTelemetry resource attribute, so it takes precedence. Runtimes that
* still export traces to their own project (e.g. Cloud Run, Firebase) fall back to
* 'GOOGLE_CLOUD_PROJECT'.
*/
private static String resolveProjectId() {
for (String envName : new String[]{"GOOGLE_CLOUD_PROJECT", "GCP_PROJECT_ID"}) {
String projectId = System.getenv(envName);
if (projectId != null && !projectId.isBlank()) {
return projectId;
}
}
return null;
String projectId = resolveOtelResourceAttribute(OTEL_GCP_PROJECT_ID_ATTRIBUTE);
if (projectId != null) {
return projectId;
}
String fallback = System.getenv("GOOGLE_CLOUD_PROJECT");
return (fallback == null || fallback.isBlank()) ? null : fallback;
}

private static String resolveOtelResourceAttribute(String attributeName) {
String otelResourceAttributes = System.getenv("OTEL_RESOURCE_ATTRIBUTES");
if (otelResourceAttributes == null || otelResourceAttributes.isBlank()) {
return null;
}
for (String pair : otelResourceAttributes.split(",")) {
int separatorIndex = pair.indexOf('=');
if (separatorIndex < 0) {
continue;
}
if (pair.substring(0, separatorIndex).trim().equals(attributeName)) {
String value = pair.substring(separatorIndex + 1).trim();
return value.isBlank() ? null : value;
}
}
return null;
}

}