-
Notifications
You must be signed in to change notification settings - Fork 9
/
client.ts
166 lines (144 loc) · 4.36 KB
/
client.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import { Client, Metrics, Plugin, Tracer, AppsignalOptions } from "./interfaces"
import { Extension } from "./extension"
import { Configuration } from "./config"
import { BaseTracer } from "./tracer"
import { BaseMetrics } from "./metrics"
import { NoopTracer, NoopMetrics } from "./noops"
import { Instrumentation } from "./instrument"
import { initCorePlugins, initCoreProbes } from "./bootstrap"
import { demo } from "./demo"
import { VERSION } from "./version"
/**
* AppSignal for Node.js's main class.
*
* Provides methods to control the AppSignal instrumentation and the system
* agent.
*
* @class
*/
export class BaseClient implements Client {
readonly VERSION = VERSION
config: Configuration
extension: Extension
instrumentation: Instrumentation
#tracer: Tracer = new BaseTracer()
#metrics: Metrics
/**
* Global accessors to Client and Config
*/
static get client(): Client {
return global.__APPSIGNAL__
}
static get config(): Configuration {
return global.__APPSIGNAL__?.config
}
/**
* Creates a new instance of the `Appsignal` object
*/
constructor(options: Partial<AppsignalOptions> = {}) {
const { ignoreInstrumentation } = options
this.config = new Configuration(options)
this.extension = new Extension()
this.storeInGlobal()
if (this.isActive) {
this.extension.start()
this.#metrics = new BaseMetrics()
} else {
this.#metrics = new NoopMetrics()
}
this.instrumentation = new Instrumentation(this.tracer(), this.metrics())
initCorePlugins(this.instrumentation, { ignoreInstrumentation })
initCoreProbes(this.metrics())
}
/**
* Returns `true` if the agent is loaded and configuration is valid
*/
get isActive(): boolean {
return Extension.isLoaded && this.config.isValid && this.config.data.active!
}
set isActive(arg) {
console.warn("Cannot set isActive property")
}
/**
* Starts AppSignal with the given configuration. If no configuration is set
* yet it will try to automatically load the configuration using the
* environment loaded from environment variables and the current working
* directory.
*/
public start(): void {
if (this.config.isValid) {
this.extension.start()
} else {
console.error("Not starting, no valid AppSignal configuration found")
}
}
/**
* Stops the AppSignal agent.
*
* Call this before the end of your program to make sure the
* agent is stopped as well.
*/
public stop(calledBy?: string): void {
if (calledBy) {
console.log(`Stopping AppSignal (${calledBy})`)
} else {
console.log("Stopping AppSignal")
}
this.extension.stop()
}
/**
* Returns the current `Tracer` instance.
*
* If the agent is inactive when this method is called, the method
* returns a `NoopTracer`, which will do nothing.
*/
public tracer(): Tracer {
if (!this.isActive) {
return new NoopTracer()
}
return this.#tracer
}
/**
* Returns the current `Metrics` object.
*
* To track application-wide metrics, you can send custom metrics to AppSignal.
* These metrics enable you to track anything in your application, from newly
* registered users to database disk usage. These are not replacements for custom
* instrumentation, but provide an additional way to make certain data in your
* code more accessible and measurable over time.
*
* With different types of metrics (gauges, counters and measurements)
* you can track any kind of data from your apps and tag them with metadata
* to easily spot the differences between contexts.
*/
public metrics(): Metrics {
return this.#metrics
}
/**
* Allows a named module to be modified by a function. The function `fn`
* returns a `Plugin`, which will be loaded by the instrumentation manager
* when the module is required.
*/
public instrument<T>({
PLUGIN_NAME: name,
instrument: fn
}: {
PLUGIN_NAME: string
instrument: (module: T, tracer: Tracer, meter: Metrics) => Plugin<T>
}): this {
this.instrumentation.load(name, fn)
return this
}
/**
* Sends a demonstration/test sample for a exception and a performance issue.
*/
public demo() {
return demo(this.tracer())
}
/**
* Stores the client in global object after initializing
*/
private storeInGlobal(): void {
global.__APPSIGNAL__ = this
}
}