
    Vh7                    "   d dl mZ dZdZd dlZd dlZd dlZd dlZd dlm	Z	 d dl
mZ d dlmZ d dlmZmZ d d	lmZ d d
lmZ 	 d dlmZmZmZmZmZ dZ G d d      Z G d d      Z G d de       Z! G d de      Z"y# e$ rZeZY dZ[7dZ[ww xY w)    )annotationsa`  
author: Victor Martinez (@v1v)  <VictorMartinezRubio@gmail.com>
name: elastic
type: notification
short_description: Create distributed traces for each Ansible task in Elastic APM
version_added: 3.8.0
description:
  - This callback creates distributed traces for each Ansible task in Elastic APM.
  - You can configure the plugin with environment variables.
  - See U(https://www.elastic.co/guide/en/apm/agent/python/current/configuration.html).
options:
  hide_task_arguments:
    default: false
    type: bool
    description:
      - Hide the arguments for a task.
    env:
      - name: ANSIBLE_OPENTELEMETRY_HIDE_TASK_ARGUMENTS
  apm_service_name:
    default: ansible
    type: str
    description:
      - The service name resource attribute.
    env:
      - name: ELASTIC_APM_SERVICE_NAME
  apm_server_url:
    type: str
    description:
      - Use the APM server and its environment variables.
    env:
      - name: ELASTIC_APM_SERVER_URL
  apm_secret_token:
    type: str
    description:
      - Use the APM server token.
    env:
      - name: ELASTIC_APM_SECRET_TOKEN
  apm_api_key:
    type: str
    description:
      - Use the APM API key.
    env:
      - name: ELASTIC_APM_API_KEY
  apm_verify_server_cert:
    default: true
    type: bool
    description:
      - Verifies the SSL certificate if an HTTPS connection.
    env:
      - name: ELASTIC_APM_VERIFY_SERVER_CERT
  traceparent:
    type: str
    description:
      - The L(W3C Trace Context header traceparent,https://www.w3.org/TR/trace-context-1/#traceparent-header).
    env:
      - name: TRACEPARENT
requirements:
  - elastic-apm (Python library)
a3  
examples: |-
  Enable the plugin in ansible.cfg:
    [defaults]
    callbacks_enabled = community.general.elastic

  Set the environment variable:
    export ELASTIC_APM_SERVER_URL=<your APM server URL)>
    export ELASTIC_APM_SERVICE_NAME=your_service_name
    export ELASTIC_APM_API_KEY=your_APM_API_KEY
N)OrderedDict)closing)basename)AnsibleErrorAnsibleRuntimeError)
raise_from)CallbackBase)Clientcapture_spantrace_parent_from_string
instrumentlabelc                      e Zd ZdZd Zd Zy)TaskDataz(
    Data about an individual task.
    c                    || _         || _        || _        || _        t	               | _        t        j                         | _        || _        || _	        y N)
uuidnamepathplayr   	host_datatimestartactionargs)selfr   r   r   r   r   r   s          n/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/community/general/plugins/callback/elastic.py__init__zTaskData.__init__j   sB    				$YY[
	    c                    |j                   | j                  v rH|j                  dk(  r8| j                  |j                      j                   d|j                   |_        ny || j                  |j                   <   y )Nincluded
)r   r   statusresult)r   hosts     r   add_hostzTaskData.add_hostt   s]    99&{{j(!%		!:!A!A B"T[[MR$(tyy!r    N)__name__
__module____qualname____doc__r   r'    r    r   r   r   e   s    )r    r   c                      e Zd ZdZd Zy)HostDataz(
    Data about an individual host.
    c                n    || _         || _        || _        || _        t	        j                         | _        y r   )r   r   r$   r%   r   finish)r   r   r   r$   r%   s        r   r   zHostData.__init__   s+    		iikr    N)r(   r)   r*   r+   r   r,   r    r   r.   r.      s    "r    r.   c                  `    e Zd Zd Zd Zd Zd Zd Zd Ze	d        Z
e	d        Ze	d	        Zy
)ElasticSourcec                j   d| _         d | _        t        t        j                               | _        t        j                         | _        	 t        j                  t        j                               | _
        t        j                         | _        || _        y # t        $ r}d | _
        Y d }~6d }~ww xY w)N )ansible_playbookansible_versionstrr   uuid4sessionsocketgethostnamer&   gethostbyname
ip_address	Exceptiongetpassgetuseruser_display)r   displayes      r   r   zElasticSource.__init__   s     "#4::<(&&(		#$2263E3E3GHDO OO%		  	#"DOO	#s   ,B 	B2!B--B2c                @   |j                   }||v ry|j                         j                         }|j                         }|j                  }d}	|j
                  s2|s0dj                  d |j                  j                         D              }	t        ||||||	      ||<   y)z2 record the start of a task for one or more hosts Nz, c              3  0   K   | ]  \  }}| d |   yw)=Nr,   ).0kvs      r   	<genexpr>z+ElasticSource.start_task.<locals>.<genexpr>   s     GTQ1QCjGs   )
