Normal view

There are new articles available, click to refresh the page.
Before yesterdayMain stream

A primer on predicates for LogUI

By: hoakley
3 April 2025 at 14:30

All good log browsers provide tools to narrow down the log entries they display. Without those, it would be easy to waste all day wandering through tens of thousands of entries. One common tool provided by macOS, directly and in the log command tool, is filtering using predicates. Although LogUI provides easy access to simple predicates, to get the best from them, it’s worth digging a little deeper, as I do here.

Instant predicates

LogUI’s instant predicates filter log entries according to any of four basic predicate types:

  • subsystem, such as com.apple.sharing, the field shown in yellow in log extracts;
  • eventMessage, the text message listed in white/black at the end of each entry;
  • processImagePath, such as mediaanalysisd, shown in blue, the name of the process making that entry;
  • senderImagePath, such as libxpc.dylib, shown in red, the name of the process sending that entry.

These are quick to enter in the text box to the right of the popup menu in the window’s toolbar, but in many circumstances can prove too broad, and need narrowing down further. In other situations, you want to browse entries from two subsystems, or using a combination of criteria. The best way to do that is to write a short predicate. For single use, you can do that in the one-off predicate editor using the Set button.

When you want to reuse that, you can add it to the predicate popup menu using Settings Predicate (currently a bit kludgy).

Predicates

macOS can use predicates in other situations, most commonly for Spotlight search. If you’re interested in those, see Apple’s Predicate Programming Guide. Here I’ll describe predicates as they’re more commonly used to filter log entries, as they’re usually much simpler.

Each simple predicate consist of three parts:

  • the name of one of the fields in a log entry, such as subsystem or eventMessage. This sets where the filter looks in each entry;
  • an operator, which might be == for ‘equals’ exactly, or for text is commonly CONTAINS[c] for case-insensitive contains;
  • text or a numeric value to look for, such as “error” or 513. Only those entries equalling or containing (or whatever the operator means) this in the specified field will then be returned from the log and displayed.

Here are some basic examples.

eventMessage CONTAINS[c] "error"
entries will only be those with the text error in their message field.

subsystem == "com.apple.duetactivityscheduler"
entries will all have that text, ignoring case, but only that text, as the name of their subsystem.

subsystem CONTAINS[c] "com.apple.xpc"
entries will have any subsystem containing that text, which also includes com.apple.xpc.activity.

Fields

Although you can use any of the fields shown in LogUI (and some that aren’t), the most commonly used are, in order as they are shown in LogUI’s window:

  • eventType (red) – matches the type of event, such as logEvent (1024), traceEvent (768), activityCreateEvent (513), or activityTransitionEvent (514). Can be given as characters (case-sensitive) without quotation marks, or using the digits given in parentheses. Use these only with the operators == or !=, as they are treated as numbers rather than text.
  • category (green) – this matches the category, and varies according to subsystem. This is given as text in quotation marks, and is normally lower-case.
  • messageType (white/black) – matches the type of message for logEvent and traceEvent, and includes default (0), release (0), info (1), debug (2), error (16), and fault (17). Can be given as characters (case-sensitive) without quotation marks, or digits as shown in parentheses. Use these only with the operators == or !=, as they are treated as numbers rather than text.
  • senderImagePath (red) – this matches the text pattern in the name of the sender, which might be the name of a library, extension, or executable.
  • processImagePath (blue) – this matches the text pattern in the name of the process that originated the event.
  • subsystem (yellow) – this matches the subsystem specifier, e.g. com.apple.TimeMachine, given as text in quotation marks. You may find it best to use CONTAINS[c] rather than ==, to allow for differences in case and extended subsystem specifiers.
  • eventMessage (white/black) – for this, you specify a text pattern, or text, within the message, given as text in quotation marks.

Operators

The following comparisons and other operators are available:

  • == (two equals signs) for equality
  • != or <> for inequality
  • >= or => for greater than or equal to
  • <= or =< for less than or equal to
  • > for greater than
  • < for less than
  • AND or && for logical and
  • OR or || for logical or
  • NOT or ! for logical not
  • BEGINSWITH, CONTAINS, ENDSWITH, LIKE, MATCHES for string comparisons, using regex expressions when desired; strings can be compared with case insensitivity and diacritic insensitivity by appending [cd] to the operator, e.g. CONTAINS[c] means case-insensitive comparison
  • FALSE, TRUE, NULL have their expected literal meanings.

