Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add battery IORegistry and sysmontap cpuusage #475

Merged
merged 11 commits into from
Nov 5, 2024

Conversation

kvs-coder
Copy link
Contributor

No description provided.

Copy link
Owner

@danielpaulus danielpaulus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kvs-coder do you need some help with it or why is it drafT? :-D

@kvs-coder
Copy link
Contributor Author

kvs-coder commented Oct 14, 2024

@kvs-coder do you need some help with it or why is it drafT? :-D

hey @danielpaulus

it is draft because I started working on this, but then needed to switch context, and then had vacation :D

I'm resuming working on this to provide the possibility to read device's stats (like Xcode does, but without beautiful visual representation, just cold numbers)

If you have already some insights regarding this, I'm all ears :)

@kvs-coder kvs-coder changed the title Draft: sysmontap Draft: Battery temperature Oct 17, 2024
@fish-sauce fish-sauce force-pushed the vk-sysmontap branch 2 times, most recently from b94c3df to 0260f48 Compare October 18, 2024 13:21
@kvs-coder kvs-coder changed the title Draft: Battery temperature Add Battery IORegistry Oct 18, 2024
@fish-sauce fish-sauce force-pushed the vk-sysmontap branch 4 times, most recently from 3599c87 to 1ada922 Compare October 23, 2024 14:45
@kvs-coder kvs-coder changed the title Add Battery IORegistry Add battery IORegistry and sysmontap cpuusage Oct 23, 2024
ios/instruments/instruments_sysmontap.go Outdated Show resolved Hide resolved
ios/dtx_codec/channel.go Outdated Show resolved Hide resolved
ios/instruments/instruments_deviceinfo.go Outdated Show resolved Hide resolved
main.go Outdated Show resolved Hide resolved
ios/instruments/instruments_sysmontap.go Outdated Show resolved Hide resolved
Comment on lines 158 to 163
if msg.PayloadHeader.MessageType == UnknownTypeOne {
d.mutex.Unlock()
d.messageReceiver.msgChannel <- msg

return
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dispatcher implementations are getting those messages already atm, and we would change that with this filter here. Lets continue to send them to the Dispatcher, in our case now the GlobalDispatcher.

Since GlobalDispatcher only handles very few messages, we would need something that forwards it from there, or allow to pass in a custom Dispatcher for the global channel

Copy link
Contributor Author

@kvs-coder kvs-coder Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

according to the logs, it doesn't look like that it handles few messages, it is enormous amount of them, I tried already putting the logic in GlobalDispatcher only :D

it results in the problem here:

1 136 129 1 137 129 1 138 129 1 139 129 1 140 129 1 141 129 1 142 129 1 143 129 1 144 129 1 145 129 1 146 129 1 147 129 1 148 129 1 149 129 1 150 129 1 151 129 1 152 129 1 153 129 1 154 129 1 155 129 1 156 129 1 157 129 1 158 129 1 159 129 1 160 129 1 161 129 1 162 129 1 163 129 1 164 129 1 165 129 1 166 129 1 167 129 1 168 129 1 169 129 1 170 129 1 171 129 1 172 129 1 173 129 1 174 129 1 175 129 1 176 129 1 177 129 1 178 129 1 179 129 1 180 129 1 181 129 1  216 3 217 3 218 3 219 3 220 3 221 3 222 3 223 3 224 3 225 3 226 3 227 3 228 3 229 3 230 3 231 3 232 3 233 3 234 3 235 3 236 3 237 3 238 3 239 3 240 3 241 3 242 3 243 3 244 3 245 3 246 3 247 3 248 3 249 3 250 3 251 3 252 3 253 3 254 3 255 4 0 4 1 4 2 4  0 0 0 0 0 0 4 2 0 0 0 0 0 0 126 189 0 0 0 0 0 0 0 0 0 0 0 0 0 2 200 208]","level":"fatal","msg":"Start call error","time":"2024-11-01T10:09:30-05:00"}

you generally receive infinite bytes stream and then ends up with the error. That is why I provided the solution as it is now in the MR :)

I checked, with this current code, it has no negative effect on our side executions as this sysmontap gets only desired message and then we close the connection and the channel

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked, with this current code, it has no negative effect on our side executions as this sysmontap gets only desired message and then we close the connection and the channel

Since UnknownTypeOne was added during the work of XCUITest for iOS 17 I strongly assume that a message with that type is sometimes sent during a test execution. And if that happens, we would block here forever as d.messageReceiver.msgChannel is nil. Pretty much any occasion of a message of that type would block forever, unless something calls Channel.Receive, but that would also only help on the global channel.

That problem is solved with having it in the Dispatcher interface as unhandled messages are only thrown away there.

We would need something in this method