_uuidget_namestripget_pathr   no_logjoinr   itemsr   )
r   
tasks_datahide_task_arguments	play_nametaskr   r   r   r   r   s
             r   
start_taskzElasticSource.start_task   s     zz:}}$$&}}{{#699GTYY__5FGHD#D$iN
4r    c                   |j                   j                  }t        |d      r9|j                  -|j                  j                  }|j                  j                  }nd}d}||   }| j
                  A|j                  d   j                  d      r#|j                  d   j                  d      | _        |j                  t        ||||             y)z0 record the results of a task for a single host _hostNincluder   _ansible_version)
_taskrL   hasattrrY   r   r6   _task_fieldsgetr'   r.   )r   rS   r$   r%   	task_uuid	host_uuid	host_namerV   s           r   finish_taskzElasticSource.finish_task   s     LL&&	67#(@**I))I!I!I)$'F,?,?,G,K,KL^,_#)#6#6v#>#B#BCU#VD hy)VVDEr    c
                   g }
d}|j                         D ]$  \  }}||j                  }|
j                  |       & | j                  |||||	      }|rt	        |      5  t                |r t        |      }|j                  d||       n|j                  d|       | j                  t        | j                         t        | j                  | j                  | j                         | j                  t        | j                         |
D ]7  }|j                  j                         D ]  \  }}| j                  |||        9 |j!                  t"        |||z
         ddd       yy# 1 sw Y   yxY w)	zF generate distributed traces from the collected TaskData and HostData NSession)trace_parentr   )r   )r6   )ansible_sessionansible_host_nameansible_host_user)ansible_host_ip)r   r%   duration)rR   r   appendinit_apm_clientr   r   r   begin_transactionr6   r   r9   r&   rA   r=   r   create_span_dataend_transactionr(   )r   rS   r$   end_timetraceparentapm_service_nameapm_server_urlapm_verify_server_certapm_secret_tokenapm_api_keytasksparent_start_timer`   rV   apm_cliparent	task_datara   r   s                      r   generate_distributed_tracesz)ElasticSource.generate_distributed_traces   s     )//1 	OIt ($(JJ!LL	
 &&~7GI_aqs~! m5kBF--ifTe-f--i?P-Q''3$*>*>?dlldiicgclclm??.$//:!& MI090C0C0I0I0K M,	9--gy)LMM ''XfxZkOk'l%m m m ms   DE00E9c                   d|j                    d|j                   d|j                    }d}d}d}|j                  dk(  rd}ny|j                  j                  }	|	j                  dd      }|j                  d	k(  r%| j                  |	      }| j                  |	      }d
}n|j                  dk(  rd|	v r|	d   }nd}d}t        |j                   |j                  d|j                  |j                  z
  |j                  ||j                  |||j                   |j                  d      5 }
||
_        d
|v rGt        |j                   d| d|       }|j                  t!        |      ||j"                  fd       ddd       y# 1 sw Y   yxY w)z6 create the span with the given TaskData and HostData [z] z: successNr"   r   rcfailedfailureskippedskip_reasonunknownzansible.task.run)zansible.task.argszansible.task.messagezansible.task.modulezansible.task.namezansible.task.resultzansible.task.host.namezansible.task.host.status)r   	span_typerk   labelsz failed with error message )messageT)exc_infohandled)r   r   r$   r%   _resultr_   get_error_messageenrich_error_messager   r   r0   r   r   outcomer   capture_exceptiontype__traceback__)r   rz   r|   r   r   r   r$   enriched_error_messager   resspan	exceptions               r   ro   zElasticSource.create_span_data   s    9>>""Y^^$4By~~6FG!%z)B""**Cq!B8+005)-)B)B3)G&"!!Y. C'!-0G'G").. )$6#,#3#3ioo#E7@~~:A9B9I9I7;9;<ENN>G>N>N"P	
Q 	x UY!DLF"/9;K;K:LBtfTo  qG  pH  9I  J	))DOYPYPgPg3hrv)w	x 	x 	xs   &AFFc           	     ,    |rt        ||d||dd      S y )NFT)service_name
server_urlverify_server_certsecret_tokenapi_keyuse_elastic_traceparent_headerdebug)r   )r   rt   rs   ru   rv   rw   s         r   rm   zElasticSource.init_apm_client  s,    '7%3-2'7"-9= $& & r    c                x    | j                  d      t        j                  | d         S | j                  dd      S )Nr   msgr   )r_   r2   
_last_line)r%   s    r   r   zElasticSource.get_error_message  s8    ::k". ++F;,?@@zz%**r    c                J    | j                         j                  d      }|d   S )Nr#   )rN   split)textliness     r   r   zElasticSource._last_line  s"    

