newrelic-lambda-cli 0.9.1__py2.py3-none-any.whl → 0.9.3__py2.py3-none-any.whl

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.
@@ -21,6 +21,9 @@ from newrelic_lambda_cli.types import (
21
21
  IntegrationInstall,
22
22
  IntegrationUpdate,
23
23
  LayerInstall,
24
+ OtelIngestionInstall,
25
+ OtelIngestionUninstall,
26
+ OtelIngestionUpdate,
24
27
  )
25
28
  from newrelic_lambda_cli.utils import parse_arn
26
29
 
@@ -333,7 +336,17 @@ class NewRelicGQL(object):
333
336
 
334
337
 
335
338
  def validate_gql_credentials(input):
336
- assert isinstance(input, (IntegrationInstall, IntegrationUpdate, LayerInstall))
339
+
340
+ assert isinstance(
341
+ input,
342
+ (
343
+ IntegrationInstall,
344
+ IntegrationUpdate,
345
+ LayerInstall,
346
+ OtelIngestionInstall,
347
+ OtelIngestionUpdate,
348
+ ),
349
+ )
337
350
 
338
351
  try:
339
352
  return NewRelicGQL(input.nr_account_id, input.nr_api_key, input.nr_region)
@@ -2,7 +2,13 @@
2
2
 
3
3
  import click
4
4
 
5
- from newrelic_lambda_cli.cli import functions, integrations, layers, subscriptions
5
+ from newrelic_lambda_cli.cli import (
6
+ functions,
7
+ integrations,
8
+ layers,
9
+ otel_ingestions,
10
+ subscriptions,
11
+ )
6
12
 
7
13
 
8
14
  @click.group()
@@ -17,6 +23,7 @@ def cli(ctx, verbose):
17
23
  def register_groups(group):
18
24
  functions.register(group)
19
25
  integrations.register(group)
26
+ otel_ingestions.register(group)
20
27
  layers.register(group)
21
28
  subscriptions.register(group)
22
29
 
@@ -107,7 +107,11 @@ def register(group):
107
107
  def install(ctx, **kwargs):
108
108
  """Install New Relic AWS Lambda Layers"""
109
109
  input = LayerInstall(session=None, verbose=ctx.obj["VERBOSE"], **kwargs)
110
-
110
+ input = input._replace(
111
+ session=boto3.Session(
112
+ profile_name=input.aws_profile, region_name=input.aws_region
113
+ )
114
+ )
111
115
  if input.aws_permissions_check:
112
116
  permissions.ensure_layer_install_permissions(input)
113
117
 
@@ -181,7 +185,11 @@ def install(ctx, **kwargs):
181
185
  def uninstall(ctx, **kwargs):
182
186
  """Uninstall New Relic AWS Lambda Layers"""
183
187
  input = LayerUninstall(session=None, verbose=ctx.obj["VERBOSE"], **kwargs)
184
-
188
+ input = input._replace(
189
+ session=boto3.Session(
190
+ profile_name=input.aws_profile, region_name=input.aws_region
191
+ )
192
+ )
185
193
  if input.aws_permissions_check:
186
194
  permissions.ensure_layer_uninstall_permissions(input)
187
195
 
@@ -0,0 +1,219 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import boto3
4
+ import click
5
+
6
+ from newrelic_lambda_cli import api, otel_ingestions, permissions, integrations
7
+ from newrelic_lambda_cli.types import (
8
+ OtelIngestionInstall,
9
+ OtelIngestionUninstall,
10
+ OtelIngestionUpdate,
11
+ )
12
+ from newrelic_lambda_cli.cli.decorators import add_options, AWS_OPTIONS, NR_OPTIONS
13
+ from newrelic_lambda_cli.cliutils import done, failure
14
+
15
+
16
+ @click.group(name="otel-ingestions")
17
+ def ingestion_group():
18
+ """Manage New Relic AWS Lambda Otel Log Ingestion lambda"""
19
+ pass
20
+
21
+
22
+ def register(group):
23
+ group.add_command(ingestion_group)
24
+ ingestion_group.add_command(install)
25
+ ingestion_group.add_command(uninstall)
26
+ ingestion_group.add_command(update)
27
+
28
+
29
+ @click.command(name="install")
30
+ @add_options(AWS_OPTIONS)
31
+ @click.option(
32
+ "--aws-role-policy",
33
+ help="Alternative AWS role policy to use for integration",
34
+ metavar="<arn>",
35
+ )
36
+ @click.option(
37
+ "--stackname",
38
+ default=otel_ingestions.OTEL_INGEST_STACK_NAME,
39
+ help=f"The AWS Cloudformation stack name which contains the {otel_ingestions.OTEL_INGEST_LAMBDA_NAME} lambda function",
40
+ metavar="<arn>",
41
+ show_default=False,
42
+ required=False,
43
+ )
44
+ @click.option(
45
+ "--memory-size",
46
+ "-m",
47
+ default=128,
48
+ help="Memory size (in MiB) for the log ingestion function",
49
+ metavar="<size>",
50
+ show_default=True,
51
+ type=click.INT,
52
+ )
53
+ @add_options(NR_OPTIONS)
54
+ @click.option(
55
+ "--timeout",
56
+ "-t",
57
+ default=30,
58
+ help="Timeout (in seconds) for the New Relic log ingestion function",
59
+ metavar="<secs>",
60
+ show_default=True,
61
+ type=click.INT,
62
+ )
63
+ @click.option(
64
+ "--role-name",
65
+ default=None,
66
+ help="The name of a pre-created execution role for the log ingest function",
67
+ metavar="<role_name>",
68
+ show_default=False,
69
+ )
70
+ @click.option(
71
+ "--tag",
72
+ "tags",
73
+ default=[],
74
+ help="A tag to be added to the CloudFormation Stack (can be used multiple times)",
75
+ metavar="<key> <value>",
76
+ multiple=True,
77
+ nargs=2,
78
+ )
79
+ @click.pass_context
80
+ def install(ctx, **kwargs):
81
+ """Install New Relic AWS OTEL Ingestion Lambda"""
82
+ input = OtelIngestionInstall(session=None, verbose=ctx.obj["VERBOSE"], **kwargs)
83
+
84
+ input = input._replace(
85
+ session=boto3.Session(
86
+ profile_name=input.aws_profile, region_name=input.aws_region
87
+ )
88
+ )
89
+
90
+ if input.aws_permissions_check:
91
+ permissions.ensure_integration_install_permissions(input)
92
+
93
+ click.echo("Validating New Relic credentials")
94
+ gql_client = api.validate_gql_credentials(input)
95
+
96
+ click.echo("Retrieving integration license key")
97
+ nr_license_key = api.retrieve_license_key(gql_client)
98
+
99
+ install_success = True
100
+
101
+ click.echo(
102
+ f"Creating {otel_ingestions.OTEL_INGEST_LAMBDA_NAME} Lambda function in AWS account"
103
+ )
104
+ res = otel_ingestions.install_otel_log_ingestion(input, nr_license_key)
105
+ install_success = res and install_success
106
+
107
+
108
+ @click.command(name="uninstall")
109
+ @add_options(AWS_OPTIONS)
110
+ @click.option(
111
+ "--nr-account-id",
112
+ "-a",
113
+ envvar="NEW_RELIC_ACCOUNT_ID",
114
+ help="New Relic Account ID",
115
+ metavar="<id>",
116
+ required=False,
117
+ type=click.INT,
118
+ )
119
+ @click.option(
120
+ "--stackname",
121
+ default=otel_ingestions.OTEL_INGEST_STACK_NAME,
122
+ help=f"The AWS Cloudformation stack name which contains the {otel_ingestions.OTEL_INGEST_LAMBDA_NAME} lambda function",
123
+ metavar="<arn>",
124
+ show_default=False,
125
+ required=False,
126
+ )
127
+ @click.option("--force", "-f", help="Force uninstall non-interactively", is_flag=True)
128
+ def uninstall(**kwargs):
129
+ """Uninstall New Relic AWS OTEL Ingestion Lambda"""
130
+ input = OtelIngestionUninstall(session=None, **kwargs)
131
+
132
+ input = input._replace(
133
+ session=boto3.Session(
134
+ profile_name=input.aws_profile, region_name=input.aws_region
135
+ )
136
+ )
137
+
138
+ if input.aws_permissions_check:
139
+ permissions.ensure_integration_uninstall_permissions(input)
140
+
141
+ integrations.remove_log_ingestion_function(input, otel=True)
142
+
143
+ done("Uninstall Complete")
144
+
145
+
146
+ @click.command(name="update")
147
+ @add_options(AWS_OPTIONS)
148
+ @click.option(
149
+ "--stackname",
150
+ default=otel_ingestions.OTEL_INGEST_STACK_NAME,
151
+ help=f"The AWS Cloudformation stack name which contains the {otel_ingestions.OTEL_INGEST_LAMBDA_NAME} lambda function",
152
+ metavar="<arn>",
153
+ show_default=False,
154
+ required=False,
155
+ )
156
+ @click.option(
157
+ "--memory-size",
158
+ "-m",
159
+ help="Memory size (in MiB) for the log ingestion function",
160
+ metavar="<size>",
161
+ type=click.INT,
162
+ )
163
+ @add_options(NR_OPTIONS)
164
+ @click.option(
165
+ "--timeout",
166
+ "-t",
167
+ help="Timeout (in seconds) for the New Relic log ingestion function",
168
+ metavar="<secs>",
169
+ type=click.INT,
170
+ )
171
+ @click.option(
172
+ "--role-name",
173
+ default=None,
174
+ help="The name of a new pre-created execution role for the log ingest function",
175
+ metavar="<role_name>",
176
+ show_default=False,
177
+ )
178
+ @click.option(
179
+ "--stackname",
180
+ default="NewRelicOtelLogIngestion",
181
+ help="The AWS Cloudformation stack name which contains the newrelic-log-ingestion lambda function",
182
+ metavar="<arn>",
183
+ show_default=False,
184
+ required=False,
185
+ )
186
+ @click.option(
187
+ "--tag",
188
+ "tags",
189
+ default=[],
190
+ help="A tag to be added to the CloudFormation Stack (can be used multiple times)",
191
+ metavar="<key> <value>",
192
+ multiple=True,
193
+ nargs=2,
194
+ )
195
+ def update(**kwargs):
196
+ """UpdateNew New Relic AWS OTEL Ingestion Lambda"""
197
+ input = OtelIngestionUpdate(session=None, **kwargs)
198
+
199
+ input = input._replace(
200
+ session=boto3.Session(
201
+ profile_name=input.aws_profile, region_name=input.aws_region
202
+ )
203
+ )
204
+
205
+ if input.aws_permissions_check:
206
+ permissions.ensure_integration_install_permissions(input)
207
+
208
+ update_success = True
209
+
210
+ click.echo(
211
+ f"Updating {otel_ingestions.OTEL_INGEST_LAMBDA_NAME} Lambda function in AWS account"
212
+ )
213
+ res = otel_ingestions.update_otel_log_ingestion(input)
214
+ update_success = res and update_success
215
+
216
+ if update_success:
217
+ done("Update Complete")
218
+ else:
219
+ failure("Update Incomplete. See messages above for details.", exit=True)
@@ -61,28 +61,60 @@ def register(group):
61
61
  metavar="<pattern>",