There are others as well, but you’ll seldom use them to filter log entries.

Building complex predicates

To see the scheduling and dispatch of background activities by DAS-CTS, you need to look at log extracts showing both their entries. Use the predicate
subsystem == "com.apple.duetactivityscheduler" OR subsystem CONTAINS "com.apple.xpc"
to do that. The first part of it includes those entries from DAS, and the second includes those for XPC and its relatives that run CTS. Using an OR between the two parts combines both sets of entries in the one extract.

To see the reports posted by XProtect Remediator, you need to look at those entries made by its subsystem that have the right category, using the predicate
subsystem == "com.apple.XProtectFramework.PluginAPI" AND category == "XPEvent.structured"
Using the AND operator ensures that the only entries shown come from that one subsystem, and they are given just that category.

Time Machine involves a combination of different subsystems and messages. To get a good overview of relevant entries, you can use
subsystem == "com.apple.TimeMachine" OR
(subsystem == "com.apple.duetactivityscheduler" AND eventMessage CONTAINS[c] "Rescoring all") OR
(subsystem == "com.apple.xpc.activity" AND eventMessage CONTAINS[c] "com.apple.backupd-auto") OR
eventMessage CONTAINS[c] "backup" OR
eventMessage CONTAINS[c] "Time Machine" OR eventMessage CONTAINS[c] "TimeMachine"

I’ve broken this down into separate lines, but you shouldn’t do that in the predicate. Taking it line by line it becomes simpler to understand. Use parentheses () to group each part of the predicate carefully as shown.

You can see other examples in the Help book for my free utility Mints: the Further Information pages towards the end give each of the predicates that Mints uses for its log extracts.

Quick summary

  • [field name] [operator] [text or numeric value]
  • common field names: senderImagePath, processImagePath, subsystem, eventMessage
  • common operators: ==, CONTAINS[c]
  • filter info: “text”
  • combine filters using AND, OR.

LogUI build 37 now has more power for browsing the log

By: hoakley
1 April 2025 at 14:30

By anyone’s standards, the macOS log contains a great many entries, and being able to filter out the noise is essential. This is accomplished by applying predicates to determine which entries are extracted and shown in a log browser like LogUI. However, using predicates requires knowledge about the log and its entries, and forms the greatest barrier for most users. This new version of LogUI improves features to help you use predicates to make the log more accessible.

This all happens in the toolbar of its browser window.

The section at the left of the lower row of tools now provides two methods to apply your own predicates: a one-off predicate editor, and an editor for custom entries in its popup menu.

One-off predicates

Click on the Set button to open the one-off predicate editor.

Here you can compose and paste in your own custom predicates that will extract only the log entries that you’re interested in. In this example, only entries whose subsystem is com.apple.duetactivityscheduler, or contains com.apple.xpc, will be gathered and displayed. Those tell you what’s going on with DAS and CTS scheduling and dispatch of background activities.

LogUI keeps that one-off predicate, even after a restart, as it’s automatically written to its preference file.

Once you’ve clicked Save, selecting the [ … ] item in the predicate menu will apply that predicate to each log extract you obtain.

There’s also an additional standard predicate using the senderImagePath.

Custom menu predicates

Predicates listed in that menu below blowhole are custom predicates saved to LogUI’s preferences using its new Predicate tab in its Settings. This editor is very basic at the moment, and its use a little awkward. This is because SwiftUI much prefers menu contents to be static, so adding items to the predicate menu doesn’t go down too well. This editor allows you to add one predicate at a time, in plain text format.

Click on the Append button here and there’ll be a new predicate named XProtect Remediator with the predicate shown. You can only add one new predicate, then need to quit the app before adding another. I’m sorry that’s so laborious, but once you have set up your custom predicates you can return to using LogUI fully.

The Settings General pane now contains a button to Reset Predicates back to their defaults.

Predicates

A basic predicate is composed of a log field name, like subsystem, followed by an operator such as == (equals) or CONTAINS[c] (case-insensitive contains), and a filter term, usually a string like "com.apple.xpc". So the predicate
subsystem CONTAINS[c] "com.apple.xpc"
will return all log entries with their subsystem containing the text com.apple.xpc. You can combine those basic elements into a more selective predicate using combinators such as AND and OR, so
subsystem == "com.apple.duetactivityscheduler" OR subsystem CONTAINS|c] "com.apple.xpc"
returns entries with a subsystem of precisely com.apple.duetactivityscheduler together with those whose subsystem contains the text com.apple.xpc.

