@skdevlabs/pharos-sdk
v0.0.3
Published
Official SDK for Pharos uptime and incident monitoring
Maintainers
Readme
Pharos SDK
Official TypeScript/JavaScript SDK for Pharos uptime and incident monitoring.
Installation
npm install pharos-sdk
# or
pnpm add pharos-sdk
# or
yarn add pharos-sdkGetting Your API Key
Before using the SDK, you need to create an API key in the Pharos dashboard:
- Log in to your Pharos account
- Navigate to Settings > API Keys
- Click Create API Key
- Give your key a descriptive name (e.g., "Production Server", "CI/CD Pipeline")
- Copy the API key immediately - you won't be able to see it again!
- Store it securely in your environment variables
Security Best Practices:
- Never commit API keys to version control
- Store keys in environment variables (
.envfiles) - Use different keys for different environments (dev, staging, production)
- Rotate keys periodically
- Revoke keys immediately if compromised
Quick Start
import { PharosClient } from 'pharos-sdk';
const pharos = new PharosClient({
apiKey: process.env.PHAROS_API_KEY!, // Use environment variables
serviceName: 'my-service',
environment: 'production',
});
// Send a health ping
await pharos.health.ping();Configuration
const pharos = new PharosClient({
// Required
apiKey: process.env.PHAROS_API_KEY!, // Get from Pharos dashboard
// Optional
baseUrl: 'https://usepharos.online', // Default: https://usepharos.online (or your self-hosted URL)
serviceName: 'my-service', // Default: 'unknown'
environment: 'production', // Default: 'production'
timeout: 5000, // Default: 5000ms
maxRetries: 3, // Default: 3
retryDelay: 1000, // Default: 1000ms (exponential backoff)
});Environment Variables
Create a .env file in your project root:
PHAROS_API_KEY=phk_your_api_key_here
PHAROS_BASE_URL=https://usepharos.online # Optional, defaults to https://usepharos.onlineAPI Key Management
Creating API Keys
- Via Dashboard: Go to Settings > API Keys > Create API Key
- Name Convention: Use descriptive names that indicate the purpose
- ✅ Good:
production-web-server,staging-worker,ci-cd-pipeline - ❌ Bad:
key1,test,mykey
- ✅ Good:
Rotating API Keys
To rotate your API keys without downtime:
- Create a new API key in the dashboard
- Update your application to use the new key
- Deploy the changes
- Revoke the old key after confirming the new one works
Revoking API Keys
If a key is compromised or no longer needed:
- Go to Settings > API Keys
- Find the key you want to revoke
- Click the revoke button
- Confirm the action
Note: Revoking a key immediately blocks all API requests using that key.
Features
Health Endpoints
Create standardized, Pharos-compatible health endpoints with built-in dependency checking:
// Basic health endpoint (no checks)
const response = await pharos.createHealthResponse();
// Returns: { status: "ok", timestamp: "...", service: "...", environment: "...", uptimeSec: 123 }
// Health endpoint with dependency checks
const response = await pharos.createHealthResponse({
version: "1.0.0",
checks: {
db: {
fn: async () => {
await db.ping();
return { status: "ok", latencyMs: 12 };
},
critical: true, // Service is "down" if this fails
timeout: 2000,
},
redis: async () => {
// Shorthand format (non-critical by default)
await redis.ping();
return { status: "ok", latencyMs: 5 };
},
},
});Next.js App Router
// app/api/health/route.ts
import { PharosClient } from '@skdevlabs/pharos-sdk';
import { respondNextJs } from '@skdevlabs/pharos-sdk/adapters/nextjs';
const pharos = new PharosClient({
apiKey: process.env.PHAROS_API_KEY!,
serviceName: 'my-app',
});
export async function GET() {
return await respondNextJs(pharos, {
version: process.env.npm_package_version,
checks: {
db: async () => {
await db.ping();
return { status: 'ok' };
}
}
});
}Express
import express from 'express';
import { PharosClient } from '@skdevlabs/pharos-sdk';
const app = express();
const pharos = new PharosClient({
apiKey: process.env.PHAROS_API_KEY!,
serviceName: 'my-express-app',
});
app.get('/health', async (req, res) => {
const { statusCode, headers, body } = await pharos.respond({
checks: {
db: async () => {
await db.ping();
return { status: 'ok', latencyMs: 12 };
}
}
});
res.status(statusCode).set(headers).send(body);
});Fastify
import fastify from 'fastify';
import { PharosClient } from '@skdevlabs/pharos-sdk';
const app = fastify();
const pharos = new PharosClient({
apiKey: process.env.PHAROS_API_KEY!,
serviceName: 'my-fastify-app',
});
app.get('/health', async (request, reply) => {
const { statusCode, headers, body } = await pharos.respond({
checks: {
db: async () => {
await db.ping();
return { status: 'ok' };
}
}
});
reply.code(statusCode).headers(headers).send(body);
});Health Response Schema
All health endpoints return a standardized response:
{
status: "ok" | "degraded" | "down",
timestamp: "2025-12-31T12:00:00.000Z",
service: "my-service",
environment: "production",
version: "1.0.0", // optional
uptimeSec: 123.45,
checks: { // optional
db: { status: "ok", latencyMs: 12 },
redis: { status: "ok", latencyMs: 5 }
},
meta: { // optional
region: "us-west-2",
instanceId: "i-123"
}
}HTTP Status Codes:
200: Service is "ok" or "degraded"503: Service is "down" (critical check failed)
Health Checks (Legacy)
Send lightweight health pings from your application's health endpoints:
// In your Express health endpoint
app.get('/health', async (req, res) => {
await pharos.health.ping();
res.json({ status: 'ok' });
});
// With metadata
await pharos.health.ping({
metadata: {
version: '1.0.0',
uptime: process.uptime(),
},
});Job Tracking
Track background jobs, cron tasks, and scheduled workers:
// Track a job lifecycle
const jobName = 'daily-backup';
const startTime = Date.now();
try {
await pharos.jobs.start({ jobName });
// ... perform your job ...
await pharos.jobs.complete({
jobName,
duration: Date.now() - startTime,
metadata: { filesProcessed: 1000 },
});
} catch (error) {
await pharos.jobs.fail({
jobName,
error: error.message,
duration: Date.now() - startTime,
});
}Incident Management
Create incidents programmatically when critical errors occur:
// System-wide incident (no endpoint required)
await pharos.incidents.create({
title: 'High memory usage detected',
severity: 'medium',
description: 'Application memory usage exceeded 80% threshold',
metadata: {
currentMemory: '850MB',
threshold: '800MB',
},
});
// Endpoint-specific incident (optional endpointId)
await pharos.incidents.create({
title: 'Database connection failed',
severity: 'high',
description: 'Unable to connect to primary database after 3 retries',
endpointId: 'your-endpoint-uuid', // Optional - only if incident relates to specific endpoint
metadata: {
region: 'us-east-1',
errorCode: 'ECONNREFUSED',
},
});Note: endpointId is optional. Use it only when the incident relates to a specific monitored endpoint. Most SDK use cases (memory issues, database problems, etc.) don't require an endpoint.
Severity levels: 'low' | 'medium' | 'high' | 'critical'
Reliability
The SDK includes built-in reliability features:
- Automatic Retries: Failed requests are automatically retried with exponential backoff
- Timeout Handling: Requests timeout after 5 seconds by default (configurable)
- 5xx Error Handling: Automatically retries on server errors (5xx)
- Network Error Handling: Retries on network failures
Error Handling
try {
await pharos.incidents.create({
title: 'Critical error',
severity: 'critical',
});
} catch (error) {
console.error('Failed to create incident:', error);
// Your fallback logic here
}TypeScript Support
The SDK is written in TypeScript and provides full type definitions out of the box.
import type {
PharosConfig,
IncidentSeverity,
JobStartOptions,
} from 'pharos-sdk';Examples
Express.js Health Endpoint
import express from 'express';
import { PharosClient } from 'pharos-sdk';
const app = express();
const pharos = new PharosClient({
apiKey: process.env.PHAROS_API_KEY!,
serviceName: 'api-server',
});
app.get('/health', async (req, res) => {
try {
await pharos.health.ping();
res.json({ status: 'healthy' });
} catch (error) {
res.status(500).json({ status: 'unhealthy' });
}
});Cron Job Monitoring
import { PharosClient } from 'pharos-sdk';
const pharos = new PharosClient({
apiKey: process.env.PHAROS_API_KEY!,
serviceName: 'cron-worker',
});
async function runDailyBackup() {
const jobName = 'daily-backup';
const startTime = Date.now();
await pharos.jobs.start({ jobName });
try {
// Perform backup
await performBackup();
await pharos.jobs.complete({
jobName,
duration: Date.now() - startTime,
});
} catch (error) {
await pharos.jobs.fail({
jobName,
error: error instanceof Error ? error.message : 'Unknown error',
duration: Date.now() - startTime,
});
throw error;
}
}Critical Error Alerting
import { PharosClient } from 'pharos-sdk';
const pharos = new PharosClient({
apiKey: process.env.PHAROS_API_KEY!,
serviceName: 'payment-processor',
});
async function processPayment(amount: number) {
try {
// Process payment logic
await chargeCustomer(amount);
} catch (error) {
// Create incident for payment failures
await pharos.incidents.create({
title: 'Payment processing failed',
severity: 'critical',
description: `Failed to process payment of $${amount}`,
metadata: {
amount,
errorMessage: error.message,
timestamp: new Date().toISOString(),
},
});
throw error;
}
}License
MIT
