@aj-2000-test/goodlogs-sdk 0.1.19 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +295 -36
- package/dist/index.d.ts +295 -36
- package/dist/index.js +3 -3
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
'use strict';var
|
|
2
|
-
`);if(!e)return;for(let t=3;t<Math.min(e.length,8);t++){let n=e[t]?.trim();if(!n||n.includes("goodlogs")&&(n.includes("client.")||n.includes("index.")))continue;let i=n.match(/at\s+(?:(.+?)\s+\()?(.+?):(\d+):\d+\)?/);if(i){let
|
|
1
|
+
'use strict';var m={us:"https://goodlogs-api-us.happyhill-a7c56143.centralindia.azurecontainerapps.io",eu:"https://goodlogs-api-eu.yellowmeadow-422296f6.japaneast.azurecontainerapps.io",ap:"https://goodlogs-api-ap.delightfulsand-90b72c09.southeastasia.azurecontainerapps.io"};function _(r){let e=r.split("_");return e.length>=4&&e[0]==="gl"?e[2]:"eu"}function d(r,e){if(e)return e;let t=_(r);return m[t]||m.eu}var R=5e3,I=50,u="0.2.2",h="gl_anon_id",g="gl_session_id";function c(){return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,r=>{let e=Math.random()*16|0;return (r==="x"?e:e&3|8).toString(16)})}function $(){let r={$goodlogs_sdk:"js",$goodlogs_sdk_version:u};return typeof navigator>"u"||(typeof screen<"u"&&(r.$screen=`${screen.width}x${screen.height}`),typeof navigator<"u"&&(r.$language=navigator.language??""),typeof location<"u"&&(r.$url=location.href,r.$path=location.pathname,r.$page=location.pathname.split("/").filter(Boolean).pop()||"/"),typeof document<"u"&&(document.referrer&&(r.$referrer=document.referrer),document.title&&(r.$title=document.title))),r}function P(r,e){let t={$session_id:r,$distinct_id:e,$goodlogs_sdk:"js",$goodlogs_sdk_version:u};return typeof navigator>"u"||typeof location<"u"&&(t.$url=location.href,t.$path=location.pathname),t}function x(){if(!(typeof document<"u"))try{let e=new Error().stack?.split(`
|
|
2
|
+
`);if(!e)return;for(let t=3;t<Math.min(e.length,8);t++){let n=e[t]?.trim();if(!n||n.includes("goodlogs")&&(n.includes("client.")||n.includes("index.")))continue;let i=n.match(/at\s+(?:(.+?)\s+\()?(.+?):(\d+):\d+\)?/);if(i){let o=i[1]||"<anonymous>",s=i[2]?.replace(/^.*[/\\]/,"")??"",a=i[3];return `${o}@${s}:${a}`}}}catch{}}function T(){if(typeof localStorage<"u"){let r=localStorage.getItem(h);if(r)return r;let e=c();return localStorage.setItem(h,e),e}return c()}function A(){if(typeof sessionStorage<"u"){let r=sessionStorage.getItem(g);if(r)return r;let e=c();return sessionStorage.setItem(g,e),e}return c()}var v=class{constructor(e){this.logBuffer=[];this.eventBuffer=[];this.timer=null;this.visibilityHandler=null;this.clickHandler=null;this.lastPath="";this.apiKey=e.apiKey,this.endpoint=d(e.apiKey,e.endpoint).replace(/\/+$/,""),this.flushInterval=e.flushInterval??R,this.batchSize=e.batchSize??I,this.defaultContext=e.defaultContext??{},this.onError=e.onError??(()=>{}),this.disabled=e.disabled??false,this.telemetry=e.telemetry??true,this.anonymousId=T(),this.sessionId=A(),this.disabled&&typeof console<"u"&&console.warn("[GoodLogs] SDK is disabled. No events or logs will be sent."),this.disabled||(this.startTimer(),this.attachPageLifecycle(),e.autocapture!==false&&(this.attachClickCapture(),this.captureWebVitals(),this.attachPageviewCapture()),this.sendTelemetry("init","info"));}log(e,t,n){if(this.disabled)return;let i=65536,o=t;t.length>i&&(o=t.slice(0,i-100)+`
|
|
3
3
|
|
|
4
|
-
[truncated \u2014 original ${t.length} chars, limit ${i}]`,this.onError(new Error(`Log message truncated from ${t.length} to ${i} chars`)));let
|
|
4
|
+
[truncated \u2014 original ${t.length} chars, limit ${i}]`,this.onError(new Error(`Log message truncated from ${t.length} to ${i} chars`)));let s=x(),a={severity:e,message:o,properties:{...this.defaultContext,...P(this.sessionId,this.anonymousId),...s?{code_location:s}:{},...n},timestamp:new Date().toISOString()};this.logBuffer.push(a),this.logBuffer.length>=this.batchSize&&this.flush();}debug(e,t){this.log("debug",e,t);}info(e,t){this.log("info",e,t);}warn(e,t){this.log("warn",e,t);}error(e,t){this.log("error",e,t);}fatal(e,t){this.log("fatal",e,t);}identify(e){this.anonymousId=e,typeof localStorage<"u"&&localStorage.setItem(h,e);}getDistinctId(){return this.anonymousId}reset(){this.anonymousId=c(),this.sessionId=c(),typeof localStorage<"u"&&localStorage.setItem(h,this.anonymousId),typeof sessionStorage<"u"&&sessionStorage.setItem(g,this.sessionId);}getSessionId(){return this.sessionId}newSession(){this.sessionId=c(),typeof sessionStorage<"u"&&sessionStorage.setItem(g,this.sessionId);}setSessionId(e){this.sessionId=e,typeof sessionStorage<"u"&&sessionStorage.setItem(g,e);}track(e,t){if(this.disabled)return;let{distinctId:n,...i}=t??{},o={event:e,distinctId:n??this.anonymousId,properties:{...$(),...i,$session_id:this.sessionId},timestamp:new Date().toISOString()};this.eventBuffer.push(o),this.eventBuffer.length>=this.batchSize&&this.flush();}async flush(){let e=this.logBuffer.splice(0),t=this.eventBuffer.splice(0),n=[];e.length>0&&n.push(this.sendLogs(e)),t.length>0&&n.push(this.sendEvents(t)),await Promise.all(n);}async shutdown(){this.stopTimer(),this.detachPageLifecycle(),this.detachClickCapture(),await this.flush();}async sendLogs(e){for(let n=0;n<e.length;n+=500){let o=e.slice(n,n+500).map(s=>({severity:s.severity,message:s.message,properties:s.properties,timestamp:s.timestamp}));await this.postWithRetry("/v1/logs",o,s=>{for(let a of s)this.logBuffer.push({severity:a.severity,message:a.message,properties:a.properties,timestamp:a.timestamp});});}}async sendEvents(e){for(let n=0;n<e.length;n+=500){let o=e.slice(n,n+500).map(s=>({event:s.event,distinctId:s.distinctId,properties:s.properties,timestamp:s.timestamp}));await this.postWithRetry("/v1/events",o,s=>{for(let a of s)this.eventBuffer.push({event:a.event,distinctId:a.distinctId,properties:a.properties,timestamp:a.timestamp});});}}async postWithRetry(e,t,n,i=0){try{let o=await fetch(`${this.endpoint}${e}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,"X-GoodLogs-SDK":`js/${u}`},body:JSON.stringify({batch:t})});if(o.status===429||o.status===503){if(i<4){let a=Math.min(1e3*Math.pow(2,i),8e3),l=Math.random()*500;return await new Promise(p=>setTimeout(p,a+l)),this.postWithRetry(e,t,n,i+1)}this.onError(new Error(`GoodLogs rate limited after ${i} retries`));return}if(!o.ok){let a=await o.text().catch(()=>""),l=new Error(`GoodLogs API error ${o.status}: ${a}`);this.onError(l),o.status>=500&&i===0&&n(t);return}let s=await o.json().catch(()=>null);if(s&&s.rejected&&s.rejected>0){let a=t.slice(s.accepted??0);a.length>0&&n(a);}}catch(o){let s=o instanceof Error?o:new Error(String(o));i===0&&n(t),this.onError(s);}}startTimer(){this.timer=setInterval(()=>{this.flush();},this.flushInterval);let e=this.timer;typeof e?.unref=="function"&&e.unref();}stopTimer(){this.timer!==null&&(clearInterval(this.timer),this.timer=null);}attachPageLifecycle(){typeof document>"u"||(this.visibilityHandler=()=>{document.visibilityState==="hidden"&&this.keepaliveFlush();},document.addEventListener("visibilitychange",this.visibilityHandler));}captureWebVitals(){if(!(typeof PerformanceObserver>"u")){try{new PerformanceObserver(e=>{let t=e.getEntries()[0];t&&this.track("$web_vital",{properties:{$metric:"FCP",$value_ms:Math.round(t.startTime)}});}).observe({type:"paint",buffered:!0});}catch{}try{new PerformanceObserver(e=>{let t=e.getEntries(),n=t[t.length-1];n&&this.track("$web_vital",{properties:{$metric:"LCP",$value_ms:Math.round(n.startTime)}});}).observe({type:"largest-contentful-paint",buffered:!0});}catch{}try{let e=0;if(new PerformanceObserver(t=>{for(let n of t.getEntries())n.hadRecentInput||(e+=n.value);}).observe({type:"layout-shift",buffered:!0}),typeof document<"u"){let t=()=>{e>0&&this.track("$web_vital",{properties:{$metric:"CLS",$value:Math.round(e*1e3)/1e3}});};document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&t();});}}catch{}try{if(typeof performance<"u"){let e=performance.getEntriesByType?.("navigation")?.[0];e?.responseStart&&this.track("$web_vital",{properties:{$metric:"TTFB",$value_ms:Math.round(e.responseStart)}});}}catch{}try{new PerformanceObserver(e=>{for(let t of e.getEntries()){let n=t.duration;n>0&&this.track("$web_vital",{properties:{$metric:"INP",$value_ms:Math.round(n)}});}}).observe({type:"event",buffered:!0});}catch{}}}attachPageviewCapture(){if(typeof document>"u"||typeof location>"u")return;this.lastPath=location.pathname,this.track("$pageview");let e=()=>{typeof location<"u"&&location.pathname!==this.lastPath&&(this.lastPath=location.pathname,this.track("$pageview"));};if(typeof history<"u"){let t=history.pushState,n=history.replaceState;history.pushState=function(...i){t.apply(this,i),e();},history.replaceState=function(...i){n.apply(this,i),e();};}typeof addEventListener<"u"&&addEventListener("popstate",e);}attachClickCapture(){typeof document>"u"||(this.clickHandler=e=>{let n=e.target?.closest?.("a, button, [data-gl-event], [role='button']");if(!n)return;let i=n.getAttribute?.("data-gl-event"),o=n.tagName?.toLowerCase()??"",s=(n.textContent??"").trim().slice(0,50),a=n.getAttribute?.("href")??void 0,l=(n.className??"").toString().slice(0,80);this.track(i||"$click",{properties:{$element_tag:o,$element_text:s||void 0,$element_href:a,$element_classes:l||void 0}});},document.addEventListener("click",this.clickHandler));}detachClickCapture(){this.clickHandler&&typeof document<"u"&&(document.removeEventListener("click",this.clickHandler),this.clickHandler=null);}detachPageLifecycle(){this.visibilityHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=null);}keepaliveFlush(){let e=this.logBuffer.splice(0),t=this.eventBuffer.splice(0),n={"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,"X-GoodLogs-SDK":`js/${u}`};e.length>0&&fetch(`${this.endpoint}/v1/logs`,{method:"POST",headers:n,body:JSON.stringify({batch:e.map(i=>({severity:i.severity,message:i.message,properties:i.properties,timestamp:i.timestamp}))}),keepalive:true}).catch(()=>{}),t.length>0&&fetch(`${this.endpoint}/v1/events`,{method:"POST",headers:n,body:JSON.stringify({batch:t.map(i=>({event:i.event,distinctId:i.distinctId,properties:i.properties,timestamp:i.timestamp}))}),keepalive:true}).catch(()=>{});}sendTelemetry(e,t,n){!this.telemetry||this.disabled||fetch(`${this.endpoint}/v1/telemetry`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,"X-GoodLogs-SDK":`js/${u}`},body:JSON.stringify({source:"sdk",event:e,level:t,metadata:{...n,sdk_version:u}}),keepalive:true}).catch(()=>{});}};var y=class{constructor(e){if(!e.apiKey)throw new Error("apiKey is required");if(!e.apiKey.startsWith("gl_sk_"))throw new Error("GoodLogsClient requires a secret API key (gl_sk_...)");this.apiKey=e.apiKey,this.endpoint=d(e.apiKey,e.endpoint),this.timeout=e.timeout??3e4,this.alerts=new b(this),this.slos=new S(this),this.ai=new k(this);}async _request(e,t,n){let i=`${this.endpoint}${t}`,o={Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},s=new AbortController,a=setTimeout(()=>s.abort(),this.timeout);try{let l=await fetch(i,{method:e,headers:o,body:n?JSON.stringify(n):void 0,signal:s.signal});if(!l.ok){let p=await l.json().catch(()=>({})),E=p?.error?.message??`API error ${l.status}`;throw new f(l.status,E,p?.error?.code)}return l.status===204?void 0:await l.json()}finally{clearTimeout(a);}}_get(e){return this._request("GET",e)}_post(e,t){return this._request("POST",e,t)}_put(e,t){return this._request("PUT",e,t)}_delete(e){return this._request("DELETE",e)}info(){return this._get("/v1/info")}schema(){return this._get("/v1/schema")}gql(e){return this._post("/v1/gql/query",{q:e})}gqlBatch(e){return this._post("/v1/gql",{queries:e})}gqlAutocomplete(e,t){let n=`/v1/gql/autocomplete?q=${encodeURIComponent(e)}`;return t!==void 0&&(n+=`&cursor=${t}`),this._get(n)}nl2gql(e,t){return this._post("/v1/gql/nl",{prompt:e,mode:t})}},b=class{constructor(e){this.client=e;}list(){return this.client._get("/v1/alerts")}create(e){return this.client._post("/v1/alerts",e)}update(e,t){return this.client._put(`/v1/alerts/${e}`,t)}delete(e){return this.client._delete(`/v1/alerts/${e}`)}mute(e,t){return this.client._post(`/v1/alerts/${e}/mute`,{minutes:t})}},S=class{constructor(e){this.client=e;}list(){return this.client._get("/v1/slos")}create(e){return this.client._post("/v1/slos",e)}update(e,t){return this.client._put(`/v1/slos/${e}`,t)}delete(e){return this.client._delete(`/v1/slos/${e}`)}},k=class{constructor(e){this.client=e;}chat(e,t){return this.client._post("/v1/ai/chat",{message:e,session_id:t})}},f=class extends Error{constructor(t,n,i){super(n);this.status=t;this.code=i;this.name="GoodLogsApiError";}};var w="0.1.0";function C(r,e){let t=d(e?.apiKey??"",e?.endpoint).replace(/\/+$/,""),n={"Content-Type":"application/json","X-GoodLogs-SDK":w};e?.token&&(n.Authorization=`Bearer ${e.token}`),fetch(`${t}/v1/telemetry`,{method:"POST",headers:n,body:JSON.stringify({source:r.source,event:r.event,level:r.level??"info",metadata:{...r.metadata,sdk_version:w}}),keepalive:true}).catch(()=>{});}exports.GoodLogs=v;exports.GoodLogsApiError=f;exports.GoodLogsClient=y;exports.REGION_URLS=m;exports.resolveEndpoint=d;exports.resolveRegion=_;exports.sendTelemetry=C;
|
package/dist/index.d.cts
CHANGED
|
@@ -22,9 +22,7 @@ interface GoodLogsOptions {
|
|
|
22
22
|
interface LogEntry {
|
|
23
23
|
severity: Severity;
|
|
24
24
|
message: string;
|
|
25
|
-
|
|
26
|
-
codeLocation?: string;
|
|
27
|
-
context?: Record<string, unknown>;
|
|
25
|
+
properties?: Record<string, unknown>;
|
|
28
26
|
timestamp?: string;
|
|
29
27
|
}
|
|
30
28
|
interface EventEntry {
|
|
@@ -52,36 +50,12 @@ declare class GoodLogs {
|
|
|
52
50
|
private anonymousId;
|
|
53
51
|
private sessionId;
|
|
54
52
|
constructor(options: GoodLogsOptions);
|
|
55
|
-
log(severity: Severity, message: string,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
metadata?: Record<string, unknown>;
|
|
62
|
-
codeLocation?: string;
|
|
63
|
-
context?: Record<string, unknown>;
|
|
64
|
-
}): void;
|
|
65
|
-
info(message: string, opts?: {
|
|
66
|
-
metadata?: Record<string, unknown>;
|
|
67
|
-
codeLocation?: string;
|
|
68
|
-
context?: Record<string, unknown>;
|
|
69
|
-
}): void;
|
|
70
|
-
warn(message: string, opts?: {
|
|
71
|
-
metadata?: Record<string, unknown>;
|
|
72
|
-
codeLocation?: string;
|
|
73
|
-
context?: Record<string, unknown>;
|
|
74
|
-
}): void;
|
|
75
|
-
error(message: string, opts?: {
|
|
76
|
-
metadata?: Record<string, unknown>;
|
|
77
|
-
codeLocation?: string;
|
|
78
|
-
context?: Record<string, unknown>;
|
|
79
|
-
}): void;
|
|
80
|
-
fatal(message: string, opts?: {
|
|
81
|
-
metadata?: Record<string, unknown>;
|
|
82
|
-
codeLocation?: string;
|
|
83
|
-
context?: Record<string, unknown>;
|
|
84
|
-
}): void;
|
|
53
|
+
log(severity: Severity, message: string, properties?: Record<string, unknown>): void;
|
|
54
|
+
debug(message: string, properties?: Record<string, unknown>): void;
|
|
55
|
+
info(message: string, properties?: Record<string, unknown>): void;
|
|
56
|
+
warn(message: string, properties?: Record<string, unknown>): void;
|
|
57
|
+
error(message: string, properties?: Record<string, unknown>): void;
|
|
58
|
+
fatal(message: string, properties?: Record<string, unknown>): void;
|
|
85
59
|
/** Set the user ID for all subsequent events. Replaces the anonymous ID. */
|
|
86
60
|
identify(userId: string): void;
|
|
87
61
|
/** Get the current anonymous/user ID. */
|
|
@@ -94,9 +68,8 @@ declare class GoodLogs {
|
|
|
94
68
|
newSession(): void;
|
|
95
69
|
/** Set a specific session ID. */
|
|
96
70
|
setSessionId(id: string): void;
|
|
97
|
-
track(event: string,
|
|
71
|
+
track(event: string, properties?: Record<string, unknown> & {
|
|
98
72
|
distinctId?: string;
|
|
99
|
-
properties?: Record<string, unknown>;
|
|
100
73
|
}): void;
|
|
101
74
|
flush(): Promise<void>;
|
|
102
75
|
/** Flush remaining data and stop the timer */
|
|
@@ -126,6 +99,292 @@ declare class GoodLogs {
|
|
|
126
99
|
private sendTelemetry;
|
|
127
100
|
}
|
|
128
101
|
|
|
102
|
+
interface LogRecord {
|
|
103
|
+
id: number;
|
|
104
|
+
severity: string;
|
|
105
|
+
message: string;
|
|
106
|
+
properties: Record<string, unknown>;
|
|
107
|
+
timestamp: string;
|
|
108
|
+
}
|
|
109
|
+
interface GqlResult {
|
|
110
|
+
query: string;
|
|
111
|
+
data: unknown[];
|
|
112
|
+
columns?: string[];
|
|
113
|
+
source?: string;
|
|
114
|
+
error?: string;
|
|
115
|
+
}
|
|
116
|
+
interface GqlBatchResult {
|
|
117
|
+
status: "ok" | "error";
|
|
118
|
+
query?: unknown;
|
|
119
|
+
data?: unknown;
|
|
120
|
+
error?: string;
|
|
121
|
+
}
|
|
122
|
+
interface GqlAutocompleteResult {
|
|
123
|
+
suggestions: string[];
|
|
124
|
+
valid: boolean;
|
|
125
|
+
error?: string;
|
|
126
|
+
parsed?: Record<string, unknown>;
|
|
127
|
+
}
|
|
128
|
+
interface Nl2GqlResult {
|
|
129
|
+
gql: string;
|
|
130
|
+
valid: boolean;
|
|
131
|
+
error?: string;
|
|
132
|
+
parsed?: Record<string, unknown>;
|
|
133
|
+
}
|
|
134
|
+
interface SchemaField {
|
|
135
|
+
name: string;
|
|
136
|
+
type: string;
|
|
137
|
+
count?: number;
|
|
138
|
+
}
|
|
139
|
+
interface SchemaResponse {
|
|
140
|
+
events: SchemaField[];
|
|
141
|
+
properties: SchemaField[];
|
|
142
|
+
log_properties: SchemaField[];
|
|
143
|
+
[key: string]: unknown;
|
|
144
|
+
}
|
|
145
|
+
interface AlertRule {
|
|
146
|
+
id: string;
|
|
147
|
+
project_id: string;
|
|
148
|
+
name: string;
|
|
149
|
+
metric: string;
|
|
150
|
+
alert_type: string;
|
|
151
|
+
status: string;
|
|
152
|
+
severity: string;
|
|
153
|
+
threshold: number;
|
|
154
|
+
window_minutes: number;
|
|
155
|
+
cooldown_minutes: number;
|
|
156
|
+
notify_email: boolean;
|
|
157
|
+
webhook_url?: string;
|
|
158
|
+
enabled: boolean;
|
|
159
|
+
pattern?: string;
|
|
160
|
+
change_percent?: number;
|
|
161
|
+
muted_until?: string;
|
|
162
|
+
message_template?: string;
|
|
163
|
+
notify_channels: NotifyChannel[];
|
|
164
|
+
last_triggered_at?: string;
|
|
165
|
+
last_value?: number;
|
|
166
|
+
anomaly_sigma?: number;
|
|
167
|
+
composite_rules: string[];
|
|
168
|
+
composite_operator?: string;
|
|
169
|
+
created_at: string;
|
|
170
|
+
updated_at: string;
|
|
171
|
+
}
|
|
172
|
+
interface NotifyChannel {
|
|
173
|
+
type: string;
|
|
174
|
+
url?: string;
|
|
175
|
+
to?: string;
|
|
176
|
+
secret?: string;
|
|
177
|
+
}
|
|
178
|
+
interface CreateAlertRule {
|
|
179
|
+
name: string;
|
|
180
|
+
metric: string;
|
|
181
|
+
threshold: number;
|
|
182
|
+
window_minutes?: number;
|
|
183
|
+
notify_email?: boolean;
|
|
184
|
+
webhook_url?: string;
|
|
185
|
+
alert_type?: string;
|
|
186
|
+
pattern?: string;
|
|
187
|
+
change_percent?: number;
|
|
188
|
+
message_template?: string;
|
|
189
|
+
notify_channels?: NotifyChannel[];
|
|
190
|
+
severity?: string;
|
|
191
|
+
cooldown_minutes?: number;
|
|
192
|
+
anomaly_sigma?: number;
|
|
193
|
+
composite_rules?: string[];
|
|
194
|
+
composite_operator?: string;
|
|
195
|
+
}
|
|
196
|
+
interface UpdateAlertRule {
|
|
197
|
+
name?: string;
|
|
198
|
+
metric?: string;
|
|
199
|
+
threshold?: number;
|
|
200
|
+
window_minutes?: number;
|
|
201
|
+
notify_email?: boolean;
|
|
202
|
+
webhook_url?: string;
|
|
203
|
+
enabled?: boolean;
|
|
204
|
+
pattern?: string;
|
|
205
|
+
change_percent?: number;
|
|
206
|
+
message_template?: string;
|
|
207
|
+
notify_channels?: NotifyChannel[];
|
|
208
|
+
severity?: string;
|
|
209
|
+
cooldown_minutes?: number;
|
|
210
|
+
anomaly_sigma?: number;
|
|
211
|
+
}
|
|
212
|
+
interface MuteAlertRequest {
|
|
213
|
+
minutes: number;
|
|
214
|
+
}
|
|
215
|
+
interface SloDefinition {
|
|
216
|
+
id: string;
|
|
217
|
+
project_id: string;
|
|
218
|
+
name: string;
|
|
219
|
+
description?: string;
|
|
220
|
+
metric: string;
|
|
221
|
+
status: string;
|
|
222
|
+
target_percent: number;
|
|
223
|
+
threshold?: number;
|
|
224
|
+
window_days: number;
|
|
225
|
+
current_percent?: number;
|
|
226
|
+
budget_remaining?: number;
|
|
227
|
+
budget_burn_rate?: number;
|
|
228
|
+
enabled: boolean;
|
|
229
|
+
created_at: string;
|
|
230
|
+
updated_at: string;
|
|
231
|
+
}
|
|
232
|
+
interface CreateSlo {
|
|
233
|
+
name: string;
|
|
234
|
+
description?: string;
|
|
235
|
+
metric?: string;
|
|
236
|
+
target_percent?: number;
|
|
237
|
+
threshold?: number;
|
|
238
|
+
window_days?: number;
|
|
239
|
+
}
|
|
240
|
+
interface UpdateSlo {
|
|
241
|
+
name?: string;
|
|
242
|
+
description?: string;
|
|
243
|
+
target_percent?: number;
|
|
244
|
+
threshold?: number;
|
|
245
|
+
window_days?: number;
|
|
246
|
+
enabled?: boolean;
|
|
247
|
+
}
|
|
248
|
+
interface AiChatRequest {
|
|
249
|
+
message: string;
|
|
250
|
+
session_id?: string;
|
|
251
|
+
}
|
|
252
|
+
interface AiChatResponse {
|
|
253
|
+
reply: string;
|
|
254
|
+
session_id: string;
|
|
255
|
+
tool_calls?: AiToolCall[];
|
|
256
|
+
}
|
|
257
|
+
interface AiToolCall {
|
|
258
|
+
tool: string;
|
|
259
|
+
input: Record<string, unknown>;
|
|
260
|
+
result: unknown;
|
|
261
|
+
}
|
|
262
|
+
interface ProjectInfo {
|
|
263
|
+
project: {
|
|
264
|
+
id: string;
|
|
265
|
+
name: string;
|
|
266
|
+
slug: string;
|
|
267
|
+
region: string;
|
|
268
|
+
};
|
|
269
|
+
org: {
|
|
270
|
+
id: string;
|
|
271
|
+
name: string;
|
|
272
|
+
plan: string;
|
|
273
|
+
};
|
|
274
|
+
usage?: Record<string, unknown>;
|
|
275
|
+
keys?: {
|
|
276
|
+
count: number;
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
interface GoodLogsClientOptions {
|
|
280
|
+
/** Secret API key (gl_sk_...) — required for all read/write operations */
|
|
281
|
+
apiKey: string;
|
|
282
|
+
/** API endpoint (default: auto-resolved from API key region) */
|
|
283
|
+
endpoint?: string;
|
|
284
|
+
/** Request timeout in ms (default: 30000) */
|
|
285
|
+
timeout?: number;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* GoodLogs programmatic API client.
|
|
290
|
+
*
|
|
291
|
+
* Provides typed access to all /v1 read & write endpoints:
|
|
292
|
+
* analytics, logs, GQL queries, alerts, SLOs, AI chat, and schema.
|
|
293
|
+
*
|
|
294
|
+
* Requires a **secret** API key (`gl_sk_...`) with appropriate scopes.
|
|
295
|
+
*
|
|
296
|
+
* ```ts
|
|
297
|
+
* import { GoodLogsClient } from "@aj-2000-test/goodlogs-sdk";
|
|
298
|
+
*
|
|
299
|
+
* const client = new GoodLogsClient({ apiKey: "gl_sk_us_..." });
|
|
300
|
+
*
|
|
301
|
+
* // Query logs
|
|
302
|
+
* const { logs, total } = await client.logs.list({ severity: "error", limit: 10 });
|
|
303
|
+
*
|
|
304
|
+
* // Run GQL query
|
|
305
|
+
* const result = await client.gql("count | where severity = 'error' | last 1h");
|
|
306
|
+
*
|
|
307
|
+
* // Manage alerts
|
|
308
|
+
* const alerts = await client.alerts.list();
|
|
309
|
+
* await client.alerts.create({ name: "High Errors", metric: "error_count", threshold: 100 });
|
|
310
|
+
* ```
|
|
311
|
+
*/
|
|
312
|
+
declare class GoodLogsClient {
|
|
313
|
+
private readonly endpoint;
|
|
314
|
+
private readonly apiKey;
|
|
315
|
+
private readonly timeout;
|
|
316
|
+
/** Alert CRUD methods */
|
|
317
|
+
readonly alerts: AlertsApi;
|
|
318
|
+
/** SLO CRUD methods */
|
|
319
|
+
readonly slos: SlosApi;
|
|
320
|
+
/** AI chat methods */
|
|
321
|
+
readonly ai: AiApi;
|
|
322
|
+
constructor(options: GoodLogsClientOptions);
|
|
323
|
+
/** @internal */
|
|
324
|
+
_request<T>(method: string, path: string, body?: unknown): Promise<T>;
|
|
325
|
+
/** @internal */
|
|
326
|
+
_get<T>(path: string): Promise<T>;
|
|
327
|
+
/** @internal */
|
|
328
|
+
_post<T>(path: string, body?: unknown): Promise<T>;
|
|
329
|
+
/** @internal */
|
|
330
|
+
_put<T>(path: string, body?: unknown): Promise<T>;
|
|
331
|
+
/** @internal */
|
|
332
|
+
_delete<T>(path: string): Promise<T>;
|
|
333
|
+
/** Get project info, org, usage, and key count */
|
|
334
|
+
info(): Promise<ProjectInfo>;
|
|
335
|
+
/** Get full schema (event names, property fields, log properties) */
|
|
336
|
+
schema(): Promise<SchemaResponse>;
|
|
337
|
+
/** Run a single GQL query */
|
|
338
|
+
gql(query: string): Promise<GqlResult>;
|
|
339
|
+
/**
|
|
340
|
+
* Run multiple GQL queries in a single request.
|
|
341
|
+
* Returns an array of results (same index as input).
|
|
342
|
+
* Each result has `status: "ok"` with `data`, or `status: "error"` with `error`.
|
|
343
|
+
*/
|
|
344
|
+
gqlBatch(queries: string[]): Promise<GqlBatchResult[]>;
|
|
345
|
+
/** Get GQL autocomplete suggestions */
|
|
346
|
+
gqlAutocomplete(query: string, cursor?: number): Promise<GqlAutocompleteResult>;
|
|
347
|
+
/** Convert natural language to GQL */
|
|
348
|
+
nl2gql(prompt: string, mode?: string): Promise<Nl2GqlResult>;
|
|
349
|
+
}
|
|
350
|
+
declare class AlertsApi {
|
|
351
|
+
private client;
|
|
352
|
+
constructor(client: GoodLogsClient);
|
|
353
|
+
/** List all alert rules */
|
|
354
|
+
list(): Promise<AlertRule[]>;
|
|
355
|
+
/** Create a new alert rule */
|
|
356
|
+
create(rule: CreateAlertRule): Promise<AlertRule>;
|
|
357
|
+
/** Update an alert rule */
|
|
358
|
+
update(alertId: string, rule: UpdateAlertRule): Promise<AlertRule>;
|
|
359
|
+
/** Delete an alert rule */
|
|
360
|
+
delete(alertId: string): Promise<void>;
|
|
361
|
+
/** Mute an alert for N minutes */
|
|
362
|
+
mute(alertId: string, minutes: number): Promise<void>;
|
|
363
|
+
}
|
|
364
|
+
declare class SlosApi {
|
|
365
|
+
private client;
|
|
366
|
+
constructor(client: GoodLogsClient);
|
|
367
|
+
/** List all SLO definitions */
|
|
368
|
+
list(): Promise<SloDefinition[]>;
|
|
369
|
+
/** Create a new SLO */
|
|
370
|
+
create(slo: CreateSlo): Promise<SloDefinition>;
|
|
371
|
+
/** Update an SLO */
|
|
372
|
+
update(sloId: string, slo: UpdateSlo): Promise<SloDefinition>;
|
|
373
|
+
/** Delete an SLO */
|
|
374
|
+
delete(sloId: string): Promise<void>;
|
|
375
|
+
}
|
|
376
|
+
declare class AiApi {
|
|
377
|
+
private client;
|
|
378
|
+
constructor(client: GoodLogsClient);
|
|
379
|
+
/** Send a message to AI chat */
|
|
380
|
+
chat(message: string, sessionId?: string): Promise<AiChatResponse>;
|
|
381
|
+
}
|
|
382
|
+
declare class GoodLogsApiError extends Error {
|
|
383
|
+
readonly status: number;
|
|
384
|
+
readonly code?: string | undefined;
|
|
385
|
+
constructor(status: number, message: string, code?: string | undefined);
|
|
386
|
+
}
|
|
387
|
+
|
|
129
388
|
interface TelemetryEvent {
|
|
130
389
|
/** "sdk" | "dashboard" | "api" | custom */
|
|
131
390
|
source: string;
|
|
@@ -164,4 +423,4 @@ declare function resolveRegion(apiKey: string): string;
|
|
|
164
423
|
/** Resolve API endpoint from key. User-provided endpoint always wins. */
|
|
165
424
|
declare function resolveEndpoint(apiKey: string, userEndpoint?: string): string;
|
|
166
425
|
|
|
167
|
-
export { type EventEntry, GoodLogs, type GoodLogsOptions, type LogEntry, REGION_URLS, type Severity, type TelemetryEvent, type TelemetryOptions, resolveEndpoint, resolveRegion, sendTelemetry };
|
|
426
|
+
export { type AiChatRequest, type AiChatResponse, type AiToolCall, type AlertRule, type CreateAlertRule, type CreateSlo, type EventEntry, GoodLogs, GoodLogsApiError, GoodLogsClient, type GoodLogsClientOptions, type GoodLogsOptions, type GqlAutocompleteResult, type GqlBatchResult, type GqlResult, type LogEntry, type LogRecord, type MuteAlertRequest, type Nl2GqlResult, type NotifyChannel, type ProjectInfo, REGION_URLS, type SchemaField, type SchemaResponse, type Severity, type SloDefinition, type TelemetryEvent, type TelemetryOptions, type UpdateAlertRule, type UpdateSlo, resolveEndpoint, resolveRegion, sendTelemetry };
|
package/dist/index.d.ts
CHANGED
|
@@ -22,9 +22,7 @@ interface GoodLogsOptions {
|
|
|
22
22
|
interface LogEntry {
|
|
23
23
|
severity: Severity;
|
|
24
24
|
message: string;
|
|
25
|
-
|
|
26
|
-
codeLocation?: string;
|
|
27
|
-
context?: Record<string, unknown>;
|
|
25
|
+
properties?: Record<string, unknown>;
|
|
28
26
|
timestamp?: string;
|
|
29
27
|
}
|
|
30
28
|
interface EventEntry {
|
|
@@ -52,36 +50,12 @@ declare class GoodLogs {
|
|
|
52
50
|
private anonymousId;
|
|
53
51
|
private sessionId;
|
|
54
52
|
constructor(options: GoodLogsOptions);
|
|
55
|
-
log(severity: Severity, message: string,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
metadata?: Record<string, unknown>;
|
|
62
|
-
codeLocation?: string;
|
|
63
|
-
context?: Record<string, unknown>;
|
|
64
|
-
}): void;
|
|
65
|
-
info(message: string, opts?: {
|
|
66
|
-
metadata?: Record<string, unknown>;
|
|
67
|
-
codeLocation?: string;
|
|
68
|
-
context?: Record<string, unknown>;
|
|
69
|
-
}): void;
|
|
70
|
-
warn(message: string, opts?: {
|
|
71
|
-
metadata?: Record<string, unknown>;
|
|
72
|
-
codeLocation?: string;
|
|
73
|
-
context?: Record<string, unknown>;
|
|
74
|
-
}): void;
|
|
75
|
-
error(message: string, opts?: {
|
|
76
|
-
metadata?: Record<string, unknown>;
|
|
77
|
-
codeLocation?: string;
|
|
78
|
-
context?: Record<string, unknown>;
|
|
79
|
-
}): void;
|
|
80
|
-
fatal(message: string, opts?: {
|
|
81
|
-
metadata?: Record<string, unknown>;
|
|
82
|
-
codeLocation?: string;
|
|
83
|
-
context?: Record<string, unknown>;
|
|
84
|
-
}): void;
|
|
53
|
+
log(severity: Severity, message: string, properties?: Record<string, unknown>): void;
|
|
54
|
+
debug(message: string, properties?: Record<string, unknown>): void;
|
|
55
|
+
info(message: string, properties?: Record<string, unknown>): void;
|
|
56
|
+
warn(message: string, properties?: Record<string, unknown>): void;
|
|
57
|
+
error(message: string, properties?: Record<string, unknown>): void;
|
|
58
|
+
fatal(message: string, properties?: Record<string, unknown>): void;
|
|
85
59
|
/** Set the user ID for all subsequent events. Replaces the anonymous ID. */
|
|
86
60
|
identify(userId: string): void;
|
|
87
61
|
/** Get the current anonymous/user ID. */
|
|
@@ -94,9 +68,8 @@ declare class GoodLogs {
|
|
|
94
68
|
newSession(): void;
|
|
95
69
|
/** Set a specific session ID. */
|
|
96
70
|
setSessionId(id: string): void;
|
|
97
|
-
track(event: string,
|
|
71
|
+
track(event: string, properties?: Record<string, unknown> & {
|
|
98
72
|
distinctId?: string;
|
|
99
|
-
properties?: Record<string, unknown>;
|
|
100
73
|
}): void;
|
|
101
74
|
flush(): Promise<void>;
|
|
102
75
|
/** Flush remaining data and stop the timer */
|
|
@@ -126,6 +99,292 @@ declare class GoodLogs {
|
|
|
126
99
|
private sendTelemetry;
|
|
127
100
|
}
|
|
128
101
|
|
|
102
|
+
interface LogRecord {
|
|
103
|
+
id: number;
|
|
104
|
+
severity: string;
|
|
105
|
+
message: string;
|
|
106
|
+
properties: Record<string, unknown>;
|
|
107
|
+
timestamp: string;
|
|
108
|
+
}
|
|
109
|
+
interface GqlResult {
|
|
110
|
+
query: string;
|
|
111
|
+
data: unknown[];
|
|
112
|
+
columns?: string[];
|
|
113
|
+
source?: string;
|
|
114
|
+
error?: string;
|
|
115
|
+
}
|
|
116
|
+
interface GqlBatchResult {
|
|
117
|
+
status: "ok" | "error";
|
|
118
|
+
query?: unknown;
|
|
119
|
+
data?: unknown;
|
|
120
|
+
error?: string;
|
|
121
|
+
}
|
|
122
|
+
interface GqlAutocompleteResult {
|
|
123
|
+
suggestions: string[];
|
|
124
|
+
valid: boolean;
|
|
125
|
+
error?: string;
|
|
126
|
+
parsed?: Record<string, unknown>;
|
|
127
|
+
}
|
|
128
|
+
interface Nl2GqlResult {
|
|
129
|
+
gql: string;
|
|
130
|
+
valid: boolean;
|
|
131
|
+
error?: string;
|
|
132
|
+
parsed?: Record<string, unknown>;
|
|
133
|
+
}
|
|
134
|
+
interface SchemaField {
|
|
135
|
+
name: string;
|
|
136
|
+
type: string;
|
|
137
|
+
count?: number;
|
|
138
|
+
}
|
|
139
|
+
interface SchemaResponse {
|
|
140
|
+
events: SchemaField[];
|
|
141
|
+
properties: SchemaField[];
|
|
142
|
+
log_properties: SchemaField[];
|
|
143
|
+
[key: string]: unknown;
|
|
144
|
+
}
|
|
145
|
+
interface AlertRule {
|
|
146
|
+
id: string;
|
|
147
|
+
project_id: string;
|
|
148
|
+
name: string;
|
|
149
|
+
metric: string;
|
|
150
|
+
alert_type: string;
|
|
151
|
+
status: string;
|
|
152
|
+
severity: string;
|
|
153
|
+
threshold: number;
|
|
154
|
+
window_minutes: number;
|
|
155
|
+
cooldown_minutes: number;
|
|
156
|
+
notify_email: boolean;
|
|
157
|
+
webhook_url?: string;
|
|
158
|
+
enabled: boolean;
|
|
159
|
+
pattern?: string;
|
|
160
|
+
change_percent?: number;
|
|
161
|
+
muted_until?: string;
|
|
162
|
+
message_template?: string;
|
|
163
|
+
notify_channels: NotifyChannel[];
|
|
164
|
+
last_triggered_at?: string;
|
|
165
|
+
last_value?: number;
|
|
166
|
+
anomaly_sigma?: number;
|
|
167
|
+
composite_rules: string[];
|
|
168
|
+
composite_operator?: string;
|
|
169
|
+
created_at: string;
|
|
170
|
+
updated_at: string;
|
|
171
|
+
}
|
|
172
|
+
interface NotifyChannel {
|
|
173
|
+
type: string;
|
|
174
|
+
url?: string;
|
|
175
|
+
to?: string;
|
|
176
|
+
secret?: string;
|
|
177
|
+
}
|
|
178
|
+
interface CreateAlertRule {
|
|
179
|
+
name: string;
|
|
180
|
+
metric: string;
|
|
181
|
+
threshold: number;
|
|
182
|
+
window_minutes?: number;
|
|
183
|
+
notify_email?: boolean;
|
|
184
|
+
webhook_url?: string;
|
|
185
|
+
alert_type?: string;
|
|
186
|
+
pattern?: string;
|
|
187
|
+
change_percent?: number;
|
|
188
|
+
message_template?: string;
|
|
189
|
+
notify_channels?: NotifyChannel[];
|
|
190
|
+
severity?: string;
|
|
191
|
+
cooldown_minutes?: number;
|
|
192
|
+
anomaly_sigma?: number;
|
|
193
|
+
composite_rules?: string[];
|
|
194
|
+
composite_operator?: string;
|
|
195
|
+
}
|
|
196
|
+
interface UpdateAlertRule {
|
|
197
|
+
name?: string;
|
|
198
|
+
metric?: string;
|
|
199
|
+
threshold?: number;
|
|
200
|
+
window_minutes?: number;
|
|
201
|
+
notify_email?: boolean;
|
|
202
|
+
webhook_url?: string;
|
|
203
|
+
enabled?: boolean;
|
|
204
|
+
pattern?: string;
|
|
205
|
+
change_percent?: number;
|
|
206
|
+
message_template?: string;
|
|
207
|
+
notify_channels?: NotifyChannel[];
|
|
208
|
+
severity?: string;
|
|
209
|
+
cooldown_minutes?: number;
|
|
210
|
+
anomaly_sigma?: number;
|
|
211
|
+
}
|
|
212
|
+
interface MuteAlertRequest {
|
|
213
|
+
minutes: number;
|
|
214
|
+
}
|
|
215
|
+
interface SloDefinition {
|
|
216
|
+
id: string;
|
|
217
|
+
project_id: string;
|
|
218
|
+
name: string;
|
|
219
|
+
description?: string;
|
|
220
|
+
metric: string;
|
|
221
|
+
status: string;
|
|
222
|
+
target_percent: number;
|
|
223
|
+
threshold?: number;
|
|
224
|
+
window_days: number;
|
|
225
|
+
current_percent?: number;
|
|
226
|
+
budget_remaining?: number;
|
|
227
|
+
budget_burn_rate?: number;
|
|
228
|
+
enabled: boolean;
|
|
229
|
+
created_at: string;
|
|
230
|
+
updated_at: string;
|
|
231
|
+
}
|
|
232
|
+
interface CreateSlo {
|
|
233
|
+
name: string;
|
|
234
|
+
description?: string;
|
|
235
|
+
metric?: string;
|
|
236
|
+
target_percent?: number;
|
|
237
|
+
threshold?: number;
|
|
238
|
+
window_days?: number;
|
|
239
|
+
}
|
|
240
|
+
interface UpdateSlo {
|
|
241
|
+
name?: string;
|
|
242
|
+
description?: string;
|
|
243
|
+
target_percent?: number;
|
|
244
|
+
threshold?: number;
|
|
245
|
+
window_days?: number;
|
|
246
|
+
enabled?: boolean;
|
|
247
|
+
}
|
|
248
|
+
interface AiChatRequest {
|
|
249
|
+
message: string;
|
|
250
|
+
session_id?: string;
|
|
251
|
+
}
|
|
252
|
+
interface AiChatResponse {
|
|
253
|
+
reply: string;
|
|
254
|
+
session_id: string;
|
|
255
|
+
tool_calls?: AiToolCall[];
|
|
256
|
+
}
|
|
257
|
+
interface AiToolCall {
|
|
258
|
+
tool: string;
|
|
259
|
+
input: Record<string, unknown>;
|
|
260
|
+
result: unknown;
|
|
261
|
+
}
|
|
262
|
+
interface ProjectInfo {
|
|
263
|
+
project: {
|
|
264
|
+
id: string;
|
|
265
|
+
name: string;
|
|
266
|
+
slug: string;
|
|
267
|
+
region: string;
|
|
268
|
+
};
|
|
269
|
+
org: {
|
|
270
|
+
id: string;
|
|
271
|
+
name: string;
|
|
272
|
+
plan: string;
|
|
273
|
+
};
|
|
274
|
+
usage?: Record<string, unknown>;
|
|
275
|
+
keys?: {
|
|
276
|
+
count: number;
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
interface GoodLogsClientOptions {
|
|
280
|
+
/** Secret API key (gl_sk_...) — required for all read/write operations */
|
|
281
|
+
apiKey: string;
|
|
282
|
+
/** API endpoint (default: auto-resolved from API key region) */
|
|
283
|
+
endpoint?: string;
|
|
284
|
+
/** Request timeout in ms (default: 30000) */
|
|
285
|
+
timeout?: number;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* GoodLogs programmatic API client.
|
|
290
|
+
*
|
|
291
|
+
* Provides typed access to all /v1 read & write endpoints:
|
|
292
|
+
* analytics, logs, GQL queries, alerts, SLOs, AI chat, and schema.
|
|
293
|
+
*
|
|
294
|
+
* Requires a **secret** API key (`gl_sk_...`) with appropriate scopes.
|
|
295
|
+
*
|
|
296
|
+
* ```ts
|
|
297
|
+
* import { GoodLogsClient } from "@aj-2000-test/goodlogs-sdk";
|
|
298
|
+
*
|
|
299
|
+
* const client = new GoodLogsClient({ apiKey: "gl_sk_us_..." });
|
|
300
|
+
*
|
|
301
|
+
* // Query logs
|
|
302
|
+
* const { logs, total } = await client.logs.list({ severity: "error", limit: 10 });
|
|
303
|
+
*
|
|
304
|
+
* // Run GQL query
|
|
305
|
+
* const result = await client.gql("count | where severity = 'error' | last 1h");
|
|
306
|
+
*
|
|
307
|
+
* // Manage alerts
|
|
308
|
+
* const alerts = await client.alerts.list();
|
|
309
|
+
* await client.alerts.create({ name: "High Errors", metric: "error_count", threshold: 100 });
|
|
310
|
+
* ```
|
|
311
|
+
*/
|
|
312
|
+
declare class GoodLogsClient {
|
|
313
|
+
private readonly endpoint;
|
|
314
|
+
private readonly apiKey;
|
|
315
|
+
private readonly timeout;
|
|
316
|
+
/** Alert CRUD methods */
|
|
317
|
+
readonly alerts: AlertsApi;
|
|
318
|
+
/** SLO CRUD methods */
|
|
319
|
+
readonly slos: SlosApi;
|
|
320
|
+
/** AI chat methods */
|
|
321
|
+
readonly ai: AiApi;
|
|
322
|
+
constructor(options: GoodLogsClientOptions);
|
|
323
|
+
/** @internal */
|
|
324
|
+
_request<T>(method: string, path: string, body?: unknown): Promise<T>;
|
|
325
|
+
/** @internal */
|
|
326
|
+
_get<T>(path: string): Promise<T>;
|
|
327
|
+
/** @internal */
|
|
328
|
+
_post<T>(path: string, body?: unknown): Promise<T>;
|
|
329
|
+
/** @internal */
|
|
330
|
+
_put<T>(path: string, body?: unknown): Promise<T>;
|
|
331
|
+
/** @internal */
|
|
332
|
+
_delete<T>(path: string): Promise<T>;
|
|
333
|
+
/** Get project info, org, usage, and key count */
|
|
334
|
+
info(): Promise<ProjectInfo>;
|
|
335
|
+
/** Get full schema (event names, property fields, log properties) */
|
|
336
|
+
schema(): Promise<SchemaResponse>;
|
|
337
|
+
/** Run a single GQL query */
|
|
338
|
+
gql(query: string): Promise<GqlResult>;
|
|
339
|
+
/**
|
|
340
|
+
* Run multiple GQL queries in a single request.
|
|
341
|
+
* Returns an array of results (same index as input).
|
|
342
|
+
* Each result has `status: "ok"` with `data`, or `status: "error"` with `error`.
|
|
343
|
+
*/
|
|
344
|
+
gqlBatch(queries: string[]): Promise<GqlBatchResult[]>;
|
|
345
|
+
/** Get GQL autocomplete suggestions */
|
|
346
|
+
gqlAutocomplete(query: string, cursor?: number): Promise<GqlAutocompleteResult>;
|
|
347
|
+
/** Convert natural language to GQL */
|
|
348
|
+
nl2gql(prompt: string, mode?: string): Promise<Nl2GqlResult>;
|
|
349
|
+
}
|
|
350
|
+
declare class AlertsApi {
|
|
351
|
+
private client;
|
|
352
|
+
constructor(client: GoodLogsClient);
|
|
353
|
+
/** List all alert rules */
|
|
354
|
+
list(): Promise<AlertRule[]>;
|
|
355
|
+
/** Create a new alert rule */
|
|
356
|
+
create(rule: CreateAlertRule): Promise<AlertRule>;
|
|
357
|
+
/** Update an alert rule */
|
|
358
|
+
update(alertId: string, rule: UpdateAlertRule): Promise<AlertRule>;
|
|
359
|
+
/** Delete an alert rule */
|
|
360
|
+
delete(alertId: string): Promise<void>;
|
|
361
|
+
/** Mute an alert for N minutes */
|
|
362
|
+
mute(alertId: string, minutes: number): Promise<void>;
|
|
363
|
+
}
|
|
364
|
+
declare class SlosApi {
|
|
365
|
+
private client;
|
|
366
|
+
constructor(client: GoodLogsClient);
|
|
367
|
+
/** List all SLO definitions */
|
|
368
|
+
list(): Promise<SloDefinition[]>;
|
|
369
|
+
/** Create a new SLO */
|
|
370
|
+
create(slo: CreateSlo): Promise<SloDefinition>;
|
|
371
|
+
/** Update an SLO */
|
|
372
|
+
update(sloId: string, slo: UpdateSlo): Promise<SloDefinition>;
|
|
373
|
+
/** Delete an SLO */
|
|
374
|
+
delete(sloId: string): Promise<void>;
|
|
375
|
+
}
|
|
376
|
+
declare class AiApi {
|
|
377
|
+
private client;
|
|
378
|
+
constructor(client: GoodLogsClient);
|
|
379
|
+
/** Send a message to AI chat */
|
|
380
|
+
chat(message: string, sessionId?: string): Promise<AiChatResponse>;
|
|
381
|
+
}
|
|
382
|
+
declare class GoodLogsApiError extends Error {
|
|
383
|
+
readonly status: number;
|
|
384
|
+
readonly code?: string | undefined;
|
|
385
|
+
constructor(status: number, message: string, code?: string | undefined);
|
|
386
|
+
}
|
|
387
|
+
|
|
129
388
|
interface TelemetryEvent {
|
|
130
389
|
/** "sdk" | "dashboard" | "api" | custom */
|
|
131
390
|
source: string;
|
|
@@ -164,4 +423,4 @@ declare function resolveRegion(apiKey: string): string;
|
|
|
164
423
|
/** Resolve API endpoint from key. User-provided endpoint always wins. */
|
|
165
424
|
declare function resolveEndpoint(apiKey: string, userEndpoint?: string): string;
|
|
166
425
|
|
|
167
|
-
export { type EventEntry, GoodLogs, type GoodLogsOptions, type LogEntry, REGION_URLS, type Severity, type TelemetryEvent, type TelemetryOptions, resolveEndpoint, resolveRegion, sendTelemetry };
|
|
426
|
+
export { type AiChatRequest, type AiChatResponse, type AiToolCall, type AlertRule, type CreateAlertRule, type CreateSlo, type EventEntry, GoodLogs, GoodLogsApiError, GoodLogsClient, type GoodLogsClientOptions, type GoodLogsOptions, type GqlAutocompleteResult, type GqlBatchResult, type GqlResult, type LogEntry, type LogRecord, type MuteAlertRequest, type Nl2GqlResult, type NotifyChannel, type ProjectInfo, REGION_URLS, type SchemaField, type SchemaResponse, type Severity, type SloDefinition, type TelemetryEvent, type TelemetryOptions, type UpdateAlertRule, type UpdateSlo, resolveEndpoint, resolveRegion, sendTelemetry };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
2
|
-
`);if(!e)return;for(let t=3;t<Math.min(e.length,8);t++){let n=e[t]?.trim();if(!n||n.includes("goodlogs")&&(n.includes("client.")||n.includes("index.")))continue;let i=n.match(/at\s+(?:(.+?)\s+\()?(.+?):(\d+):\d+\)?/);if(i){let
|
|
1
|
+
var m={us:"https://goodlogs-api-us.happyhill-a7c56143.centralindia.azurecontainerapps.io",eu:"https://goodlogs-api-eu.yellowmeadow-422296f6.japaneast.azurecontainerapps.io",ap:"https://goodlogs-api-ap.delightfulsand-90b72c09.southeastasia.azurecontainerapps.io"};function _(r){let e=r.split("_");return e.length>=4&&e[0]==="gl"?e[2]:"eu"}function d(r,e){if(e)return e;let t=_(r);return m[t]||m.eu}var R=5e3,I=50,u="0.2.2",h="gl_anon_id",g="gl_session_id";function c(){return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,r=>{let e=Math.random()*16|0;return (r==="x"?e:e&3|8).toString(16)})}function $(){let r={$goodlogs_sdk:"js",$goodlogs_sdk_version:u};return typeof navigator>"u"||(typeof screen<"u"&&(r.$screen=`${screen.width}x${screen.height}`),typeof navigator<"u"&&(r.$language=navigator.language??""),typeof location<"u"&&(r.$url=location.href,r.$path=location.pathname,r.$page=location.pathname.split("/").filter(Boolean).pop()||"/"),typeof document<"u"&&(document.referrer&&(r.$referrer=document.referrer),document.title&&(r.$title=document.title))),r}function P(r,e){let t={$session_id:r,$distinct_id:e,$goodlogs_sdk:"js",$goodlogs_sdk_version:u};return typeof navigator>"u"||typeof location<"u"&&(t.$url=location.href,t.$path=location.pathname),t}function x(){if(!(typeof document<"u"))try{let e=new Error().stack?.split(`
|
|
2
|
+
`);if(!e)return;for(let t=3;t<Math.min(e.length,8);t++){let n=e[t]?.trim();if(!n||n.includes("goodlogs")&&(n.includes("client.")||n.includes("index.")))continue;let i=n.match(/at\s+(?:(.+?)\s+\()?(.+?):(\d+):\d+\)?/);if(i){let o=i[1]||"<anonymous>",s=i[2]?.replace(/^.*[/\\]/,"")??"",a=i[3];return `${o}@${s}:${a}`}}}catch{}}function T(){if(typeof localStorage<"u"){let r=localStorage.getItem(h);if(r)return r;let e=c();return localStorage.setItem(h,e),e}return c()}function A(){if(typeof sessionStorage<"u"){let r=sessionStorage.getItem(g);if(r)return r;let e=c();return sessionStorage.setItem(g,e),e}return c()}var v=class{constructor(e){this.logBuffer=[];this.eventBuffer=[];this.timer=null;this.visibilityHandler=null;this.clickHandler=null;this.lastPath="";this.apiKey=e.apiKey,this.endpoint=d(e.apiKey,e.endpoint).replace(/\/+$/,""),this.flushInterval=e.flushInterval??R,this.batchSize=e.batchSize??I,this.defaultContext=e.defaultContext??{},this.onError=e.onError??(()=>{}),this.disabled=e.disabled??false,this.telemetry=e.telemetry??true,this.anonymousId=T(),this.sessionId=A(),this.disabled&&typeof console<"u"&&console.warn("[GoodLogs] SDK is disabled. No events or logs will be sent."),this.disabled||(this.startTimer(),this.attachPageLifecycle(),e.autocapture!==false&&(this.attachClickCapture(),this.captureWebVitals(),this.attachPageviewCapture()),this.sendTelemetry("init","info"));}log(e,t,n){if(this.disabled)return;let i=65536,o=t;t.length>i&&(o=t.slice(0,i-100)+`
|
|
3
3
|
|
|
4
|
-
[truncated \u2014 original ${t.length} chars, limit ${i}]`,this.onError(new Error(`Log message truncated from ${t.length} to ${i} chars`)));let
|
|
4
|
+
[truncated \u2014 original ${t.length} chars, limit ${i}]`,this.onError(new Error(`Log message truncated from ${t.length} to ${i} chars`)));let s=x(),a={severity:e,message:o,properties:{...this.defaultContext,...P(this.sessionId,this.anonymousId),...s?{code_location:s}:{},...n},timestamp:new Date().toISOString()};this.logBuffer.push(a),this.logBuffer.length>=this.batchSize&&this.flush();}debug(e,t){this.log("debug",e,t);}info(e,t){this.log("info",e,t);}warn(e,t){this.log("warn",e,t);}error(e,t){this.log("error",e,t);}fatal(e,t){this.log("fatal",e,t);}identify(e){this.anonymousId=e,typeof localStorage<"u"&&localStorage.setItem(h,e);}getDistinctId(){return this.anonymousId}reset(){this.anonymousId=c(),this.sessionId=c(),typeof localStorage<"u"&&localStorage.setItem(h,this.anonymousId),typeof sessionStorage<"u"&&sessionStorage.setItem(g,this.sessionId);}getSessionId(){return this.sessionId}newSession(){this.sessionId=c(),typeof sessionStorage<"u"&&sessionStorage.setItem(g,this.sessionId);}setSessionId(e){this.sessionId=e,typeof sessionStorage<"u"&&sessionStorage.setItem(g,e);}track(e,t){if(this.disabled)return;let{distinctId:n,...i}=t??{},o={event:e,distinctId:n??this.anonymousId,properties:{...$(),...i,$session_id:this.sessionId},timestamp:new Date().toISOString()};this.eventBuffer.push(o),this.eventBuffer.length>=this.batchSize&&this.flush();}async flush(){let e=this.logBuffer.splice(0),t=this.eventBuffer.splice(0),n=[];e.length>0&&n.push(this.sendLogs(e)),t.length>0&&n.push(this.sendEvents(t)),await Promise.all(n);}async shutdown(){this.stopTimer(),this.detachPageLifecycle(),this.detachClickCapture(),await this.flush();}async sendLogs(e){for(let n=0;n<e.length;n+=500){let o=e.slice(n,n+500).map(s=>({severity:s.severity,message:s.message,properties:s.properties,timestamp:s.timestamp}));await this.postWithRetry("/v1/logs",o,s=>{for(let a of s)this.logBuffer.push({severity:a.severity,message:a.message,properties:a.properties,timestamp:a.timestamp});});}}async sendEvents(e){for(let n=0;n<e.length;n+=500){let o=e.slice(n,n+500).map(s=>({event:s.event,distinctId:s.distinctId,properties:s.properties,timestamp:s.timestamp}));await this.postWithRetry("/v1/events",o,s=>{for(let a of s)this.eventBuffer.push({event:a.event,distinctId:a.distinctId,properties:a.properties,timestamp:a.timestamp});});}}async postWithRetry(e,t,n,i=0){try{let o=await fetch(`${this.endpoint}${e}`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,"X-GoodLogs-SDK":`js/${u}`},body:JSON.stringify({batch:t})});if(o.status===429||o.status===503){if(i<4){let a=Math.min(1e3*Math.pow(2,i),8e3),l=Math.random()*500;return await new Promise(p=>setTimeout(p,a+l)),this.postWithRetry(e,t,n,i+1)}this.onError(new Error(`GoodLogs rate limited after ${i} retries`));return}if(!o.ok){let a=await o.text().catch(()=>""),l=new Error(`GoodLogs API error ${o.status}: ${a}`);this.onError(l),o.status>=500&&i===0&&n(t);return}let s=await o.json().catch(()=>null);if(s&&s.rejected&&s.rejected>0){let a=t.slice(s.accepted??0);a.length>0&&n(a);}}catch(o){let s=o instanceof Error?o:new Error(String(o));i===0&&n(t),this.onError(s);}}startTimer(){this.timer=setInterval(()=>{this.flush();},this.flushInterval);let e=this.timer;typeof e?.unref=="function"&&e.unref();}stopTimer(){this.timer!==null&&(clearInterval(this.timer),this.timer=null);}attachPageLifecycle(){typeof document>"u"||(this.visibilityHandler=()=>{document.visibilityState==="hidden"&&this.keepaliveFlush();},document.addEventListener("visibilitychange",this.visibilityHandler));}captureWebVitals(){if(!(typeof PerformanceObserver>"u")){try{new PerformanceObserver(e=>{let t=e.getEntries()[0];t&&this.track("$web_vital",{properties:{$metric:"FCP",$value_ms:Math.round(t.startTime)}});}).observe({type:"paint",buffered:!0});}catch{}try{new PerformanceObserver(e=>{let t=e.getEntries(),n=t[t.length-1];n&&this.track("$web_vital",{properties:{$metric:"LCP",$value_ms:Math.round(n.startTime)}});}).observe({type:"largest-contentful-paint",buffered:!0});}catch{}try{let e=0;if(new PerformanceObserver(t=>{for(let n of t.getEntries())n.hadRecentInput||(e+=n.value);}).observe({type:"layout-shift",buffered:!0}),typeof document<"u"){let t=()=>{e>0&&this.track("$web_vital",{properties:{$metric:"CLS",$value:Math.round(e*1e3)/1e3}});};document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&t();});}}catch{}try{if(typeof performance<"u"){let e=performance.getEntriesByType?.("navigation")?.[0];e?.responseStart&&this.track("$web_vital",{properties:{$metric:"TTFB",$value_ms:Math.round(e.responseStart)}});}}catch{}try{new PerformanceObserver(e=>{for(let t of e.getEntries()){let n=t.duration;n>0&&this.track("$web_vital",{properties:{$metric:"INP",$value_ms:Math.round(n)}});}}).observe({type:"event",buffered:!0});}catch{}}}attachPageviewCapture(){if(typeof document>"u"||typeof location>"u")return;this.lastPath=location.pathname,this.track("$pageview");let e=()=>{typeof location<"u"&&location.pathname!==this.lastPath&&(this.lastPath=location.pathname,this.track("$pageview"));};if(typeof history<"u"){let t=history.pushState,n=history.replaceState;history.pushState=function(...i){t.apply(this,i),e();},history.replaceState=function(...i){n.apply(this,i),e();};}typeof addEventListener<"u"&&addEventListener("popstate",e);}attachClickCapture(){typeof document>"u"||(this.clickHandler=e=>{let n=e.target?.closest?.("a, button, [data-gl-event], [role='button']");if(!n)return;let i=n.getAttribute?.("data-gl-event"),o=n.tagName?.toLowerCase()??"",s=(n.textContent??"").trim().slice(0,50),a=n.getAttribute?.("href")??void 0,l=(n.className??"").toString().slice(0,80);this.track(i||"$click",{properties:{$element_tag:o,$element_text:s||void 0,$element_href:a,$element_classes:l||void 0}});},document.addEventListener("click",this.clickHandler));}detachClickCapture(){this.clickHandler&&typeof document<"u"&&(document.removeEventListener("click",this.clickHandler),this.clickHandler=null);}detachPageLifecycle(){this.visibilityHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=null);}keepaliveFlush(){let e=this.logBuffer.splice(0),t=this.eventBuffer.splice(0),n={"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,"X-GoodLogs-SDK":`js/${u}`};e.length>0&&fetch(`${this.endpoint}/v1/logs`,{method:"POST",headers:n,body:JSON.stringify({batch:e.map(i=>({severity:i.severity,message:i.message,properties:i.properties,timestamp:i.timestamp}))}),keepalive:true}).catch(()=>{}),t.length>0&&fetch(`${this.endpoint}/v1/events`,{method:"POST",headers:n,body:JSON.stringify({batch:t.map(i=>({event:i.event,distinctId:i.distinctId,properties:i.properties,timestamp:i.timestamp}))}),keepalive:true}).catch(()=>{});}sendTelemetry(e,t,n){!this.telemetry||this.disabled||fetch(`${this.endpoint}/v1/telemetry`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,"X-GoodLogs-SDK":`js/${u}`},body:JSON.stringify({source:"sdk",event:e,level:t,metadata:{...n,sdk_version:u}}),keepalive:true}).catch(()=>{});}};var y=class{constructor(e){if(!e.apiKey)throw new Error("apiKey is required");if(!e.apiKey.startsWith("gl_sk_"))throw new Error("GoodLogsClient requires a secret API key (gl_sk_...)");this.apiKey=e.apiKey,this.endpoint=d(e.apiKey,e.endpoint),this.timeout=e.timeout??3e4,this.alerts=new b(this),this.slos=new S(this),this.ai=new k(this);}async _request(e,t,n){let i=`${this.endpoint}${t}`,o={Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},s=new AbortController,a=setTimeout(()=>s.abort(),this.timeout);try{let l=await fetch(i,{method:e,headers:o,body:n?JSON.stringify(n):void 0,signal:s.signal});if(!l.ok){let p=await l.json().catch(()=>({})),E=p?.error?.message??`API error ${l.status}`;throw new f(l.status,E,p?.error?.code)}return l.status===204?void 0:await l.json()}finally{clearTimeout(a);}}_get(e){return this._request("GET",e)}_post(e,t){return this._request("POST",e,t)}_put(e,t){return this._request("PUT",e,t)}_delete(e){return this._request("DELETE",e)}info(){return this._get("/v1/info")}schema(){return this._get("/v1/schema")}gql(e){return this._post("/v1/gql/query",{q:e})}gqlBatch(e){return this._post("/v1/gql",{queries:e})}gqlAutocomplete(e,t){let n=`/v1/gql/autocomplete?q=${encodeURIComponent(e)}`;return t!==void 0&&(n+=`&cursor=${t}`),this._get(n)}nl2gql(e,t){return this._post("/v1/gql/nl",{prompt:e,mode:t})}},b=class{constructor(e){this.client=e;}list(){return this.client._get("/v1/alerts")}create(e){return this.client._post("/v1/alerts",e)}update(e,t){return this.client._put(`/v1/alerts/${e}`,t)}delete(e){return this.client._delete(`/v1/alerts/${e}`)}mute(e,t){return this.client._post(`/v1/alerts/${e}/mute`,{minutes:t})}},S=class{constructor(e){this.client=e;}list(){return this.client._get("/v1/slos")}create(e){return this.client._post("/v1/slos",e)}update(e,t){return this.client._put(`/v1/slos/${e}`,t)}delete(e){return this.client._delete(`/v1/slos/${e}`)}},k=class{constructor(e){this.client=e;}chat(e,t){return this.client._post("/v1/ai/chat",{message:e,session_id:t})}},f=class extends Error{constructor(t,n,i){super(n);this.status=t;this.code=i;this.name="GoodLogsApiError";}};var w="0.1.0";function C(r,e){let t=d(e?.apiKey??"",e?.endpoint).replace(/\/+$/,""),n={"Content-Type":"application/json","X-GoodLogs-SDK":w};e?.token&&(n.Authorization=`Bearer ${e.token}`),fetch(`${t}/v1/telemetry`,{method:"POST",headers:n,body:JSON.stringify({source:r.source,event:r.event,level:r.level??"info",metadata:{...r.metadata,sdk_version:w}}),keepalive:true}).catch(()=>{});}export{v as GoodLogs,f as GoodLogsApiError,y as GoodLogsClient,m as REGION_URLS,d as resolveEndpoint,_ as resolveRegion,C as sendTelemetry};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aj-2000-test/goodlogs-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "GoodLogs SDK —
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "GoodLogs SDK — ingest logs/events + programmatic API client for queries, alerts, AI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"files": [
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
|
+
"sideEffects": false,
|
|
19
20
|
"scripts": {
|
|
20
21
|
"build": "tsup",
|
|
21
22
|
"dev": "tsup --watch",
|