It’s a common strategy to test a new API directly with curl. It feels intuitive, fast, and removes the overhead of a language runtime. For example, if you are testing out the Google Cloud Logging API, you might start with a simple request to list logs from a Kubernetes container.:
curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
https://logging.googleapis.com/v2/entries:list \
-d '{
"resourceNames": ["projects/your-project-id"],
"filter": "resource.type=\"k8s_container\""
}'
The JSON returns perfectly. But then, you move that logic into a Node.js application using the official @google-cloud/logging library.
import { Logging } from "@google-cloud/logging";
export async function readLogsAsync() {
// Common approach: Initializing the client without explicit auth
const logging = new Logging();
const [entries, , response] = await logging.getEntries({
filter: 'resource.type="k8s_container"',
resourceNames: ['projects/your-project-id'],
});
console.log(entries.length, response.nextPageToken);
}
All of a sudden, the code fails with a cryptic error: Error: Could not load the default credentials.
This happens because of a disconnect between how the gcloud CLI manages session tokens and how the Google Cloud client libraries search for credentials.
While your curl command relies on the explicit token you provided via gcloud auth print-access-token, the client libraries are designed to look for Application Default Credentials (ADC).
Running gcloud auth login authenticates, but it does not create the specific credential file that the Node.js library requires to run locally.
🤫 Authenticate for local development
The most efficient way to solve this is to provide the library with the credentials it is looking for. Run the gcloud auth application-default login command in your terminal.
gcloud auth application-default login
This opens a browser window to authorize your account and saves a JSON file to your local configuration folder. Once this is done, your Node.js code will automatically find these credentials—no code changes required.
🏡 Moving to Production
Once you get your local environment running, you need to think about "productionizing" your code. Hardcoded project IDs and lack of robust error handling are common causes of production outages.
- 🛡️ Robust Error Handling
In production, your app should handle permission issues or network timeouts gracefully.
try {
const [entries] = await logging.getEntries({
filter: 'resource.type="k8s_container"',
resourceNames: [`projects/${process.env.GOOGLE_CLOUD_PROJECT}`],
pageSize: 10,
});
} catch (error) {
if (error.code === 7) {
console.error("Permission Denied: Check your Service Account roles.");
} else {
console.error("Unexpected Logging Error:", error.message);
}
}
- 🎭 Service Accounts
In production, you shouldn't use your personal user credentials. Use a Service Account with the "Logs Viewer" role.
- 🌍 Environment Variables
Avoid hardcoding project IDs. Use an environment variable to make your code portable across staging and production environments.
const PROJECT_ID = process.env.GOOGLE_CLOUD_PROJECT || 'your-project-id';
...
export async function readLogsAsync() {
const logging = new Logging({ projectId: PROJECT_ID });
- Structured Logging
Instead of just reading logs, think about how you write them. Using structured JSON logs makes them much easier to query later in the Cloud Logging console.
If you are running on Google Kubernetes Engine (GKE), you don't even need to use the Logging library to write logs. Printing a JSON string to stdout allows GKE to parse your data into searchable fields automatically.
export function logStructuredStatus() {
const logEntry = {
severity: "INFO",
message: "Container health check successful",
container_info: { version: "v2.1.0", uptime: process.uptime() },
http_stats: { active_connections: 42 }
};
// GKE picks this up and converts it to a structured log automatically
console.log(JSON.stringify(logEntry));
}
Get started
I'll be sharing a more thorough walk-through on using the native observability features provided with GKE real soon—including how to automate this stuff so you can avoid the manual debugging of credential errors.
In the meantime, dive deeper here:
- 📖 How Application Default Credentials work – Understand the "magic" behind the lookup.
- 🛠️ Providing credentials to ADC – Setup guides for every environment.
Top comments (0)