""4(Ryr    c                    | j                  dd      }| j                  d      }| j                  d      }d| d| d| dS )	Nr   r   r   stderrz
message: "z"
exception: "z"
stderr: "")r_   )r%   r   r   r   s       r   r   z"ElasticSource.enrich_error_message  sL    **UH-JJ{+	H%WI%6ykPVxWYZZr    N)r(   r)   r*   r   rW   rc   r}   ro   rm   staticmethodr   r   r   r,   r    r   r2   r2      sd     O$F&mB&xP& + +
   [ [r    r2   c                       e Zd ZdZdZdZdZdZd fd	Zd fd	Z	d Z
d	 Zd
 Zd Zd Zd ZddZd Zd Zd Zd Zd Z xZS )CallbackModulezD
    This callback creates distributed traces with Elastic APM.
    g       @notificationzcommunity.general.elasticTc                0   t         t        |   |       d | _        d | _        d | _        d| _        d | _        d | _        d| _	        d| _
        t        rt        t        d      t               t               | _        t        | j                         | _        y )N)rC   Fr   z6The `elastic-apm` must be installed to use this plugin)superr   r   rT   rs   r5   rr   rU   rS   errorsdisabledELASTIC_LIBRARY_IMPORT_ERRORr	   r   r   r2   rB   elastic)r   rC   	__class__s     r   r   zCallbackModule.__init__/  s    nd,W,=#'  $ $ 'UV,. &-$T]];r    c                   t         t        |   |||       | j                  d      | _        | j                  d      | _        | j
                  sd| _        | j                  d      | _        | j                  d      | _        | j                  d      | _        | j                  d      | _	        | j                  d	      | _
        y )
N)	task_keysvar_optionsdirectrT   rs   ansiblert   rv   rw   ru   rr   )r   r   set_options
get_optionrT   rs   rt   rv   rw   ru   rr   )r   r   r   r   r   s       r   r   zCallbackModule.set_optionsC  s    nd/)<G7= 	0 	? $(??3H#I  $0B C$$$-D!"oo.>? $0B C??=9&*oo6N&O#??=9r    c                8    t        |j                        | _        y r   )r   
_file_namer5   )r   playbooks     r   v2_playbook_on_startz#CallbackModule.v2_playbook_on_startT  s     ()<)< =r    c                .    |j                         | _        y r   )rM   rU   )r   r   s     r   v2_playbook_on_play_startz(CallbackModule.v2_playbook_on_play_startW  s    r    c                |    | j                   j                  | j                  | j                  | j                  |       y r   r   rW   rS   rT   rU   r   rV   s     r   v2_runner_on_no_hostsz$CallbackModule.v2_runner_on_no_hostsZ  .    OO$$NN		
r    c                |    | j                   j                  | j                  | j                  | j                  |       y r   r   )r   rV   is_conditionals      r   v2_playbook_on_task_startz(CallbackModule.v2_playbook_on_task_startb  r   r    c                |    | j                   j                  | j                  | j                  | j                  |       y r   r   r   s     r   !v2_playbook_on_cleanup_task_startz0CallbackModule.v2_playbook_on_cleanup_task_startj  r   r    c                |    | j                   j                  | j                  | j                  | j                  |       y r   r   r   s     r   !v2_playbook_on_handler_task_startz0CallbackModule.v2_playbook_on_handler_task_startr  r   r    c                |    | xj                   dz  c_         | j                  j                  | j                  d|       y )N   r   )r   r   rc   rS   )r   r%   ignore_errorss      r   v2_runner_on_failedz"CallbackModule.v2_runner_on_failedz  s/    q  OO	
r    c                R    | j                   j                  | j                  d|       y )Nokr   rc   rS   r   r%   s     r   v2_runner_on_okzCallbackModule.v2_runner_on_ok  s!      OO	
r    c                R    | j                   j                  | j                  d|       y )Nr   r   r   s     r   v2_runner_on_skippedz#CallbackModule.v2_runner_on_skipped  s!      OO	
r    c                R    | j                   j                  | j                  d|       y )Nr"   r   )r   included_files     r   v2_playbook_on_includez%CallbackModule.v2_playbook_on_include  s!      OO	
r    c                "   | j                   dk(  rd}nd}| j                  j                  | j                  |t	        j                         | j
                  | j                  | j                  | j                  | j                  | j                  	       y )Nr   r   r   )r   r   r}   rS   r   rr   rs   rt   ru   rv   rw   )r   statsr$   s      r   v2_playbook_on_statsz#CallbackModule.v2_playbook_on_stats  ss    ;;!FF00OOIIK!!''!!
	
r    c                .    | xj                   dz  c_         y )Nr   )r   )r   r%   kwargss      r   v2_runner_on_async_failedz(CallbackModule.v2_runner_on_async_failed  s    qr    r   )NNN)F)r(   r)   r*   r+   CALLBACK_VERSIONCALLBACK_TYPECALLBACK_NAMECALLBACK_NEEDS_ENABLEDr   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__)r   s   @r   r   r   %  sf     "M/M!<(:">)








"r    r   )#
__future__r   DOCUMENTATIONEXAMPLESr?   r:   r   r   collectionsr   
contextlibr   os.pathr   ansible.errorsr   r   ansible.module_utils.sixr	   ansible.plugins.callbackr
   
elasticapmr   r   r   r   r   r   ImportErrorimp_excr   r.   objectr2   r   r,   r    r   <module>r      s   
 #:z
     #   < / 1(\\ $( ) )4
" 
"V[F V[rD\ DM  +#* +s   A= =BB		B