62
62
  show_default=False,
63
63
  )
64
+ @click.option(
65
+ "--otel",
66
+ "-o",
67
+ help="Subscribe to OTEL log ingestion function",
68
+ is_flag=True,
69
+ )
64
70
  def install(**kwargs):
65
71
  """Install New Relic AWS Lambda Log Subscriptions"""
66
72
  input = SubscriptionInstall(session=None, **kwargs)
67
-
73
+ if input.otel and input.filter_pattern == DEFAULT_FILTER_PATTERN:
74
+ input = input._replace(
75
+ filter_pattern="",
76
+ )
77
+ if input.otel and input.stackname == "NewRelicLogIngestion":
78
+ input = input._replace(
79
+ stackname="NewRelicOtelLogIngestion",
80
+ )
81
+ input = input._replace(
82
+ session=boto3.Session(
83
+ profile_name=input.aws_profile, region_name=input.aws_region
84
+ )
85
+ )
68
86
  if input.aws_permissions_check:
69
87
  permissions.ensure_subscription_install_permissions(input)
70
88
 
71
89
  functions = get_aliased_functions(input)
72
90
 
73
91
  with ThreadPoolExecutor() as executor:
74
- futures = [
75
- executor.submit(
76
- subscriptions.create_log_subscription,
77
- input._replace(
78
- session=boto3.Session(
79
- profile_name=input.aws_profile, region_name=input.aws_region
80
- )
81
- ),
82
- function,
83
- )
84
- for function in functions
85
- ]
92
+ if input.otel:
93
+ futures = [
94
+ executor.submit(
95
+ subscriptions.create_otel_log_subscription,
96
+ input._replace(
97
+ session=boto3.Session(
98
+ profile_name=input.aws_profile, region_name=input.aws_region
99
+ )
100
+ ),
101
+ function,
102
+ )
103
+ for function in functions
104
+ ]
105
+ else:
106
+ futures = [
107
+ executor.submit(
108
+ subscriptions.create_log_subscription,
109
+ input._replace(
110
+ session=boto3.Session(
111
+ profile_name=input.aws_profile, region_name=input.aws_region
112
+ )
113
+ ),
114
+ function,
115
+ )
116
+ for function in functions
117
+ ]
86
118
  install_success = all(future.result() for future in as_completed(futures))
87
119
 
88
120
  if install_success:
@@ -102,14 +134,6 @@ def install(**kwargs):
102
134
  multiple=True,
103
135
  required=True,
104
136
  )
105
- @click.option(
106
- "--stackname",
107
- default="NewRelicLogIngestion",
108
- help="The AWS Cloudformation stack name which contains the newrelic-log-ingestion lambda function",
109
- metavar="<arn>",
110
- show_default=False,
111
- required=False,
112
- )
113
137
  @click.option(
114
138
  "excludes",
115
139
  "--exclude",
@@ -118,28 +142,52 @@ def install(**kwargs):
118
142
  metavar="<name>",
119
143
  multiple=True,
120
144
  )
145
+ @click.option(
146
+ "--otel",
147
+ "-o",
148
+ help="Subscribe to OTEL log ingestion function",
149
+ is_flag=True,
150
+ )
121
151
  def uninstall(**kwargs):
122
152
  """Uninstall New Relic AWS Lambda Log Subscriptions"""
123
153
  input = SubscriptionUninstall(session=None, **kwargs)
124
-
154
+ input = input._replace(
155
+ session=boto3.Session(
156
+ profile_name=input.aws_profile, region_name=input.aws_region
157
+ )
158
+ )
125
159
  if input.aws_permissions_check:
126
160
  permissions.ensure_subscription_uninstall_permissions(input)
127
161
 
128
162
  functions = get_aliased_functions(input)
129
163
 
130
164
  with ThreadPoolExecutor() as executor:
131
- futures = [
132
- executor.submit(
133
- subscriptions.remove_log_subscription,
134
- input._replace(
135
- session=boto3.Session(
136
- profile_name=input.aws_profile, region_name=input.aws_region
137
- )
138
- ),
139
- function,
140
- )
141
- for function in functions
142
- ]
165
+ if input.otel:
166
+ futures = [
167
+ executor.submit(
168
+ subscriptions.remove_otel_log_subscription,
169
+ input._replace(
170
+ session=boto3.Session(
171
+ profile_name=input.aws_profile, region_name=input.aws_region
172
+ )
173
+ ),
174
+ function,
175
+ )
176
+ for function in functions
177
+ ]
178
+ else:
179
+ futures = [
180
+ executor.submit(
181
+ subscriptions.remove_log_subscription,
182
+ input._replace(
183
+ session=boto3.Session(
184
+ profile_name=input.aws_profile, region_name=input.aws_region
185
+ )
186
+ ),
187
+ function,
188
+ )
189
+ for function in functions
190
+ ]
143
191
  uninstall_success = all(future.result() for future in as_completed(futures))
144
192
 
145
193
  if uninstall_success:
@@ -14,6 +14,7 @@ from newrelic_lambda_cli.types import (
14
14
  IntegrationInstall,
15
15
  IntegrationUninstall,
16
16
  IntegrationUpdate,
17
+ OtelIngestionUninstall,
17
18
  )
18
19
  from newrelic_lambda_cli.utils import catch_boto_errors, NR_DOCS_ACT_LINKING_URL
19
20
 
@@ -165,9 +166,11 @@ def _create_role(input):
165
166
  {"ParameterKey": "PolicyName", "ParameterValue": role_policy_name},
166
167
  ],
167
168
  Capabilities=["CAPABILITY_NAMED_IAM"],
168
- Tags=[{"Key": key, "Value": value} for key, value in input.tags]
169
- if input.tags
170
- else [],
169
+ Tags=(
170
+ [{"Key": key, "Value": value} for key, value in input.tags]
171
+ if input.tags
172
+ else []
173
+ ),
171
174
  )
172
175
 
173
176
  click.echo("Waiting for stack creation to complete... ", nl=False)
@@ -268,9 +271,11 @@ def _import_log_ingestion_function(input, nr_license_key):
268
271
  TemplateBody=template.read(),
269
272
  Parameters=parameters,
270
273
  Capabilities=capabilities,
271
- Tags=[{"Key": key, "Value": value} for key, value in input.tags]
272
- if input.tags
273
- else [],
274
+ Tags=(
275
+ [{"Key": key, "Value": value} for key, value in input.tags]
276
+ if input.tags
277
+ else []
278
+ ),
274
279
  ChangeSetType="IMPORT",
275
280
  ChangeSetName=change_set_name,
276
281
  ResourcesToImport=[
@@ -311,9 +316,11 @@ def _create_log_ingestion_function(
311
316
  TemplateURL=template_url,
312
317
  Parameters=parameters,
313
318
  Capabilities=capabilities,
314
- Tags=[{"Key": key, "Value": value} for key, value in input.tags]
315
- if input.tags
316
- else [],
319
+ Tags=(
320
+ [{"Key": key, "Value": value} for key, value in input.tags]
321
+ if input.tags
322
+ else []
323
+ ),
317
324
  ChangeSetType=mode,
318
325
  ChangeSetName=change_set_name,
319
326
  )
@@ -444,9 +451,11 @@ def update_log_ingestion_function(input):
444
451
  TemplateBody=json.dumps(template_body),
445
452
  Parameters=params,
446
453
  Capabilities=["CAPABILITY_IAM"],
447
- Tags=[{"Key": key, "Value": value} for key, value in input.tags]
448
- if input.tags
449
- else [],
454
+ Tags=(
455
+ [{"Key": key, "Value": value} for key, value in input.tags]
456
+ if input.tags
457
+ else []
458
+ ),
450
459
  )
451
460
 
452
461
  try:
@@ -496,18 +505,20 @@ def update_log_ingestion_function(input):
496
505
 
497
506
 
498
507
  @catch_boto_errors
499
- def remove_log_ingestion_function(input):
500
- assert isinstance(input, IntegrationUninstall)
501
-
508
+ def remove_log_ingestion_function(input, otel: bool = False):
509
+ assert isinstance(input, (IntegrationUninstall, OtelIngestionUninstall))
510
+ log_ingestion_lambda = "log ingestion" if not otel else "OTEL log ingestion"
502
511
  client = input.session.client("cloudformation")
503
512
  stack_status = _check_for_ingest_stack(input.session, input.stackname)
504
513
  if stack_status is None:
505
514
  click.echo(
506
- "No New Relic AWS Lambda log ingestion found in region %s, skipping"
507
- % input.session.region_name
515
+ "No New Relic AWS Lambda %s found in region %s, skipping"
516
+ % (log_ingestion_lambda, input.session.region_name)
508
517
  )
509
518
  return
510
- click.echo("Deleting New Relic log ingestion stack '%s'" % input.stackname)
519
+ click.echo(
520
+ "Deleting New Relic %s stack '%s'" % (log_ingestion_lambda, input.stackname)
521
+ )
511
522
  client.delete_stack(StackName=input.stackname)
512
523
  click.echo(
513
524
  "Waiting for stack deletion to complete, this may take a minute... ", nl=False
@@ -755,9 +766,11 @@ def install_license_key(input, nr_license_key, policy_name=None):
755
766
  TemplateBody=template.read(),
756
767
  Parameters=parameters,
757
768
  Capabilities=["CAPABILITY_NAMED_IAM"],
758
- Tags=[{"Key": key, "Value": value} for key, value in input.tags]
759
- if input.tags
760
- else [],
769
+ Tags=(
770
+ [{"Key": key, "Value": value} for key, value in input.tags]
771
+ if input.tags
772
+ else []
773
+ ),
761
774
  ChangeSetType=mode,
762
775
  ChangeSetName=change_set_name,
763
776
  )
@@ -202,6 +202,18 @@ def _add_new_relic(input, config, nr_license_key):
202
202
  "NEW_RELIC_LAMBDA_EXTENSION_ENABLED"
203
203
  ] = "false"
204
204
 
205
+ if "dotnet" in runtime:
206
+ update_kwargs["Environment"]["Variables"]["CORECLR_ENABLE_PROFILING"] = "1"
207
+ update_kwargs["Environment"]["Variables"][
208
+ "CORECLR_PROFILER"
209
+ ] = "{36032161-FFC0-4B61-B559-F6C5D41BAE5A}"
210
+ update_kwargs["Environment"]["Variables"][
211
+ "CORECLR_NEWRELIC_HOME"
212
+ ] = "/opt/lib/newrelic-dotnet-agent"
213
+ update_kwargs["Environment"]["Variables"][
214
+ "CORECLR_PROFILER_PATH"
215
+ ] = "/opt/lib/newrelic-dotnet-agent/libNewRelicProfiler.so"
216
+
205
217
  return update_kwargs
206
218
 
207
219
 
