macos: send logs to unified logging

This commit is contained in:
Mitchell Hashimoto
2022-10-31 15:15:32 -07:00
parent 7608d7921f
commit 9e3bbc1598
3 changed files with 60 additions and 9 deletions

View File

@ -115,3 +115,11 @@ than 5 MB on all platforms. The debug version is around 70MB.
When targeting macOS, a macOS application bundle will be created at When targeting macOS, a macOS application bundle will be created at
`zig-out/Ghostty.app`. This can be copied as-is and used like a normal app. `zig-out/Ghostty.app`. This can be copied as-is and used like a normal app.
This app will be not be signed or notarized. This app will be not be signed or notarized.
When running the app, logs are available via macOS unified logging such
as `Console.app`. The easiest way I've found is to just use the CLI:
```sh
$ sudo log stream --level debug --predicate 'subsystem=="com.mitchellh.ghostty"'
...
```

View File

@ -6,5 +6,5 @@ void zig_os_log_with_type(
os_log_type_t type, os_log_type_t type,
const char *message const char *message
) { ) {
os_log_with_type(log, type, "%s", message); os_log_with_type(log, type, "%{public}s", message);
} }

View File

@ -5,6 +5,7 @@ const glfw = @import("glfw");
const fontconfig = @import("fontconfig"); const fontconfig = @import("fontconfig");
const freetype = @import("freetype"); const freetype = @import("freetype");
const harfbuzz = @import("harfbuzz"); const harfbuzz = @import("harfbuzz");
const macos = @import("macos");
const tracy = @import("tracy"); const tracy = @import("tracy");
const renderer = @import("renderer.zig"); const renderer = @import("renderer.zig");
@ -12,15 +13,13 @@ const App = @import("App.zig");
const cli_args = @import("cli_args.zig"); const cli_args = @import("cli_args.zig");
const Config = @import("config.zig").Config; const Config = @import("config.zig").Config;
const log = std.log.scoped(.main);
pub fn main() !void { pub fn main() !void {
// Output some debug information right away // Output some debug information right away
log.info("dependency harfbuzz={s}", .{harfbuzz.versionString()}); std.log.info("dependency harfbuzz={s}", .{harfbuzz.versionString()});
if (options.fontconfig) { if (options.fontconfig) {
log.info("dependency fontconfig={d}", .{fontconfig.version()}); std.log.info("dependency fontconfig={d}", .{fontconfig.version()});
} }
log.info("renderer={}", .{renderer.Renderer}); std.log.info("renderer={}", .{renderer.Renderer});
const GPA = std.heap.GeneralPurposeAllocator(.{}); const GPA = std.heap.GeneralPurposeAllocator(.{});
var gpa: ?GPA = gpa: { var gpa: ?GPA = gpa: {
@ -92,7 +91,7 @@ pub fn main() !void {
return error.ConfigFileInConfigFile; return error.ConfigFileInConfigFile;
} }
} }
log.info("config={}", .{config}); std.log.info("config={}", .{config});
// We want to log all our errors // We want to log all our errors
glfw.setErrorCallback(glfwErrorCallback); glfw.setErrorCallback(glfwErrorCallback);
@ -112,10 +111,54 @@ pub fn tracy_enabled() bool {
return options.tracy_enabled; return options.tracy_enabled;
} }
//pub const log_level: std.log.Level = .debug; // Our log level is always at least info in every build mode.
pub const log_level: std.log.Level = switch (builtin.mode) {
.Debug => .debug,
else => .info,
};
// The function std.log will call.
pub fn log(
comptime level: std.log.Level,
comptime scope: @TypeOf(.EnumLiteral),
comptime format: []const u8,
args: anytype,
) void {
// Stuff we can do before the lock
const level_txt = comptime level.asText();
const prefix = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
// Lock so we are thread-safe
std.debug.getStderrMutex().lock();
defer std.debug.getStderrMutex().unlock();
// On Mac, we use unified logging. To view this:
//
// sudo log stream --level debug --predicate 'subsystem=="com.mitchellh.ghostty"'
//
if (builtin.os.tag == .macos) {
// Convert our levels to Mac levels
const mac_level: macos.os.LogType = switch (level) {
.debug => .debug,
.info => .info,
.warn => .err,
.err => .fault,
};
// Initialize a logger. This is slow to do on every operation
// but we shouldn't be logging too much.
const logger = macos.os.Log.create("com.mitchellh.ghostty", @tagName(scope));
defer logger.release();
logger.log(std.heap.c_allocator, mac_level, format, args);
}
// Always try default to send to stderr
const stderr = std.io.getStdErr().writer();
nosuspend stderr.print(level_txt ++ prefix ++ format ++ "\n", args) catch return;
}
fn glfwErrorCallback(code: glfw.Error, desc: [:0]const u8) void { fn glfwErrorCallback(code: glfw.Error, desc: [:0]const u8) void {
log.warn("glfw error={} message={s}", .{ code, desc }); std.log.warn("glfw error={} message={s}", .{ code, desc });
} }
test { test {