03 Aug 2023 12:04 PM - last edited on 14 Aug 2023 10:09 AM by MaciejNeumann
Hello,
I'm having a trouble activating trace from Google Cloud Function.
I set up this python code allowing me to check if the snapshot of the day-1 is well done.
So far so good.
I want to activate the traces behind to trace the information in Dynatrace.
I followed the following documentation (here), but the trace does not go up.
Code content of main :
# isort: off
import setup_tracing # import the module containing your setup code
# isort: on
# import other modules
import google.auth
import google.auth.transport.requests
from google.auth.transport.requests import AuthorizedSession
import requests
import json
from datetime import date
from datetime import timedelta
credentials, project = google.auth.default()
request = google.auth.transport.requests.Request()
credentials.refresh(request)
authed_session = AuthorizedSession(credentials)
import flask
from dynatrace.opentelemetry.gcf import wrap_handler
@wrap_handler
def main(data, context):
yesterday = date.today() - timedelta(days=1)
trigger_run_url = "https://compute.googleapis.com/compute/v1/projects/project_id/global/snapshots"
r = authed_session.get(trigger_run_url)
data = r.json()
print(data)
items_list = data["items"]
result = False
for item in items_list:
creationTime = item["creationTimestamp"]
if yesterday.strftime("%Y-%m-%d") in creationTime:
result = True
print(result)
message = "Hello World"
return flask.Response(message, 200)
Content code of setup_tracing :
from opentelemetry.sdk.resources import Resource
from opentelemetry.semconv.resource import ResourceAttributes
from dynatrace.opentelemetry.tracing.api import configure_dynatrace
tracer_provider = configure_dynatrace(
resource=Resource.create({ResourceAttributes.SERVICE_NAME: "snapshot-list"})
)
When i run my cloud function, it doesn't give me an error in execution.
Does somebody have an idea ?
Thanks,
Romain.
03 Aug 2023 03:39 PM - edited 03 Aug 2023 03:39 PM
Did you make sure to complete the prerequisites outlined below?
https://www.dynatrace.com/support/help/shortlink/monitor-gcf-otel
Also, make sure the settings in the UI are correct from the link here. I'd double check the code instrumentation as well. I'm wondering if you potentially need the OTel exporters?
https://www.dynatrace.com/support/help/shortlink/otel-wt-python
03 Aug 2023 04:46 PM
Hello,
About the prerequisites
I am on a SaaS environment
I don't think going through OneAgent. I set up the GCP subscription by Dynatrace Operation Suite which supervises the projects defined in scope and monitors each service added to my environment (Including Cloudfunction).
It is well activated.
Also the feature minimum opt in version
This feature is also activated.
I will exploit the track to export the trace by Otel and come back to you.
Thanks,
Romain.
04 Aug 2023 10:44 AM
Hello,
I tested Otel instrumentation to ingest traces into Dynatrace.
The result is not conclusive but I'm now able to provide more information following the implementation of logs at debug level in my cloudfunction.
Here is the new version of code :
import logging
import google.cloud.logging
client = google.cloud.logging.Client()
client.setup_logging()
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
import google.auth
import google.auth.transport.requests
from google.auth.transport.requests import AuthorizedSession
import requests
import json
from datetime import date
from datetime import timedelta
credentials, project = google.auth.default()
request = google.auth.transport.requests.Request()
credentials.refresh(request)
authed_session = AuthorizedSession(credentials)
from opentelemetry.sdk.resources import Resource
# Import exporters
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
# Trace imports
from opentelemetry.trace import set_tracer_provider
from opentelemetry.trace import get_tracer_provider
from opentelemetry.sdk.trace import TracerProvider, sampling
from opentelemetry.sdk.trace.export import BatchSpanProcessor
# ===== GENERAL SETUP =====
DT_API_URL = "https://{environmentid}.live.dynatrace.com/api/v2/otlp"
DT_API_TOKEN = "api_token"
merged = dict()
for name in ["dt_metadata_e617c525669e072eebe3d0f08212e8f2.json", "/var/lib/dynatrace/enrichment/dt_metadata.json"]:
try:
data = ''
with open(name) as f:
data = json.load(f if name.startswith("/var") else open(f.read()))
merged.update(data)
except:
pass
merged.update({
"service.name": "python-test", #TODO Replace with the name of your application
"service.version": "1.0.0", #TODO Replace with the version of your application
})
resource = Resource.create(merged)
# ===== TRACING SETUP =====
tracer_provider = TracerProvider(sampler=sampling.ALWAYS_ON, resource=resource)
set_tracer_provider(tracer_provider)
tracer_provider.add_span_processor(
BatchSpanProcessor(
OTLPSpanExporter(
endpoint = DT_API_URL + "/v1/traces",
headers = {
"Authorization": "Api-Token " + DT_API_TOKEN
}
)
)
)
def main(data, context):
tracer = get_tracer_provider().get_tracer("my-tracer")
with tracer.start_as_current_span("rbe") as span:
logger.debug("This is a log message.")
span.set_attribute("http.method", "GET")
span.set_attribute("net.protocol.version", "1.1")
yesterday = date.today() - timedelta(days=1)
trigger_run_url = "https://compute.googleapis.com/compute/v1/projects/project_id/global/snapshots"
r = authed_session.get(trigger_run_url)
# Check the response.
if r.status_code == 200:
logger.debug("The API call was successful.")
else:
logger.debug("The API call failed.")
d = r.json()
print(d)
items_list = d["items"]
result = False
for item in items_list:
creationTime = item["creationTimestamp"]
if yesterday.strftime("%Y-%m-%d") in creationTime:
result = True
print(result)
span.end()
You can find in attachment, the screenshot of the logs.
I already put forward a first hypothesis on this subject:
The service name "python-test" is not known in my environment.
I imagine it's to associate the trace with a service.
If the service is not known, does it trace it anyway?
And how can I define the name of my service that I don't know?
As a reminder, this is a cloudfunction discovered by a GCP subscription and visible in my environment by the following path:
GCP > project_id > cloudfunction_name
Thanks,
Romain.
30 Aug 2023 04:41 PM
Hello,
My problem is no longer relevant. Using gcf python instrumentation runs flawlessly.
The cause has been identified. It was an absence of DDUs on my subscription.
Thanks again for your time,
Romain.