Some years ago I wrote a primer here, and you’ll find some useful predicates in the Further Information section in the Help book for Mints. I’ll be writing more here to help you get the best out of LogUI.

There are a couple of oddities with predicates. SwiftUI tends to like using typographic double-quotation marks, but the macOS predicate builder doesn’t accept them as a substitute for straight marks. So LogUI changes all styled marks to straight ones automatically for you, to ensure those shouldn’t cause a problem. However, when it encounters errors it can behave erratically; while I’m trying to make this more robust, I apologise in advance if using a broken predicate upsets LogUI. It’s worth being careful to check your predicates before trying to use them.

LogUI version 1.0 build 37 is now available from here: logui137

My next task is to improve editing and saving predicates to its preferences, to make them accessible as menu customisations.

LogUI log browser build 31 has better filters

By: hoakley
20 March 2025 at 15:30

This week’s new features in my lightweight log browser LogUI tackle two important areas: initial checks to confirm that the app can access the log, and improving the filtering of log entries using predicates.

LogUI has three key requirements:

  • that the Mac is running macOS 14.6 or later, as enforced by macOS;
  • that it’s run from an admin account, as that has the privileges required to access the log;
  • that there are log records it can access in the path /var/db/diagnostics, as without those it hasn’t got anything to work with.

LogUI 1.0 build 31 now contains code to check the latter two, run soon after launch. If either fails, you’ll see an informative alert, and the app will quit when you click to dismiss that.

LogUI now has internal features to support a wide range of filters that can be applied when fetching log entries. These are an essential means of reducing the number of entries displayed, and of focussing your attention on what’s important.

This is reflected in its Settings, which now refer to Text rather than a Subsystem. The window toolbar now has a Predicate popup menu, and its text box is labelled text rather than Subsystem.

This menu offers the following options:

  • none, which applies no filtering and displays all log entries;
  • subsystem, which uses the text entered as the name of the subsystem whose entries are to be displayed, as in the previous builds;
  • eventMessage, which shows only those log entries whose message contains the text entered;
  • processImagePath, which shows only entries whose process name (or path) contains the text entered;
  • [Edit], which in future will open an on-the-fly predicate editor, but currently doesn’t filter;
  • TimeMachineBasic to blowhole, which use set predicates to display log entries for those features. The first two are different levels of detail for Time Machine backups, error finds entries with that word in their message, kernel finds entries with the kernel as their process, and blowhole finds entries made by my command tool for writing entries in the log.

Text entered is not case-sensitive.

Although it’s currently possible to change and extend those, that involves delicate surgery to LogUI’s preferences Property List, and I don’t intend you to hack that just yet. The next features will provide a proper editor in LogUI’s Settings, and the on-the-fly editor accessed through this menu.

Otherwise LogUI should work just the same as the last build. These new features are documented in its Help book, a separate copy of which is supplied in its Zip archive.

LogUI 1.0 build 31 is now available from here: logui131
and I will shortly be giving it an entry in my log browser Product Page, to make it easier to access. I’m also looking at building an auto-update mechanism into it.

Please let me know how you get on with this, and whether it proves useful to you. Enjoy!

Browse your Mac’s log with LogUI

By: hoakley
14 March 2025 at 15:30

If you ever need to understand what’s going on in your Mac, reading its log is essential. However much you might stare at Activity Monitor, read source code or disassemble components of macOS, what you can see in the log tells you what has really happened. Whether it’s a bug or an unexpected event, it’s the only way to look back and discover what went on.

For most, Console isn’t the right tool. It only offers the options of viewing its live stream, or making an archive of the whole log and wading through that when you need to look at an event in the past. Although my log browser Ulbow gives much better access, for many it’s still a daunting task. I’ve now switched almost entirely to using my new lightweight log browser, LogUI, and here explain how you can use it. Although it’s currently an early release with limited features, you should find it ideal for getting started.

LogUI 1.0 build 27 is available from here: logui127

This comes as a Zip archive, so unZip it, and move the LogUI app to another folder before running it for the first time; your main Applications folder is fine, and almost anywhere will do nicely. Alongside it is a copy of the PDF Help file that’s also inside the app, so you can refer to it when you’re not running LogUI. As the two are identical, you can trash the separate copy if you’re happy to use that inside the app.

