1 | ;
|
2 | /*!
|
3 | * Copyright 2015 Google Inc. All Rights Reserved.
|
4 | *
|
5 | * Licensed under the Apache License, Version 2.0 (the "License");
|
6 | * you may not use this file except in compliance with the License.
|
7 | * You may obtain a copy of the License at
|
8 | *
|
9 | * http://www.apache.org/licenses/LICENSE-2.0
|
10 | *
|
11 | * Unless required by applicable law or agreed to in writing, software
|
12 | * distributed under the License is distributed on an "AS IS" BASIS,
|
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 | * See the License for the specific language governing permissions and
|
15 | * limitations under the License.
|
16 | */
|
17 | Object.defineProperty(exports, "__esModule", { value: true });
|
18 | exports.Entry = exports.TRACE_SAMPLED_KEY = exports.TRACE_KEY = exports.SPAN_ID_KEY = exports.SOURCE_LOCATION_KEY = exports.OPERATION_KEY = exports.LABELS_KEY = exports.INSERT_ID_KEY = void 0;
|
19 | // eslint-disable-next-line @typescript-eslint/no-var-requires
|
20 | const EventId = require('eventid');
|
21 | const extend = require("extend");
|
22 | const common_1 = require("./utils/common");
|
23 | const http_request_1 = require("./utils/http-request");
|
24 | const context_1 = require("./utils/context");
|
25 | const eventId = new EventId();
|
26 | exports.INSERT_ID_KEY = 'logging.googleapis.com/insertId';
|
27 | exports.LABELS_KEY = 'logging.googleapis.com/labels';
|
28 | exports.OPERATION_KEY = 'logging.googleapis.com/operation';
|
29 | exports.SOURCE_LOCATION_KEY = 'logging.googleapis.com/sourceLocation';
|
30 | exports.SPAN_ID_KEY = 'logging.googleapis.com/spanId';
|
31 | exports.TRACE_KEY = 'logging.googleapis.com/trace';
|
32 | exports.TRACE_SAMPLED_KEY = 'logging.googleapis.com/trace_sampled';
|
33 | /**
|
34 | * Create an entry object to define new data to insert into a meta.
|
35 | *
|
36 | * Note, {@link https://cloud.google.com/logging/quotas|Cloud Logging Quotas and limits}
|
37 | * dictates that the maximum log entry size, including all
|
38 | * {@link https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry|LogEntry Resource properties},
|
39 | * cannot exceed approximately 256 KB.
|
40 | *
|
41 | * See {@link https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry|LogEntry JSON representation}
|
42 | *
|
43 | * @class
|
44 | *
|
45 | * @param {?object} [metadata] See a
|
46 | * [LogEntry
|
47 | * Resource](https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry).
|
48 | * @param {object|string} data The data to use as the value for this log
|
49 | * entry.
|
50 | *
|
51 | * If providing an object, these value types are supported:
|
52 | * - `String`
|
53 | * - `Number`
|
54 | * - `Boolean`
|
55 | * - `Buffer`
|
56 | * - `Object`
|
57 | * - `Array`
|
58 | *
|
59 | * Any other types are stringified with `String(value)`.
|
60 | *
|
61 | * @example
|
62 | * ```
|
63 | * const {Logging} = require('@google-cloud/logging');
|
64 | * const logging = new Logging();
|
65 | * const syslog = logging.log('syslog');
|
66 | *
|
67 | * const metadata = {
|
68 | * resource: {
|
69 | * type: 'gce_instance',
|
70 | * labels: {
|
71 | * zone: 'global',
|
72 | * instance_id: '3'
|
73 | * }
|
74 | * }
|
75 | * };
|
76 | *
|
77 | * const entry = syslog.entry(metadata, {
|
78 | * delegate: 'my_username'
|
79 | * });
|
80 | *
|
81 | * syslog.alert(entry, (err, apiResponse) => {
|
82 | * if (!err) {
|
83 | * // Log entry inserted successfully.
|
84 | * }
|
85 | * });
|
86 | *
|
87 | * //-
|
88 | * // You will also receive `Entry` objects when using
|
89 | * // Logging#getEntries() and Log#getEntries().
|
90 | * //-
|
91 | * logging.getEntries((err, entries) => {
|
92 | * if (!err) {
|
93 | * // entries[0].data = The data value from the log entry.
|
94 | * }
|
95 | * });
|
96 | * ```
|
97 | */
|
98 | class Entry {
|
99 | constructor(metadata, data) {
|
100 | /**
|
101 | * @name Entry#metadata
|
102 | * @type {object}
|
103 | * @property {Date} timestamp
|
104 | * @property {number} insertId
|
105 | */
|
106 | this.metadata = extend({
|
107 | timestamp: new Date(),
|
108 | }, metadata);
|
109 | // JavaScript date has a very coarse granularity (millisecond), which makes
|
110 | // it quite likely that multiple log entries would have the same timestamp.
|
111 | // The Logging API doesn't guarantee to preserve insertion order for entries
|
112 | // with the same timestamp. The service does use `insertId` as a secondary
|
113 | // ordering for entries with the same timestamp. `insertId` needs to be
|
114 | // globally unique (within the project) however.
|
115 | //
|
116 | // We use a globally unique monotonically increasing EventId as the
|
117 | // insertId.
|
118 | this.metadata.insertId = this.metadata.insertId || eventId.new();
|
119 | /**
|
120 | * @name Entry#data
|
121 | * @type {object}
|
122 | */
|
123 | this.data = data;
|
124 | }
|
125 | /**
|
126 | * Serialize an entry to the format the API expects. Read more:
|
127 | * https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry
|
128 | *
|
129 | * @param {object} [options] Configuration object.
|
130 | * @param {boolean} [options.removeCircular] Replace circular references in an
|
131 | * object with a string value, `[Circular]`.
|
132 | * @param {string} [projectId] GCP Project ID.
|
133 | */
|
134 | toJSON(options = {}, projectId = '') {
|
135 | const entry = extend(true, {}, this.metadata);
|
136 | // Format log message
|
137 | if (Object.prototype.toString.call(this.data) === '[object Object]') {
|
138 | entry.jsonPayload = common_1.objToStruct(this.data, {
|
139 | removeCircular: !!options.removeCircular,
|
140 | stringify: true,
|
141 | });
|
142 | }
|
143 | else if (typeof this.data === 'string') {
|
144 | entry.textPayload = this.data;
|
145 | }
|
146 | // Format log timestamp
|
147 | if (entry.timestamp instanceof Date) {
|
148 | const seconds = entry.timestamp.getTime() / 1000;
|
149 | const secondsRounded = Math.floor(seconds);
|
150 | entry.timestamp = {
|
151 | seconds: secondsRounded,
|
152 | nanos: Math.floor((seconds - secondsRounded) * 1e9),
|
153 | };
|
154 | }
|
155 | else if (typeof entry.timestamp === 'string') {
|
156 | entry.timestamp = common_1.zuluToDateObj(entry.timestamp);
|
157 | }
|
158 | // Format httpRequest
|
159 | const req = this.metadata.httpRequest;
|
160 | if (http_request_1.isRawHttpRequest(req)) {
|
161 | entry.httpRequest = http_request_1.makeHttpRequestData(req);
|
162 | // Format trace and span
|
163 | const traceContext = this.extractTraceFromHeaders(projectId);
|
164 | if (traceContext) {
|
165 | if (!this.metadata.trace && traceContext.trace)
|
166 | entry.trace = traceContext.trace;
|
167 | if (!this.metadata.spanId && traceContext.spanId)
|
168 | entry.spanId = traceContext.spanId;
|
169 | if (this.metadata.traceSampled === undefined)
|
170 | entry.traceSampled = traceContext.traceSampled;
|
171 | }
|
172 | }
|
173 | return entry;
|
174 | }
|
175 | /**
|
176 | * Serialize an entry to a standard format for any transports, e.g. agents.
|
177 | * Read more: https://cloud.google.com/logging/docs/structured-logging
|
178 | */
|
179 | toStructuredJSON(projectId = '') {
|
180 | const meta = this.metadata;
|
181 | // Mask out the keys that need to be renamed.
|
182 | /* eslint-disable @typescript-eslint/no-unused-vars */
|
183 | const { textPayload, jsonPayload, insertId, trace, spanId, traceSampled, operation, sourceLocation, labels, ...validKeys } = meta;
|
184 | /* eslint-enable @typescript-eslint/no-unused-vars */
|
185 | const entry = extend(true, {}, validKeys);
|
186 | // Re-map keys names.
|
187 | entry[exports.LABELS_KEY] = meta.labels
|
188 | ? Object.assign({}, meta.labels)
|
189 | : undefined;
|
190 | entry[exports.INSERT_ID_KEY] = meta.insertId || undefined;
|
191 | entry[exports.TRACE_KEY] = meta.trace || undefined;
|
192 | entry[exports.SPAN_ID_KEY] = meta.spanId || undefined;
|
193 | entry[exports.TRACE_SAMPLED_KEY] =
|
194 | 'traceSampled' in meta && meta.traceSampled !== null
|
195 | ? meta.traceSampled
|
196 | : undefined;
|
197 | // Format log payload.
|
198 | entry.message =
|
199 | meta.textPayload || meta.jsonPayload || meta.protoPayload || undefined;
|
200 | entry.message = this.data || entry.message;
|
201 | // Format timestamp
|
202 | if (meta.timestamp instanceof Date) {
|
203 | entry.timestamp = meta.timestamp.toISOString();
|
204 | }
|
205 | // Format httprequest
|
206 | const req = meta.httpRequest;
|
207 | if (http_request_1.isRawHttpRequest(req)) {
|
208 | entry.httpRequest = http_request_1.makeHttpRequestData(req);
|
209 | // Detected trace context from headers if applicable.
|
210 | const traceContext = this.extractTraceFromHeaders(projectId);
|
211 | if (traceContext) {
|
212 | if (!entry[exports.TRACE_KEY] && traceContext.trace)
|
213 | entry[exports.TRACE_KEY] = traceContext.trace;
|
214 | if (!entry[exports.SPAN_ID_KEY] && traceContext.spanId)
|
215 | entry[exports.SPAN_ID_KEY] = traceContext.spanId;
|
216 | if (entry[exports.TRACE_SAMPLED_KEY] === undefined)
|
217 | entry[exports.TRACE_SAMPLED_KEY] = traceContext.traceSampled;
|
218 | }
|
219 | }
|
220 | return entry;
|
221 | }
|
222 | /**
|
223 | * extractTraceFromHeaders extracts trace and span information from raw HTTP
|
224 | * request headers only.
|
225 | * @private
|
226 | */
|
227 | extractTraceFromHeaders(projectId) {
|
228 | const rawReq = this.metadata.httpRequest;
|
229 | if (rawReq && 'headers' in rawReq) {
|
230 | return context_1.getOrInjectContext(rawReq, projectId, false);
|
231 | }
|
232 | return null;
|
233 | }
|
234 | /**
|
235 | * Create an Entry object from an API response, such as `entries:list`.
|
236 | *
|
237 | * @private
|
238 | *
|
239 | * @param {object} entry An API representation of an entry. See a
|
240 | * {@link https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry| LogEntry}.
|
241 | * @returns {Entry}
|
242 | */
|
243 | static fromApiResponse_(entry) {
|
244 | let data = entry[entry.payload];
|
245 | if (entry.payload === 'jsonPayload') {
|
246 | data = common_1.structToObj(data);
|
247 | }
|
248 | const serializedEntry = new Entry(entry, data);
|
249 | if (entry.timestamp) {
|
250 | let ms = Number(entry.timestamp.seconds) * 1000;
|
251 | ms += Number(entry.timestamp.nanos) / 1e6;
|
252 | serializedEntry.metadata.timestamp = new Date(ms);
|
253 | }
|
254 | return serializedEntry;
|
255 | }
|
256 | }
|
257 | exports.Entry = Entry;
|
258 | //# sourceMappingURL=entry.js.map |
\ | No newline at end of file |