Logs that show size of upload

Is there a log somewhere that tells me how many bytes my upload of a new app contains? To be more specific, the build tool tells me the size of the image, but I have heard that only the delta is actually sent over the air for an update. Is there a way to see how many bytes of data are actually sent on an update? Thanks.

Hey, I actually put together a script for this, not too long ago:

release1 = <OLD_RELEASE_ID>
release2 = <NEW_RELEASE_ID>

sdk.pine.get({
    resource: 'release',
    options: {
        $filter: {
            id:{ $in: [ release1, release2 ]},
        },
        $orderby: 'id asc',
        $expand: {
            image__is_part_of__release: {
                $select: 'id',
                $expand: {
                    image: {
                        $select: [
                            'id'
                        ],
                        $expand: {
                            is_a_build_of__service: {
                                $select: 'service_name'
                            }
                        }
                    }
                }
            }
        }
    }
}).then(([r1, r2]) => {
    r1services = { }
    _.each(r1.image__is_part_of__release, (ipr) => {
        r1services[ ipr.image[0].is_a_build_of__service[0].service_name] = ipr.image[0].id;
    })
    r2services = { }
    _.each(r2.image__is_part_of__release, (ipr) => {
        r2services[ ipr.image[0].is_a_build_of__service[0].service_name] = ipr.image[0].id;
    })

    deltaSizes = { }
    return Promise.all(_.map(r1services, (id, name) => { 
        return sdk.pine.get({ resource: 'delta', options: { $filter: { originates_from__image: id, produces__image: r2services[name] }, $select: 'size' } }).then(([ img ]) => { if (img != null) { deltaSizes[name] = img.size } else { deltaSizes[name] = 0 }});
    })).then(() => console.log(deltaSizes))
})

Replace the releaseIds with the one currently running on a device, and the one you want to move to, and execute this in the developer console whilst on the dashboard (so that your permissions are automatically loaded).

Let me know if you need any further help!

1 Like

Hi thanks for sharing the script. Sorry it took me so long to get around to trying it. I am not sure what you mean by “execute this in the developer console”. Could you further clarify? I am on a mac, I do have node installed. I use npm to install the balena cli. I have been using the cli to login, and also to git push balena to my devices. Thats about all I know about using the developer console. I copied your script into a local file and named it delta-size.js. I am not sure what to do from here. Can you show me a screen shot of how to execute from the command line? Thanks very much.

Hi @chetferry. You can run the above from the developer console of your browser. Just log in to the dashboard.balena-cloud.com with your account, then open the developer console. Some more info for doing that on:

Getting

vendor~scripts.ce8d4690c4b150510932.chunk.js:87 Unhandled rejection e: Request error: Database error    at https://dashboard.balena-cloud.com/vendor~scripts.ce8d4690c4b150510932.chunk.js:87:266672

I’m logged into my dashboard and on the page of the application I’m interested in, I’m in Brave Browser which is Chromium based.

I’ve tried both the short and the full release id.

@cnr it sounds like you’re possibly not using the correct ID; the one to use for this command is the one from the end of the URL when you’re on the page in the dashboard for that release. It will be a number only (not alphanumeric). Let me know if this helps!

1 Like

Ahhh, gotcha.

Yes, that worked, I think. It returns “2499524”, is that bits or bytes? OP asked for bytes, but just want to make sure.

Can you disambiguate the two release identifiers for me?

The long release number is the release git commit level, and the release id is how balenaCloud keeps track of it on your side?

@cnr my colleague and I working right now are reasonably sure that it’s bytes, but we can ping someone from the API team to double check if you’d like.

You’re right about the release identifiers!

1 Like

Cool, accurate by a factor of 8 is good enough for right now, but it would be good to be confident in the future :slight_smile: Thanks!

@cnr we have confirmed that it’s bytes

1 Like

This script is no longer working for me.

I run this:

release1 = 1047872
release2 = 1073973

sdk.pine.get({
    resource: 'release',
    options: {
        $filter: {
            id:{ $in: [ release1, release2 ]},
        },
        $orderby: 'id asc',
        $expand: {
            image__is_part_of__release: {
                $select: 'id',
                $expand: {
                    image: {
                        $select: [
                            'id'
                        ],
                        $expand: {
                            is_a_build_of__service: {
                                $select: 'service_name'
                            }
                        }
                    }
                }
            }
        }
    }
}).then(([r1, r2]) => {
    r1services = { }
    _.each(r1.image__is_part_of__release, (ipr) => {
        r1services[ ipr.image[0].is_a_build_of__service[0].service_name] = ipr.image[0].id;
    })
    r2services = { }
    _.each(r2.image__is_part_of__release, (ipr) => {
        r2services[ ipr.image[0].is_a_build_of__service[0].service_name] = ipr.image[0].id;
    })

    deltaSizes = { }
    return Promise.all(_.map(r1services, (id, name) => { 
        return sdk.pine.get({ resource: 'delta', options: { $filter: { originates_from__image: id, produces__image: r2services[name] }, $select: 'size' } }).then(([ img ]) => { if (img != null) { deltaSizes[name] = img.size } else { deltaSizes[name] = 0 }});
    })).then(() => console.log(deltaSizes))
})

And the error messages are:

D {_bitField: 0, _fulfillmentHandler0: undefined, _rejectionHandler0: undefined, _promise0: undefined, _receiver0: undefined, …}
_bitField: 67108864
_fulfillmentHandler0: undefined
_promise0: undefined
_receiver0: undefined
_rejectionHandler0: D
_bitField: 167772160
_fulfillmentHandler0: undefined
_promise0: undefined
_receiver0: undefined
_rejectionHandler0: undefined
_trace: at
_length: 2
_parent: at
_length: 1
_parent: undefined
_promiseCreated: null
_promisesCreated: 0
stack: "Error↵    at D.N [as _captureStackTrace] (https://dashboard.balena-cloud.com/vendor~scripts.2d58fac16bc96cdc9290.chunk.js:31:36179)↵    at D._then (https://dashboard.balena-cloud.com/vendor~scripts.2d58fac16bc96cdc9290.chunk.js:31:62143)↵    at D.then (https://dashboard.balena-cloud.com/vendor~scripts.2d58fac16bc96cdc9290.chunk.js:31:60493)↵    at <anonymous>:29:4"
__proto__: Error
_promiseCreated: null
_promisesCreated: 0
stack: "Error↵    at D.N [as _captureStackTrace] (https://dashboard.balena-cloud.com/vendor~scripts.2d58fac16bc96cdc9290.chunk.js:31:36179)↵    at D._then (https://dashboard.balena-cloud.com/vendor~scripts.2d58fac16bc96cdc9290.chunk.js:31:62143)↵    at D.then (https://dashboard.balena-cloud.com/vendor~scripts.2d58fac16bc96cdc9290.chunk.js:31:60493)↵    at <anonymous>:42:9↵    at l (https://dashboard.balena-cloud.com/vendor~scripts.2d58fac16bc96cdc9290.chunk.js:31:93728)↵    at D._settlePromiseFromHandler (https://dashboard.balena-cloud.com/vendor~scripts.2d58fac16bc96cdc9290.chunk.js:31:66688)↵    at D._settlePromise (https://dashboard.balena-cloud.com/vendor~scripts.2d58fac16bc96cdc9290.chunk.js:31:67488)↵    at D._settlePromise0 (https://dashboard.balena-cloud.com/vendor~scripts.2d58fac16bc96cdc9290.chunk.js:31:68187)↵    at D._settlePromises (https://dashboard.balena-cloud.com/vendor~scripts.2d58fac16bc96cdc9290.chunk.js:31:69539)↵    at https://dashboard.balena-cloud.com/vendor~scripts.2d58fac16bc96cdc9290.chunk.js:31:22651"
__proto__: Error
attachExtraTrace: ƒ (t)
arguments: (...)
caller: (...)
length: 1
name: ""
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: vendor~scripts.2d58f…cdc9290.chunk.js:31
[[Scopes]]: Scopes[5]
constructor: ƒ at(t)
arguments: (...)
caller: (...)
length: 1
name: "at"
prototype: Error {constructor: ƒ, constructor$: ƒ, uncycle: ƒ, attachExtraTrace: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: vendor~scripts.2d58f…cdc9290.chunk.js:31
[[Scopes]]: Scopes[5]
constructor$: ƒ Error()
stackTraceLimit: 50
arguments: (...)
caller: (...)
captureStackTrace: ƒ captureStackTrace()
length: 1
name: "Error"
prototype: {name: "Error", message: "", constructor: ƒ, toString: ƒ}
__BluebirdErrorTypes__: {CancellationError: ƒ, TimeoutError: ƒ, OperationalError: ƒ, RejectionError: ƒ, AggregateError: ƒ}
__proto__: ƒ ()
[[Scopes]]: Scopes[0]
uncycle: ƒ ()
arguments: (...)
caller: (...)
length: 0
name: ""
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: vendor~scripts.2d58f…cdc9290.chunk.js:31
[[Scopes]]: Scopes[5]
__proto__: Object
Symbol(Symbol.toStringTag): (...)
__proto__: Object
_trace: at {_parent: undefined, _promisesCreated: 0, _length: 1, _promiseCreated: null, stack: "Error↵    at D.N [as _captureStackTrace] (https://…dc9290.chunk.js:31:60493)↵    at <anonymous>:29:4"}
Symbol(Symbol.toStringTag): (...)
__proto__: Object

and

{dame_gothel: 0}
dame_gothel: 0
__proto__:
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()

Hi @cnr , the first stack trace you provided is simply the unresolved promise being printed, this is a common pattern in most browser consoles where the result of the last statement is printed as if you had run console.log. The second trace is the result of the final console.log(deltaSizes). Since the value is zero it seems that there might not be any available deltas. Could you run await sdk.pine.get({ resource: 'delta' }) and post the results here?

I don’ know why, but it wouldn’t let me upload the logs, here they are from a while ago

dashboard.balena-cloud.com-1569346605557.log (35.2 KB)

Hey, are you sure a delta has been calculated between the two images you are checking for? The delta will only be calculated on-demand when a device actually requests it

Ah, well that’s a problem for me. How do I know how big an update will be before I release it if I first have to release it?

@cnr I think the approach would be disable rolling releases on your app and then use the pinning API, this would allow you to push the image with out having to actually release it to devices. Then the other side of the puzzle would be to construct an API call that requests a delta between the currently “pinned” release and the “latest” release. Once the delta is generated then you can query the size.

I am trying to find out from our API engineers on the best way to construct the API call to request a delta between two images, when I have that I will post it here :slight_smile:

1 Like

Yeah, I’ve switched almost completely over to pinning the releases, so that would work for me.

In the interim, maybe I need to set up a ‘Test’ device locally, push the initial version to it, then push new version to that device only, then it will be forced to calculate the delta and I can subsequently query it with Cameron’s script.

Okay, so I think this is the way I would go:

  1. disable rolling release
  2. push a new release
  3. trigger delta between pinned release and latest. This can be done using the API call: https://delta.balena-cloud.com/api/v2/delta?src=<SRC_IMG>&dest=<DEST_IMG> where <SRC_IMG> is the source/pinned release image ID (or name) and <DEST_IMG> is the “latest” image.
  4. get update delta size using Camerons script (probably on some poll interval as the delta will take a minute or more to generate).

Your approach with a test device is also a pretty good way to go. Let me know if you need clarification on any of the above

1 Like

Huh, not working for me.

I’m calling the API with:
curl "https://delta.$BASE_URL/api/v2/delta?src=1047872&dest=1092753" -H "Authorization: Bearer $authToken"

I waited 2 hours and I received a delta of 0 (the difference is definitely not 0)

My authToken is working with all other commands, I tried the src and dest commands both ways, and I even tried switching out the delta.balena-cloud.com with api.balena-cloud.com, none of these worked.

Wondering what I’m doing wrong. Thank you again for all the help :slight_smile:

Hi,
This call curl "https://delta.$BASE_URL/api/v2/delta?src=1047872&dest=1092753" -H "Authorization: Bearer $authToken" only triggers the delta generation. The script from above can be run once this finishes and this should then produce the size. I can confirm that the delta for this request was generated and with the script you should be to see the size of this delta.

1 Like