User Identification
User identification allows you to associate logs with specific users, making it easier to track user actions, debug user-specific issues, and maintain audit trails.
Basic Usage
Use Log.identify()
to associate logs with a specific user:
// Identify user with id, email, and token
Log.identify('user_12345', 'john.doe@company.com', 'auth_token_abc123');
// All subsequent logs will be associated with this user
Log.info('User performed action');
Log.error('User encountered error', {
context: { action: 'checkout' }
});
// Logout to make subsequent logs anonymous
Log.logout();
Method Signature
Log.identify(id, email?, token?)
Parameters
id
(string, required): Unique user identifieremail
(string, optional): User's email addresstoken
(string, optional): Authentication token
User Identification Examples
Basic Identification
// Minimal identification with just ID
Log.identify('user_12345');
// With email
Log.identify('user_12345', 'john.doe@company.com');
// Complete identification
Log.identify('user_12345', 'john.doe@company.com', 'jwt_token_here');
Express.js Integration
// Login endpoint
app.post('/api/login', async (req, res) => {
try {
const { email, password } = req.body;
const user = await authService.authenticate(email, password);
// Identify user in logs
Log.identify(user.id, user.email, user.token);
Log.info('User login successful', {
context: { userId: user.id, loginMethod: 'email' },
tags: ['authentication', 'login']
});
res.json({ token: user.token });
} catch (error) {
Log.error('Login failed', {
context: { email: req.body.email },
tags: ['authentication', 'error']
}, error);
res.status(401).json({ error: 'Invalid credentials' });
}
});
// Logout endpoint
app.post('/api/logout', (req, res) => {
Log.info('User logout', {
tags: ['authentication', 'logout']
});
Log.logout();
res.json({ message: 'Logged out successfully' });
});
Middleware Integration
// Authentication middleware
const authMiddleware = async (req, res, next) => {
try {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({ error: 'No token provided' });
}
const user = await authService.verifyToken(token);
// Identify user for all subsequent logs in this request
Log.identify(user.id, user.email, token);
req.user = user;
next();
} catch (error) {
Log.error('Authentication failed', {
context: { token: token?.substring(0, 10) + '...' },
tags: ['authentication', 'middleware']
}, error);
res.status(401).json({ error: 'Invalid token' });
}
};
// Protected route
app.get('/api/profile', authMiddleware, (req, res) => {
Log.info('Profile accessed', {
context: { userId: req.user.id },
tags: ['profile', 'access']
});
res.json(req.user);
});
User Context in Logs
Once a user is identified, all subsequent logs will include user information:
// After identification
Log.identify('user_123', 'john@example.com');
// These logs will automatically include user context
Log.info('Order created', {
context: { orderId: 'order_456' },
tags: ['orders']
});
Log.error('Payment failed', {
context: { paymentId: 'pay_789' },
tags: ['payment', 'error']
});
Logout Functionality
Use Log.logout()
to make subsequent logs anonymous:
// User logs out
Log.logout();
// Subsequent logs will be anonymous
Log.info('Anonymous action performed');
Session Management
Session-based Identification
// Express session example
app.use(session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: false
}));
app.post('/api/login', async (req, res) => {
const user = await authService.authenticate(req.body.email, req.body.password);
// Store in session
req.session.userId = user.id;
req.session.userEmail = user.email;
// Identify in logs
Log.identify(user.id, user.email);
Log.info('User session created', {
context: { sessionId: req.session.id },
tags: ['session', 'login']
});
res.json({ success: true });
});
// Middleware to restore user identification from session
app.use((req, res, next) => {
if (req.session.userId) {
Log.identify(req.session.userId, req.session.userEmail);
}
next();
});
JWT Token Integration
import jwt from 'jsonwebtoken';
// JWT middleware
const jwtMiddleware = (req, res, next) => {
const token = req.headers.authorization?.replace('Bearer ', '');
if (token) {
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
// Identify user from JWT payload
Log.identify(decoded.userId, decoded.email, token);
req.user = decoded;
} catch (error) {
Log.error('JWT verification failed', {
context: { tokenPrefix: token.substring(0, 10) },
tags: ['jwt', 'authentication']
}, error);
}
}
next();
};
Best Practices
User Identification Best Practices
- Set user context early: Configure user identification as soon as user is authenticated
- Include relevant information: Add email and token when available
- Clear on logout: Always call
Log.logout()
when user logs out - Use consistent user IDs: Maintain the same user ID format across your application
- Consider privacy: Be mindful of PII in user identification data
Common Patterns
Single Page Applications
// React/Vue.js example
class AuthService {
async login(email, password) {
try {
const response = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
});
const data = await response.json();
if (data.success) {
// Store token and identify user
localStorage.setItem('token', data.token);
Log.identify(data.user.id, data.user.email, data.token);
Log.info('User authenticated', {
context: { loginType: 'spa' },
tags: ['authentication', 'spa']
});
}
return data;
} catch (error) {
Log.error('Login request failed', {
context: { email },
tags: ['authentication', 'spa', 'error']
}, error);
throw error;
}
}
logout() {
localStorage.removeItem('token');
Log.logout();
Log.info('User logged out', {
tags: ['authentication', 'logout', 'spa']
});
}
// Restore user identification on app start
restoreSession() {
const token = localStorage.getItem('token');
if (token) {
try {
const payload = jwt.decode(token);
if (payload && payload.exp > Date.now() / 1000) {
Log.identify(payload.userId, payload.email, token);
Log.info('Session restored', {
context: { userId: payload.userId },
tags: ['authentication', 'session']
});
}
} catch (error) {
Log.error('Session restoration failed', {}, error);
this.logout();
}
}
}
}
Microservices Communication
// Service-to-service calls with user context
class ApiClient {
constructor() {
this.baseURL = process.env.API_BASE_URL;
}
async makeRequest(endpoint, options = {}) {
// Get current user context if available
const userContext = this.getCurrentUserContext();
const headers = {
'Content-Type': 'application/json',
...options.headers
};
// Pass user context in headers for service-to-service calls
if (userContext) {
headers['X-User-ID'] = userContext.id;
headers['X-User-Email'] = userContext.email;
}
try {
const response = await fetch(`${this.baseURL}${endpoint}`, {
...options,
headers
});
Log.info('API request completed', {
context: {
endpoint,
status: response.status,
userId: userContext?.id
},
tags: ['api', 'microservice']
});
return response;
} catch (error) {
Log.error('API request failed', {
context: { endpoint, userId: userContext?.id },
tags: ['api', 'microservice', 'error']
}, error);
throw error;
}
}
}
Next Steps
- Correlation IDs - Track user actions across services
- Global Metadata - Add consistent context to all logs
- Data Masking - Protect sensitive user information
- Tags - Organize user-related logs