func (g GlobalDispatcher) Dispatch(msg Message) {
that forwards the messages that were not handled in this method to another Dispatcher (or allow to set a customer Dispatcher on the global channel)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright, the latest commit should safely avoid potential issues with XCTests

@fish-sauce fish-sauce force-pushed the vk-sysmontap branch 2 times, most recently from eb5b7d4 to 5785d14 Compare November 4, 2024 21:54
)

type sysmontapMsgDispatcher struct {
channel chan dtx.Message
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
channel chan dtx.Message
messages chan dtx.Message


// Close closes up the DTX connection
func (s *sysmontapService) Close() error {
return s.conn.Close()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return s.conn.Close()
close(s.msgDispatcher.messages)
return s.conn.Close()

return SysmontapMessage{}, err
}

for {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you only want to read a single value here the for loop isn't needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfortunately I really need this loop, as I previously highlighted, the global channel is like a garbage can and a lot of messages come there. The very first message is not addressing to the CPU data. If I remove the loop, the method just returns SysmontapMessage{}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah right, missed the continue in there

Comment on lines 69 to 70
case <-time.After(30 * time.Second):
return SysmontapMessage{}, fmt.Errorf("exceeded waiting time message")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timeout is not necessary. As long as the connection is alive, we should simply wait for a value here. And by adding the close for the channel from a comment above we can change case msg := <-s.msgDispatcher.channel: to case msg, ok := <-s.msgDispatcher.channel: and then the read would immediately return after the close with ok: false

Comment on lines 30 to 52
func (s *systemMonitor) GetCPUUsage() (SysmontapMessage, error) {
sysAttrs, err := s.deviceInfoService.systemAttributes()
if err != nil {
return SysmontapMessage{}, err
}

procAttrs, err := s.deviceInfoService.processAttributes()
if err != nil {
return SysmontapMessage{}, err
}

err = s.sysmontapService.setConfig(procAttrs, sysAttrs)
if err != nil {
return SysmontapMessage{}, err
}

sysmontapMsg, err := s.sysmontapService.start()
if err != nil {
return SysmontapMessage{}, err
}

return sysmontapMsg, nil
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has still the same problem as the version from last week or so. To get a single CPU sample all this setup has to be done. How do you get a second sample without doing this again? As I mentioned in the older comment, you should be able to get a continuous stream of CPU samples on a single connection, not just one.

Why not move this to NewSystemMonitor? Without that being successful the systemMonitor can't do anything, right? Then we can do this as part of creating it. And the call err := s.channel.MethodCallAsync("start") should also happen there then.

Comment on lines 30 to 52
}

// Creates a new sysmontapService
func newSysmontapService(device ios.DeviceEntry) (*sysmontapService, error) {
msgDispatcher := newSysmontapMsgDispatcher()
dtxConn, err := connectInstrumentsWithMsgDispatcher(device, msgDispatcher)
if err != nil {
return nil, err
}

processControlChannel := dtxConn.RequestChannelIdentifier(sysmontapName, loggingDispatcher{dtxConn})

return &sysmontapService{channel: processControlChannel, conn: dtxConn, msgDispatcher: msgDispatcher}, nil
}

// Close closes up the DTX connection
func (s *sysmontapService) Close() error {
return s.conn.Close()
}

// start sends a start method call async and waits until the cpu info & stats come back
// the method is a part of the @protocol DTTapAuthorizedAPI
func (s *sysmontapService) start() (SysmontapMessage, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The important part here is not that start is getting sent (which shouldn't happen here anyways as mentioned in the comment about creating the systemMonitor), you are reading a sample, or message. That's what should be in the name


import "github.com/danielpaulus/go-ios/ios"

type systemMonitor struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for a separate type? Both, systemMonitor and sysmontapService contain something about CPU samples

// Dispatch prints log messages and errors when they are received and also creates local Channels when requested by the device.
func (g GlobalDispatcher) Dispatch(msg Message) {
SendAckIfNeeded(g.dtxConnection, msg)
if msg.Payload != nil {
if requestChannel == msg.Payload[0] {
g.requestChannelMessages <- msg
}
if msg.PayloadHeader.MessageType == UnknownTypeOne {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would simply move this at the end of this method without any further checks, everything that was not handled here already gets forwarded. If the receiver of this only needs a specific type of messages, it should discard them itself

ios/instruments/instruments_sysmontap.go Outdated Show resolved Hide resolved
func (dtxConn *Connection) Dispatch(msg Message) {
msgDispatcher := dtxConn.MessageDispatcher
if msgDispatcher != nil {
log.Debugf("msg dispatcher found: %v", reflect.TypeOf(msgDispatcher))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a format specifier that you can use so that you don't have to go through the reflect library

Suggested change
log.Debugf("msg dispatcher found: %v", reflect.TypeOf(msgDispatcher))
log.Debugf("msg dispatcher found: %T", msgDispatcher)

@diegoperini diegoperini merged commit 1789ded into danielpaulus:main Nov 5, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants