@@ -137,11 +137,22 @@ export class ExecutionStore {
137137 */
138138 private writeToAnalytics ( record : SaveExecutionRecord ) : void {
139139 try {
140+ if ( ! this . env . EXECUTIONS ) {
141+ console . warn (
142+ `ExecutionStore.writeToAnalytics: EXECUTIONS binding not available - skipping analytics write`
143+ ) ;
144+ return ;
145+ }
146+
140147 const durationMs =
141148 record . endedAt && record . startedAt
142149 ? record . endedAt . getTime ( ) - record . startedAt . getTime ( )
143150 : 0 ;
144151
152+ console . log (
153+ `ExecutionStore.writeToAnalytics: Writing execution ${ record . id } (status: ${ record . status } ) to dataset ${ this . getDatasetName ( ) } `
154+ ) ;
155+
145156 this . env . EXECUTIONS . writeDataPoint ( {
146157 indexes : [ record . organizationId , record . id ] ,
147158 blobs : [
@@ -165,9 +176,25 @@ export class ExecutionStore {
165176 * Query Analytics Engine using SQL API
166177 */
167178 private async queryAnalytics ( sql : string ) : Promise < any [ ] > {
179+ // Validate required credentials
180+ if ( ! this . env . CLOUDFLARE_ACCOUNT_ID || ! this . env . CLOUDFLARE_API_TOKEN ) {
181+ console . error (
182+ `ExecutionStore.queryAnalytics: Missing credentials - CLOUDFLARE_ACCOUNT_ID: ${ ! ! this . env . CLOUDFLARE_ACCOUNT_ID } , CLOUDFLARE_API_TOKEN: ${ ! ! this . env . CLOUDFLARE_API_TOKEN } `
183+ ) ;
184+ throw new Error (
185+ "Analytics Engine queries require CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN to be configured. " +
186+ "In development: add to .dev.vars file. " +
187+ "In production: use 'wrangler secret put' to set these values."
188+ ) ;
189+ }
190+
168191 try {
169192 const url = `https://api.cloudflare.com/client/v4/accounts/${ this . env . CLOUDFLARE_ACCOUNT_ID } /analytics_engine/sql` ;
170193
194+ console . log (
195+ `ExecutionStore.queryAnalytics: Querying dataset with account ID ${ this . env . CLOUDFLARE_ACCOUNT_ID . substring ( 0 , 8 ) } ...`
196+ ) ;
197+
171198 const response = await fetch ( url , {
172199 method : "POST" ,
173200 headers : {
@@ -178,6 +205,19 @@ export class ExecutionStore {
178205
179206 if ( ! response . ok ) {
180207 const error = await response . text ( ) ;
208+ console . error (
209+ `ExecutionStore.queryAnalytics: HTTP ${ response . status } - ${ error } `
210+ ) ;
211+
212+ // Check for common permission issues
213+ if ( response . status === 401 || response . status === 403 ) {
214+ throw new Error (
215+ `Analytics Engine query authentication failed (${ response . status } ). ` +
216+ `Verify your API token has "Account Analytics: Read" permission. ` +
217+ `Error: ${ error } `
218+ ) ;
219+ }
220+
181221 throw new Error (
182222 `Analytics query failed: ${ response . statusText } - ${ error } `
183223 ) ;
@@ -211,6 +251,10 @@ export class ExecutionStore {
211251 try {
212252 const dataset = this . getDatasetName ( ) ;
213253
254+ console . log (
255+ `ExecutionStore.readFromAnalytics: Querying ${ dataset } for execution ${ id } `
256+ ) ;
257+
214258 const sql = `
215259 SELECT *
216260 FROM ${ dataset }
@@ -223,12 +267,19 @@ export class ExecutionStore {
223267 const rows = await this . queryAnalytics ( sql ) ;
224268
225269 if ( rows . length === 0 ) {
270+ console . log (
271+ `ExecutionStore.readFromAnalytics: No data found for execution ${ id } `
272+ ) ;
226273 return undefined ;
227274 }
228275
229276 const row = rows [ 0 ] ;
230277 const timestamp = new Date ( row . timestamp ) ;
231278
279+ console . log (
280+ `ExecutionStore.readFromAnalytics: Found execution ${ id } with status ${ row . blob3 } `
281+ ) ;
282+
232283 return {
233284 id : row . index2 ,
234285 workflowId : row . blob1 ,
@@ -273,6 +324,10 @@ export class ExecutionStore {
273324 const limit = options ?. limit ?? 20 ;
274325 const offset = options ?. offset ?? 0 ;
275326
327+ console . log (
328+ `ExecutionStore.listFromAnalytics: Querying ${ dataset } for org ${ organizationId . substring ( 0 , 8 ) } ... (limit: ${ limit } , offset: ${ offset } )`
329+ ) ;
330+
276331 const sql = `
277332 SELECT *
278333 FROM ${ dataset }
@@ -283,6 +338,10 @@ export class ExecutionStore {
283338
284339 const rows = await this . queryAnalytics ( sql ) ;
285340
341+ console . log (
342+ `ExecutionStore.listFromAnalytics: Found ${ rows . length } executions`
343+ ) ;
344+
286345 return rows . map ( ( row ) => {
287346 const timestamp = new Date ( row . timestamp ) ;
288347 return {
0 commit comments