Skip to content

Commit

Permalink
Merge pull request #11519 from linode/staging
Browse files Browse the repository at this point in the history
Release v1.134.0 - staging → master
  • Loading branch information
jaalah-akamai authored Jan 14, 2025
2 parents 1f0844b + a738061 commit 1ef9498
Show file tree
Hide file tree
Showing 623 changed files with 22,360 additions and 5,168 deletions.
12 changes: 12 additions & 0 deletions docs/development-guide/13-coding-standards.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,19 @@ We use [ESLint](https://eslint.org/) to enforce coding and formatting standards.
If you are using VSCode it is **highly** recommended to use the [ESlint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint). The [Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) is also recommended, as it can be configured to format your code on save.

## React
### useEffect()
`useEffect()` should only be used for handling true side effects - specifically API calls, subscriptions, and DOM mutations that must occur outside React's render cycle. While you may encounter instances where `useEffect()` is used differently throughout our existing codebase, we're actively working to remove those instances. Existing code that does not adhere to the hook's proper use should not be used as precedent for implementing new `useEffect()` instances. All state updates and data transformations should be handled through event handlers and direct state management.

When Not to Use Effects:
- Prop synchronization with state
- Derived state calculations
- Post-render state updates
- Props/state triggers for child components
- Chaining state updates

Reference: https://react.dev/learn/you-might-not-need-an-effect

### useId()
[Several new hooks were introduced with the release of React 18](https://react.dev/blog/2022/03/29/react-v18#new-hooks).

It should be noted that the `useId()` hook is particularly useful for generating unique IDs for accessibility attributes. For this use case, `useId()` is preferred over hardcoding the ID because components may be rendered more than once on a page, but IDs must be unique.
Expand Down
53 changes: 28 additions & 25 deletions docs/tooling/analytics.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,35 @@
# Analytics

## Pendo

Cloud Manager uses [Pendo](https://www.pendo.io/pendo-for-your-customers/) to capture analytics, guide users, and improve the user experience. Pendo is the **preferred** method for collecting analytics, including user events, since it requires no development effort and can be accomplished via the Pendo UI.

To view Pendo dashboards, Cloud Manager developers must follow internal processes to request access.

### Set Up and Initialization

Pendo is configured in [`usePendo.js`](https://github.com/linode/manager/blob/develop/packages/manager/src/hooks/usePendo.ts). This custom hook allows us to initialize the Pendo analytics script when the [App](https://github.com/linode/manager/blob/develop/packages/manager/src/App.tsx#L56) is mounted.

Important notes:

- Pendo is only loaded if a valid `PENDO_API_KEY` is configured as an environment variable. In our development, staging, and production environments, `PENDO_API_KEY` is available at build time. See **Locally Testing Page Views & Custom Events and/or Troubleshooting Pendo** for set up with local environments.
- We load the Pendo agent from the CDN, rather than [self-hosting](https://support.pendo.io/hc/en-us/articles/360038969692-Self-hosting-the-Pendo-agent), and we have configured a [CNAME](https://support.pendo.io/hc/en-us/articles/360043539891-CNAME-for-Pendo).
- We are hashing account and visitor IDs in a way that is consistent with Akamai's standards.
- At initialization, we do string transformation on select URL patterns to **remove sensitive data**. When new URL patterns are added to Cloud Manager, verify that existing transforms remove sensitive data; if not, update the transforms.
- Pendo is currently not using any client-side (cookies or local) storage.
- Pendo makes use of the existing `data-testid` properties, used in our automated testing, for tagging elements. They are more persistent and reliable than CSS properties, which are liable to change.

### Locally Testing Page Views & Custom Events and/or Troubleshooting Pendo

1. Set the `REACT_APP_PENDO_API_KEY` environment variable in `.env`.
2. Use the browser tools Network tab, filter requests by "psp.cloud", and check that successful network requests have been made to load Pendo scripts (also visible in the browser tools Sources tab).
3. In the browser console, type `pendo.validateEnvironment()`.
4. You should see command output in the console, and it should include a hashed `accountId` and hashed `visitorId`. Each page view change or custom event that fires should be visible as a request in the Network tab.
5. If the console does not output the expected ids and instead outputs something like `Cookies are disabled in Pendo config. Is this expected?` in response to the above command, clear app storage with the browser tools. Once redirected back to Login, update the OneTrust cookie settings to enable cookies via "Manage Preferences" in the banner at the bottom of the screen. Log back into Cloud Manager and Pendo should load.

## Adobe Analytics

Cloud Manager uses Adobe Analytics to capture page view and custom event statistics. To view analytics, Cloud Manager developers must follow internal processes to request access to Adobe Analytics dashboards.
Cloud Manager uses Adobe Analytics to capture page view and custom event statistics, although Pendo is the preferred method for collecting this data where possible, as of Q4 2024. To view analytics, Cloud Manager developers must follow internal processes to request access to Adobe Analytics dashboards.

### Writing a Custom Event

Expand Down Expand Up @@ -63,27 +90,3 @@ See the `LinodeCreateForm` form events as an example.
3. In the browser console, type `_satellite.setDebug(true)`.
4. Refresh the page. You should see Adobe debug log output in the console. Each page view change or custom event that fires should be visible in the logs.
5. When viewing dashboards in Adobe Analytics, it may take ~1 hour for analytics data to update. Once this happens, locally fired events will be visible in the dev dashboard.

## Pendo

Cloud Manager uses [Pendo](https://www.pendo.io/pendo-for-your-customers/) to capture analytics, guide users, and improve the user experience. To view Pendo dashboards, Cloud Manager developers must follow internal processes to request access.

### Set Up and Initialization

Pendo is configured in [`usePendo.js`](https://github.com/linode/manager/blob/develop/packages/manager/src/hooks/usePendo.ts). This custom hook allows us to initialize the Pendo analytics script when the [App](https://github.com/linode/manager/blob/develop/packages/manager/src/App.tsx#L56) is mounted.

Important notes:

- Pendo is only loaded if a valid `PENDO_API_KEY` is configured as an environment variable. In our development, staging, and production environments, `PENDO_API_KEY` is available at build time. See **Locally Testing Page Views & Custom Events and/or Troubleshooting Pendo** for set up with local environments.
- We load the Pendo agent from the CDN, rather than [self-hosting](https://support.pendo.io/hc/en-us/articles/360038969692-Self-hosting-the-Pendo-agent).
- We are hashing account and visitor IDs in a way that is consistent with Akamai's standards.
- At initialization, we do string transformation on select URL patterns to **remove sensitive data**. When new URL patterns are added to Cloud Manager, verify that existing transforms remove sensitive data; if not, update the transforms.
- Pendo is currently not using any client-side (cookies or local) storage.
- Pendo makes use of the existing `data-testid` properties, used in our automated testing, for tagging elements. They are more persistent and reliable than CSS properties, which are liable to change.

### Locally Testing Page Views & Custom Events and/or Troubleshooting Pendo

1. Set the `REACT_APP_PENDO_API_KEY` environment variable in `.env`.
2. Use the browser tools Network tab, filter requests by "pendo", and check that successful network requests have been made to load Pendo scripts. (Also visible in browser tools Sources tab.)
3. In the browser console, type `pendo.validateEnvironment()`.
4. You should see command output in the console, and it should include a hashed `accountId` and hashed `visitorId`. Each page view change or custom event that fires should be visible as a request in the Network tab.
16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"test:sdk": "yarn workspace @linode/api-v4 test",
"test:search": "yarn workspace @linode/search test",
"test:ui": "yarn workspace @linode/ui test",
"package-versions": "node ./scripts/package-versions/index.js",
"package-versions": "yarn workspace @linode/scripts package-versions",
"storybook": "yarn workspace linode-manager storybook",
"cy:run": "yarn workspace linode-manager cy:run",
"cy:e2e": "yarn workspace linode-manager cy:e2e",
Expand All @@ -39,23 +39,25 @@
"cy:component": "yarn workspace linode-manager cy:component",
"cy:component:run": "yarn workspace linode-manager cy:component:run",
"cy:rec-snap": "yarn workspace linode-manager cy:rec-snap",
"changeset": "node scripts/changelog/changeset.mjs",
"generate-changelogs": "node scripts/changelog/generate-changelogs.mjs",
"changeset": "yarn workspace @linode/scripts changeset",
"generate-changelogs": "yarn workspace @linode/scripts generate-changelogs",
"coverage": "yarn workspace linode-manager coverage",
"coverage:summary": "yarn workspace linode-manager coverage:summary",
"junit:summary": "tsx scripts/junit-summary/index.ts",
"generate-tod": "tsx scripts/tod-payload/index.ts",
"junit:summary": "YARN_SILENT=1 yarn workspace @linode/scripts junit:summary",
"generate-tod": "YARN_SILENT=1 yarn workspace @linode/scripts generate-tod",
"docs": "bunx [email protected] dev docs",
"prepare": "husky"
},
"resolutions": {
"node-fetch": "^2.6.7",
"yaml": "^2.3.0",
"semver": "^7.5.2"
"semver": "^7.5.2",
"cookie": "^0.7.0"
},
"workspaces": {
"packages": [
"packages/*"
"packages/*",
"scripts"
]
},
"version": "0.0.0",
Expand Down
32 changes: 32 additions & 0 deletions packages/api-v4/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
## [2025-01-14] - v0.132.0

### Added:

- Types for UDP NodeBalancer support ([#11321](https://github.com/linode/manager/pull/11321))
- Tags to `KubeNodePoolResponse` and `UpdateNodePoolData` ([#11368](https://github.com/linode/manager/pull/11368))

### Changed:

- Type of `AlertDefinitionType` to `'system'|'user'` ([#11346](https://github.com/linode/manager/pull/11346))
- Property names, and types of the CreateAlertDefinitionPayload and Alert interfaces ([#11392](https://github.com/linode/manager/pull/11392))
- BaseDatabase total_disk_size_gb and used_disk_size_gb are always expected and used_disk_size_gb can be null ([#11426](https://github.com/linode/manager/pull/11426))
- Renamed `AvailableMetrics` type to `MetricDefinition` ([#11433](https://github.com/linode/manager/pull/11433))
- Changed MetricCritera, DimensionFilter and Alert Interfaces ([#11445](https://github.com/linode/manager/pull/11445))

### Fixed:

- Nullable AccountBeta ended & description properties ([#11347](https://github.com/linode/manager/pull/11347))
- Incorrect return type of `updateObjectACL` ([#11369](https://github.com/linode/manager/pull/11369))

### Removed:

- getAccountInfoBeta endpoint ([#11413](https://github.com/linode/manager/pull/11413))
- `MetricDefinitions` type ([#11433](https://github.com/linode/manager/pull/11433))

### Upcoming Features:

- Fix types for IAM API ([#11397](https://github.com/linode/manager/pull/11397))
- Add new `getAlertDefinitionByServiceTypeAndId` endpoint to fetch Cloud Pulse alert details by id and service type ([#11399](https://github.com/linode/manager/pull/11399))
- New `Block Storage Performance B1` linode capability ([#11400](https://github.com/linode/manager/pull/11400))
- Add `getKubernetesTypesBeta` function ([#11419](https://github.com/linode/manager/pull/11419))

## [2024-12-10] - v0.131.0

### Added:
Expand Down
2 changes: 1 addition & 1 deletion packages/api-v4/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@linode/api-v4",
"version": "0.131.0",
"version": "0.132.0",
"homepage": "https://github.com/linode/manager/tree/develop/packages/api-v4",
"bugs": {
"url": "https://github.com/linode/manager/issues"
Expand Down
12 changes: 0 additions & 12 deletions packages/api-v4/src/account/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,6 @@ export const getAccountInfo = () => {
return Request<Account>(setURL(`${API_ROOT}/account`), setMethod('GET'));
};

/**
* getAccountInfoBeta
*
* Return beta endpoint account information,
* including contact and billing info.
*
* @TODO LKE-E - M3-8838: Clean up after released to GA, if not otherwise in use
*/
export const getAccountInfoBeta = () => {
return Request<Account>(setURL(`${BETA_API_ROOT}/account`), setMethod('GET'));
};

/**
* getNetworkUtilization
*
Expand Down
59 changes: 31 additions & 28 deletions packages/api-v4/src/account/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,32 +59,35 @@ export interface Account {

export type BillingSource = 'linode' | 'akamai';

export type AccountCapability =
| 'Akamai Cloud Load Balancer'
| 'Akamai Cloud Pulse'
| 'Block Storage'
| 'Block Storage Encryption'
| 'Cloud Firewall'
| 'CloudPulse'
| 'Disk Encryption'
| 'Kubernetes'
| 'Kubernetes Enterprise'
| 'Linodes'
| 'LKE HA Control Planes'
| 'LKE Network Access Control List (IP ACL)'
| 'Machine Images'
| 'Managed Databases'
| 'Managed Databases Beta'
| 'NETINT Quadra T1U'
| 'NodeBalancers'
| 'Object Storage Access Key Regions'
| 'Object Storage Endpoint Types'
| 'Object Storage'
| 'Placement Group'
| 'SMTP Enabled'
| 'Support Ticket Severity'
| 'Vlans'
| 'VPCs';
export const accountCapabilities = [
'Akamai Cloud Load Balancer',
'Akamai Cloud Pulse',
'Block Storage',
'Block Storage Encryption',
'Cloud Firewall',
'CloudPulse',
'Disk Encryption',
'Kubernetes',
'Kubernetes Enterprise',
'Linodes',
'LKE HA Control Planes',
'LKE Network Access Control List (IP ACL)',
'Machine Images',
'Managed Databases',
'Managed Databases Beta',
'NETINT Quadra T1U',
'NodeBalancers',
'Object Storage Access Key Regions',
'Object Storage Endpoint Types',
'Object Storage',
'Placement Group',
'SMTP Enabled',
'Support Ticket Severity',
'Vlans',
'VPCs',
] as const;

export type AccountCapability = typeof accountCapabilities[number];

export interface AccountAvailability {
region: string; // will be slug of dc (matches id field of region object returned by API)
Expand Down Expand Up @@ -604,8 +607,8 @@ export interface AccountBeta {
label: string;
started: string;
id: string;
ended?: string;
description?: string;
ended: string | null;
description: string | null;
/**
* The datetime the account enrolled into the beta
* @example 2024-10-23T14:22:29
Expand Down
32 changes: 30 additions & 2 deletions packages/api-v4/src/cloudpulse/alerts.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { createAlertDefinitionSchema } from '@linode/validation';
import Request, { setURL, setMethod, setData } from '../request';
import Request, {
setURL,
setMethod,
setData,
setParams,
setXFilter,
} from '../request';
import { Alert, AlertServiceType, CreateAlertDefinitionPayload } from './types';
import { BETA_API_ROOT as API_ROOT } from 'src/constants';
import { BETA_API_ROOT as API_ROOT } from '../constants';
import { Params, Filter, ResourcePage } from '../types';

export const createAlertDefinition = (
data: CreateAlertDefinitionPayload,
Expand All @@ -16,3 +23,24 @@ export const createAlertDefinition = (
setMethod('POST'),
setData(data, createAlertDefinitionSchema)
);

export const getAlertDefinitions = (params?: Params, filters?: Filter) =>
Request<ResourcePage<Alert>>(
setURL(`${API_ROOT}/monitor/alert-definitions`),
setMethod('GET'),
setParams(params),
setXFilter(filters)
);

export const getAlertDefinitionByServiceTypeAndId = (
serviceType: string,
alertId: number
) =>
Request<Alert>(
setURL(
`${API_ROOT}/monitor/services/${encodeURIComponent(
serviceType
)}/alert-definitions/${encodeURIComponent(alertId)}`
),
setMethod('GET')
);
6 changes: 3 additions & 3 deletions packages/api-v4/src/cloudpulse/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import Request, { setData, setMethod, setURL } from '../request';
import {
JWEToken,
JWETokenPayLoad,
MetricDefinitions,
MetricDefinition,
ServiceTypesList,
} from './types';
import { ResourcePage as Page } from 'src/types';
import { ResourcePage } from 'src/types';

export const getMetricDefinitionsByServiceType = (serviceType: string) => {
return Request<Page<MetricDefinitions>>(
return Request<ResourcePage<MetricDefinition>>(
setURL(
`${API_ROOT}/monitor/services/${encodeURIComponent(
serviceType
Expand Down
Loading

0 comments on commit 1ef9498

Please sign in to comment.