[main] instrument the typedoc github pages with ApplicationInsights (#2237)

This commit is contained in:
siyuniu-ms 2024-01-17 10:32:10 -08:00 коммит произвёл GitHub
Родитель 1bc9e7254e
Коммит 3fd40cf8c7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
4 изменённых файлов: 158 добавлений и 1 удалений

58
.github/workflows/jekyll-gh-pages.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,58 @@
# Sample workflow for building and deploying a Jekyll site to GitHub Pages
name: Deploy Jekyll with GitHub Pages dependencies preinstalled
on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# Build job
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Build Snippet File
run: |
cd tools/applicationinsights-web-snippet
npm install
npm run build
- name: Inject Script
run: node ./tools/github-page-script-injection/injectScript.js
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Build with Jekyll
uses: actions/jekyll-build-pages@v1
with:
source: ./
destination: ./_site
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
# Deployment job
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

13
_includes/snippet.html Normal file
Просмотреть файл

@ -0,0 +1,13 @@
<script type="text/javascript">!(function (cfg){function e(){cfg.onInit&&cfg.onInit(i)}var S,p,D,t,n,i,C=window,x=document,w=C.location,I="script",b="ingestionendpoint",E="disableExceptionTracking",A="ai.device.";"instrumentationKey"[S="toLowerCase"](),p="crossOrigin",D="POST",t="appInsightsSDK",n=cfg.name||"appInsights",(cfg.name||C[t])&&(C[t]=n),i=C[n]||function(u){var d=!1,g=!1,f={initialize:!0,queue:[],sv:"7",version:2,config:u};function m(e,t){var n={},i="Browser";function a(e){e=""+e;return 1===e.length?"0"+e:e}return n[A+"id"]=i[S](),n[A+"type"]=i,n["ai.operation.name"]=w&&w.pathname||"_unknown_",n["ai.internal.sdkVersion"]="javascript:snippet_"+(f.sv||f.version),{time:(i=new Date).getUTCFullYear()+"-"+a(1+i.getUTCMonth())+"-"+a(i.getUTCDate())+"T"+a(i.getUTCHours())+":"+a(i.getUTCMinutes())+":"+a(i.getUTCSeconds())+"."+(i.getUTCMilliseconds()/1e3).toFixed(3).slice(2,5)+"Z",iKey:e,name:"Microsoft.ApplicationInsights."+e.replace(/-/g,"")+"."+t,sampleRate:100,tags:n,data:{baseData:{ver:2}},ver:4,seq:"1",aiDataContract:undefined}}var h=-1,v=0,y=["js.monitor.azure.com","js.cdn.applicationinsights.io","js.cdn.monitor.azure.com","js0.cdn.applicationinsights.io","js0.cdn.monitor.azure.com","js2.cdn.applicationinsights.io","js2.cdn.monitor.azure.com","az416426.vo.msecnd.net"],k=u.url||cfg.src;if(k){if((n=navigator)&&(~(n=(n.userAgent||"").toLowerCase()).indexOf("msie")||~n.indexOf("trident/"))&&~k.indexOf("ai.3")&&(k=k.replace(/(\/)(ai\.3\.)([^\d]*)$/,function(e,t,n){return t+"ai.2"+n})),!1!==cfg.cr)for(var e=0;e<y.length;e++)if(0<k.indexOf(y[e])){h=e;break}var i=function(e){var a,t,n,i,o,r,s,c,l,p;f.queue=[],g||(0<=h&&v+1<y.length?(a=(h+v+1)%y.length,T(k.replace(/^(.*\/\/)([\w\.]*)(\/.*)$/,function(e,t,n,i){return t+y[a]+i})),v+=1):(d=g=!0,s=k,!0!==cfg.dle&&(c=(t=function(){var e,t={},n=u.connectionString;if(n)for(var i=n.split(";"),a=0;a<i.length;a++){var o=i[a].split("=");2===o.length&&(t[o[0][S]()]=o[1])}return t[b]||(e=(n=t.endpointsuffix)?t.location:null,t[b]="https://"+(e?e+".":"")+"dc."+(n||"services.visualstudio.com")),t}()).instrumentationkey||u.instrumentationKey||"",t=(t=(t=t[b])&&"/"===t.slice(-1)?t.slice(0,-1):t)?t+"/v2/track":u.endpointUrl,(n=[]).push((i="SDK LOAD Failure: Failed to load Application Insights SDK script (See stack for details)",o=s,l=t,(p=(r=m(c,"Exception")).data).baseType="ExceptionData",p.baseData.exceptions=[{typeName:"SDKLoadFailed",message:i.replace(/\./g,"-"),hasFullStack:!1,stack:i+"\nSnippet failed to load ["+o+"] -- Telemetry is disabled\nHelp Link: https://go.microsoft.com/fwlink/?linkid=2128109\nHost: "+(w&&w.pathname||"_unknown_")+"\nEndpoint: "+l,parsedStack:[]}],r)),n.push((p=s,i=t,(l=(o=m(c,"Message")).data).baseType="MessageData",(r=l.baseData).message='AI (Internal): 99 message:"'+("SDK LOAD Failure: Failed to load Application Insights SDK script (See stack for details) ("+p+")").replace(/\"/g,"")+'"',r.properties={endpoint:i},o)),s=n,c=t,JSON&&((l=C.fetch)&&!cfg.useXhr?l(c,{method:D,body:JSON.stringify(s),mode:"cors"}):XMLHttpRequest&&((p=new XMLHttpRequest).open(D,c),p.setRequestHeader("Content-type","application/json"),p.send(JSON.stringify(s)))))))},a=function(e,t){g||setTimeout(function(){!t&&f.core||i()},500),d=!1},T=function(e){var n=x.createElement(I),e=(n.src=e,cfg[p]);return!e&&""!==e||"undefined"==n[p]||(n[p]=e),n.onload=a,n.onerror=i,n.onreadystatechange=function(e,t){"loaded"!==n.readyState&&"complete"!==n.readyState||a(0,t)},cfg.ld&&cfg.ld<0?x.getElementsByTagName("head")[0].appendChild(n):setTimeout(function(){x.getElementsByTagName(I)[0].parentNode.appendChild(n)},cfg.ld||0),n};T(k)}try{f.cookie=x.cookie}catch(l){}function t(e){for(;e.length;)!function(t){f[t]=function(){var e=arguments;d||f.queue.push(function(){f[t].apply(f,e)})}}(e.pop())}var r,s,n="track",o="TrackPage",c="TrackEvent",n=(t([n+"Event",n+"PageView",n+"Exception",n+"Trace",n+"DependencyData",n+"Metric",n+"PageViewPerformance","start"+o,"stop"+o,"start"+c,"stop"+c,"addTelemetryInitializer","setAuthenticatedUserContext","clearAuthenticatedUserContext","flush"]),f.SeverityLevel={Verbose:0,Information:1,Warning:2,Error:3,Critical:4},(u.extensionConfig||{}).ApplicationInsightsAnalytics||{});return!0!==u[E]&&!0!==n[E]&&(t(["_"+(r="onerror")]),s=C[r],C[r]=function(e,t,n,i,a){var o=s&&s(e,t,n,i,a);return!0!==o&&f["_"+r]({message:e,url:t,lineNumber:n,columnNumber:i,error:a,evt:C.event}),o},u.autoExceptionInstrumented=!0),f}(cfg.cfg),(C[n]=i).queue&&0===i.queue.length?(i.queue.push(e),i.trackPageView({})):e();})({
src: "https://js.monitor.azure.com/scripts/b/ai.3.gbl.min.js",
// name: "appInsights", // Global SDK Instance name defaults to "appInsights" when not supplied
// ld: 0, // Defines the load delay (in ms) before attempting to load the sdk. -1 = block page load and add to head. (default) = 0ms load after timeout,
// useXhr: 1, // Use XHR instead of fetch to report failures (if available),
// dle: true, // Prevent the SDK from reporting load failure log
crossOrigin: "anonymous", // When supplied this will add the provided value as the cross origin attribute on the script tag
// onInit: null, // Once the application insights instance has loaded and initialized this callback function will be called with 1 argument -- the sdk instance (DO NOT ADD anything to the sdk.queue -- As they won't get called)
cfg: { // Application Insights Configuration
connectionString: "InstrumentationKey=814a172a-92fd-4950-9023-9cf13bb65696;IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/"
}
});
</script>

Просмотреть файл

@ -31,7 +31,8 @@
"npm-pack": "node common/scripts/install-run-rush.js npm-pack --verbose",
"npm-publish": "node ./tools/release-tools/npm_publish.js",
"npm-set-latest": "node ./tools/release-tools/npm_set_latest.js",
"gh-status": "node ./tools/status-tools/github-status.js"
"gh-status": "node ./tools/status-tools/github-status.js",
"api-docs": "rush api-docs"
},
"repository": {
"type": "git",

Просмотреть файл

@ -0,0 +1,85 @@
const fs = require('fs');
const path = require('path');
// Recursively process a folder and its subfolders to search for HTML files
const processFolder = (folderPath) => {
const files = fs.readdirSync(folderPath);
files.forEach((file) => {
const filePath = path.join(folderPath, file);
if (fs.statSync(filePath).isDirectory()) {
processFolder(filePath);
} else if (path.extname(file) === '.html') {
console.log(`process ${filePath}`);
injectScript(filePath);
} else if (path.extname(file) === '.md') {
console.log(`process ${filePath}`);
injectHtml(filePath);
}
});
};
// Start processing from the 'docs' folder
const docsFolder = path.join(__dirname, '../../docs');
// Prepare the script content to be injected
const scriptFilePath = path.join(__dirname, '../applicationinsights-web-snippet/build/output/snippet.min.js');
let scriptContent = fs.readFileSync(scriptFilePath, 'utf8');
// Replace the placeholder string with the actual connection string
const connectionString = 'InstrumentationKey=814a172a-92fd-4950-9023-9cf13bb65696;IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/';
scriptContent = scriptContent.replace('YOUR_CONNECTION_STRING', connectionString);
scriptContent = `<script type="text/javascript">${scriptContent}</script>`;
// write this file into _include folder so that later github would reject it inside markdown files
const includeFolderFile = path.join(__dirname, '../../_includes/script.html');
fs.writeFileSync(includeFolderFile, scriptContent, 'utf8');
// recursively process all html files under docs folder
processFolder(docsFolder);
function injectHtml(filePath) {
// Read the content of the Markdown file
const markdownContent = fs.readFileSync(filePath, 'utf8');
// Specify the injection string
const injectionString = `{% include script.html %}`;
// Append the injection string to the end of the Markdown content
const updatedContent = `${markdownContent}\n\n${injectionString}`;
// Write the updated content back to the file
fs.writeFileSync(filePath, updatedContent, 'utf8');
console.log(`Markdown file injection completed for ${filePath}`);
}
function injectScript(filePath) {
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
// Check if the script content is already present in the file
const fileContent = fs.readFileSync(filePath, 'utf8');
// Check if the script content is already present in the file
if (fileContent.includes(scriptContent)) {
console.log(`Script already present in ${filePath}`);
return;
}
// Create the modified content by inserting the script tag right before the closing head tag
const modifiedContent = data.replace(/(<\/head[^>]*)/i, `\n${scriptContent}\n$1`);
// Save the modified content back to the file
fs.writeFile(filePath, modifiedContent, (err) => {
if (err) {
console.error('Error writing to file:', err);
return;
}
console.log(`Script injected successfully into ${filePath}`);
});
});
}