@@ -0,0 +1,276 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import json
4
+ import os
5
+ import time
6
+
7
+ import botocore
8
+ import click
9
+ import json
10
+
11
+ from newrelic_lambda_cli.cliutils import failure, success, warning
12
+ from newrelic_lambda_cli.functions import get_function
13
+ from newrelic_lambda_cli.integrations import _exec_change_set
14
+ from newrelic_lambda_cli.types import (
15
+ OtelIngestionInstall,
16
+ OtelIngestionUpdate,
17
+ )
18
+ from newrelic_lambda_cli.utils import catch_boto_errors, NR_DOCS_ACT_LINKING_URL
19
+
20
+ OTEL_INGEST_STACK_NAME = "NewRelicOtelLogIngestion"
21
+ OTEL_INGEST_LAMBDA_NAME = "newrelic-aws-otel-log-ingestion"
22
+ OTEL_SAR_APP_ID = (
23
+ "arn:aws:serverlessrepo:us-east-1:451483290750:applications/"
24
+ + OTEL_INGEST_LAMBDA_NAME
25
+ )
26
+
27
+
28
+ def _check_for_ingest_stack(session, stack_name):
29
+ return _get_cf_stack_status(session, stack_name)
30
+
31
+
32
+ def _get_cf_stack_status(session, stack_name, nr_account_id=None):
33
+ """Returns the status of the CloudFormation stack if it exists"""
34
+ try:
35
+ res = session.client("cloudformation").describe_stacks(StackName=stack_name)
36
+ except botocore.exceptions.ClientError as e:
37
+ if (
38
+ e.response
39
+ and "ResponseMetadata" in e.response
40
+ and "HTTPStatusCode" in e.response["ResponseMetadata"]
41
+ and e.response["ResponseMetadata"]["HTTPStatusCode"] in (400, 404)
42
+ ):
43
+ return None
44
+ raise click.UsageError(str(e))
45
+ else:
46
+ return res["Stacks"][0]["StackStatus"]
47
+
48
+
49
+ def get_unique_newrelic_otel_log_ingestion_name(session, stackname=None):
50
+ if not stackname:
51
+ stackname = OTEL_INGEST_STACK_NAME
52
+ stack_id = _get_otel_cf_stack_id(session, stack_name=stackname)
53
+ if stack_id:
54
+ return "%s-%s" % (OTEL_INGEST_LAMBDA_NAME, stack_id.split("/")[2].split("-")[4])
55
+
56
+
57
+ def get_newrelic_otel_log_ingestion_function(session, stackname=None):
58
+ unique_log_ingestion_name = get_unique_newrelic_otel_log_ingestion_name(
59
+ session, stackname
60
+ )
61
+ if unique_log_ingestion_name:
62
+ function = get_function(session, unique_log_ingestion_name)
63
+ return function
64
+
65
+
66
+ def _get_otel_cf_stack_id(session, stack_name, nr_account_id=None):
67
+ """Returns the StackId of the CloudFormation stack if it exists"""
68
+ try:
69
+ res = session.client("cloudformation").describe_stacks(StackName=stack_name)
70
+ except botocore.exceptions.ClientError as e:
71
+ if (
72
+ e.response
73
+ and "ResponseMetadata" in e.response
74
+ and "HTTPStatusCode" in e.response["ResponseMetadata"]
75
+ and e.response["ResponseMetadata"]["HTTPStatusCode"] in (400, 404)
76
+ ):
77
+ return None
78
+ raise click.UsageError(str(e))
79
+ else:
80
+ return res["Stacks"][0]["StackId"]
81
+
82
+
83
+ def _get_otel_sar_template_url(session):
84
+ sar_client = session.client("serverlessrepo")
85
+ template_details = sar_client.create_cloud_formation_template(
86
+ ApplicationId=OTEL_SAR_APP_ID
87
+ )
88
+ return template_details["TemplateUrl"]
89
+
90
+
91
+ def _create_otel_log_ingest_parameters(input, nr_license_key, mode="CREATE"):
92
+ assert isinstance(input, (OtelIngestionInstall, OtelIngestionUpdate))
93
+
94
+ update_mode = mode == "UPDATE"
95
+ parameters = []
96
+
97
+ if input.memory_size is not None:
98
+ parameters.append(
99
+ {"ParameterKey": "MemorySize", "ParameterValue": str(input.memory_size)}
100
+ )
101
+ elif update_mode:
102
+ parameters.append({"ParameterKey": "MemorySize", "UsePreviousValue": True})
103
+
104
+ if nr_license_key is not None:
105
+ parameters.append(
106
+ {"ParameterKey": "NRLicenseKey", "ParameterValue": nr_license_key}
107
+ )
108
+ elif update_mode:
109
+ parameters.append({"ParameterKey": "NRLicenseKey", "UsePreviousValue": True})
110
+
111
+ if input.timeout is not None:
112
+ parameters.append(
113
+ {"ParameterKey": "Timeout", "ParameterValue": str(input.timeout)}
114
+ )
115
+ elif update_mode:
116
+ parameters.append({"ParameterKey": "Timeout", "UsePreviousValue": True})
117
+
118
+ capabilities = ["CAPABILITY_IAM"]
119
+ if input.role_name is not None:
120
+ parameters.append(
121
+ {"ParameterKey": "FunctionRole", "ParameterValue": input.role_name}
122
+ )
123
+ capabilities = []
124
+ elif mode != "CREATE":
125
+ parameters.append({"ParameterKey": "FunctionRole", "UsePreviousValue": True})
126
+ capabilities = []
127
+
128
+ return parameters, capabilities
129
+
130
+
131
+ def _create_otel_log_ingestion_function(
132
+ input,
133
+ nr_license_key,
134
+ mode="CREATE",
135
+ ):
136
+ assert isinstance(input, (OtelIngestionInstall, OtelIngestionUpdate))
137
+
138
+ parameters, capabilities = _create_otel_log_ingest_parameters(
139
+ input, nr_license_key, mode
140
+ )
141
+
142
+ client = input.session.client("cloudformation")
143
+
144
+ click.echo("Fetching new CloudFormation template url for OTEL log ingestion")
145
+ template_url = _get_otel_sar_template_url(input.session)
146
+ change_set_name = "%s-%s-%d" % (input.stackname, mode, int(time.time()))
147
+ click.echo("Creating change set: %s" % change_set_name)
148
+ try:
149
+ change_set = client.create_change_set(
150
+ StackName=input.stackname,
151
+ TemplateURL=template_url,
152
+ Parameters=parameters,
153
+ Capabilities=capabilities,
154
+ Tags=(
155
+ [{"Key": key, "Value": value} for key, value in input.tags]
156
+ if input.tags
157
+ else []
158
+ ),
159
+ ChangeSetType=mode,
160
+ ChangeSetName=change_set_name,
161
+ )
162
+ except Exception as e:
163
+ print(f"Error: {e}")
164
+ _exec_change_set(client, change_set, mode, input.stackname)
165
+
166
+
167
+ @catch_boto_errors
168
+ def update_otel_log_ingestion_function(input):
169
+ assert isinstance(input, OtelIngestionUpdate)
170
+
171
+ client = input.session.client("cloudformation")
172
+
173
+ _create_otel_log_ingestion_function(
174
+ input,
175
+ nr_license_key=None,
176
+ mode="UPDATE",
177
+ )
178
+
179
+
180
+ @catch_boto_errors
181
+ def install_otel_log_ingestion(
182
+ input,
183
+ nr_license_key,
184
+ ):
185
+ """
186
+ Installs the New Relic AWS Lambda log ingestion function and role.
187
+
188
+ Returns True for success and False for failure.
189
+ """
190
+ assert isinstance(input, OtelIngestionInstall)
191
+ function = get_function(input.session, OTEL_INGEST_LAMBDA_NAME)
192
+ if function:
193
+ warning(
194
+ "It looks like an old log ingestion function is present in this region. "
195
+ "Consider manually deleting this as it is no longer used and "
196
+ "has been replaced by a log ingestion function specific to the stack."
197
+ )
198
+ stack_status = _check_for_ingest_stack(input.session, input.stackname)
199
+ if stack_status is None:
200
+ click.echo(
201
+ "Setting up CloudFormation Stack %s in region: %s"
202
+ % (input.stackname, input.session.region_name)
203
+ )
204
+ try:
205
+ _create_otel_log_ingestion_function(
206
+ input,
207
+ nr_license_key,
208
+ )
209
+ return True
210
+ except Exception as e:
211
+ failure(
212
+ "CloudFormation Stack %s exists (status: %s).\n"
213
+ "Please manually delete the stack and re-run this command."
214
+ % (input.stackname, stack_status)
215
+ )
216
+ return False
217
+ else:
218
+ function = get_newrelic_otel_log_ingestion_function(
219
+ input.session, input.stackname
220
+ )
221
+
222
+ if function is None:
223
+ failure(
224
+ "CloudFormation Stack %s exists (status: %s), but "
225
+ "%s Lambda function does not.\n"
226
+ "Please manually delete the stack and re-run this command."
227
+ % (input.stackname, stack_status, OTEL_INGEST_LAMBDA_NAME)
228
+ )
229
+ return False
230
+ else:
231
+ success(
232
+ "The CloudFormation Stack %s and "
233
+ "%s function already exists in region %s, "
234
+ "skipping"
235
+ % (input.stackname, OTEL_INGEST_LAMBDA_NAME, input.session.region_name)
236
+ )
237
+ return True
238
+
239
+
240
+ @catch_boto_errors
241
+ def update_otel_log_ingestion(input):
242
+ """
243
+ Updates the New Relic AWS Lambda log ingestion function and role.
244
+
245
+ Returns True for success and False for failure.
246
+ """
247
+ assert isinstance(input, OtelIngestionUpdate)
248
+
249
+ stack_status = _check_for_ingest_stack(input.session, input.stackname)
250
+ if stack_status is None:
251
+ failure(
252
+ "No '%s' stack in region '%s'. "
253
+ "This likely means the New Relic otel log ingestion function was "
254
+ "installed manually. "
255
+ "In order to install via the CLI, please delete this function and "
256
+ "run 'newrelic-lambda otel-ingestion install'."
257
+ % (OTEL_INGEST_STACK_NAME, input.session.region_name)
258
+ )
259
+ return False
260
+
261
+ function = get_newrelic_otel_log_ingestion_function(input.session, input.stackname)
262
+ if function is None:
263
+ failure(
264
+ "No %s function in region '%s'. "
265
+ "Run 'newrelic-lambda otel-ingestion install' to install it."
266
+ % (OTEL_INGEST_LAMBDA_NAME, input.session.region_name)
267
+ )
268
+ return False
269
+
270
+ try:
271
+ update_otel_log_ingestion_function(input)
272
+ except Exception as e:
273
+ failure("Failed to update newrelic-log-ingestion function: %s" % e)
274
+ return False
275
+ else:
276
+ return True
@@ -7,6 +7,7 @@ from newrelic_lambda_cli.cliutils import failure, success, warning
7
7
  from newrelic_lambda_cli.functions import get_function