Before opening LogUI, generate an event that you can examine in the log. One starter might be launching an app. Try to do this when your Mac is otherwise quiet and unoccupied: if Activity Monitor shows it’s busy with lots of background tasks, then the log could be filling with noise, when what you want most is peace. For the sake of simplicity, time this on an even minute, and make a mental note of that time to the second.

As soon as you’ve done that, open LogUI and you’ll be greeted by its window, with its toolbar ready for you to set up and get your first log extract. That should be set as follows:

  • Start to the current date, hour and minutes. As those are set to the time you open the window, they should already be close to the time of the event. Just after the stepper control is the seconds setting. If the event occurred a moment after the seconds changed to 00, that makes a convenient time to start your log extract.
  • Period set to around 5 seconds. This value can be floating point decimal, so might be 2.5 seconds for a smaller log extract.
  • Max entries set to 1000 to start with.
  • Show Signposts not ticked.
  • Full Fields ticked.
  • Subsystem empty.

Then click on Get Log to see the log extract for that period.

In my case, a five second period overfilled the 1000 I had set in Max entries. Scrolling to the foot of the extract showed that had been reached in less than two seconds, so I increased Max entries to 10000 and clicked Get Log again.

There are now over 5,000 entries in the extract, but they scroll smoothly enough to let me look around them.

The best way of reducing the number of entries to make them more understandable is to add a Subsystem as a filter. In this case, as I’ve launched an app, I can get most useful information from LaunchServices, by entering
com.apple.launchservices
into Subsystem. I also reduce the number of fields shown by unticking the Full Fields box, letting me concentrate on the messages. You can toggle Full Fields without having to get log entries again, as it only affects the fields within those entries that are shown in the window. Then click on Get Log again.

Scrolling down through the 358 entries remaining, I quickly reach one with a message field reading
LAUNCH: translocate to <private> from <private>
Although we could do without the privacy censorship here, it’s easy to work out that the app I just launched underwent app translocation, and that’s confirmed a little further down when LaunchServices gives its full path.

If you want a copy of the text from one or more selected entries, use the Copy command (Command-C), then paste it into any text editor. That doesn’t copy all the fields, only those you’re most likely to need elsewhere. For a full copy of that log extract, with colours indicating the fields, click on the Save as RTF button. As with LogUI’s window title, saved files are given default file names containing the start time of that log extract to help you keep them in good order.

This is the same log extract seen in my rich text editor DelightEd.

Finally, open LogUI’s Settings to enter the defaults you want its windows to open with. These match controls in its toolbar. The last of those, Light Mode, enables you to run the whole app in Light Mode if you prefer. For that to work, your Mac will also need to be in Light Mode, and you should tick that box, close the Settings window and quit the app. When you next open it, it should operate in Light Mode. Other changes made to Settings don’t need you to quit the app for them to take effect.

Enjoy!

你的荣耀手机学会「点屏幕」了,为什么笨 AI 也有未来?

By: 杜晨
10 March 2025 at 14:23

在移动世界通信大会 MWC 2025 上,我们看到荣耀和订餐订位产品 OpenTable 做的一次演示:用户用语音命令手机 AI 助理找家西班牙餐馆订个位,接着就看到手机屏幕被「接管」,一通自己操作。

这个 MWC 版本的演示,其实和荣耀去年 Magic 7 Pro 发布会上策划的那次「行为艺术」,是同一件事。

当时在深圳的发布会上,时任荣耀 CEO 的赵明指挥 AI Agent YOYO 打开美团。他的手没动,而是 YOYO 自己在屏幕上点来点去,一家店点了几十杯饮料,支付,循环到下一家,继续点,再循环,重复操作——直到最后下单了总共 2000 杯左右。

一通操作过后,深圳发布会场地周边的瑞幸门店纷纷「爆单」,门店咖啡师忙到崩溃,接到订单的骑手更是在门店排起长队。

这次效果显著却略带荒诞意味的事件营销,一定程度上让公众忽略了荣耀试图展示的核心技术:「基于 GUI 的个人 AI 智能体」

时至今日,AI Agent 功能确实已经不新鲜了。而这个技术的关键点,在「GUI」这三个字上。

GUI 全称 Graphical User Interface,图形用户界面。作为一个基于 GUI 的 AI Agent,YOYO 不再依赖传统的 API 接口,而是有了一只虚拟的「手」,直接在代替用户进行图形界面操作。整个代行操作不在「后台」,而是直接在「前台」,在用户的眼皮底下实时发生。

