Skip to content

Commit

Permalink
Analytics improvements (#3874)
Browse files Browse the repository at this point in the history
fixes #3871
<!-- Link to relevant issue (for ex: "fixes #1234") which will
automatically close the issue once the PR is merged -->

## PR Type
<!-- Please uncomment one ore more that apply to this PR -->

<!-- - Bugfix -->
<!-- - Feature -->
<!-- - Code style update (formatting) -->
<!-- - Refactoring (no functional changes, no api changes) -->
<!-- - Build or CI related changes -->
<!-- - Documentation content changes -->
<!-- - Sample app changes -->
Other... Please describe: Analytics

## Describe the new behavior?
SessionID is now sent in our analytics + sent to the pwabuilder services
as a header

## PR Checklist

- [ x] Test: run `npm run test` and ensure that all tests pass
- [x ] Target main branch (or an appropriate release branch if
appropriate for a bug fix)
- [x ] Ensure that your contribution follows [standard accessibility
guidelines](https://docs.microsoft.com/en-us/microsoft-edge/accessibility/design).
Use tools like https://webhint.io/ to validate your changes.


## Additional Information

---------

Co-authored-by: Justin Willis (HE / HIM) <[email protected]>
  • Loading branch information
jgw96 and Justin Willis (HE / HIM) authored Feb 28, 2023
1 parent 92f341c commit f4e6f11
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 92 deletions.
11 changes: 6 additions & 5 deletions apps/pwabuilder-vscode/src/library/package-utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { writeFile } from "fs/promises";
const fetch = require('node-fetch');
import { Headers, Response } from "node-fetch";
import { Response } from "node-fetch";
import { Manifest, MsixInfo } from "../interfaces";

import * as vscode from "vscode";
import { AndroidPackageOptions } from "../android-interfaces";
import { URL } from "url";

import { trackEvent, trackException } from "../services/usage-analytics";
import { getSessionID, standard_headers, trackEvent, trackException } from "../services/usage-analytics";
import { getURL } from "../services/web-publish";

export const WindowsDocsURL =
Expand Down Expand Up @@ -72,12 +72,13 @@ export async function packageForWindows(options: any) {
let response: Response | undefined;

try {

response = await fetch(
"https://pwabuilder-winserver.centralus.cloudapp.azure.com/msix/generatezip",
{
method: "POST",
body: JSON.stringify(options),
headers: new Headers({ "content-type": "application/json" }),
headers: standard_headers,
}
);
} catch (err: any) {
Expand Down Expand Up @@ -134,7 +135,7 @@ export async function buildAndroidPackage(options: AndroidPackageOptions) {
response = await fetch(generateAppUrl, {
method: "POST",
body: JSON.stringify(options),
headers: new Headers({ "content-type": "application/json" }),
headers: standard_headers,
});
} catch (err: any) {
vscode.window.showErrorMessage(
Expand All @@ -159,7 +160,7 @@ export async function buildIOSPackage(options: IOSAppPackageOptions) {
response = await fetch(generateAppUrl, {
method: "POST",
body: JSON.stringify(options),
headers: new Headers({ "content-type": "application/json" }),
headers: standard_headers,
});
} catch (err: any) {
vscode.window.showErrorMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as vscode from 'vscode';
const fetch = require('node-fetch');
import { writeFile } from 'fs/promises';
import { Manifest } from '../../interfaces';
import { trackEvent, trackException } from "../usage-analytics";
import { standard_headers, trackEvent, trackException } from "../usage-analytics";
import { findManifest } from './manifest-service';

const pwaAssetGenerator = require('pwa-asset-generator');
Expand Down Expand Up @@ -40,9 +40,7 @@ export async function generateScreenshots(skipPrompts?: boolean) {
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
headers: standard_headers,
body: JSON.stringify({
url: [urlToScreenshot]
}),
Expand Down
26 changes: 24 additions & 2 deletions apps/pwabuilder-vscode/src/services/usage-analytics.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import { setup, defaultClient } from 'applicationinsights';
import { getFlag } from '../flags';

import * as vscode from 'vscode';
import { Headers } from 'node-fetch';

const sessionID = getSessionID();
export const standard_headers = new Headers(
{
"content-type": "application/json",
"Platform-Identifier": "PWAStudio",
"Correlation-Id": sessionID,
}
)

export function initAnalytics() {
try {
// check flag first
Expand All @@ -22,13 +34,20 @@ export function initAnalytics() {
}
}

export function getSessionID() {
return vscode.env.sessionId;
}

// function to trackEvent
export function trackEvent(name: string, properties: any) {
try {
if (getFlag("analytics") === true) {

// add session id to properties
properties.sessionId = getSessionID();

defaultClient.trackEvent({
name,
name,
properties
});
}
Expand All @@ -44,7 +63,10 @@ export function trackException(err: Error) {
try {
if (getFlag("analytics") === true) {
defaultClient.trackException({
exception: err
exception: err,
properties: {
sessionId: getSessionID()
}
});
}
}
Expand Down
183 changes: 103 additions & 80 deletions libraries/manifest-validation/src/validations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,29 @@ export const maniTests: Array<Validation> = [
return value && typeof value === "string" && value.length > 0;
}
},
{
infoString: "The handle_links field specifies how links to your app are opened, either in your app itself or in the users browser",
displayString: "Manifest has handle_links field",
category: "recommended",
member: "handle_links",
defaultValue: "auto",
docsLink: "",
errorString: "handle_links is recommended and should be either auto, preferred or not-proferred",
quickFix: true,
test: (value: string) => {
if (value && typeof value === "string") {
if (value === "auto" || "preferred" || "not-preferred") {
return true;
}
else {
return false;
}
}
else {
return false;
}
}
},
{
infoString: "share_target enables your app to get shared content from other apps",
displayString: "Manifest has share_target field",
Expand All @@ -28,7 +51,7 @@ export const maniTests: Array<Validation> = [
"title": "title",
"text": "text",
"url": "url"
}
}
}),
docsLink: "https://web.dev/web-share-target/",
errorString: "share_target must be an object",
Expand Down Expand Up @@ -89,7 +112,7 @@ export const maniTests: Array<Validation> = [
quickFix: true,
test: (value: any[]) => {
const isArray = value && Array.isArray(value) && value.length > 0 ? true : false;

if (isArray) {
const anyIcon = value.find(icon => icon.purpose === "any");

Expand Down Expand Up @@ -124,7 +147,7 @@ export const maniTests: Array<Validation> = [
quickFix: false,
test: (value: any[]) => {
const isArray = value && Array.isArray(value) && value.length > 0 ? true : false;

if (isArray) {
const anyIcon = value.find(icon => isAtLeast(icon.sizes, 512, 512) && (icon.type === 'image/png' || icon.src.endsWith(".png")));

Expand Down Expand Up @@ -159,7 +182,7 @@ export const maniTests: Array<Validation> = [
quickFix: true,
test: (value: any[]) => {
const isArray = value && Array.isArray(value) && value.length > 0 ? true : false;

if (isArray) {
const wrongIcon = value.find(icon => icon.purpose === "any maskable");

Expand Down Expand Up @@ -210,8 +233,8 @@ export const maniTests: Array<Validation> = [
errorString: "short_name is required and must be a string with a length >= 3",
quickFix: true,
test: (value: string) => {
const existsAndLength = value && value.length >= 3;
return existsAndLength;
const existsAndLength = value && value.length >= 3;
return existsAndLength;
},
},
{
Expand Down Expand Up @@ -479,7 +502,7 @@ export const maniTests: Array<Validation> = [
"https://docs.pwabuilder.com/#/builder/manifest?id=prefer_related_applications-boolean",
quickFix: false, // @ Justin Willis, I added this but left it false because idk how to do quick fixes lol.
test: (value: any) => {
return typeof(value) === "boolean"
return typeof (value) === "boolean"
},
errorString: "prefer_related_applications should be set to a boolean value",
},
Expand All @@ -495,12 +518,12 @@ export const maniTests: Array<Validation> = [
quickFix: true,
test: (value: any[]) => {
let isGood;
if(value){
containsStandardCategory(value) && Array.isArray(value)
?
isGood = true
:
isGood = false;
if (value) {
containsStandardCategory(value) && Array.isArray(value)
?
isGood = true
:
isGood = false;
}

return isGood
Expand All @@ -518,7 +541,7 @@ export const maniTests: Array<Validation> = [
errorString: "lang should be set to a valid language code",
quickFix: true,
test: (value: string) =>
value && typeof value === "string" && value.length > 0 && isValidLanguageCode(value)
value && typeof value === "string" && value.length > 0 && isValidLanguageCode(value)
},
{
member: "dir",
Expand All @@ -531,7 +554,7 @@ export const maniTests: Array<Validation> = [
"https://docs.pwabuilder.com/#/builder/manifest?id=dir-string",
quickFix: true,
test: (value: string) =>
value && typeof value === "string" && value.length > 0 && (value === "ltr" || value === "rtl" || value === "auto")
value && typeof value === "string" && value.length > 0 && (value === "ltr" || value === "rtl" || value === "auto")
},
{
member: "description",
Expand Down Expand Up @@ -654,88 +677,88 @@ export const maniTests: Array<Validation> = [
export async function loopThroughKeys(manifest: Manifest): Promise<Array<Validation>> {
return new Promise((resolve) => {
let data: Array<Validation> = [];

const keys = Object.keys(manifest);

keys.forEach((key) => {
maniTests.forEach(async (test) => {
if (test.member === key && test.test) {
const testResult = await test.test(manifest[key]);
if(testResult){
test.valid = true;
data.push(test);


if (testResult) {
test.valid = true;
data.push(test);
}
else {
test.valid = false;
data.push(test);
test.valid = false;
data.push(test);
}
}
})
})

resolve(data);
})
}
export async function loopThroughRequiredKeys(manifest: Manifest): Promise<Array<Validation>> {
}

export async function loopThroughRequiredKeys(manifest: Manifest): Promise<Array<Validation>> {
return new Promise((resolve) => {
let data: Array<Validation> = [];

const keys = Object.keys(manifest);

keys.forEach((key) => {
maniTests.forEach(async (test) => {
if (test.category === "required") {
if (test.member === key && test.test) {
const testResult = await test.test(manifest[key]);

if (testResult === false) {
test.valid = false;
data.push(test);
}
else {
test.valid = true;
data.push(test);
}
}
}
let data: Array<Validation> = [];

const keys = Object.keys(manifest);

keys.forEach((key) => {
maniTests.forEach(async (test) => {
if (test.category === "required") {
if (test.member === key && test.test) {
const testResult = await test.test(manifest[key]);

if (testResult === false) {
test.valid = false;
data.push(test);
}
else {
test.valid = true;
data.push(test);
}
}
}
})
})
})

resolve(data);

resolve(data);
})
}
export async function findSingleField(field: string, value: any): Promise<singleFieldValidation> {
}

export async function findSingleField(field: string, value: any): Promise<singleFieldValidation> {
return new Promise(async (resolve) => {

// For && operations, true is the base.
let singleField = true;
let failedTests: string[] | undefined = [];

maniTests.forEach((test) => {
if (test.member === field && test.test) {

const testResult = test.test(value);

if(!testResult){
failedTests!.push(test.errorString!);
}

// If the test passes true && true = true.
// If the test fails true && false = false
// If a field has MULTIPLE tests, they will stack
// ie: true (base) && true (test 1) && false (ie test 2 fails).
singleField = singleField && testResult;

// For && operations, true is the base.
let singleField = true;
let failedTests: string[] | undefined = [];

maniTests.forEach((test) => {
if (test.member === field && test.test) {

const testResult = test.test(value);

if (!testResult) {
failedTests!.push(test.errorString!);
}

// If the test passes true && true = true.
// If the test fails true && false = false
// If a field has MULTIPLE tests, they will stack
// ie: true (base) && true (test 1) && false (ie test 2 fails).
singleField = singleField && testResult;
}
});

if (singleField) {
resolve({ "valid": singleField })
}
});

if(singleField){
resolve({"valid": singleField})
}

resolve({"valid": singleField, "errors": failedTests});

resolve({ "valid": singleField, "errors": failedTests });
})
}
Loading

0 comments on commit f4e6f11

Please sign in to comment.