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

New solution to send phone logs to the developer #609

Closed
shankari opened this issue Jan 30, 2021 · 36 comments
Closed

New solution to send phone logs to the developer #609

shankari opened this issue Jan 30, 2021 · 36 comments

Comments

@shankari
Copy link
Contributor

Right now, we have functionality to send phone logs to the developer (me).
This has the advantage of using a mechanism that is separate from the app itself so it works even if the login is broken or the server is down.
However, recently, I have found a couple of problems:

  • on iOS, if the user uses gmail instead of the mail app, this won't work
  • on android, if the file attachment is too large, this won't work. There used to be an option to save to drive, but that appears to have changed in the most recent versions. In particular, this was working a year ago on a phone where it is not working now.

And of course, it is also dependent on one developer and her email. There is no way to share the load between multiple members of a team, for example. We may want to use an alternate technique to upload the logs.

@shankari
Copy link
Contributor Author

shankari commented Jan 30, 2021

Several options:

  • set up a custom email address which will create an issue on GitHub (e.g. https://fire.fundersclub.com/)
    • this still has the size limit and the email app limitations of the current email-based solution
  • create an issue directly on GitHub from the app using the GitHub API
    • requires GitHub account
    • requiring end users to have GitHub accounts is a non-starter
    • we could potentially embed an access token into the app, but will need to figure out if it is possible to disassemble the app to retrieve it
      • Any user with pull access to a repository can create an issue. But I can't figure out how to give an access token pull access only, it seems like we can only give full access
      • there is an option to give an access token permission to "Create gists" only.
        • this might work, because I don't care that much if people create too many gists, I can just invalidate the token
        • BUT, this would also put user logs into a third party service; which means that I would need to encrypt them for safety.
        • That might actually work. Embed a public key into the app, encrypt and upload to a public file sharing service such as https://ufile.io/ or https://www.filebin.ca/ or https://easyupload.io/ or https://psty.io
  • set up a custom uploader that we run

@shankari
Copy link
Contributor Author

After considering those options, it looks like the main options are:

  1. store encrypted data on a public upload server, or
  2. store unencrypted data on an internal upload server

The advantage with (1) is that it will work even if our server is down. For the record, we would probably want to use WebCrypto with the Cloud Storage option (https://www.w3.org/TR/WebCryptoAPI/#cloud-storage). And we would get started on actually supported keyfiles in the app. However, it is a fairly complex change for what is a 10% use case.

The advantage with (2) is that we can implement it very easily - just launch a new docker container. And we could fairly easily do some automation on the backend to automatically file issues on GitHub when a new entry is received.

@shankari
Copy link
Contributor Author

Jose (https://jose.readthedocs.io/en/latest/) is a wrapper that supports encryption/decryption. There's a nice npm package for it https://www.npmjs.com/package/jose

So maybe this is not too hard after all?

@shankari
Copy link
Contributor Author

Implementing this will also allow us to make progress with #599

@shankari
Copy link
Contributor Author

Ran into problems with uploading from another iOS user as well, tried multiple times to get them to send - email never arrived.

@shankari
Copy link
Contributor Author

The flask code for https://github.com/psty-io/psty-api/ seems fairly straightforward.

  • We can remove all server routes other than upload-file
  • on the phone, we should be able to post the file directly, but can also switch to a "choose file" button to make things easier for now since we can then copy their client code over directly.

@shankari
Copy link
Contributor Author

Alas, using a file input by default does not work. The 'choose file' dialog is displayed correctly, but when selecting it, it just chooses files outside the app (e.g. from downloads)

Select file Pops up a file chooser for external files only
Screenshot_1612069594 Screenshot_1612069598 Screenshot_1612069601

@shankari
Copy link
Contributor Author

shankari commented Jan 31, 2021

It looks like it is very difficult to read the application storage directory, at least on android through the cordova file plugin

Adding some code to browse through directories:

        const listEntries = function(localFs) {
            window.resolveLocalFileSystemURL(localFs, function(fs) {
                    const reader = fs.filesystem.root.createReader();
                    reader.readEntries(function(entries) {
                        console.log("Directory listing for filesystem: "+localFs);
                        console.log(fs);
                        console.log(entries);
                        if (entries.length > 0) {
                        const fileReader = entries[0].createReader();
                        fileReader.readEntries(function(entries) {
                            console.log(entries);
                        }, onError);
                        }
                    }, onError);
            });
        }

and trying

                listEntries(cordova.file.applicationDirectory);
                listEntries(cordova.file.applicationStorageDirectory);
                listEntries(cordova.file.dataDirectory);
                listEntries(cordova.file.externalCacheDirectory);

we get

file:///storage/emulated/0/Android/data/edu.berkeley.eecs.emission.devapp/cache/
isDirectory: true, name: "email_composer", fullPath: "/email_composer/",
isFile: true, name: "loggerDB", fullPath: "/email_composer/loggerDB",

file:///data/user/0/edu.berkeley.eecs.emission.devapp/
isDirectory: true, name: "edu.berkeley.eecs.emission.devapp", fullPath: "/data/user/0/edu.berkeley.eecs.emission.devapp/",
no files

file:///android_asset/
isFile: false, isDirectory: true, name: "", fullPath: "/",
55 file entries

file:///data/user/0/edu.berkeley.eecs.emission.devapp/files/
isFile: false, isDirectory: true, name: "", fullPath: "/",

[DirectoryEntry, DirectoryEntry, DirectoryEntry]
DirectoryEntry {isFile: false, isDirectory: true, name: "files", fullPath: "/files/", filesystem: FileSystem, …}
DirectoryEntry {isFile: false, isDirectory: true, name: "Documents", fullPath: "/Documents/", filesystem: FileSystem, …}
DirectoryEntry {isFile: false, isDirectory: true, name: "phonegapdevapp", fullPath: "/phonegapdevapp/", filesystem: FileSystem, …}

the file:///data/user/0/edu.berkeley.eecs.emission.devapp/files/ filesystem is clearly correct and shows all the directories.
so the file:///data/user/0/edu.berkeley.eecs.emission.devapp/ filesystem, but appended with a databases should give us what we ant. But it seems to have a weird fullpath and it doesn't show any entries under it.

Screen Shot 2021-01-31 at 9 42 50 AM

@shankari
Copy link
Contributor Author

This seems to be a subtle issue with the way that the filesystems are registered.

Note the difference in the rootUri across working and not working.
Let's see if we can leverage the working by using getParent

1 = {LocalFilesystem@6544} 
 context = {MainActivity@6553} 
 name = "persistent"
 resourceApi = {CordovaResourceApi@6555} 
 rootEntry = {JSONObject@6563} "{"isFile":false,"isDirectory":true,"name":"","fullPath":"\/","filesystemName":"persistent","filesystem":1,"nativeURL":"file:\/\/\/data\/user\/0\/edu.berkeley.eecs.emission.devapp\/files\/files\/"}"
 rootUri = {Uri$HierarchicalUri@6564} "file:///data/user/0/edu.berkeley.eecs.emission.devapp/files/files/"
 shadow$_klass_ = {Class@5735} "class org.apache.cordova.file.LocalFilesystem"
 shadow$_monitor_ = -1954005257
4 = {LocalFilesystem@6547} 
 context = {MainActivity@6553} 
 name = "files"
 resourceApi = {CordovaResourceApi@6555} 
 rootEntry = {JSONObject@6582} "{"isFile":false,"isDirectory":true,"name":"","fullPath":"\/","filesystemName":"files","filesystem":1,"nativeURL":"file:\/\/\/data\/user\/0\/edu.berkeley.eecs.emission.devapp\/files\/"}"
 rootUri = {Uri$HierarchicalUri@6583} "file:///data/user/0/edu.berkeley.eecs.emission.devapp/files/"
 shadow$_klass_ = {Class@5735} "class org.apache.cordova.file.LocalFilesystem"
 shadow$_monitor_ = -1959718782
10 = {LocalFilesystem@6532} 
 context = {MainActivity@6553} 
 name = "root"
 resourceApi = {CordovaResourceApi@6555} 
 rootEntry = {JSONObject@6618} "{"isFile":false,"isDirectory":true,"name":"","fullPath":"\/","filesystemName":"root","filesystem":1,"nativeURL":"file:\/\/\/"}"
 rootUri = {Uri$HierarchicalUri@6534} "file:///"
 shadow$_klass_ = {Class@5735} "class org.apache.cordova.file.LocalFilesystem"
 shadow$_monitor_ = -2112832605

@shankari
Copy link
Contributor Author

So this is because of this code:

uriString = file:///data/user/0/edu.berkeley.eecs.emission.devapp/
inputURL = {LocalFilesystemURL@7220} "cdvfile://localhost/root/data/user/0/edu.berkeley.eecs.emission.devapp/"
 fsName = "root"
 isDirectory = true
 path = "/data/user/0/edu.berkeley.eecs.emission.devapp/"
 uri = {Uri$HierarchicalUri@7226} "cdvfile://localhost/root/data/user/0/edu.berkeley.eecs.emission.devapp/"
 shadow$_klass_ = {Class@5633} "class org.apache.cordova.file.LocalFilesystemURL"
 shadow$_monitor_ = -1993447398

calls filesystemForName with name = root

    private JSONObject resolveLocalFileSystemURI(String uriString) throws IOException, JSONException {
        if (uriString == null) {
            throw new MalformedURLException("Unrecognized filesystem URL");
        }
        Uri uri = Uri.parse(uriString);
        boolean isNativeUri = false;

        LocalFilesystemURL inputURL = LocalFilesystemURL.parse(uri);
        if (inputURL == null) {
            /* Check for file://, content:// urls */
            inputURL = resolveNativeUri(uri);
            isNativeUri = true;
        }

@shankari
Copy link
Contributor Author

Ok, so using the filesystem with the full path to directly get a file works. Listing directories still doesn't work, but that is OK.

            window.resolveLocalFileSystemURL(localFs, function(fs) {
                fs.filesystem.root.getFile(fs.fullPath+"databases/loggerDB", null, (fileEntry) => {

@shankari
Copy link
Contributor Author

shankari commented Jan 31, 2021

for the record, using $http also works

        $http.get("../../../databases/loggerDB").then((dirlisting) => {
            console.log(dirlisting);
        });
{data: "SQLite format 3���@  ��p��…:8080","android":{"auth":{"method":"dummy-dev"}}}", status: 200, config: {…}, statusText: "OK", headers: ƒ}
config : {method: "GET", transformRequest: Array(1), transformResponse: Array(1), url: "../../../databases/loggerDB", paramSerializer: ƒ, …}
data : "SQLite format 3���@  ��p�������.����.���.w�������AtablelogTablelogTable�CREATE TABLE logTable (ID INTEGER PRIMARY ..."
headers : ƒ (name)
status : 200
statusText : "OK"

So we can potentially remove the file dependency in the future. However, we still use the file dependency for:

  • load the correct intro templates (can be replaced by $http as well)
  • write a local file to create the JSON dump for mailing (can't be easily replaced, but maybe we can have a website/app instead later?)

Also the path (../../../) may not be consistent across native apps and UI updates with ionic deploy.

So we will continue to use the filesystem plugin for now, but can return to this as part of a bigger refactoring to remove the file plugin.

@shankari
Copy link
Contributor Author

shankari commented Jan 31, 2021

First implementation to upload is done:

        const sendToServer = function upload(url, binData) {
            var config = {
                headers: {'Content-Type': "blob"},
                transformRequest: []
            };
            return $http.post(url, binData, config);
        }

with

            readDBFile(database).then((binaryStr) => {
                sendToServer("//httpbin.org/post", binaryStr).catch(onUploadError);
            }).catch(onReadError);

However, I wonder if this is the right approach to take. File uploads typically use FormData to send the information, which allows us to send a file name, and also to use whatever encoding the standard file upload implementations use.

Let's see if we can manually use FormData instead.

@shankari
Copy link
Contributor Author

We can create a FormData object programatically
https://developer.mozilla.org/en-US/docs/Web/API/FormData

and append

formData.append(name, value, filename);

the value can be a Blob, or File, which is a subclass of Blob.
Anddd, I think we actually get a File object from the cordova filesystem plugin

File {name: "loggerDB", localURL: "cdvfile://localhost/root/data/user/0/edu.berkeley.eecs.emission.devapp/databases/loggerDB", type: null, lastModified: 1612135739000, lastModifiedDate: 1612135739000, …}
end : 552960
lastModified : 1612135739000
lastModifiedDate : 1612135739000
localURL : "cdvfile://localhost/root/data/user/0/edu.berkeley.eecs.emission.devapp/databases/loggerDB"
name : "loggerDB"
size : 552960
start : 0
type : null

So it seems like we should be able to append that directly to the FormData, and we should be able to post that as a multi-part message.

This would also allow us to, for example, add a message to the form later.

@shankari
Copy link
Contributor Author

shankari commented Feb 1, 2021

Alas, we can't append that directly. Looks like we need to load it first.

------WebKitFormBoundaryvBke9Sh8ZqPBOpPB
Content-Disposition: form-data; name="file"


------WebKitFormBoundaryvBke9Sh8ZqPBOpPB--

@shankari
Copy link
Contributor Author

shankari commented Feb 1, 2021

So the file object returned from the cordova plugin is almost but not quite the file object from javascript
https://developer.mozilla.org/en-US/docs/Web/API/File#instance_methods

In particular, it does not support text() or arrayBuffer() methods

@shankari
Copy link
Contributor Author

shankari commented Feb 1, 2021

And we can't create a new File object because the File object from the plugin.
We can create a new Blob object, but I'm not able to call text() on it and the content is not filled in.

------WebKitFormBoundaryy8GLAh2Lizi3mQMd
Content-Disposition: form-data; name="file"; filename="blob"
Content-Type: application/octet-stream


------WebKitFormBoundaryy8GLAh2Lizi3mQMd--

@shankari
Copy link
Contributor Author

shankari commented Feb 1, 2021

This appears to be because of inconsistent support for blobs

On the most recent chrome:


undefined
blob1
Blob {size: 6, type: ""}
blob1.text()
Promise {<pending>}

In the emulator

var blob1 = new Blob(["abc123"])
undefined
blob1
Blob {size: 6, type: ""}
blob1.text()
VM21820:1 Uncaught TypeError: blob1.text is not a function

And it looks like text() and stream() are not currently supported on iOS.
So let's just manually send over the binary data.

@shankari
Copy link
Contributor Author

shankari commented Feb 1, 2021

passing the raw binString works with the classic append method.

formData.append(name, value);

Does not work with the append method that takes a name.

formData.append(name, value, filename);

@shankari
Copy link
Contributor Author

shankari commented Feb 1, 2021

Wrapping the BinString in a blob doesn't work.

------WebKitFormBoundary1MyaABVCmOpWaLFg
Content-Disposition: form-data; name="reason"

Tracking stopped abruptly
------WebKitFormBoundary1MyaABVCmOpWaLFg
Content-Disposition: form-data; name="rawFile"; filename="blob"
Content-Type: application/octet-stream


------WebKitFormBoundary1MyaABVCmOpWaLFg--

shankari added a commit to shankari/e-mission-phone that referenced this issue Feb 5, 2021
Instead of emailing it.
This is a partial fix for e-mission/e-mission-docs#609

Has only been tested on android, needs to be tested on iOS as well

Main changes:
- add a new upload service
- figure out how to read the phone logs into memory from the app ecosystem
- figure out how to format them as phone data
- include a popup to gather additional information
- combine info from popup along with phone logs and upload to a test site

Change the control screen to upload instead of emailing logs

There are other improvements we can make, but let's get this checked in first
@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

Created a simple repository with a flask webserver for uploading bug logs.
https://github.com/e-mission/em-bug-upload

Flask plugins include

  • flask_uploads
  • flask_cors
  • flask_limiter

Currently trying to figure out how to format the post message so it is handled properly by the server.
Since we are getting an error where request.files does not have any entries.

<Request 'http://localhost:5647/phonelogs' [POST]>
No Files

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

Tried uploading some files to psty.io, headers are

POST /upload_file HTTP/2
Host: psty.io
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: multipart/form-data; boundary=---------------------------311967384732854600413230849623
Content-Length: 255
Origin: https://psty.io
DNT: 1
Connection: keep-alive
Referer: https://psty.io/files
Cookie: __cfduid=d637e2733f70c5a279effbb86dd7f1f411611973464
Upgrade-Insecure-Requests: 1
Pragma: no-cache
Cache-Control: no-cache
TE: Trailers

While uploading from the phone, we now get

POST /phonelogs HTTP/1.1
Accept: application/json, text/plain, */*
Content-Type: multipart/form-data
Origin: ionic://localhost
Accept-Encoding: gzip, deflate
Host: localhost:5647
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
Content-Length: 8129467
Accept-Language: en-us
Connection: keep-alive

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

Following the instructions from https://withintent.uncorkedstudios.com/multipart-form-data-file-upload-with-angularjs-c23bf6eeb298
and setting the Content-Type': to undefinedinstead of the prior"undefined"`

We now get a request that looks like this

POST /phonelogs HTTP/1.1
Accept: application/json, text/plain, */*
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryhwlJKeavX8sTp5fn
Origin: ionic://localhost
Accept-Encoding: gzip, deflate
Host: localhost:5647
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
Content-Length: 8591190
Accept-Language: en-us
Connection: keep-alive

The data is:

------WebKitFormBoundaryhwlJKeavX8sTp5fn
Content-Disposition: form-data; name="reason"

Test me
------WebKitFormBoundaryhwlJKeavX8sTp5fn
Content-Disposition: form-data; name="rawFile"

SQLite format 3���@  ®��Ù���®�.CÃ
�����������¡�%%���tableTRACK_POINTSTRACK_POINTS�CREATE TABLE TRACK_POINTS (TIMESTAMP INTEGER, LAT REAL, LNG REAL, ALTITUDE REAL, HORIZ_ACCURACY REAL, VERT_ACCURACY REAL)�L##���tableTRANSITIONSTRANSITIONS�CREATE TABLE TRANSITIONS (TIMESTAMP INTEGER, MESSAGE TEXT)í%%��+tableMODE_CHANGESMODE_CHANGES�CREATE TABLE MODE_CHANGES (TIMESTAMP INTEGER, TYPE INTEGER, CONFIDENCE INTEGEw�������AtablelogTablelogTable�CREATE TABLE logTable (ID INTEGER PRIMARY KEY NOT NULL, ts REAL, level TEXT, message TEXT)���å�9�ú�ó�ì�å�ª��O�ã�Ý}����\��Ïn
.h�Ã���L�ü�^��
Õ

But on the server, I still have:

<Request 'http://localhost:5647/phonelogs' [POST]>
ImmutableMultiDict([])
No Files

Time to check the flask message parsing.

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

It is because we added the formdata as a blob. Since it is not a "file" it doesn't show up as a file. It shows up as formdata instead.

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

One minor issue is that the file sizes seem to be slightly different

[Log] Successful file read with 8437760 characters (index.html, line 145)
[Log] Uploading file of size 8437760 (index.html, line 145)

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

Here it is

[Log] Successful file read with 8560640 characters (index.html, line 145)
[Log] Uploading file of size 8560640 (index.html, line 145)
[Log] Object (index.html, line 145)
data: "Reason My reason is good of length 17, Found file of length 8573518"

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

While trying to save it, found an issue with the flask-uploader.

  File "/dev_src/uploader.py", line 34, in uploader
    phonelogs.save(rawFileData)
  File "/usr/local/lib/python3.9/site-packages/flask_uploads.py", line 426, in save
    raise TypeError("storage must be a werkzeug.FileStorage")
TypeError: storage must be a werkzeug.FileStorage

Looking at additional documentation:
https://tedboy.github.io/flask/generated/generated/werkzeug.FileStorage.html
and

I think that this might be because we are not uploading it as "a file".

https://stackoverflow.com/questions/62227104/typeerror-storage-must-be-a-werkzeug-filestorage-in-flask-upload

The stackoverflow examples also have a bunch of stuff around form validation which I am not sure we want to do since we are not generating a form from the server. Do I want to define a form? What does it mean to get form.photo.data? Going to save manually instead using the code from psty.io

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

by manually saving the file, I can now see the file, but it is corrupted, undoubtedly because the file sizes are different

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

Switching to only sending the file instead of formdata, we get the data as bytes inside flask
but the size is still off

[Log] Successful file read with 3764224 characters (index.html, line 145)
[Log] Uploading file of size 3764224 (index.html, line 145)
[Log] Object (index.html, line 145)
data: "file data of length 4044806 written to 2021-02-08T05-22-15.loggerDB"

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

So this is a known issue, but kind of complicated
https://stackoverflow.com/questions/7431365/filereader-readasbinarystring-to-upload-files

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

Switching to reader.readAsArrayBuffer works flawlessly, albeit with a warning around

ArrayBuffer is deprecated in XMLHttpRequest.send(). Use ArrayBufferView instead.
index.html:145

File sizes match

[Log] Successful file read with 4128768 characters (index.html, line 145)
[Log] Uploading file of size 4128768 (index.html, line 145)
[Log] {data: "file data of length 4128768 written to 2021-02-08T06-11-07.loggerDB", status: 200, headers: function, config: Object, statusText: "OK"} (index.html, line 145)

And decoding the buffer works fine

$ python bin/csv_export_add_date.py /tmp/2021-02-08T06-03-18.loggerDB
exporting csv to /tmp/2021-02-08T06-03-18.loggerDB.csv
adding dates to the dataframe
exporting csv with date to /tmp/2021-02-08T06-03-18.loggerDB.withdate.log

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

ArrayBuffer is deprecated in XMLHttpRequest.send(). Use ArrayBufferView instead.
index.html:145

wrapping the ArrayBuffer in a DataView fixes this.

[Log] Successful file read with 4272128 characters (index.html, line 145)
[Log] Uploading file of size 4272128 (index.html, line 145)
[Log] {data: "file data of length 4272128 written to 2021-02-08T06-16-21.loggerDB", status: 200, headers: function, config: Object, statusText: "OK"} (index.html, line 145)

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

Does not work while wrapped into FormData

[Log] Successful file read with 4468736 characters (index.html, line 145)
[Log] DEBUG:current/map received resize event, invalidating map size (index.html, line 145)
[Log] Uploading file of size 4468736 (index.html, line 145)
[Log] {data: "file data of length 20 written to 2021-02-08_Huh", status: 200, headers: function, config: Object, statusText: "OK"} (index.html, line 145)

with the raw message being:

------WebKitFormBoundaryWSwxHIC8aGkacfuX
Content-Disposition: form-data; name="reason"

Huh
------WebKitFormBoundaryWSwxHIC8aGkacfuX
Content-Disposition: form-data; name="rawFile"

[object ArrayBuffer]
------WebKitFormBoundaryWSwxHIC8aGkacfuX--

Let's try the option of encoding the additional paramters with URL encoding

@shankari
Copy link
Contributor Author

shankari commented Feb 8, 2021

Encoding additional parameters with URL encoding works!

So now passing in the reason and the timezone.

                const params = {
                    reason: reason,
                    tz: Intl.DateTimeFormat().resolvedOptions().timeZone
                }

        const sendToServer = function upload(url, binArray, params) {
            var config = {
                headers: {'Content-Type': undefined },
                transformRequest: angular.identity,
                params: params
            };
            return $http.post(url, binArray, config);
        }

Right now, on the server side, the reason gets put into the filename, but we can potentially create an sqlite database and also decode logs automatically in the future.

$ python bin/csv_export_add_date.py ~/e-mission/em-bug-upload/logs/2021-02-08_One_more_t_America_Los_Angeles.loggerDB
exporting csv to /tmp/2021-02-08_One_more_t_America_Los_Angeles.loggerDB.csv
adding dates to the dataframe
exporting csv with date to /tmp/2021-02-08_One_more_t_America_Los_Angeles.loggerDB.withdate.log

shankari added a commit to shankari/e-mission-phone that referenced this issue Feb 8, 2021
- Read the data as an Array Buffer
    (e-mission/e-mission-docs#609 (comment))
- Wrap the ArrayBuffer as a DataView
    (e-mission/e-mission-docs#609 (comment))
- Upload directly instead of using `append`
- Change the type to `undefined` instead of `"undefined"` so we are likely to
  have it filled in properly
_ use both reqular params and a post message to pass metadata

Some cleanup required, but wanted to check in working version first.
@shankari
Copy link
Contributor Author

@shankari
Copy link
Contributor Author

Closing this now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant