4æããKaizen Platformã«ã¸ã§ã¤ã³ããã¢ããªã±ã¼ã·ã§ã³ã¨ã³ã¸ãã¢ã®ikedayu@ã¤ãã°ã§ããæ¥åã§ã¯ãã¼ã¿è§£æã解æåºç¤æ§ç¯ã主ã«è¡ã£ã¦ãã¾ãã
Kaizen Platformã§ã¯ã許å¯ãæ±ãããªãè¬ç½ªããã®æåãæ·±ã浸éãã¦ãã¦ãã¨ã³ã¸ãã¢ä¸äººã²ã¨ãã®è£éã大ããã®ãç¹å¾´ã§ããèªåã¯ããã®è£éã§ãã°ãã°èªç±ç 究çã«èº«è¿ãªåé¡ã«ææ¦ãã¦ãã¦ãä»åã¯ããã®1ã¤ã«ã¤ãã¦ç´¹ä»ããã¦ãããã¾ãã
TL;DR
- âã®ãããªBigQueryã³ã¹ããå¯è¦åããããã·ã¥ãã¼ããä½ãã¾ã
- ãæ¥ä»ãã¨ã®ã³ã¹ãã®æ¨ç§»ãã¨ãIAMã¦ã¼ã¶ã¼ãã¨ã®ã³ã¹ãããå¯è¦åãããã¨ã§ã³ã¹ãåæ¸ã®æ¹çãç«ã¦ããããªãã¾ã
- G Suiteã ãã§å®çµããã®ã§ã(G Suiteã使ã£ã¦ããä¼æ¥ã§ããã°) ããã«å°å ¥å¯è½ã§ã
課é¡: BigQueryã®ã³ã¹ãã¯ãã£ããã¨ããããããªã
Kaizen Platformã§ã¯ä»ã®ããããã®ä¼ç¤¾ã¨åãããã«æ§ã ãªç¨éã§BigQueryã使ã£ã¦ãã¾ãã ãµã¼ãã¹ã§å©ç¨ããããChartioãªã©ã®BIãã¼ã«ããèªåã®ãããªãã¼ã¿è§£æè ãç´æ¥BigQueryãå©ããªã©ãã¨ã³ã¸ãã¢/éã¨ã³ã¸ãã¢ã人é¡/é人é¡ã«é¢ããã使ç¨æ¹æ³ã¯å¤å²ã«æ¸¡ãã¾ãã ãããã£ã使ãæ¹ããã¦ãã¦ãä¼ç¤¾ã®è¦æ¨¡ã大ãããªã£ã¦ããã¨ãå½ç¶ããããä»æã®BigQueryæéé«ããâ¦ï¼ãã¨ããç¶æ ã«ãªã£ãããã¾ããããããGCPã®ã³ã³ã½ã¼ã«ã ã¨èª°ãåæ¥ã§ã©ã®ããã使ã£ã¦ããã®ããããããªããã¨ãã課é¡ãããã¾ããã
ã課éè¦å¯ãã®å°å ¥
ãã®å¯¾çã®1ã¤ã¨ãã¦Kaizen Platformã§ã¯âã®Gunosyããããã£ã¦ãããããªèª²éè¦å¯ãå°å ¥ãã¦ãããé«ã³ã¹ããªQueryã¯æ¤ç¥ãããã¨ãã§ãã¦ãã¾ããã data.gunosy.io
ãã 課éè¦å¯ã¯å¨åã®ããã¯ã³ãã³ããæ¤ç¥ãããã¨ã«ã¯åãã¦ããã®ã§ãããæ¯æ¥ã³ãã³ãç©ã¿éãªãå¾ããå¹ãã¦ããã¸ã£ããæ¤ç¥ããã®ã¯é£ããã¨ãã課é¡ãããã¾ããã
ãè²»ç¨ç®¡çãæ©è½ã®åã«
GCPãã¢ã«ã¦ã³ããã¨ã«ã³ã¹ãã管çã§ããæ©è½ãæä¾ãã¦ããã®ã§ãããã¢ã«ã¦ã³ããã¨ã«è¨å®ããã®ã大å¤ï¼ã©ã®ç¨åº¦ã®é¾å¤ãè¨å®ãã¹ããæ¤è¨ãã¤ããã®ãé£ããã¨ããåé¡ãããã¾ãã
費用管理 | BigQuery | Google Cloud
ã¨ãããã¨ã§ãã¨ããããå¯è¦åãã¦ã¿ããã¨ã«ãã¾ããã
G Suiteã使ãã
å¯è¦åã«ããã£ã¦è²ã ãªé¸æè¢ãããã¾ããããä»åã¯èªç±ç 究çãªæ§è³ªãå¼·ãã£ãã®ã§ãäºç®çãªé¢ãéç¨çãªé¢ãèããªãã¦è¯ãG Suiteãé¸æãã¾ããã(ã¡ãªã¿ã«Kaizen Platformçã«ã¯åè¿°ããããã«è£éã大ããã®ã§ããµã¼ãã¼ç«ã¦ã¦éç¨ãããã§ããã¨ãã話ã§ãä½è£ã§OKã ã¨æãã¾ãããä»åã¯åç´ã«èªåãèããããªãã£ããã¨ãã話ã§ããç¬)
æ§æã¯ãããªæãã§ããã³ã¢é¨åã¯Google Apps Scriptã¨Google Sheetsã§ãGoogle Sitesã¯ã°ã©ããåãè¾¼ãã§ããã ãã«ãªãã¾ãã
ãã®ã1. BQ(BigQuery) APIã§Jobåå¾ãã2. SS(Spreadsheet) APIã§æ¸ãåºããã3.ã°ã©ããä½æ/åãè¾¼ã¿ããç°¡åã«è§£èª¬ããã¦ããã ãã¾ãã
[Google Apps Script] BigQuery APIã§Jobåå¾
Google Apps Scriptã«ã¯Built-inã§BigQuery APIã«ã¢ã¯ã»ã¹ããObjectãç¨æããã¦ããã®ã§ãèªè¨¼ãå ¨ãèãããã¨ãªãAPIã«æ¥½ã ã¢ã¯ã»ã¹ã§ãã¾ãã BigQuery Service | Apps Script | Google Developers
APIã¢ã¯ã»ã¹é¨åã¯ãããªæãã§æ¸ãã¦ãã¾ãã
utility.getJobsFromBqApi = function(maxResults, minCreationTime, nextPageToken){ maxResults = maxResults || 1000 minCreationTime = minCreationTime || null nextPageToken = nextPageToken || null const projectId = 'myProjectId' var options = { 'maxResults': maxResults, 'stateFilter': 'done', 'projection': 'full', 'allUsers': true, 'minCreationTime': minCreationTime, 'pageToken': nextPageToken } const response = BigQuery.Jobs.list(projectId, options) return response }
注æç¹: ä¸åº¦ã«Jobãå ¨ã¦åå¾/å¦çã§ããªã
Google Apps Scriptã¯ä¸åº¦ã«å®è¡ã§ããJobã®å®è¡æéã®ä¸éã5åã«ãªã£ã¦ãã¾ãããã®ããBigQueryã®ä½¿ãæ¹ã«ãããã¾ããããµã¼ãã¹ãBIãã¼ã«ã§ã®å©ç¨ãããå ´åã¯ä¸åº¦ã«ã§ããªãã±ã¼ã¹ãå¤ãã¨æãã¾ãããã®ããã ãã¼ã¿ç®¡çç¨ã®ã¹ãã¬ããã·ã¼ãã« state
ã·ã¼ããä½æããä¸è¨ãããããä¿åãã¦ããä½ãã«ãªã£ã¦ãã¾ãã
tmpLatestTime
: å ¨ä»¶åå¾ã§ããªãã£ãã¨ãã«æ¬¡åminCreationTime
ãã©ã¡ã¼ã¿ã¨ãã¦ä½¿ãUnixTimestampnextPagetoken
: å ¨ä»¶åå¾ã§ããªãã£ãã¨ãã«æ¬¡åpageToken
ãã©ã¡ã¼ã¿ã¨ãã¦ä½¿ãtoken
ã¡ãªã¿ã«latestTime
ã¯åå¾ãããã¼ã¿ã®ææ°æ¥æ(UnixTimestamp)ãä¿åãã¦ãã¾ãã
claspã§ã³ã¼ã管ç
ä»ã¾ã§ã¯Google Apps Scriptãã³ã¼ã管çããã®ã¯GoogleDriveä¸ã§è¡ããªããã°ãªãããGoogle Apps Script APIã使ã£ã¦ããæãã«ãã¦ãããthird party libraryã¯ãã£ãã®ã§ãããä»å¹´ãå
¬å¼CLIã® clasp
ãçºè¡¨ãããã®ã§æè¿æ¸ãGoogle Apps Scriptã³ã¼ãã¯å
¨ã¦ããã§ç®¡çãã¦ã¾ããåä½ãä¸å®å®ãªæãããã¾ãããç¶ç¶çã«éçºãããã¦ãã¦ã©ãã©ãä¿®æ£ããã¦ãã¾ããã大ä½æºè¶³ãã¦ä½¿ã£ã¦ã¾ãã
[Google Apps Script] ã¹ãã¬ããã·ã¼ãã«ãã¼ã¿æ¸ãåºã
BigQuery APIããåå¾ããJobãã¼ã¿ãã¹ãã¬ããã·ã¼ãã«æ¸ãåºãã¾ããè¦æè¦æã®å®è£ ã ãåãåºãã¨ãããªæãã«ãªãã¾ãã
var SheetManager = function(){ this.thisMonth = Utilities.formatDate(new Date(), "UTC", "YYYYMM") this.spreadSheet = SpreadsheetApp.openById(SSID) this.priceSheet = this.spreadSheet.getSheetByName(this.thisMonth) } SheetManager.prototype.setPrices = function(prices){ priceArr = this.convertPricesToArr(prices) this.priceSheet.getRange(2, 1, priceArr.length, priceArr[0].length).setValues(priceArr); } SheetManager.prototype.convertPricesToArr = function (prices){ var priceArr = [] Object.keys(prices).forEach(function(date) { var emailPrice = Object.keys(prices[date]).forEach(function(email) { priceArr.push([date, email, prices[date][email]]); }); }); // Sortãã¦ããåºå priceArr.sort(utility.sortFunction) return priceArr }
注æç¹: ã¹ãã¬ããã·ã¼ãã®ã»ã«ã®ä¸éã¯40000
æåã¯åå¾ããJobæ
å ±ãã¹ãã¬ããã·ã¼ãã«æ¸ãåºãã¦ããã®ã§ãããããã«ã¨ã©ã¼ãçºçãå§ãã¾ãããããã¯ã¹ãã¬ããã·ã¼ãã®ã»ã«ã®æ°ã«40000ã¨ããä¸éããã£ãããã§ãããã®ããåå¾ã®åº¦ã«ã¢ã°ãªã²ã¼ã·ã§ã³ãè¡ã£ã¦ãã¾ãã
ã³ã¼ããæç²ãã¦ç´¹ä»ããã¨ä¸ã®ãããªæãã§ããã¢ã°ãªã²ã¼ã·ã§ã³ã«é¢ãã¦ã¯Objectã使ã£ãæç´ãªå®è£
ããã¦ãã¾ããã¾ãGoogle Sheetsã¨Google Apps Scriptã§TimeZoneãéãã®ã§ Utilities.formatDate
ã使ãã¨ããããã¤ã³ãã§ãã
var CostManager = function(){ this.sheetManager = new SheetManager() } CostManager.prototype.getCurrentPrices = function(){ this.prices = this.sheetManager.getCurrentPrices() } CostManager.prototype.updateJobs = function(){ var that = this this.jobs.forEach(function(job){ const stats = job['statistics'] const totalBytes = stats['query'] ? stats['query']['totalBytesBilled'] : 0 const timeStamp = parseInt(stats['creationTime']) const date = Utilities.formatDate(new Date(timeStamp + 1000*60*60*13), "UTC", "YYYY-MM-DD") const teraBytes = parseInt(totalBytes, 10)/Math.pow(1000, 4) const price = teraBytes * 5 const email = job['user_email'] // ããéé¡ãçºçãã¦ããã°pricesãupdate if(price > 0){ if(!that.prices[date]) { that.prices[date] = {} } if(!that.prices[date][email]){ that.prices[date][email] = 0 } that.prices[date][email] += price } }) } SheetManager.prototype.getCurrentPrices = function(){ data = this.priceSheet.getDataRange().getValues().slice(1) const prices = {} data.forEach(function(d){ var date = Utilities.formatDate(d[0], "JST", "YYYY-MM-DD") var email = d[1] var price = d[2] if(!prices[date]) {prices[date] = {}} prices[date][email] = price }) return prices }
ããã§ç¡äºJobãã¼ã¿ãæ¸ãåºããã¨ãåºæ¥ã¾ããã
[Google Sheets/Google Sites] ã°ã©ããä½æ/åãè¾¼ã¿
ããããã¾ã§æ¥ãã°ããã¨ã¯Google Sheetsã¨Google Sitesãããã£ã¦ããã®ã¿ã«ãªãã¾ãã ããã·ã¥ãã¼ãã«è¡¨ç¤ºããããã¼ã¿ã¯ããç¨åº¦çµãããã®ã§ä»åã¯å½æåã®è¡¨ç¤ºãããããã¨ã«ãã¾ãã æåã¯æãã¨ã«Google Sitesã®ã°ã©ããåãæ¿ããæ¹æ³ã«ã¤ãã¦æ©ãã ã®ã§ããããããä¸çªãæ軽ããªã¨æã£ã¦ãã¾ããã¾ãå ã»ã©ç´¹ä»ãããstateãã·ã¼ãã«å¯¾è±¡æ(ä»æ)ãå ¥ããããGoogle Apps Scriptã§æ¸ãã¾ãã
次ã«ãcurrentãã·ã¼ããä½ããINDIRECT
é¢æ°ã§å¯¾è±¡æã®ãã¼ã¿ãèªã¿è¾¼ãã§ãã¾ãã(æãã¨ã«ã¹ãã¬ããã·ã¼ããä½æãã¦ãã¼ã¿ãæ¸ãè¾¼ãã§ãã¾ã) INDIRECT
é¢æ°ã¯åãã¦ä½¿ã£ãã®ã§ãããæååãevalãã¦ããããããªé¢æ°ã§ä¾¿å©ã§ããã
èªã¿è¾¼ãã§ãããããcurrentãã·ã¼ãã§ã°ã©ããä½æãã¾ãã ãããããã¨ã«ãã£ã¦ããstateãã·ã¼ãã®å¯¾è±¡æãæ¸ãæããã ãã§ããã¼ã¿åã³ã°ã©ãã対象æã®ãã¼ã¿ã«åãæ¿ããã¾ãã
ãã¨ã¯ãGoogle Sitesã®ã°ã©ãåãè¾¼ã¿æ©è½ã使ãã ãã§ãã
ããã§æãã¨ã«èªåã§åãæ¿ããããã·ã¥ãã¼ããã§ãã¾ããããã§ãããã§ããã§ãï¼
解決/ã¾ã¨ã/è£è¶³
Google Apps Script/Google Sheets/Google Sitesã使ã£ã¦ãã¢ã«ã¦ã³ããã¨/æ¥ä»ãã¨ã®BigQueryã³ã¹ããå¯è¦åã§ããããã·ã¥ãã¼ããä½æã§ãã¾ããã
å¯è¦åãã¦ããã£ããã¨
社å ã§å ¬éãã¦ã¿ãã¨ããã課éè¦å¯ã ãã§ã¯ããããªãã£ãå¾åããå©ç¨æã®å¤ãã¢ã«ã¦ã³ããå¤æãã¾ãããã¾ããã¢ã«ã¦ã³ã管çã®é¢ã§ããå²ã¨ãã£ããã¨ã¢ã«ã¦ã³ããåãã¦ããã®ã§ãä»å¾SREä¸å¿ã«æ´çãã¦ããããã¨ãããã¨ã«ãªããã³ã¹ãåæ¸ã®æµãã«è²¢ç®ãããã¨ãã§ãã¦è¯ãã£ãã§ãï¼
ã¡ãªã¿ã«ãããã¿ã¤ãã¯Pythonã§ä½ãã¾ããã
æåã¯Jupyterï¼Matplotlibã§ã°ã©ãããã£ã¨ä½ã£ã¦ã¿ã¦å®æå½¢ã®ã¤ã¡ã¼ã¸ãåºãã¾ããããããã¿ã¤ã -> æ¬çªãããã¯ãä½æãã¨ããæµãã¯å®çªã§ãããä»åãå®æå½¢ã®ã¤ã¡ã¼ã¸ã«é¢ãã¦ã¯ææ»ãããªãã£ãã®ã§ã¨ã¦ãæç¨ã ãªãã¨æ¹ãã¦æãã¾ããã
åç
æåããæ軽ã«ä½ããã¨èãã¦ããã®ã§ãããä½ã£ã¦ã¿ããæå¤ã¨èãããã¨ãå¤ãã¦ãããã¾ããæ軽ãããªããªã£ã¦ãã¾ã£ããªãã¨æã£ã¦ãã¾ããç¬ ãã®è¨äºã§ãå ¨ã¦ã®æé ãç´¹ä»ããããªãã£ãã®ã§ãããä¸æç¹çããã¾ããããTwitterãªã©ã§è³ªåãã¦ããã ããã°å¹¸ãã§ãmm
æå¾ã«
Kaizen Platformã¯ãä»åã®ãããªèªç±ç 究çãªãã¨ã«ãã©ãã©ãææ¦ããã¦ããããé¢ç½ãç°å¢ãªã®ã§ãã¾ãã©ãã©ãææ¦ãã¦ããããã¨æã£ã¦ã¾ãããããªé¢ç½ãç°å¢ã§åãã¦ã¿ããæ¹ã¯æ¡ç¨ãã¼ã¸ãæ¯éãã§ãã¯ãã¦ã¿ã¦ãã ããï¼ã§ã¯ã§ã¯ã