8
8
  from newrelic_lambda_cli.integrations import get_unique_newrelic_log_ingestion_name
9
9
  from newrelic_lambda_cli.integrations import get_newrelic_log_ingestion_function
10
+ from newrelic_lambda_cli.otel_ingestions import get_newrelic_otel_log_ingestion_function
10
11
  from newrelic_lambda_cli.types import (
11
12
  LayerInstall,
12
13
  SubscriptionInstall,
@@ -48,12 +49,16 @@ def _get_subscription_filters(session, function_name):
48
49
 
49
50
 
50
51
  def _create_subscription_filter(
51
- session, function_name, destination_arn, filter_pattern
52
+ session,
53
+ function_name,
54
+ destination_arn,
55
+ filter_pattern,
56
+ filter_name="NewRelicLogStreaming",
52
57
  ):
53
58
  try:
54
59
  session.client("logs").put_subscription_filter(
55
60
  logGroupName=_get_log_group_name(function_name),
56
- filterName="NewRelicLogStreaming",
61
+ filterName=filter_name,
57
62
  filterPattern=filter_pattern,
58
63
  destinationArn=destination_arn,
59
64
  )
@@ -137,6 +142,66 @@ def create_log_subscription(input, function_name):
137
142
  return True
138
143
 
139
144
 
145
+ @catch_boto_errors
146
+ def create_otel_log_subscription(input, function_name):
147
+ assert isinstance(input, SubscriptionInstall)
148
+
149
+ destination = get_newrelic_otel_log_ingestion_function(
150
+ input.session, input.stackname
151
+ )
152
+ if destination is None:
153
+ failure(
154
+ "Could not find newrelic-otel-log-ingestion function. Is the New Relic AWS "
155
+ "integration installed?"
156
+ )
157
+ return False
158
+ destination_arn = destination["Configuration"]["FunctionArn"]
159
+
160
+ subscription_filters = _get_subscription_filters(input.session, function_name)
161
+ if subscription_filters is None:
162
+ return False
163
+ newrelic_filters = [
164
+ filter
165
+ for filter in subscription_filters
166
+ if "NewRelicOtelLogStreaming" in filter["filterName"]
167
+ ]
168
+ if len(subscription_filters) > len(newrelic_filters):
169
+ warning(
170
+ "WARNING: Found otel log subscription filter that was not installed by New "
171
+ "Relic. This may prevent the New Relic log subscription filter from being "
172
+ "installed. If you know you don't need this log subscription filter, you "
173
+ "should first remove it and rerun this command. If your organization "
174
+ "requires this log subscription filter, please contact New Relic at "
175
+ "serverless@newrelic.com for assistance with getting the AWS log "
176
+ "subscription filter limit increased."
177
+ )
178
+ if not newrelic_filters:
179
+ click.echo("Adding New Relic otel log subscription to '%s'" % function_name)
180
+ return _create_subscription_filter(
181
+ input.session,
182
+ function_name,
183
+ destination_arn,
184
+ input.filter_pattern,
185
+ "NewRelicOtelLogStreaming",
186
+ )
187
+ else:
188
+ click.echo(
189
+ "Found log subscription for '%s', verifying configuration" % function_name
190
+ )
191
+ newrelic_filter = newrelic_filters[0]
192
+ if newrelic_filter["filterPattern"] != input.filter_pattern:
193
+ return _remove_subscription_filter(
194
+ input.session, function_name, newrelic_filter["filterName"]
195
+ ) and _create_subscription_filter(
196
+ input.session,
197
+ function_name,
198
+ destination_arn,
199
+ input.filter_pattern,
200
+ "NewRelicOtelLogStreaming",
201
+ )
202
+ return True
203
+
204
+
140
205
  @catch_boto_errors
141
206
  def remove_log_subscription(input, function_name):
142
207
  assert isinstance(input, (LayerInstall, SubscriptionUninstall))
@@ -158,3 +223,27 @@ def remove_log_subscription(input, function_name):
158
223
  return _remove_subscription_filter(
159
224
  input.session, function_name, newrelic_filter["filterName"]
160
225
  )
226
+
227
+
228
+ @catch_boto_errors
229
+ def remove_otel_log_subscription(input, function_name):
230
+ assert isinstance(input, (SubscriptionUninstall))
231
+ subscription_filters = _get_subscription_filters(input.session, function_name)
232
+ if subscription_filters is None:
233
+ return False
234
+ newrelic_filters = [
235
+ filter
236
+ for filter in subscription_filters
237
+ if "NewRelicOtelLogStreaming" in filter["filterName"]
238
+ ]
239
+ if not newrelic_filters:
240
+ click.echo(
241
+ "No New Relic otel subscription filters found for '%s', skipping"
242
+ % function_name
243
+ )
244
+ return True
245
+ newrelic_filter = newrelic_filters[0]
246
+ click.echo("Removing New Relic otel log subscription from '%s'" % function_name)
247
+ return _remove_subscription_filter(
248
+ input.session, function_name, newrelic_filter["filterName"]
249
+ )
@@ -49,6 +49,48 @@ INTEGRATION_UPDATE_KEYS = [
49
49
  "tags",
50
50
  ]
51
51
 
52
+ OTEL_INGESTION_INSTALL_KEYS = [
53
+ "session",
54
+ "verbose",
55
+ "aws_profile",
56
+ "aws_region",
57
+ "aws_permissions_check",
58
+ "aws_role_policy",
59
+ "stackname",
60
+ "memory_size",
61
+ "nr_account_id",
62
+ "nr_api_key",
63
+ "nr_region",
64
+ "timeout",
65
+ "role_name",
66
+ "tags",
67
+ ]
68
+
69
+ OTEL_INGESTION_UNINSTALL_KEYS = [
70
+ "session",
71
+ "aws_profile",
72
+ "aws_region",
73
+ "aws_permissions_check",
74
+ "stackname",
75
+ "nr_account_id",
76
+ "force",
77
+ ]
78
+
79
+ OTEL_INGESTION_UPDATE_KEYS = [
80
+ "session",
81
+ "aws_profile",
82
+ "aws_region",
83
+ "aws_permissions_check",
84
+ "stackname",
85
+ "memory_size",
86
+ "nr_account_id",
87
+ "nr_api_key",
88
+ "nr_region",
89
+ "timeout",
90
+ "role_name",
91
+ "tags",
92
+ ]
93
+
52
94
  LAYER_INSTALL_KEYS = [
53
95
  "session",
54
96
  "verbose",
@@ -86,6 +128,7 @@ SUBSCRIPTION_INSTALL_KEYS = [
86
128
  "stackname",
87
129
  "excludes",
88
130
  "filter_pattern",
131
+ "otel",
89
132
  ]
90
133
 
91
134
  SUBSCRIPTION_UNINSTALL_KEYS = [
@@ -94,8 +137,8 @@ SUBSCRIPTION_UNINSTALL_KEYS = [
94
137
  "aws_region",
95
138
  "aws_permissions_check",
96
139
  "functions",
97
- "stackname",
98
140
  "excludes",
141
+ "otel",
99
142
  ]
100
143
 
101
144
 
@@ -103,6 +146,13 @@ IntegrationInstall = namedtuple("IntegrationInstall", INTEGRATION_INSTALL_KEYS)
103
146
  IntegrationUninstall = namedtuple("IntegrationUninstall", INTEGRATION_UNINSTALL_KEYS)
104
147
  IntegrationUpdate = namedtuple("IntegrationUpdate", INTEGRATION_UPDATE_KEYS)
105
148
 
149
+ OtelIngestionInstall = namedtuple("OtelIngestionInstall", OTEL_INGESTION_INSTALL_KEYS)
150
+ OtelIngestionUninstall = namedtuple(
151
+ "OtelIngestionUninstall", OTEL_INGESTION_UNINSTALL_KEYS
152
+ )
153
+ OtelIngestionUpdate = namedtuple("OtelIngestionUpdate", OTEL_INGESTION_UPDATE_KEYS)
154
+
155
+
106
156
  LayerInstall = namedtuple("LayerInstall", LAYER_INSTALL_KEYS)
107
157
  LayerUninstall = namedtuple("LayerUninstall", LAYER_UNINSTALL_KEYS)
108
158
 
@@ -10,6 +10,8 @@ NR_DOCS_ACT_LINKING_URL = "https://docs.newrelic.com/docs/serverless-function-mo
10
10
  NEW_RELIC_ARN_PREFIX_TEMPLATE = "arn:aws:lambda:%s:451483290750"
11
11
  RUNTIME_CONFIG = {
12
12
  "dotnetcore3.1": {"LambdaExtension": True},
13
+ "dotnet6": {"LambdaExtension": True},
14
+ "dotnet8": {"LambdaExtension": True},
13
15
  "java21": {
14
16
  "Handler": "com.newrelic.java.HandlerWrapper::",
15
17
  "LambdaExtension": True,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: newrelic-lambda-cli
3
- Version: 0.9.1
3
+ Version: 0.9.3
4
4
  Summary: A CLI to install the New Relic AWS Lambda integration and layers.
5
5
  Home-page: https://github.com/newrelic/newrelic-lambda-cli
6
6
  Author: New Relic
@@ -8,12 +8,12 @@ Author-email: serverless-dev@newrelic.com
8
8
  Requires-Python: >=3.3
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
- Requires-Dist: boto3 <5
12
- Requires-Dist: click >=7.1.2
11
+ Requires-Dist: boto3<5
12
+ Requires-Dist: click>=7.1.2
13
13
  Requires-Dist: colorama
14
- Requires-Dist: emoji <3,>=2
15
- Requires-Dist: gql <3,>=2
16
- Requires-Dist: requests <3
14
+ Requires-Dist: emoji<3,>=2
15
+ Requires-Dist: gql<3,>=2
16
+ Requires-Dist: requests<3
17
17
  Requires-Dist: tabulate
18
18
 
19
19
  [![Community Plus header](https://github.com/newrelic/opensource-website/raw/master/src/images/categories/Community_Plus.png)](https://opensource.newrelic.com/oss-category/#community-plus)
@@ -34,6 +34,9 @@ A CLI to install the New Relic AWS Lambda integration and layers.
34
34
  * [AWS Lambda Layers](#aws-lambda-layers)
35
35
  * [AWS Lambda Functions](#aws-lambda-functions)
36
36
  * [NewRelic Log Subscription](#newRelic-log-subscription)
37
+ * [NewRelic Otel Log Ingestions](#newRelic-otel-ingestions-install)
38
+ * [NewRelic Otel Log Subscription](#newRelic-otel-log-subscription)
39
+
37
40
  * **[Docker](#docker)**
38
41
  * **[Contributing](#contributing)**
39
42
  * **[Code Style](#code-style)**
@@ -52,6 +55,8 @@ A CLI to install the New Relic AWS Lambda integration and layers.
52
55
  ## Runtimes Supported
53
56
 
54
57
  * dotnetcore3.1
58
+ * dotnet6
59
+ * dotnet8
55
60
  * java8.al2
56
61
  * java11
57
62
  * java17
@@ -61,6 +66,7 @@ A CLI to install the New Relic AWS Lambda integration and layers.
61
66
  * nodejs20.x
62
67
  * provided
63
68
  * provided.al2
69
+ * provided.al2023
64
70
  * python3.7
65
71
  * python3.8
66
72
  * python3.9
@@ -270,6 +276,72 @@ newrelic-lambda subscriptions uninstall --function <name or arn>
270
276
  | `--aws-profile` or `-p` | No | The AWS profile to use for this command. Can also use `AWS_PROFILE`. Will also check `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables if not using AWS CLI. |
271
277
  | `--aws-region` or `-r` | No | The AWS region this function is located. Can use `AWS_DEFAULT_REGION` environment variable. Defaults to AWS session region. |
272
278
 
279
+ ### NewRelic Otel Ingestions Install
280
+
281
+ #### Install Otel Log Ingestion
282
+
283
+ ```bash
284
+ newrelic-lambda otel-ingestions install \
285
+ --nr-account-id <account id> \
286
+ --nr-api-key <api key>
287
+ ```
288
+
289
+ | Option | Required? | Description |
290
+ |--------|-----------|-------------|
291
+ | `--nr-account-id` or `-a` | Yes | The [New Relic Account ID](https://docs.newrelic.com/docs/accounts/install-new-relic/account-setup/account-id) for this integration. Can also use the `NEW_RELIC_ACCOUNT_ID` environment variable. |
292
+ | `--nr-api-key` or `-k` | Yes | Your [New Relic User API Key](https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys#user-api-key). Can also use the `NEW_RELIC_API_KEY` environment variable. |
293
+ | `--memory-size` or `-m` | No | Memory size (in MiB) for the New Relic log ingestion function. Default to 128MB. |
294
+ | `--nr-region` | No | The New Relic region to use for the integration. Can use the `NEW_RELIC_REGION` environment variable. Can be either `eu` or `us`. Defaults to `us`. |
295
+ | `--timeout` or `-t` | No | Timeout (in seconds) for the New Relic log ingestion function. Defaults to 30 seconds. |
296
+ | `--role-name` | No | Role name for the ingestion function. If you prefer to create and manage an IAM role for the function to assume out of band, do so and specify that role's name here. This avoids needing CAPABILITY_IAM. |
297
+ | `--aws-profile` or `-p` | No | The AWS profile to use for this command. Can also use `AWS_PROFILE`. Will also check `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables if not using AWS CLI. |
298
+ | `--aws-region` or `-r` | No | The AWS region for the integration. Can use `AWS_DEFAULT_REGION` environment variable. Defaults to AWS session region. |
299
+ | `--aws-role-policy` | No | Specify an alternative IAM role policy ARN for this integration. |
300
+ | `--tag <key> <value>` | No | Sets tags on the CloudFormation Stacks this CLI creates. Can be used multiple times, example: `--tag key1 value1 --tag key2 value2`. |
301
+ | `--stackname` | No | The AWS Cloudformation stack name which contains the newrelic-aws-otel-log-ingestion lambda function. If no value is provided, the command searches for the NewRelicOtelLogIngestion stack |
302
+
303
+
304
+ #### Uninstall Otel Log Ingestion
305
+
306
+ ```bash
307
+ newrelic-lambda otel-ingestions uninstall
308
+ ```
309
+
310
+ | Option | Required? | Description |
311
+ |--------|-----------|-------------|
312
+ | `--aws-profile` or `-p` | No | The AWS profile to use for this command. Can also use `AWS_PROFILE`. Will also check `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables if not using AWS CLI. |
313
+ | `--aws-region` or `-r` | No | The AWS region for the integration. Can use `AWS_DEFAULT_REGION` environment variable. Defaults to AWS session region. |
314
+ | `--force` or `-f` | No | Forces uninstall non-interactively |
315
+ | `--nr-account-id` or `-a` | No | The [New Relic Account ID](https://docs.newrelic.com/docs/accounts/install-new-relic/account-setup/account-id) for the integration. Only required if also uninstalling the New Relic AWS Lambda integration. Can also use the `NEW_RELIC_ACCOUNT_ID` environment variable. |
316
+ | `--stackname` | No | The AWS Cloudformation stack name which contains the newrelic-aws-otel-log-ingestion lambda function. If no value is provided, the command searches for the NewRelicOtelLogIngestion stack |
317
+
318
+ ### NewRelic Otel Log Subscription
319
+
320
+ #### Install Otel Log Subscription
321
+
322
+ ```bash
323
+ newrelic-lambda subscriptions install --function <name or arn> --otel
324
+ ```
325
+
326
+ | Option | Required? | Description |
327
+ |--------|-----------|-------------|
328
+ | `--function` or `-f` | Yes | The AWS Lambda function name or ARN in which to remove a log subscription. Can provide multiple `--function` arguments. Will also accept `all`, `installed` and `not-installed` similar to `newrelic-lambda functions list`. |
329
+ | `--otel` or `-o` | Yes | Use this flag to install subscription filters for Lambdas that are instrumented with OpenTelemetry (Otel) |
330
+ | `--stackname` | No | The AWS Cloudformation stack name which contains the newrelic-aws-otel-log-ingestion lambda function. If no value is provided, the command searches for the NewRelicOtelLogIngestion stack |
331
+
332
+
333
+ #### Uninstall Otel Log Subscription
334
+
335
+ ```bash
336
+ newrelic-lambda subscriptions uninstall --function <name or arn> --otel
337
+ ```
338
+
339
+ | Option | Required? | Description |
340
+ |--------|-----------|-------------|
341
+ | `--function` or `-f` | Yes | The AWS Lambda function name or ARN in which to remove a log subscription. Can provide multiple `--function` arguments. Will also accept `all`, `installed` and `not-installed` similar to `newrelic-lambda functions list`. |
342
+ | `--otel` or `-o` | Yes | Use this flag to install subscription filters for Lambdas that are instrumented with OpenTelemetry (Otel) |
343
+ | `--stackname` | No | The AWS Cloudformation stack name which contains the newrelic-aws-otel-log-ingestion lambda function. If no value is provided, the command searches for the NewRelicOtelLogIngestion stack |
344
+
273
345
  ## Docker
274
346
 
275
347
  Now, you can run newrelic-lambda-cli as a container.
@@ -0,0 +1,27 @@
1
+ newrelic_lambda_cli/__init__.py,sha256=u4cy7hwbrNjK3xtldGQD_51aoNgSqGQ3IzFYsuvaIM4,149
2
+ newrelic_lambda_cli/api.py,sha256=b75XwylRhW9pcA6aZ9EjBW1yIFOGHhhULDD5hNhMyes,15065
3
+ newrelic_lambda_cli/cliutils.py,sha256=x2pWlL3DJ9t98QNElp_rhawNQoIZ0vd55R2jpo3_oI0,902
4
+ newrelic_lambda_cli/functions.py,sha256=p57ZUw424BaSUA_Gw8DrYsJOYKROEHEaXgARadqwcP0,2800
5
+ newrelic_lambda_cli/integrations.py,sha256=r0gxfEqVHTGu3xbr4dOCDwm0-Yhoz3KntfeQRWvoWrQ,31266
6
+ newrelic_lambda_cli/layers.py,sha256=7ntl48RVEoRO4iiD3yzsxgqNkx013vXO5wQuoP6M0-I,14805
7
+ newrelic_lambda_cli/otel_ingestions.py,sha256=vi1Mlfc9nRvRWV7STwK7fDXZGozG8ufKohmpHcaWGic,9250
8
+ newrelic_lambda_cli/permissions.py,sha256=H7v5IMpKaJIWC4Dff2YcTis4BKAAFIJr9IHWUj1LnF4,9093
9
+ newrelic_lambda_cli/subscriptions.py,sha256=RDg5x_IajnZy2BzcONk1ZaLbb17XYLLNv6xJH1SBPcg,9533
10
+ newrelic_lambda_cli/types.py,sha256=z4K_ALDhF-iOKpyQUekbzETa586mr9bMpK9RCuffVQ8,3293
11
+ newrelic_lambda_cli/utils.py,sha256=dYcSFZj7Mpgr5f8YSaAjt80N1q9akcOj1_puL8iRHak,5324
12
+ newrelic_lambda_cli/cli/__init__.py,sha256=FciF2RVqQbpMKqEiN8qjO6qmdLB6Yv8LyyyPYcfJNrc,622
13
+ newrelic_lambda_cli/cli/decorators.py,sha256=a3agkVfy8omkUSL4aKblwSX95xtxYOGASULDYcJDPHk,1786
14
+ newrelic_lambda_cli/cli/functions.py,sha256=RSh2Cowe1_oQup8q5YRidp03z-BITo2uzvDh4zvLr4I,2601
15
+ newrelic_lambda_cli/cli/integrations.py,sha256=aQAWcCCU2kBmbF8fLKwKB9bzSY0uipvnojajjTkhqEs,10461
16
+ newrelic_lambda_cli/cli/layers.py,sha256=3CTukG79vM2Gzx3NFXsqUEjy5mNQ4rawIh53oQeCyCI,6180
17
+ newrelic_lambda_cli/cli/otel_ingestions.py,sha256=4rTm9iYUo2qdMeqxJSrYLCA6ZXHy5bJnjDn9x54pCYc,6096
18
+ newrelic_lambda_cli/cli/subscriptions.py,sha256=bUupv5iv3mUkC8t31nnI3BahoKxDnUJ8Rgq4QHJcFNU,5890
19
+ newrelic_lambda_cli/templates/import-template.yaml,sha256=0r1yeoqpnqtEMggWomALkPG10NiANPWWBqz03rChch8,3771
20
+ newrelic_lambda_cli/templates/license-key-secret.yaml,sha256=ZldQaLXsyF1K2I4X_AsLdH7kRmLkPUYI3talmhqQyHg,1849
21
+ newrelic_lambda_cli/templates/nr-lambda-integration-role.yaml,sha256=s7T73B_k-mAwgzJrD2xn8YGUNgn2E1V7Exifrl81ViU,2874
22
+ newrelic_lambda_cli-0.9.3.dist-info/LICENSE,sha256=uuxDzQm0yfq_tNZX0tQYzsZUVRIF0jm3dBLZUojSYzI,11345
23
+ newrelic_lambda_cli-0.9.3.dist-info/METADATA,sha256=izwIavIZMu-SUxSO7V8QRvihAmqwSn4OuQo4EMl1Qk4,26815
24
+ newrelic_lambda_cli-0.9.3.dist-info/WHEEL,sha256=M4n4zmFKzQZk4mLCcycNIzIXO7YPKE_b5Cw4PnhHEg8,109
25
+ newrelic_lambda_cli-0.9.3.dist-info/entry_points.txt,sha256=iks2k9Y4WNgIecsDzreIvMV9pGCjwwKTf33LKKvl2A8,65
26
+ newrelic_lambda_cli-0.9.3.dist-info/top_level.txt,sha256=dxX2w58VgSUFiPD8C_lFuY-T2C1kjfeY0xi8iTh0r44,20
27
+ newrelic_lambda_cli-0.9.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (72.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py2-none-any
5
5
  Tag: py3-none-any
@@ -1,25 +0,0 @@
1
- newrelic_lambda_cli/__init__.py,sha256=u4cy7hwbrNjK3xtldGQD_51aoNgSqGQ3IzFYsuvaIM4,149
2
- newrelic_lambda_cli/api.py,sha256=tkjuR_qkD2uZgXfXPFR6YKnmRiNYkrEmqQEeUgDtNn8,14848
3
- newrelic_lambda_cli/cliutils.py,sha256=x2pWlL3DJ9t98QNElp_rhawNQoIZ0vd55R2jpo3_oI0,902
4
- newrelic_lambda_cli/functions.py,sha256=p57ZUw424BaSUA_Gw8DrYsJOYKROEHEaXgARadqwcP0,2800
5
- newrelic_lambda_cli/integrations.py,sha256=X9OuBK_sNfjb1cjbZ1dctd_YTVyEeCCGsPaJp0Bni1U,30864
6
- newrelic_lambda_cli/layers.py,sha256=Gnt9pdG1Tfh79Y8ZWWJyMVXEB6xnW2UaSuo5zoYLa3U,14270
7
- newrelic_lambda_cli/permissions.py,sha256=H7v5IMpKaJIWC4Dff2YcTis4BKAAFIJr9IHWUj1LnF4,9093
8
- newrelic_lambda_cli/subscriptions.py,sha256=wh6vroU8RfSEwqAMObjPNVPb0TbBxUYYPO_c3mY7miA,6166
9
- newrelic_lambda_cli/types.py,sha256=kzubT5cGiI-k6h_8b_iTaj3bnsNwolhjgSbpFJT9iBk,2304
10
- newrelic_lambda_cli/utils.py,sha256=cwYX_zG72EjGT92l43mEAJRygrClUNseKDyssQ6D_2Q,5240
11
- newrelic_lambda_cli/cli/__init__.py,sha256=n_QPd3oJqkFxryy-pJ-Y_AsqsmgbTb3dlQCjPJueaYQ,544
12
- newrelic_lambda_cli/cli/decorators.py,sha256=a3agkVfy8omkUSL4aKblwSX95xtxYOGASULDYcJDPHk,1786
13
- newrelic_lambda_cli/cli/functions.py,sha256=RSh2Cowe1_oQup8q5YRidp03z-BITo2uzvDh4zvLr4I,2601
14
- newrelic_lambda_cli/cli/integrations.py,sha256=aQAWcCCU2kBmbF8fLKwKB9bzSY0uipvnojajjTkhqEs,10461
15
- newrelic_lambda_cli/cli/layers.py,sha256=dVlBB0rnhnWEXl9EygEjSiJknNnIQgPbF8L5hsdkMfU,5886
16
- newrelic_lambda_cli/cli/subscriptions.py,sha256=qwV4WUW9fbju0t4-aSfIrPdeEa4QvIJ8bfwTvMnm7zs,4251
17
- newrelic_lambda_cli/templates/import-template.yaml,sha256=0r1yeoqpnqtEMggWomALkPG10NiANPWWBqz03rChch8,3771
18
- newrelic_lambda_cli/templates/license-key-secret.yaml,sha256=ZldQaLXsyF1K2I4X_AsLdH7kRmLkPUYI3talmhqQyHg,1849
19
- newrelic_lambda_cli/templates/nr-lambda-integration-role.yaml,sha256=s7T73B_k-mAwgzJrD2xn8YGUNgn2E1V7Exifrl81ViU,2874
20
- newrelic_lambda_cli-0.9.1.dist-info/LICENSE,sha256=uuxDzQm0yfq_tNZX0tQYzsZUVRIF0jm3dBLZUojSYzI,11345
21
- newrelic_lambda_cli-0.9.1.dist-info/METADATA,sha256=rKXVnaSVtnjbs_5xuj_CdvJh8fRMWEpB5_LAnrTACag,21703
22
- newrelic_lambda_cli-0.9.1.dist-info/WHEEL,sha256=DZajD4pwLWue70CAfc7YaxT1wLUciNBvN_TTcvXpltE,110
23
- newrelic_lambda_cli-0.9.1.dist-info/entry_points.txt,sha256=iks2k9Y4WNgIecsDzreIvMV9pGCjwwKTf33LKKvl2A8,65
24
- newrelic_lambda_cli-0.9.1.dist-info/top_level.txt,sha256=dxX2w58VgSUFiPD8C_lFuY-T2C1kjfeY0xi8iTh0r44,20
25
- newrelic_lambda_cli-0.9.1.dist-info/RECORD,,