Pulumi's Node.js SDK for infrastructure-as-code platform that allows you to create, deploy, and manage infrastructure using familiar programming languages and tools.
85
Pulumi's logging system provides structured logging and error handling for infrastructure deployment diagnostics, enabling better observability and debugging of infrastructure operations.
function hasErrors(): boolean;
function debug(msg: string, resource?: Resource, streamId?: number, ephemeral?: boolean): void;
function info(msg: string, resource?: Resource, streamId?: number, ephemeral?: boolean): void;
function warn(msg: string, resource?: Resource, streamId?: number, ephemeral?: boolean): void;
function error(msg: string, resource?: Resource, streamId?: number, ephemeral?: boolean): void;class RunError extends Error {
readonly __pulumiRunError: boolean;
static isInstance(obj: any): obj is RunError;
}
class ResourceError extends Error {
readonly __pulumResourceError: boolean;
resource: Resource | undefined;
hideStack?: boolean;
constructor(message: string, resource: Resource | undefined, hideStack?: boolean);
static isInstance(obj: any): obj is ResourceError;
}
class InputPropertyError extends Error {
readonly __pulumiInputPropertyError: boolean;
propertyPath: string;
reason: string;
constructor(args: InputPropertyErrorDetails);
static isInstance(obj: any): obj is InputPropertyError;
}
class InputPropertiesError extends Error {
readonly __pulumiInputPropertiesError: boolean;
reasons: InputPropertyError[];
constructor(errors: InputPropertyError[]);
static isInstance(obj: any): obj is InputPropertiesError;
}
interface InputPropertyErrorDetails {
propertyPath: string;
reason: string;
}
function isGrpcError(err: Error): boolean;import * as pulumi from "@pulumi/pulumi";
// Simple logging without resource context
pulumi.log.info("Starting infrastructure deployment");
pulumi.log.debug("Configuration loaded successfully");
pulumi.log.warn("Using default values for missing configuration");
// Check for errors
if (pulumi.log.hasErrors()) {
pulumi.log.error("Deployment failed due to previous errors");
process.exit(1);
}import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const bucket = new aws.s3.Bucket("my-bucket", {
acl: "private",
});
// Log with resource context
pulumi.log.info("Creating S3 bucket with private ACL", bucket);
pulumi.log.debug(`Bucket configuration: ${JSON.stringify({
acl: "private",
versioning: false,
})}`, bucket);
bucket.id.apply(id => {
pulumi.log.info(`S3 bucket created with ID: ${id}`, bucket);
});
// Warning with resource context
if (!bucket.versioning) {
pulumi.log.warn("Bucket versioning is disabled - consider enabling for production", bucket);
}import * as pulumi from "@pulumi/pulumi";
// Throw RunError for clean program termination
if (!process.env.AWS_REGION) {
throw new pulumi.RunError("AWS_REGION environment variable is required");
}
// Throw ResourceError for resource-specific issues
const database = new aws.rds.Instance("prod-db", {
engine: "postgres",
instanceClass: "db.t3.micro",
});
// Validate resource configuration
database.engine.apply(engine => {
if (engine !== "postgres" && engine !== "mysql") {
throw new pulumi.ResourceError(
`Unsupported database engine: ${engine}`,
database,
false // Don't hide stack trace
);
}
});import * as pulumi from "@pulumi/pulumi";
function validateBucketName(name: string): void {
const errors: pulumi.InputPropertyError[] = [];
if (!name) {
errors.push(new pulumi.InputPropertyError({
propertyPath: "bucketName",
reason: "bucketName is required"
}));
}
if (name && name.length < 3) {
errors.push(new pulumi.InputPropertyError({
propertyPath: "bucketName",
reason: "bucketName must be at least 3 characters long"
}));
}
if (name && !/^[a-z0-9.-]+$/.test(name)) {
errors.push(new pulumi.InputPropertyError({
propertyPath: "bucketName",
reason: "bucketName can only contain lowercase letters, numbers, periods, and hyphens"
}));
}
if (errors.length > 0) {
throw new pulumi.InputPropertiesError(errors);
}
}
// Use validation
try {
validateBucketName("MyBucket"); // Will throw error
} catch (error) {
if (pulumi.InputPropertiesError.isInstance(error)) {
error.reasons.forEach(reason => {
pulumi.log.error(`Validation failed for ${reason.propertyPath}: ${reason.reason}`);
});
}
}import * as pulumi from "@pulumi/pulumi";
class InfrastructureLogger {
private context: string;
constructor(context: string) {
this.context = context;
}
logOperation(operation: string, resource?: pulumi.Resource): void {
pulumi.log.info(`[${this.context}] ${operation}`, resource);
}
logConfig(config: any, resource?: pulumi.Resource): void {
pulumi.log.debug(`[${this.context}] Configuration: ${JSON.stringify(config)}`, resource);
}
logWarning(message: string, resource?: pulumi.Resource): void {
pulumi.log.warn(`[${this.context}] ${message}`, resource);
}
logError(message: string, error?: Error, resource?: pulumi.Resource): void {
const errorMsg = error ? `${message}: ${error.message}` : message;
pulumi.log.error(`[${this.context}] ${errorMsg}`, resource);
}
}
// Usage
const logger = new InfrastructureLogger("WebApp");
const bucket = new aws.s3.Bucket("web-assets", {
acl: "public-read",
});
logger.logOperation("Creating S3 bucket for web assets", bucket);
logger.logConfig({ acl: "public-read", versioning: false }, bucket);
bucket.id.apply(id => {
logger.logOperation(`S3 bucket created: ${id}`, bucket);
});import * as pulumi from "@pulumi/pulumi";
const config = new pulumi.Config();
const debugMode = config.getBoolean("debug") || false;
const environment = config.get("environment") || "development";
function conditionalLog(level: "debug" | "info" | "warn" | "error", message: string, resource?: pulumi.Resource): void {
// Only log debug messages in debug mode
if (level === "debug" && !debugMode) {
return;
}
// Add environment prefix in production
const prefixedMessage = environment === "production" ? `[PROD] ${message}` : message;
switch (level) {
case "debug":
pulumi.log.debug(prefixedMessage, resource);
break;
case "info":
pulumi.log.info(prefixedMessage, resource);
break;
case "warn":
pulumi.log.warn(prefixedMessage, resource);
break;
case "error":
pulumi.log.error(prefixedMessage, resource);
break;
}
}
// Usage
conditionalLog("debug", "Detailed configuration loaded");
conditionalLog("info", "Starting deployment");
conditionalLog("warn", "Using development configuration in production");import * as pulumi from "@pulumi/pulumi";
async function createResourceWithRetry<T extends pulumi.Resource>(
createFn: () => T,
maxRetries: number = 3
): Promise<T> {
let lastError: Error | undefined;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
pulumi.log.debug(`Attempt ${attempt}/${maxRetries} to create resource`);
return createFn();
} catch (error) {
lastError = error as Error;
pulumi.log.warn(`Attempt ${attempt} failed: ${error.message}`);
if (attempt === maxRetries) {
pulumi.log.error(`All ${maxRetries} attempts failed`);
break;
}
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
throw new pulumi.RunError(`Failed to create resource after ${maxRetries} attempts: ${lastError?.message}`);
}
// Usage
const bucket = await createResourceWithRetry(() => new aws.s3.Bucket("retry-bucket", {
acl: "private",
}));import * as pulumi from "@pulumi/pulumi";
function logDiagnosticInfo(): void {
pulumi.log.info(`Project: ${pulumi.getProject()}`);
pulumi.log.info(`Stack: ${pulumi.getStack()}`);
pulumi.log.info(`Organization: ${pulumi.getOrganization()}`);
const config = new pulumi.Config();
const allConfig = Object.keys(process.env)
.filter(key => key.startsWith('PULUMI_CONFIG_'))
.reduce((acc, key) => {
const configKey = key.replace('PULUMI_CONFIG_', '').toLowerCase();
acc[configKey] = config.get(configKey) || '<not set>';
return acc;
}, {} as Record<string, string>);
pulumi.log.debug(`Configuration: ${JSON.stringify(allConfig)}`);
}
// Log diagnostic info at startup
logDiagnosticInfo();import * as pulumi from "@pulumi/pulumi";
class PerformanceLogger {
private timers: Map<string, number> = new Map();
startTimer(label: string): void {
this.timers.set(label, Date.now());
pulumi.log.debug(`Started timer: ${label}`);
}
endTimer(label: string, resource?: pulumi.Resource): void {
const startTime = this.timers.get(label);
if (startTime) {
const duration = Date.now() - startTime;
pulumi.log.info(`${label} completed in ${duration}ms`, resource);
this.timers.delete(label);
}
}
}
const perfLogger = new PerformanceLogger();
perfLogger.startTimer("S3 Bucket Creation");
const bucket = new aws.s3.Bucket("perf-bucket");
bucket.id.apply(() => {
perfLogger.endTimer("S3 Bucket Creation", bucket);
});Install with Tessl CLI
npx tessl i tessl/npm-pulumi--pulumidocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10