需要澄清的是:Magic 7 Pro 市售机型用户的体验可能会与发布会演示存在差异。据财联社报道,当时现场演示用的测试机权限更高,能够自动免密支付和循环点单,这才不停地点出了2000杯饮料。至少在目前,市售机型需要用户明确告知点单细节(例如品牌、品名、杯型、温度等),并且在支付环节需要用户接管确认。

这个细节确实重要,但也不至于抹杀这项技术的存在意义。正相反,我们认为,「基于 GUI」是个很另类,很有趣,颇具试验性的 AI Agent实现路径。

AI Agent 交互的「前台」新路

荣耀 YOYO 的核心是多模态模型,GUI 交互的本质是语言+视觉的理解。

  • 自然语言处理 (NLP):理解「点一杯冰美式」的指令;
  • 屏幕状态感知:识别当前界面中的内容,找到正确的按钮、输入框等界面元素;
  • 拟人化操作:像人类一样点击按钮、输入信息;
  • 循环操作:在新的界面中持续解析内容、定位和点击界面元素。

关于 GUI 的操作部分,这最后一步具体是怎样实现的,荣耀方面没有明确透露。一种稳妥的猜测是:它能够获得手机的无障碍功能 (accessibility features) 或类似的底层权限,从而控制屏幕点击事件。

这最后一步并不是什么难事,甚至比前面几步都简单得多。但除了此前智谱的 AutoGLM 等极少数之外,确实很少有其它第三方开发者和终端厂商在走 GUI 交互的路径。

在过去,虚拟助理控制软件和智能硬件的方式主要是通过 API 调用以及物联网协议。这可以理解为一种纯数字 (digital) 的通讯方式。

今年一月,谷歌在三星的指定机型上激活了基于 Gemini 2.0 的 AI Agent 功能。这次合作也是通过 API 或类似方式实现的(谷歌称之为 Gemini 扩展),初期仅支持 Gmail、谷歌地图、三星日历、三星时钟等第一方应用,以及 Spotify 等极少量第三方应用。

想要做到规模化,扩充支持的应用,需要开发者做一定量的 API 接入工作,同时也需要用户许可使用 Gemini 扩展。

▲Gemini 控制手机演示   图源:Google

谷歌依赖 API 调用后台接口,而荣耀通过 GUI 模拟前台操作,二者在实现逻辑上形成了明显区别。后者的好处,在于可以规避 API 调用这一常规方式,绕过了其背后的商业博弈和数据成本,也可以更快、更容易地扩充支持的应用,实现规模化并改善用户体验。

成本是个关键问题。一方面是云服务费用,因为无论是 API 提供方还是调用方都需要运行服务器来进行操作。另一方面,通过 API 交换的数据也具有价值,因此具有更高数据价值的 API,往往收费也更高。

以美团举例,其订单服务在内的基础 API 收费标准为每百次调用0.15元(前百万次免费)。这还只是基础类 API,如果涉及价值更高的管理类 API,调用收费提高到每百次0.3元,且无免费额度。

另外,API 的使用也暗含着一些隐性的商业竞争要素。调用方获得了数据,同时也在向提供方发送数据,而不排除在特定条件下,双方都不希望肥水流向外人田。

而在基于 GUI 的方案下,至少就目前的演示效果来看,荣耀既不需要向美团支付 API 费用,双方也无需担心数据的归属,包括与之关联的隐私安全等问题。

AI Agent 只是在「模仿人类」点击屏幕,多么原始却有效的交互方式。

回归模拟,返璞归真

这种「返祖」式技术路径,让人联想到谷歌在2018年推出的 AI 电话助手 Duplex

Duplex 的思路在当时同样有点脑洞清奇:谷歌合成了一个 AI 语音,替用户给餐馆打电话订位。这个 AI 语音听起来并不生硬,甚至能够模仿真人的口音、语速、语调,以及加入「嗯」、「you know」 之类的填充词。

▲Duplex 技术演示 图源:Google

今时今日,AI 生成语音已经彻底「污染」了电销和客服行业,让人感到厌烦。但至少在当时,用顶尖的 NLP和语音合成技术,通过「打电话」这种模拟人类的方式订餐,这种另类的,从数字到模拟 (analog) 的交互方式,确实令人耳目一新。

