Skip to content

Commit c205e35

Browse files
committed
First version
Signed-off-by: Wouter01 <wouterhennen@gmail.com>
0 parents  commit c205e35

9 files changed

Lines changed: 426 additions & 0 deletions

File tree

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
/*.xcodeproj
5+
xcuserdata/
6+
DerivedData/
7+
.swiftpm/config/registries.json
8+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
9+
.netrc

Package.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// swift-tools-version: 5.8
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "LogStream",
8+
platforms: [
9+
.macOS(.v10_15),
10+
.macCatalyst(.v13)
11+
],
12+
products: [
13+
.library(
14+
name: "LogStream",
15+
targets: ["LogStream"]),
16+
],
17+
targets: [
18+
.target(
19+
name: "LogStream",
20+
dependencies: ["ExternalAppLoggerHeaders"]
21+
),
22+
23+
.target(
24+
name: "ExternalAppLoggerHeaders",
25+
path: "Sources/Headers",
26+
linkerSettings: [
27+
.linkedFramework("LoggingSupport")
28+
]
29+
)
30+
]
31+
)

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# LogStream
2+
3+
This package provides some utilities to capture logs of other processes. This can be useful when working with extensions using [ExtensionKit](https://developer.apple.com/documentation/extensionkit).
4+
5+
The logs captured are the same ones visible in Console.app.
6+
7+
## Usage
8+
9+
```swift
10+
// Specify the process identifier of which to capture logs.
11+
let pid: pid_t = ...
12+
let logStream = LogStream.logs(for: pid)
13+
14+
Task {
15+
for await log in logStream {
16+
print("\(log.process) says: \(log.message)")
17+
}
18+
}
19+
```
20+
21+

Sources/Headers/_.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//
2+
// _.c
3+
//
4+
//
5+
// Created by Wouter Hennen on 22/05/2023.
6+
//
7+
8+

Sources/Headers/include/Header.h

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
//===-- ActivityStreamSPI.h -------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef OSActivityLogMessageEvent_h
10+
#define OSActivityLogMessageEvent_h
11+
12+
#include <sys/time.h>
13+
@import Foundation;
14+
15+
NS_ASSUME_NONNULL_BEGIN
16+
17+
/// Describes a basic activity event reported by LoggingSupport.
18+
/// The implementation of this class resides in the LoggingSupport framework.
19+
@interface OSActivityEvent : NSObject
20+
21+
@property (readonly, nonatomic) NSUInteger activityID;
22+
@property (copy, nonatomic) NSString *eventMessage;
23+
@property (readonly, nonatomic) NSUInteger eventType;
24+
@property (readonly, nonatomic) NSUInteger machTimestamp;
25+
@property (readonly, nonatomic) NSUInteger parentActivityID;
26+
@property (readonly, nonatomic) BOOL persisted;
27+
@property (readonly, copy, nonatomic) NSString *process;
28+
@property (readonly, nonatomic) int processID;
29+
@property (readonly, copy, nonatomic) NSString *processImagePath;
30+
@property (readonly, copy, nonatomic) NSUUID *processImageUUID;
31+
@property (readonly, nonatomic) NSUInteger processUniqueID;
32+
@property (readonly, copy, nonatomic) NSString *sender;
33+
@property (readonly, copy, nonatomic) NSString *senderImagePath;
34+
@property (readonly, copy, nonatomic) NSUUID *senderImageUUID;
35+
@property (readonly, nonatomic) NSUInteger threadID;
36+
@property (readonly, nonatomic) struct timeval timeGMT;
37+
@property (readonly, copy, nonatomic) NSDate *timestamp;
38+
@property (readonly, copy, nonatomic) NSTimeZone *timezone;
39+
@property (retain, nonatomic) NSString *timezoneName;
40+
@property (readonly, nonatomic) NSUInteger traceID;
41+
@property (readonly, nonatomic) struct timezone tz;
42+
43+
-(BOOL)persisted;
44+
-(id)description;
45+
-(id)properties;
46+
-(void)_addProperties:(id)arg0 ;
47+
-(id)_initWithProperties:(id)arg0;
48+
49+
@end
50+
51+
NS_ASSUME_NONNULL_END
52+
53+
54+
/// A subclass of OSActivityEvent,
55+
/// with additional fields suitable for an informational log message.
56+
@interface OSActivityLogMessageEvent : OSActivityEvent
57+
58+
@property (readonly, copy, nonatomic) NSString * _Nullable category;
59+
@property (readonly, nonatomic) unsigned char messageType;
60+
@property (readonly, nonatomic) NSUInteger senderProgramCounter;
61+
@property (readonly, copy, nonatomic) NSString * _Nullable subsystem;
62+
63+
-(instancetype _Nonnull)initWithEntry:(struct os_activity_stream_entry_s * _Nonnull)arg0 ;
64+
//-(void)_addProperties:(id)arg0 ;
65+
66+
@end
67+
68+
#define OS_ACTIVITY_MAX_CALLSTACK 32
69+
70+
// Enums
71+
enum {
72+
OS_ACTIVITY_STREAM_TYPE_ACTIVITY_CREATE = 0x0201,
73+
OS_ACTIVITY_STREAM_TYPE_ACTIVITY_TRANSITION = 0x0202,
74+
OS_ACTIVITY_STREAM_TYPE_ACTIVITY_USERACTION = 0x0203,
75+
76+
OS_ACTIVITY_STREAM_TYPE_TRACE_MESSAGE = 0x0300,
77+
78+
OS_ACTIVITY_STREAM_TYPE_LOG_MESSAGE = 0x0400,
79+
OS_ACTIVITY_STREAM_TYPE_LEGACY_LOG_MESSAGE = 0x0480,
80+
81+
OS_ACTIVITY_STREAM_TYPE_SIGNPOST_BEGIN = 0x0601,
82+
OS_ACTIVITY_STREAM_TYPE_SIGNPOST_END = 0x0602,
83+
OS_ACTIVITY_STREAM_TYPE_SIGNPOST_EVENT = 0x0603,
84+
85+
OS_ACTIVITY_STREAM_TYPE_STATEDUMP_EVENT = 0x0A00,
86+
};
87+
typedef uint32_t os_activity_stream_type_t;
88+
89+
// Types
90+
91+
typedef uint64_t os_activity_id_t;
92+
typedef struct os_activity_stream_s *os_activity_stream_t;
93+
typedef struct os_activity_stream_entry_s *os_activity_stream_entry_t;
94+
95+
#define OS_ACTIVITY_STREAM_COMMON() \
96+
uint64_t trace_id; \
97+
uint64_t timestamp; \
98+
uint64_t thread; \
99+
const uint8_t *image_uuid; \
100+
const char *image_path; \
101+
struct timeval tv_gmt; \
102+
struct timezone tz; \
103+
uint32_t offset
104+
105+
typedef struct os_activity_stream_common_s {
106+
OS_ACTIVITY_STREAM_COMMON();
107+
} * os_activity_stream_common_t;
108+
109+
struct os_activity_create_s {
110+
OS_ACTIVITY_STREAM_COMMON();
111+
const char *name;
112+
os_activity_id_t creator_aid;
113+
uint64_t unique_pid;
114+
};
115+
116+
struct os_activity_transition_s {
117+
OS_ACTIVITY_STREAM_COMMON();
118+
os_activity_id_t transition_id;
119+
};
120+
121+
typedef struct os_log_message_s {
122+
OS_ACTIVITY_STREAM_COMMON();
123+
const char *format;
124+
const uint8_t *buffer;
125+
size_t buffer_sz;
126+
const uint8_t *privdata;
127+
size_t privdata_sz;
128+
const char *subsystem;
129+
const char *category;
130+
uint32_t oversize_id;
131+
uint8_t ttl;
132+
bool persisted;
133+
} * os_log_message_t;
134+
135+
typedef struct os_trace_message_v2_s {
136+
OS_ACTIVITY_STREAM_COMMON();
137+
const char *format;
138+
const void *buffer;
139+
size_t bufferLen;
140+
xpc_object_t __unsafe_unretained payload;
141+
} * os_trace_message_v2_t;
142+
143+
typedef struct os_activity_useraction_s {
144+
OS_ACTIVITY_STREAM_COMMON();
145+
const char *action;
146+
bool persisted;
147+
} * os_activity_useraction_t;
148+
149+
typedef struct os_signpost_s {
150+
OS_ACTIVITY_STREAM_COMMON();
151+
const char *format;
152+
const uint8_t *buffer;
153+
size_t buffer_sz;
154+
const uint8_t *privdata;
155+
size_t privdata_sz;
156+
const char *subsystem;
157+
const char *category;
158+
uint64_t duration_nsec;
159+
uint32_t callstack_depth;
160+
uint64_t callstack[OS_ACTIVITY_MAX_CALLSTACK];
161+
} * os_signpost_t;
162+
163+
typedef struct os_activity_statedump_s {
164+
OS_ACTIVITY_STREAM_COMMON();
165+
char *message;
166+
size_t message_size;
167+
char image_path_buffer[PATH_MAX];
168+
} * os_activity_statedump_t;
169+
170+
struct os_activity_stream_entry_s {
171+
os_activity_stream_type_t type;
172+
173+
// information about the process streaming the data
174+
pid_t pid;
175+
uint64_t proc_id;
176+
const uint8_t *proc_imageuuid;
177+
const char *proc_imagepath;
178+
179+
// the activity associated with this streamed event
180+
os_activity_id_t activity_id;
181+
os_activity_id_t parent_id;
182+
183+
union {
184+
struct os_activity_stream_common_s common;
185+
struct os_activity_create_s activity_create;
186+
struct os_activity_transition_s activity_transition;
187+
struct os_log_message_s log_message;
188+
struct os_trace_message_v2_s trace_message;
189+
struct os_activity_useraction_s useraction;
190+
struct os_signpost_s signpost;
191+
struct os_activity_statedump_s statedump;
192+
};
193+
};
194+
195+
// Blocks
196+
197+
typedef bool (^os_activity_stream_block_t)(os_activity_stream_entry_t entry,
198+
int error);
199+
200+
#endif /* OSActivityLogMessageEvent_h */
201+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//
2+
// ActivityStream.swift
3+
//
4+
//
5+
// Created by Wouter Hennen on 22/05/2023.
6+
//
7+
8+
/// Options for configuring the behavior of an activity stream.
9+
public struct ActivityStreamOptions: OptionSet {
10+
public let rawValue: UInt32
11+
12+
public init(rawValue: UInt32) {
13+
self.rawValue = rawValue
14+
}
15+
}
16+
17+
public extension ActivityStreamOptions {
18+
static let processOnly = ActivityStreamOptions(rawValue: 1 << 0)
19+
static let skipDecode = ActivityStreamOptions(rawValue: 1 << 1)
20+
static let payload = ActivityStreamOptions(rawValue: 1 << 2)
21+
static let historical = ActivityStreamOptions(rawValue: 1 << 3)
22+
static let callStack = ActivityStreamOptions(rawValue: 1 << 4)
23+
static let debug = ActivityStreamOptions(rawValue: 1 << 5)
24+
static let buffered = ActivityStreamOptions(rawValue: 1 << 6)
25+
static let noSensitive = ActivityStreamOptions(rawValue: 1 << 7)
26+
static let info = ActivityStreamOptions(rawValue: 1 << 8)
27+
static let promiscuous = ActivityStreamOptions(rawValue: 1 << 9)
28+
static let preciseTimestamps = ActivityStreamOptions(rawValue: 1 << 9)
29+
}

Sources/LogStream/LogMessage.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// LogMessage.swift
3+
//
4+
//
5+
// Created by Wouter Hennen on 22/05/2023.
6+
//
7+
8+
import OSLog
9+
10+
/// Represents a log message captured from the activity logs.
11+
public struct LogMessage {
12+
/// The log message string.
13+
public let message: String
14+
15+
/// The date and time when the log message was captured.
16+
public let date: Date
17+
18+
/// The subsystem associated with the log message, if available.
19+
public let subsystem: String?
20+
21+
/// The category associated with the log message, if available.
22+
public let category: String?
23+
24+
/// The type of the log message, indicating its severity level.
25+
public let type: OSLogType
26+
27+
/// The name of the process that generated the log message.
28+
public let process: String
29+
30+
/// The process identifier (PID) of the process that generated the log message.
31+
public let processID: pid_t
32+
}

0 commit comments

Comments
 (0)