Skip to content

Commit c18e832

Browse files
authored
Adds performance monitoring triggers to v2 alerts (#1223)
* rebasing master * add return to app distro * merge changelog * yank trace * add alert type to index * add link into tsdoc * fix get opts * linter * lineup with master * linter * adding logic to convert a payload to api council spec * fix wording of optional fields
1 parent 7783ae6 commit c18e832

File tree

13 files changed

+410
-12
lines changed

13 files changed

+410
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Add performance monitoring triggers to v2 alerts (#1223).

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"./v2/alerts/appDistribution": "./lib/v2/providers/alerts/appDistribution.js",
6565
"./v2/alerts/billing": "./lib/v2/providers/alerts/billing.js",
6666
"./v2/alerts/crashlytics": "./lib/v2/providers/alerts/crashlytics.js",
67+
"./v2/alerts/performance": "./lib/v2/providers/alerts/performance.js",
6768
"./v2/eventarc": "./lib/v2/providers/eventarc.js",
6869
"./v2/identity": "./lib/v2/providers/identity.js",
6970
"./v2/database": "./lib/v2/providers/database.js",
@@ -125,6 +126,9 @@
125126
"v2/alerts/crashlytics": [
126127
"lib/v2/providers/alerts/crashlytics"
127128
],
129+
"v2/alerts/performance": [
130+
"lib/v2/providers/alerts/performance"
131+
],
128132
"v2/base": [
129133
"lib/v2/base"
130134
],

spec/runtime/manifest.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { stackToWire, ManifestStack } from '../../src/runtime/manifest';
21
import { expect } from 'chai';
2+
import { ManifestStack, stackToWire } from '../../src/runtime/manifest';
33
import * as params from '../../src/v2/params';
44

55
describe('stackToWire', () => {
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import { expect } from 'chai';
2+
import * as alerts from '../../../../src/v2/providers/alerts';
3+
import * as performance from '../../../../src/v2/providers/alerts/performance';
4+
import { FULL_ENDPOINT, FULL_OPTIONS } from '../fixtures';
5+
6+
const APPID = '123456789';
7+
const myHandler = () => 42;
8+
9+
const APP_EVENT_FILTER = {
10+
appid: APPID,
11+
};
12+
13+
describe('performance', () => {
14+
describe('onThresholdAlertPublished', () => {
15+
it('should create a function with alertType & appId', () => {
16+
const func = performance.onThresholdAlertPublished(APPID, myHandler);
17+
18+
expect(func.__endpoint).to.deep.equal({
19+
platform: 'gcfv2',
20+
labels: {},
21+
eventTrigger: {
22+
eventType: alerts.eventType,
23+
eventFilters: {
24+
...APP_EVENT_FILTER,
25+
alerttype: performance.thresholdAlert,
26+
},
27+
retry: false,
28+
},
29+
});
30+
});
31+
32+
it('should create a function with opts', () => {
33+
const func = performance.onThresholdAlertPublished(
34+
{ ...FULL_OPTIONS },
35+
myHandler
36+
);
37+
38+
expect(func.__endpoint).to.deep.equal({
39+
...FULL_ENDPOINT,
40+
eventTrigger: {
41+
eventType: alerts.eventType,
42+
eventFilters: {
43+
alerttype: performance.thresholdAlert,
44+
},
45+
retry: false,
46+
},
47+
});
48+
});
49+
50+
it('should create a function with appid in opts', () => {
51+
const func = performance.onThresholdAlertPublished(
52+
{ ...FULL_OPTIONS, appId: APPID },
53+
myHandler
54+
);
55+
56+
expect(func.__endpoint).to.deep.equal({
57+
...FULL_ENDPOINT,
58+
eventTrigger: {
59+
eventType: alerts.eventType,
60+
eventFilters: {
61+
...APP_EVENT_FILTER,
62+
alerttype: performance.thresholdAlert,
63+
},
64+
retry: false,
65+
},
66+
});
67+
});
68+
69+
it('should create a function without opts or appId', () => {
70+
const func = performance.onThresholdAlertPublished(myHandler);
71+
72+
expect(func.__endpoint).to.deep.equal({
73+
platform: 'gcfv2',
74+
labels: {},
75+
eventTrigger: {
76+
eventType: alerts.eventType,
77+
eventFilters: {
78+
alerttype: performance.thresholdAlert,
79+
},
80+
retry: false,
81+
},
82+
});
83+
});
84+
85+
it('should create a function with a run method', () => {
86+
const func = performance.onThresholdAlertPublished(
87+
APPID,
88+
(event) => event
89+
);
90+
91+
const res = func.run('input' as any);
92+
93+
expect(res).to.equal('input');
94+
});
95+
});
96+
97+
describe('getOptsAndApp', () => {
98+
it('should parse a string', () => {
99+
const [opts, appId] = performance.getOptsAndApp(APPID);
100+
101+
expect(opts).to.deep.equal({});
102+
expect(appId).to.equal(APPID);
103+
});
104+
105+
it('should parse an options object without appId', () => {
106+
const myOpts: performance.PerformanceOptions = {
107+
region: 'us-west1',
108+
};
109+
110+
const [opts, appId] = performance.getOptsAndApp(myOpts);
111+
112+
expect(opts).to.deep.equal({ region: 'us-west1' });
113+
expect(appId).to.be.undefined;
114+
});
115+
116+
it('should parse an options object with appId', () => {
117+
const myOpts: performance.PerformanceOptions = {
118+
appId: APPID,
119+
region: 'us-west1',
120+
};
121+
122+
const [opts, appId] = performance.getOptsAndApp(myOpts);
123+
124+
expect(opts).to.deep.equal({ region: 'us-west1' });
125+
expect(appId).to.equal(APPID);
126+
});
127+
});
128+
129+
describe('convertPayload', () => {
130+
it('should return the same payload', () => {
131+
const payload = {
132+
a: 'b',
133+
conditionPercentile: 23,
134+
appVersion: '3',
135+
};
136+
137+
const convertedPayload = performance.convertPayload(payload as any);
138+
139+
expect(convertedPayload).to.deep.eq(payload);
140+
});
141+
142+
it('should return the same payload if the fields are undefined', () => {
143+
const payload = {
144+
a: 'b',
145+
};
146+
147+
const convertedPayload = performance.convertPayload(payload as any);
148+
149+
expect(convertedPayload).to.deep.eq({
150+
a: 'b',
151+
});
152+
});
153+
154+
it('should remove fields', () => {
155+
const payload = {
156+
a: 'b',
157+
conditionPercentile: 0,
158+
appVersion: '',
159+
};
160+
161+
const convertedPayload = performance.convertPayload(payload as any);
162+
163+
expect(convertedPayload).to.deep.eq({
164+
a: 'b',
165+
});
166+
});
167+
});
168+
});

src/runtime/manifest.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ export interface ManifestStack {
102102
* @internal
103103
*/
104104
export function stackToWire(stack: ManifestStack): Object {
105-
let wireStack = stack as any;
106-
let traverse = function traverse(obj: Object) {
105+
const wireStack = stack as any;
106+
const traverse = function traverse(obj: Object) {
107107
for (const [key, val] of Object.entries(obj)) {
108108
if (val instanceof Expression) {
109109
obj[key] = val.toCEL();

src/v2/params/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@
2727

2828
import {
2929
BooleanParam,
30+
Expression,
3031
FloatParam,
3132
IntParam,
3233
ListParam,
3334
Param,
3435
ParamOptions,
35-
StringParam,
3636
SecretParam,
37-
Expression,
37+
StringParam,
3838
} from './types';
3939

4040
export { ParamOptions, Expression };

src/v2/params/types.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export abstract class Expression<
4646
function quoteIfString<T extends string | number | boolean | string[]>(
4747
literal: T
4848
): T {
49-
//TODO(vsfan@): CEL's string escape semantics are slightly different than Javascript's, what do we do here?
49+
// TODO(vsfan@): CEL's string escape semantics are slightly different than Javascript's, what do we do here?
5050
return typeof literal === 'string' ? (`"${literal}"` as T) : literal;
5151
}
5252

@@ -171,14 +171,14 @@ export interface SelectOptions<T = unknown> {
171171
value: T;
172172
}
173173

174-
export type ParamSpec<T = unknown> = {
174+
export interface ParamSpec<T = unknown> {
175175
name: string;
176176
default?: T;
177177
label?: string;
178178
description?: string;
179179
type: ParamValueType;
180180
input?: ParamInput<T>;
181-
};
181+
}
182182

183183
export type ParamOptions<T = unknown> = Omit<ParamSpec<T>, 'name' | 'type'>;
184184

@@ -219,8 +219,8 @@ export abstract class Param<
219219
}
220220

221221
export class SecretParam {
222-
name: string;
223222
static type: ParamValueType = 'secret';
223+
name: string;
224224

225225
constructor(name: string) {
226226
this.name = name;

src/v2/providers/alerts/alerts.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export type AlertType =
7070
| 'billing.automatedPlanUpdate'
7171
| 'appDistribution.newTesterIosDevice'
7272
| 'appDistribution.inAppFeedback'
73+
| 'performance.threshold'
7374
| string;
7475

7576
/**

src/v2/providers/alerts/appDistribution.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727

2828
import { CloudEvent, CloudFunction } from '../../core';
2929
import * as options from '../../options';
30-
import { FirebaseAlertData, getEndpointAnnotation } from './alerts';
3130
import { Expression } from '../../params';
31+
import { FirebaseAlertData, getEndpointAnnotation } from './alerts';
3232

3333
/**
3434
* The internal payload object for adding a new tester device to app distribution.

src/v2/providers/alerts/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import * as appDistribution from './appDistribution';
3131
import * as billing from './billing';
3232
import * as crashlytics from './crashlytics';
33+
import * as performance from './performance';
3334

34-
export { appDistribution, billing, crashlytics };
35+
export { appDistribution, billing, crashlytics, performance };
3536
export * from './alerts';

0 commit comments

Comments
 (0)