目前荣耀正在推进的基于 GUI 的 AI Agent,在我看来同样属于一种从数字到模拟的实现方式,用原始与先进相结合的思路,带来了全新的可能性。

基于 GUI 不一定是实现手机 AI Agent 的最佳路径,但不可否认它确实很有趣,甚至有点「硬来」的意思。

  • 对于用户来说,使唤这样的 AI Agent没有学习成本,不需要研究提示语法;
  • 而对于第三方应用和服务平台来说,也几乎不需要额外的开发成本就可以接入。甚至反过来看,它们也无法拒绝被「接入」,因为压根就没有发生真正意义上的「接入」行为。至少以 Android 目前的沙箱机制来看,应用层不太能够「抵抗」系统底层的行为。

基于 GUI 的 AI Agent,既是一种对传统人机交互的致敬,也为 AI Agent 的落地和体验提升,提供了一种降低门槛、提高兼容性的路径。

有时候,最趁手的工具,真就只是一根干净简洁的大棒。

大模型与人机交互结合,「笨」AI 也有未来

在今天用户的主要需求场景上,有两种 AI Agent。一种是高智商型,能够解答复杂问题,完成困难的工作,比如 DeepSeek、Claude、以及前几天大热门的 Manus。这也是现在最流行最受关注的 AI Agent/Chatbot种类。

但我们同样需要另一种懂事能干的 AI Agent,它对用户的使用技巧没有很高的门槛,用户只要输入一两句简单直白的命令,它就能理解,并且把各种并不复杂的事给办好。

今天可以点外卖,将来它还能够帮你挂机放置类游戏,给指定好友的朋友圈点赞,甚至自动把刚拍下的一张照片修改一下发到社交网络。只要是用户能做的,基于 GUI 的 AI agent一样能做。门槛低,上限高,适应性强,用起来更顺手,可能是这一类 AI Agent的主要特色。

这类选手不需要成为理解世界的大学者,只当好执行任务的工具人就足矣。

2013年的电影《云端情人》(Her),曾经赋予人们展开无限的遐想。当时也正值 NLP 技术大爆发,许多优秀的语音场景产品和技术涌现出来。一些研究者和从业者笃信,自然语言对话将会成为 AI 交流的最主流方式。

然而去年昙花一现的硬件产品 AI Pin,以及开发它的 Humane 公司越走越黑的路,不禁令人怀疑《云端情人》设想的乌托邦是否那般美好,语音究竟是不是 Chatbot/Agent的终极答案。

飞书文档 - 图片

▲Humane AI Pin 图源:Humane

进入触屏时代,交互的门槛显著降低,以至于幼儿也能轻松地掌握。按照 AI 开发者们经常采用的比喻,大模型们的「智力」也恰如儿童。那么让 AI 通过触屏界面学习人类行为,听上去上还是很有希望的。

毕竟,你的伴侣不一定需要一首 AI 写的诗,却可能需要你按烂屏幕去抢一张周杰伦的演唱会门票。

前几天 Manus 刷屏,再次佐证了我们曾做出的一个预测:大模型将成为智能手机新的操作系统,自然用户界面 (Natural user interface, NUI) 将逐步替代现有的 GUI。

至少在目前看来,历经半个世纪发展的 GUI 仍会是人机交互的绝对主流。不过,大模型与 UI 结合,对人机交互进行一次前所未有的重新定义,甚至成为新的操作系统——这样的未来,的确越来越清晰了。

#欢迎关注爱范儿官方微信公众号:爱范儿(微信号:ifanr),更多精彩内容第一时间为您奉上。

爱范儿 | 原文链接 · 查看评论 · 新浪微博


LogUI build 25 replaced by build 27

By: hoakley
5 March 2025 at 02:26

I have just replaced LogUI 1.0 build 25 with build 27. This:

  • completes support for Signposts by including them in RTF files,
  • changes the Settings dialog to use Full Fields for consistency,
  • updates technical info with a link to original source code.

You can now download build 27 from here: logui127
or from the link in the original article.

LogUI build 25 can select and copy log entries, and more

By: hoakley
4 March 2025 at 15:30

Last week I introduced my new prototype log browser, LogUI, which seems to have been popular with many. As I now use it in preference to its predecessor Ulbow, I’ve spent a little time adding some new and improved features to bring you version 1.0 build 25. Changes include:

  • support for discontinuous selection of log entries,
  • support for copying text from selected log entries,
  • subsystem names are now case-insensitive,
  • support for Signposts,
  • window names change to include the start time of each log excerpt,
  • RTF saved file names change to reflect the start of each log excerpt.

Settings

These now let you set app defaults for displaying full log entries, and for fetching and displaying Signposts.

Browser controls

The only addition to these is the option to Show Signposts. When that’s ticked, Get Log also fetches all Signposts during the set period, and displays them inline with regular log entries.

LogUI now supports all types of log entry:

  • regular log entries,
  • Activities, events such as clicks/taps and others,
  • Boundaries, markers such as the start of the boot process,
  • Signposts, used to record significant steps and assess performance.

Signposts have their own custom fields, including signpost ID, name, and type, which are displayed when Full Fields are enabled. The only caution with Signposts is that they can outnumber regular log entries, so if you don’t need to see them, it’s better to leave them turned off.

I’m grateful to Joe for asking for the subsystem to be case-insensitive. This means that you can enter com.apple.TimeMachine or com.apple.timemachine as the subsystem and LogUI will display entries with a subsystem name of com.apple.TimeMachine for both. No longer will case trip you up.

Log entries

The biggest changes are in the selection and copying of log entries. You can now select log entries in a browser window. Selections can be multiple continuous using the Shift key modifier, and discontinuous using the Command key modifier. When one or more entries have been selected, you can then copy their text contents using the Copy command or Command-C. Copied text can then be pasted into an app that supports handling of text items in the Clipboard.

Because there are many different fields possible in each entry, copied text consists of a standard set:
date level sender process subsystem message
each separated by a Tab character.

If you want more fields with colour, save the log excerpt in RTF, open it in an RTF editor and copy from that.

If you’re a developer and are wondering how I have implemented this copy feature for a SwiftUI List, let me know and I’ll explain how I managed to pin this tail on the donkey while I was blindfolded, or how persistent guessing overcame the absence of documentation or example code.

Naming

To distinguish between windows and saved RTF files, LogUI now automatically names and renames its windows and the default file names suggested when saving files. Names are based on the Start date and time of the current log excerpt in that window. To begin with, when there’s no log extract, each new window is named LogUI. When it gains its first extract, the date and time are appended to that, e.g. LogUI 2025_03_03_08-14-00, and a similar default file name is offered. When you obtain a new log excerpt in the same window, those names are updated to reflect the changed Start date and time.

Help book

This has been updated to include all these changes.

LogUI 1.0 build 27 is now available from here: logui127
It still requires a minimum macOS version of 14.6, I’m afraid, because of the SwiftUI features it has to rely on.

Enjoy!

Postscript

I have replaced build 25 with 27. This completes support for Signposts, by including them in saved RTF files. I’ve also taken the opportunity to make a small correction in the Settings dialog, and to add a link to the technical info to the log access source code.

Introducing LogUI: an experimental log browser

By: hoakley
26 February 2025 at 15:30

Although I often use my free log browser Ulbow daily, and it serves its purpose well, it’s time to move on with changing macOS and its APIs, and do better. Ulbow still relies on the log command tool to get its log extracts, and its front end is thoroughly AppKit.

Apple introduced the Unified log in macOS Sierra back in 2016, and at that time the only way to access it was using the log command tool, which isn’t among those for which it has provided source code. It wasn’t until Catalina in 2019 that Apple provided an API allowing developers to obtain log entries direct. As that wasn’t retro-fitted, the few apps that access the log couldn’t use that on Macs running Mojave or earlier, limiting its usefulness until relatively recently. When I developed Consolation in 2017, and its successor Ulbow two years later in 2019, I therefore continued to rely on the log command tool to obtain log extracts.

By a curious coincidence, SwiftUI was also first released for macOS in 2019, although it has taken an extraordinarily long time to approach maturity. Over the last couple of years it has improved to the point where some outstanding apps like OmniFocus have now abandoned the older AppKit API in favour of SwiftUI.

Last summer I had a first go at writing a potential replacement for Ulbow using the combination of OSLog to give direct access to log entries, and SwiftUI for its interface. At that time I reached an impasse largely as a result of excessive memory use and a memory leak that I was unable to resolve, and concluded that “Ulbow already performs better than LogUI ever could.”

