contextual_shelf 0.1.0 copy "contextual_shelf: ^0.1.0" to clipboard
contextual_shelf: ^0.1.0 copied to clipboard

shelf using contextual logger

example/contextual_shelf_example.dart

import 'package:contextual/contextual.dart';
import 'package:contextual_shelf/contextual_shelf.dart';

import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;

/// Custom log profile that logs non-GET requests and API requests
class ApiLogProfile implements LogProfile {
  @override
  bool shouldLogRequest(shelf.Request request) {
    return request.method != 'GET' || request.url.path.startsWith('api/');
  }
}

/// This example demonstrates how to use contextual_shelf with a Shelf server.
/// It shows request logging, error handling, and custom log formatting.
void main() async {
  // Create a logger with multiple channels
  final logger = Logger()
    ..addChannel(
      'console',
      ConsoleLogDriver(),
      formatter: PrettyLogFormatter(),
    )
    ..addChannel(
      'file',
      DailyFileLogDriver('logs/server.log'),
      formatter: JsonLogFormatter(),
    );

  // Create a custom log writer with sanitization
  final logWriter = DefaultLogWriter(
    logger,
    sanitizer: Sanitizer(mask: '[REDACTED]'),
  );

  // Create a log profile that determines which requests to log
  final logProfile = ApiLogProfile();

  // Create the HTTP logger middleware
  final httpLogger = HttpLogger(logProfile, logWriter);

  // Create a handler pipeline with logging middleware
  final handler = const shelf.Pipeline()
      .addMiddleware(httpLogger.middleware)
      .addHandler(_handleRequest);

  // Start the server
  final server = await io.serve(handler, 'localhost', 8080);
  print('Server running on port ${server.port}');

  // Log server startup
  logger.info(
      'Server started',
      Context({
        'port': server.port,
        'address': server.address.host,
      }));
}

/// Example request handler that demonstrates different scenarios
Future<shelf.Response> _handleRequest(shelf.Request request) async {
  try {
    switch (request.url.path) {
      case 'api/users':
        // Simulate successful API request
        return shelf.Response.ok(
          '{"status": "success", "data": ["user1", "user2"]}',
          headers: {'content-type': 'application/json'},
        );

      case 'api/error':
        // Simulate error condition
        throw Exception('Simulated API error');

      case 'api/slow':
        // Simulate slow request
        await Future.delayed(Duration(seconds: 2));
        return shelf.Response.ok('Slow response');

      case 'api/auth':
        // Simulate authenticated request
        final auth = request.headers['authorization'];
        if (auth == null) {
          return shelf.Response.unauthorized('No authorization provided');
        }
        return shelf.Response.ok('Authenticated');

      default:
        // Handle static content or other routes
        return shelf.Response.ok('Hello from Shelf!');
    }
  } catch (e, _) {
    // Errors will be logged by the middleware
    return shelf.Response.internalServerError(
      body: 'Internal Server Error',
    );
  }
}

String getCurrentFileAndLine() {
  // Generate a current stack trace.
  final stackTrace = StackTrace.current.toString();

  // The stack trace is a multi-line string; each line looks something like:
  //   #0      MyClass.myMethod (file:///path/to/file.dart:42:16)
  // We can split on newlines and parse the line that describes this method call.
  final traceLines = stackTrace.split('\n');

  // The first frame (#0) usually corresponds to the current line in Dart.
  // Adjust the index if you need a different call site.
  final frame = traceLines.isNotEmpty ? traceLines[1] : '';

  // A quick (naive) pattern match to find parentheses and extract file info.
  // You might want to refine this or use a regex for more robust parsing.
  final fileInfoStart = frame.indexOf('(');
  final fileInfoEnd = frame.indexOf(')');

  if (fileInfoStart != -1 && fileInfoEnd != -1 && fileInfoStart < fileInfoEnd) {
    final fileInfo = frame.substring(fileInfoStart + 1, fileInfoEnd);
    return fileInfo; // something like "file:///path/to/file.dart:42:16"
  }

  // If parsing fails for some reason, return the raw frame or an empty string.
  return frame;
}
0
likes
140
points
21
downloads

Publisher

verified publisherglenfordwilliams.com

Weekly Downloads

shelf using contextual logger

Homepage
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

contextual, shelf

More

Packages that depend on contextual_shelf