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

Added personalization monitors #1142

Merged
merged 14 commits into from
Aug 19, 2024
14 changes: 7 additions & 7 deletions bundlesize.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
"brotiliSize": 133
},
"dist/alloy.js": {
"uncompressedSize": 578928,
"gzippedSize": 88244,
"brotiliSize": 68739
"uncompressedSize": 583092,
"gzippedSize": 89038,
"brotiliSize": 69312
},
"dist/alloy.min.js": {
"uncompressedSize": 119915,
"gzippedSize": 39760,
"brotiliSize": 34596
"uncompressedSize": 122217,
"gzippedSize": 40474,
"brotiliSize": 35152
}
}
}
8 changes: 8 additions & 0 deletions sandbox/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@
<script>
window.__alloyMonitors = window.__alloyMonitors || [];
window.__alloyMonitors.push({
onContentRendering(data) {
console.log("Alloy Content Rendering");
console.log("data", data.status, data);
},
onContentHiding(data) {
console.log("Alloy Content Hiding");
console.log("data", data.status);
},
onInstanceCreated(data) {
console.log("Alloy Instance Created");
console.log(data.instanceName);
Expand Down
38 changes: 37 additions & 1 deletion src/components/Personalization/createFetchDataHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/
import { groupBy } from "../../utils/index.js";
import {groupBy, isNonEmptyArray} from "../../utils/index.js";
import PAGE_WIDE_SCOPE from "../../constants/pageWideScope.js";

const DECISIONS_HANDLE = "personalization:decisions";

export default ({
logger,
prehidingStyle,
showContainers,
hideContainers,
Expand Down Expand Up @@ -44,6 +46,16 @@ export default ({

onResponse(({ response }) => {
const handles = response.getPayloadsByType(DECISIONS_HANDLE);
if(!isNonEmptyArray(handles)){
logger.logOnContentRendering({
status: "no-offers",
message: "No offers were returned.",
logLevel: "info",
detail: {
query: personalizationDetails.createQueryDetails()
}
});
}
const propositions = handles.map((handle) => createProposition(handle));
const {
page: pagePropositions = [],
Expand All @@ -63,6 +75,30 @@ export default ({
[...pagePropositions, ...currentViewPropositions],
nonRenderedPropositions,
));
if (isNonEmptyArray(pagePropositions)) {
logger.logOnContentRendering({
status: "rendering-started",
message: "Started rendering propositions for page-wide scope.",
logLevel: "info",
detail: {
scope: PAGE_WIDE_SCOPE,
propositions: pagePropositions.map(proposition => proposition.toJSON())
},
});
}

if (isNonEmptyArray(currentViewPropositions)) {
logger.logOnContentRendering({
status: "rendering-started",
message: `Rendering propositions started for view scope - ${personalizationDetails.getViewName()}.`,
logLevel: "info",
detail: {
scope: personalizationDetails.getViewName(),
propositions: currentViewPropositions.map(proposition => proposition.toJSON())
},
});
}

render().then(handleNotifications);

// Render could take a long time especially if one of the renders
Expand Down
13 changes: 12 additions & 1 deletion src/components/Personalization/createViewChangeHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag
governing permissions and limitations under the License.
*/

export default ({ processPropositions, viewCache }) => {
export default ({ processPropositions, viewCache, logger }) => {
return ({ personalizationDetails, onResponse }) => {
let returnedPropositions;
let returnedDecisions;
Expand All @@ -28,6 +28,17 @@ export default ({ processPropositions, viewCache }) => {
if (personalizationDetails.isRenderDecisions()) {
({ render, returnedPropositions, returnedDecisions } =
processPropositions(propositions));

logger.logOnContentRendering({
status: "rendering-started",
message: `Started rendering propositions for view scope - ${viewName}.`,
logLevel: "info",
detail: {
scope: viewName,
propositions: propositions.map(proposition => proposition.toJSON())
},
});

return render();
}
({ returnedPropositions, returnedDecisions } = processPropositions(
Expand Down
77 changes: 46 additions & 31 deletions src/components/Personalization/flicker/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,36 +56,51 @@ export const showElements = (prehidingSelector) => {
}
};

export const hideContainers = (prehidingStyle) => {
if (!prehidingStyle) {
return;
}

// If containers prehiding style has been added
// by customer's prehiding snippet we don't
// want to add the same node
const node = getElementById(PREHIDING_ID);

if (node) {
return;
}

const nonce = getNonce();
const attrs = { id: PREHIDING_ID, ...(nonce && { nonce }) };
const props = { textContent: prehidingStyle };
const styleNode = createNode(STYLE, attrs, props);

appendNode(document.head, styleNode);
};

export const showContainers = () => {
// If containers prehiding style exists
// we will remove it
const node = getElementById(PREHIDING_ID);

if (!node) {
return;
export const createHideContainers = ( logger ) => {
return ( prehidingStyle ) => {
if (!prehidingStyle) {
return;
}

// If containers prehiding style has been added
// by customer's prehiding snippet we don't
// want to add the same node
const node = getElementById(PREHIDING_ID);

if (node) {
return;
}

const nonce = getNonce();
const attrs = { id: PREHIDING_ID, ...(nonce && { nonce }) };
const props = { textContent: prehidingStyle };
const styleNode = createNode(STYLE, attrs, props);

logger.logOnContentHiding({
status: "hide-containers",
message: "Prehiding style applied to hide containers.",
logLevel: "info",
});

appendNode(document.head, styleNode);
};
}

export const createShowContainers = ( logger ) => {
return () => {
// If containers prehiding style exists
// we will remove it
const node = getElementById(PREHIDING_ID);

if (!node) {
return;
}

logger.logOnContentHiding({
status: "show-containers",
message: "Prehiding style removed to show containers.",
logLevel: "info",
});
removeNode(node);
}

removeNode(node);
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ OF ANY KIND, either express or implied. See the License for the specific languag
governing permissions and limitations under the License.
*/

import {groupBy} from "../../../utils/index.js";

export default ({ schemaProcessors, logger }) => {
const wrapRenderWithLogging = (render, item) => () => {
return Promise.resolve()
Expand All @@ -21,11 +23,19 @@ export default ({ schemaProcessors, logger }) => {
return true;
})
.catch((error) => {
if (logger.enabled) {
const { message, stack } = error;
const warning = `Failed to execute action ${item.toString()}. ${message} ${stack}`;
logger.warn(warning);
}
const { message, stack } = error;
const warning = `Failed to execute action ${item.toString()}. ${message} ${stack}`;
logger.logOnContentRendering({
status: "rendering-failed",
detail: {
propositionDetails: item.getProposition().getNotification(),
item: item.toJSON()
},
error,
message: warning,
logLevel: "warn",
});

return false;
});
};
Expand Down Expand Up @@ -186,7 +196,18 @@ export default ({ schemaProcessors, logger }) => {
});
const render = () => {
return Promise.all(renderers.map((renderer) => renderer())).then(
(metas) => metas.filter((meta) => meta),
(metas) => {
const renderedPropositions = metas.filter((meta) => meta);
const propsByScope = groupBy(renderedPropositions, (p) => p.scope);
logger.logOnContentRendering({
status: "rendering-succeeded",
detail: {...propsByScope},
message: `Scopes: ${propsByScope} successfully executed.`,
logLevel: "info",
});

return renderedPropositions;
},
);
};
return { returnedPropositions, returnedDecisions, render };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ export default ({ logger, executeRedirect, collect }) =>
decisionsMeta: [item.getProposition().getNotification()],
documentMayUnload: true,
}).then(() => {
logger.logOnContentRendering({
status: "rendering-redirect",
detail: {
propositionDetails: item.getProposition().getNotification(),
redirect: content,
},
message: `Redirect action ${item.toString()} executed.`,
logLevel: "info",
});
return executeRedirect(content);
// Execute redirect will never resolve. If there are bottom of page events that are waiting
// for display notifications from this request, they will never run because this promise will
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ export default ({ preprocess, isPageWideSurface }) => {

return {
getScope() {
if (!scope) {
return scope;
}
return scope;
},
getScopeType() {
Expand Down
7 changes: 6 additions & 1 deletion src/components/Personalization/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import createComponent from "./createComponent.js";
import { initDomActionsModules } from "./dom-actions/index.js";
import createCollect from "../../utils/createCollect.js";
import { hideContainers, showContainers } from "./flicker/index.js";
import { createHideContainers, createShowContainers } from "./flicker/index.js";
import createFetchDataHandler from "./createFetchDataHandler.js";
import collectClicks from "./dom-actions/clicks/collectClicks.js";
import isAuthoringModeEnabled from "./utils/isAuthoringModeEnabled.js";
Expand Down Expand Up @@ -70,6 +70,9 @@ const createPersonalization = ({ config, logger, eventManager, consent }) => {
} = config;
const collect = createCollect({ eventManager, mergeDecisionsMeta });

const showContainers = createShowContainers(logger);
const hideContainers = createHideContainers(logger);

const { storeInteractionMeta, getInteractionMetas } =
createInteractionStorage();

Expand Down Expand Up @@ -133,6 +136,7 @@ const createPersonalization = ({ config, logger, eventManager, consent }) => {
createProposition,
notificationHandler,
consent,
logger,
});

const onClickHandler = createOnClickHandler({
Expand All @@ -148,6 +152,7 @@ const createPersonalization = ({ config, logger, eventManager, consent }) => {
const viewChangeHandler = createViewChangeHandler({
processPropositions,
viewCache,
logger,
});
const applyPropositions = createApplyPropositions({
processPropositions,
Expand Down
13 changes: 13 additions & 0 deletions src/core/createLogger.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ export default ({ getDebugEnabled, console, getMonitors, context }) => {
data.error,
);
},
logOnContentHiding(data) {
notifyMonitors("onContentHiding", {
status: data.status,
});
log(data.logLevel, data.message);
},
logOnContentRendering(data) {
notifyMonitors("onContentRendering", {
status: data.status,
payload: data.detail,
});
log(data.logLevel, data.message);
},
/**
* Outputs informational message to the web console. In some
* browsers a small "i" icon is displayed next to these items
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe("Personalization::createFetchDataHandler", () => {
let renderedPropositions;
let notificationHandler;
let consent;

let logger;
let cacheUpdate;
let personalizationDetails;
let event;
Expand All @@ -36,6 +36,7 @@ describe("Personalization::createFetchDataHandler", () => {
let response;

beforeEach(() => {
logger = jasmine.createSpyObj("logger", ["logOnContentRendering"]);
prehidingStyle = "myprehidingstyle";
showContainers = jasmine.createSpy("showContainers");
hideContainers = jasmine.createSpy("hideContainers");
Expand Down Expand Up @@ -80,6 +81,7 @@ describe("Personalization::createFetchDataHandler", () => {
createProposition,
notificationHandler,
consent,
logger,
});
fetchDataHandler({
cacheUpdate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ describe("Personalization::createViewChangeHandler", () => {
let personalizationDetails;
let event;
let onResponse;

let logger;
let createProposition;

beforeEach(() => {
logger = jasmine.createSpyObj("logger", ["logOnContentRendering"]);
processPropositions = jasmine.createSpy("processPropositions");
viewCache = jasmine.createSpyObj("viewCache", ["getView"]);

Expand All @@ -43,6 +44,7 @@ describe("Personalization::createViewChangeHandler", () => {

const run = async () => {
const viewChangeHandler = createViewChangeHandler({
logger,
processPropositions,
viewCache,
});
Expand All @@ -69,6 +71,7 @@ describe("Personalization::createViewChangeHandler", () => {

const { decisionsMeta, result } = await run();

expect(logger.logOnContentRendering).toHaveBeenCalledTimes(1);
expect(processPropositions).toHaveBeenCalledTimes(1);
expect(decisionsMeta).toEqual("decisionMeta");

Expand Down
Loading
Loading