More recently I have returned to that project and accepted that trying to support older versions of macOS before Sonoma is too great an impediment. Calling on some newer features in SwiftUI I have made better progress and, although not entirely continent in its use of memory, I now have an experimental version that I’m using daily. It appears robust and stable, and shouldn’t run away with all your Mac’s memory. Although it currently lacks key features like Find/Search and the ability to copy text from its browser window, it can store log extracts in rich text format.

Its Settings establish defaults common to all new browser windows:

  • Subsystem allows you to filter entries by a single predicate for one specified subsystem.
  • Period lets you set a default period for log excerpts, given in decimal seconds, so you can set 2.5 seconds if you wish.
  • Max entries is the limit of entries to be fetched and displayed. This can be set as high as 20,000 or even more.
  • Light Mode will set the app’s windows to Light Mode when you next open the app, if your Mac is also set to run in Light Mode. This allows you to opt out of Dark Mode if you really must.

Window controls let you override the first three of those defaults, and add

  • Start, a date and time to start the log excerpt.
  • Full Fields, whether to show all fields or just a shortened selection.
  • Get Log button to get a log excerpt.
  • Save as RTF button to write the log excerpt out to a rich text file.
  • The count of entries in the current excerpt.

The end result is, I think, a considerable improvement on Ulbow, in terms of readability, without sacrificing too much space as in Console’s rigid columns.

This experimental release comes with its own PDF documentation, also accessible within the app as its Help book. I’d be very grateful if you could take it out for a spin and see how robust its log engine is, and whether you prefer its new layout for log entries. You can download a copy from here: logui120
Note that it requires a minimum macOS version of 14.6, to ensure that it doesn’t rob your Mac of memory.

Once its engine is reliable, I will add more features, starting with Search/Find support, and the ability to copy entries from its window.

Thank you, and happy logging around.

预言在应验:五年前所讨论的未来人机交互的新范式_6.ylog

By: Steven
16 June 2024 at 22:58

从 2024 年的今天,回望 2019 年的 Apple 和 Ive 团队,我们会发现有些变化和趋势似乎是早已注定的。在过往的观察和分析中,我们所预言的事情正在成为现实和主流。常言道以史为镜可以知兴替,今天再看当时的 Apple 和 Ive 团队,关于产品的演进思路和设计策略的变化都早有端倪,也能预见在 AI 席卷的浪潮下,Apple 将会如何应对。

在这一期,你会听到:

—- 二十年前的专利文件:通体透光的 iPhone

—- 国产厂商和 Apple 在设计上的差异

—- 成功的设计:AirPods 只是剪掉线的 EarPods

—- 塑料手机的设计巅峰:iPhone 5c

—- 刘海与机器视觉:早早布局的 AI 伏笔

—- 未来十年的人机交互:人和人之间怎么交互?

—- 设计策略上的「S型曲线」体现在哪里?

—- 产品路径上迷路的 iPad

—- 光洁的划痕:是矫情还是哲学?

—- 史上最佳手机壳:iPhone 5c 的多彩硅胶壳

—- 拟物化的残党,现在理解扁平化的先进性了吗?

|相关图片|

首款 Unibody 设计于 2008 年 10 月发布
截图来自:Designed by Apple in California

查看更多图片和设计讨论:Mac Pro 2019

|拓展阅读|

如何评价 iPhone X 的工业设计?

交互的王,时代的狂!万字详解灵动岛的今生来世!

十年轮回?经典进化!工业设计师深入解读 iPhone12!

从技术寿命 S 曲线,看阳极氧化铝的设计

抽象的产品,用户「界面」的设计

如何看待 Evans Hankey 从 Apple 设计团队离职?

注定会离职的 Jonathan Ive 和科技产品的设计趋势

|登场人物|

苏志斌:工业设计师,车联网智能硬件产品经理 / 联创,《设以观复》作者

王汉洋:AI 行业从业者,多档播客主播,《拯救东北1910》《山有虎》作者

|相关链接|

若你所使用的播客客户端未能完整显示插图,或遇网络问题未能正常播放,请访问:

荒野楼阁 WildloG 的地址:https://suithink.me/zlink/podcast/

阅读设计相关的各类文章:https://suithink.me/zlink/idea/

|其他社交网络媒体|

苏志斌 @ 知乎|SUiTHiNK @ 即刻 / 微博

苏志斌SUiTHiNK @ Bilibili / YouTube / 小红书

|联络邮箱|

suithink.su@gmail.com

欢迎在 小宇宙、Spotify、YouTube、Apple Podcast 收听本节目,期待你的留言。

❌
❌