|
25 | 25 | import weakref |
26 | 26 | from collections import OrderedDict |
27 | 27 |
|
| 28 | +from newrelic.api.application import application_instance |
28 | 29 | import newrelic.core.database_node |
29 | 30 | import newrelic.core.error_node |
| 31 | +from newrelic.core.log_event_node import LogEventNode |
30 | 32 | import newrelic.core.root_node |
31 | 33 | import newrelic.core.transaction_node |
32 | 34 | import newrelic.packages.six as six |
33 | | -from newrelic.api.time_trace import TimeTrace |
| 35 | +from newrelic.api.time_trace import TimeTrace, get_linking_metadata |
34 | 36 | from newrelic.common.encoding_utils import ( |
35 | 37 | DistributedTracePayload, |
36 | 38 | NrTraceState, |
|
46 | 48 | obfuscate, |
47 | 49 | ) |
48 | 50 | from newrelic.core.attribute import ( |
| 51 | + MAX_LOG_MESSAGE_LENGTH, |
49 | 52 | MAX_NUM_USER_ATTRIBUTES, |
50 | 53 | create_agent_attributes, |
51 | 54 | create_attributes, |
52 | 55 | create_user_attributes, |
53 | 56 | process_user_attribute, |
| 57 | + truncate, |
54 | 58 | ) |
55 | 59 | from newrelic.core.attribute_filter import ( |
56 | 60 | DST_ERROR_COLLECTOR, |
57 | 61 | DST_NONE, |
58 | 62 | DST_TRANSACTION_TRACER, |
59 | 63 | ) |
60 | | -from newrelic.core.config import DEFAULT_RESERVOIR_SIZE |
| 64 | +from newrelic.core.config import DEFAULT_RESERVOIR_SIZE, LOG_EVENT_RESERVOIR_SIZE |
61 | 65 | from newrelic.core.custom_event import create_custom_event |
62 | 66 | from newrelic.core.stack_trace import exception_stack |
63 | 67 | from newrelic.core.stats_engine import CustomMetrics, SampledDataSet |
@@ -204,7 +208,6 @@ def __init__(self, application, enabled=None, source=None): |
204 | 208 |
|
205 | 209 | self._errors = [] |
206 | 210 | self._slow_sql = [] |
207 | | - self._custom_events = SampledDataSet(capacity=DEFAULT_RESERVOIR_SIZE) |
208 | 211 |
|
209 | 212 | self._stack_trace_count = 0 |
210 | 213 | self._explain_plan_count = 0 |
@@ -320,6 +323,13 @@ def __init__(self, application, enabled=None, source=None): |
320 | 323 | if self._settings: |
321 | 324 | self.enabled = True |
322 | 325 |
|
| 326 | + if self._settings: |
| 327 | + self._custom_events = SampledDataSet(capacity=self._settings.event_harvest_config.harvest_limits.custom_event_data) |
| 328 | + self._log_events = SampledDataSet(capacity=self._settings.event_harvest_config.harvest_limits.log_event_data) |
| 329 | + else: |
| 330 | + self._custom_events = SampledDataSet(capacity=DEFAULT_RESERVOIR_SIZE) |
| 331 | + self._log_events = SampledDataSet(capacity=LOG_EVENT_RESERVOIR_SIZE) |
| 332 | + |
323 | 333 | def __del__(self): |
324 | 334 | self._dead = True |
325 | 335 | if self._state == self.STATE_RUNNING: |
@@ -562,6 +572,7 @@ def __exit__(self, exc, value, tb): |
562 | 572 | errors=tuple(self._errors), |
563 | 573 | slow_sql=tuple(self._slow_sql), |
564 | 574 | custom_events=self._custom_events, |
| 575 | + log_events=self._log_events, |
565 | 576 | apdex_t=self.apdex, |
566 | 577 | suppress_apdex=self.suppress_apdex, |
567 | 578 | custom_metrics=self._custom_metrics, |
@@ -1465,6 +1476,31 @@ def set_transaction_name(self, name, group=None, priority=None): |
1465 | 1476 | self._group = group |
1466 | 1477 | self._name = name |
1467 | 1478 |
|
| 1479 | + |
| 1480 | + def record_log_event(self, message, level=None, timestamp=None, priority=None): |
| 1481 | + settings = self.settings |
| 1482 | + if not (settings and settings.application_logging and settings.application_logging.enabled and settings.application_logging.forwarding and settings.application_logging.forwarding.enabled): |
| 1483 | + return |
| 1484 | + |
| 1485 | + timestamp = timestamp if timestamp is not None else time.time() |
| 1486 | + level = str(level) if level is not None else "UNKNOWN" |
| 1487 | + |
| 1488 | + if not message or message.isspace(): |
| 1489 | + _logger.debug("record_log_event called where message was missing. No log event will be sent.") |
| 1490 | + return |
| 1491 | + |
| 1492 | + message = truncate(message, MAX_LOG_MESSAGE_LENGTH) |
| 1493 | + |
| 1494 | + event = LogEventNode( |
| 1495 | + timestamp=timestamp, |
| 1496 | + level=level, |
| 1497 | + message=message, |
| 1498 | + attributes=get_linking_metadata(), |
| 1499 | + ) |
| 1500 | + |
| 1501 | + self._log_events.add(event, priority=priority) |
| 1502 | + |
| 1503 | + |
1468 | 1504 | def record_exception(self, exc=None, value=None, tb=None, params=None, ignore_errors=None): |
1469 | 1505 | # Deprecation Warning |
1470 | 1506 | warnings.warn( |
@@ -1814,6 +1850,34 @@ def record_custom_event(event_type, params, application=None): |
1814 | 1850 | application.record_custom_event(event_type, params) |
1815 | 1851 |
|
1816 | 1852 |
|
| 1853 | +def record_log_event(message, level=None, timestamp=None, application=None, priority=None): |
| 1854 | + """Record a log event. |
| 1855 | +
|
| 1856 | + Args: |
| 1857 | + record (logging.Record): |
| 1858 | + application (newrelic.api.Application): Application instance. |
| 1859 | + """ |
| 1860 | + |
| 1861 | + if application is None: |
| 1862 | + transaction = current_transaction() |
| 1863 | + if transaction: |
| 1864 | + transaction.record_log_event(message, level, timestamp) |
| 1865 | + else: |
| 1866 | + application = application_instance(activate=False) |
| 1867 | + |
| 1868 | + if application and application.enabled: |
| 1869 | + application.record_log_event(message, level, timestamp, priority=priority) |
| 1870 | + else: |
| 1871 | + _logger.debug( |
| 1872 | + "record_log_event has been called but no transaction or application was running. As a result, " |
| 1873 | + "the following event has not been recorded. message: %r level: %r timestamp %r. To correct " |
| 1874 | + "this problem, supply an application object as a parameter to this record_log_event call.", |
| 1875 | + message, level, timestamp, |
| 1876 | + ) |
| 1877 | + elif application.enabled: |
| 1878 | + application.record_log_event(message, level, timestamp, priority=priority) |
| 1879 | + |
| 1880 | + |
1817 | 1881 | def accept_distributed_trace_payload(payload, transport_type="HTTP"): |
1818 | 1882 | transaction = current_transaction() |
1819 | 1883 | if transaction: |
|
0 commit comments